Added winebuild support for generating a .dbg.c file containing the
[wine] / programs / wineconsole / dialog.c
1 /* dialog management for wineconsole
2  * USER32 backend
3  * Copyright (c) 2001 Eric Pouech
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include "commctrl.h"
23 #include "prsht.h"
24 #include "winecon_user.h"
25
26 enum WCUSER_ApplyTo {
27     /* Prop sheet CFG */
28     WCUSER_ApplyToCursorSize, 
29     WCUSER_ApplyToHistorySize, WCUSER_ApplyToHistoryMode, WCUSER_ApplyToMenuMask,
30     WCUSER_ApplyToEditMode,
31     /* Prop sheet FNT */
32     WCUSER_ApplyToFont, WCUSER_ApplyToAttribute,
33     /* Prop sheep CNF */
34     WCUSER_ApplyToBufferSize, WCUSER_ApplyToWindow
35 };
36
37 struct dialog_info 
38 {
39     struct config_data* config;         /* pointer to configuration used for dialog box */
40     struct inner_data*  data;           /* pointer to current winecon info */
41     HWND                hDlg;           /* handle to active propsheet */
42     int                 nFont;          /* number of font size in size LB */
43     struct font_info 
44     {
45         UINT                    height;
46         UINT                    weight;
47         WCHAR                   faceName[LF_FACESIZE];
48     }                   *font;          /* array of nFont. index sync'ed with SIZE LB */
49     void        (*apply)(struct dialog_info*, HWND, enum WCUSER_ApplyTo, DWORD);
50 };
51
52 /******************************************************************
53  *              WCUSER_ApplyDefault
54  *
55  *
56  */
57 static void WCUSER_ApplyDefault(struct dialog_info* di, HWND hDlg, enum WCUSER_ApplyTo apply, DWORD val)
58 {
59     switch (apply)
60     {
61     case WCUSER_ApplyToCursorSize:
62     case WCUSER_ApplyToHistorySize:
63     case WCUSER_ApplyToHistoryMode:
64     case WCUSER_ApplyToBufferSize:
65     case WCUSER_ApplyToWindow:
66         /* not saving those for now... */
67         break;
68     case WCUSER_ApplyToMenuMask:
69         di->config->menu_mask = val;
70         break;
71     case WCUSER_ApplyToEditMode:
72         di->config->quick_edit = val;
73         break;
74     case WCUSER_ApplyToFont:
75         {
76             LOGFONT     lf;
77             HFONT       hFont;
78
79             WCUSER_FillLogFont(&lf, di->font[val].faceName, 
80                                di->font[val].height, di->font[val].weight);
81             hFont = WCUSER_CopyFont(di->config, PRIVATE(di->data)->hWnd, &lf);
82             DeleteObject(hFont);
83         }
84         break;
85     case WCUSER_ApplyToAttribute:
86         di->config->def_attr = val;
87         break;
88     }
89     WINECON_RegSave(di->config);
90 }
91
92 /******************************************************************
93  *              WCUSER_ApplyCurrent
94  *
95  *
96  */
97 static void WCUSER_ApplyCurrent(struct dialog_info* di, HWND hDlg, enum WCUSER_ApplyTo apply, DWORD val)
98 {
99     switch (apply)
100     {
101     case WCUSER_ApplyToCursorSize:
102         {
103             CONSOLE_CURSOR_INFO cinfo;
104             cinfo.dwSize = val;
105             cinfo.bVisible = di->config->cursor_visible;
106             /* this shall update (through notif) curcfg */
107             SetConsoleCursorInfo(di->data->hConOut, &cinfo);
108         }
109         break;
110     case WCUSER_ApplyToHistorySize:
111         di->config->history_size = val;
112         WINECON_SetHistorySize(di->data->hConIn, val);
113         break;
114     case WCUSER_ApplyToHistoryMode:
115         WINECON_SetHistoryMode(di->data->hConIn, val);
116         break;
117     case WCUSER_ApplyToMenuMask:
118         di->config->menu_mask = val;
119         break;
120     case WCUSER_ApplyToEditMode:
121         di->config->quick_edit = val;
122         break;
123     case WCUSER_ApplyToFont:
124         {
125             LOGFONT lf;
126             WCUSER_FillLogFont(&lf, di->font[val].faceName, 
127                                di->font[val].height, di->font[val].weight);
128             WCUSER_SetFont(di->data, &lf);
129         }
130         break;
131     case WCUSER_ApplyToAttribute:
132         di->config->def_attr = val;
133         SetConsoleTextAttribute(di->data->hConOut, val);
134         break;
135     case WCUSER_ApplyToBufferSize:
136         /* this shall update (through notif) curcfg */
137         SetConsoleScreenBufferSize(di->data->hConOut, *(COORD*)val);
138         break;
139     case WCUSER_ApplyToWindow:
140         /* this shall update (through notif) curcfg */
141         SetConsoleWindowInfo(di->data->hConOut, FALSE, (SMALL_RECT*)val);
142         break;
143     }
144 }
145
146 /******************************************************************
147  *              WCUSER_OptionDlgProc
148  *
149  * Dialog prop for the option property sheet
150  */
151 static BOOL WINAPI WCUSER_OptionDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
152 {
153     struct dialog_info*         di;
154     unsigned                    idc;
155     
156     switch (msg) 
157     {
158     case WM_INITDIALOG:
159         di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
160         di->hDlg = hDlg;
161         SetWindowLong(hDlg, DWL_USER, (DWORD)di);
162
163         if (di->config->cursor_size <= 25)      idc = IDC_OPT_CURSOR_SMALL;
164         else if (di->config->cursor_size <= 50) idc = IDC_OPT_CURSOR_MEDIUM;
165         else                                    idc = IDC_OPT_CURSOR_LARGE;
166         SendDlgItemMessage(hDlg, idc, BM_SETCHECK, BST_CHECKED, 0L);
167         SetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, WINECON_GetHistorySize(di->data->hConIn),  FALSE);
168         if (WINECON_GetHistoryMode(di->data->hConIn))
169             SendDlgItemMessage(hDlg, IDC_OPT_HIST_DOUBLE, BM_SETCHECK, BST_CHECKED, 0L);
170         SendDlgItemMessage(hDlg, IDC_OPT_CONF_CTRL, BM_SETCHECK, 
171                            (di->config->menu_mask & MK_CONTROL) ? BST_CHECKED : BST_UNCHECKED, 0L);
172         SendDlgItemMessage(hDlg, IDC_OPT_CONF_SHIFT, BM_SETCHECK, 
173                            (di->config->menu_mask & MK_SHIFT) ? BST_CHECKED : BST_UNCHECKED, 0L);
174         SendDlgItemMessage(hDlg, IDC_OPT_QUICK_EDIT, BM_SETCHECK, 
175                            (di->config->quick_edit) ? BST_CHECKED : BST_UNCHECKED, 0L);
176         return FALSE; /* because we set the focus */
177     case WM_COMMAND:
178         break;
179     case WM_NOTIFY:
180     {
181         NMHDR*  nmhdr = (NMHDR*)lParam;
182         DWORD   val;
183         BOOL    done;
184
185         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
186
187         switch (nmhdr->code) 
188         {
189         case PSN_SETACTIVE:
190             /* needed in propsheet to keep properly the selected radio button
191              * otherwise, the focus would be set to the first tab stop in the
192              * propsheet, which would always activate the first radio button
193              */
194             if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED) 
195                 idc = IDC_OPT_CURSOR_SMALL;
196             else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED)
197                 idc = IDC_OPT_CURSOR_MEDIUM;
198             else
199                 idc = IDC_OPT_CURSOR_LARGE;
200             PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, idc), TRUE);
201             di->hDlg = hDlg;
202             break;
203         case PSN_APPLY:
204             if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED) val = 25;
205             else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED) val = 50;
206             else val = 99;
207             (di->apply)(di, hDlg, WCUSER_ApplyToCursorSize, val);
208
209             val = GetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, &done, FALSE);
210             if (done) (di->apply)(di, hDlg, WCUSER_ApplyToHistorySize, val);
211
212             (di->apply)(di, hDlg, WCUSER_ApplyToHistoryMode, 
213                         IsDlgButtonChecked(hDlg, IDC_OPT_HIST_DOUBLE) & BST_CHECKED);
214
215             val = 0;
216             if (IsDlgButtonChecked(hDlg, IDC_OPT_CONF_CTRL) & BST_CHECKED)  val |= MK_CONTROL;
217             if (IsDlgButtonChecked(hDlg, IDC_OPT_CONF_SHIFT) & BST_CHECKED) val |= MK_SHIFT;
218             (di->apply)(di, hDlg, WCUSER_ApplyToMenuMask, val);
219
220             val = (IsDlgButtonChecked(hDlg, IDC_OPT_QUICK_EDIT) & BST_CHECKED) ? TRUE : FALSE;
221             (di->apply)(di, hDlg, WCUSER_ApplyToEditMode, val);
222
223             SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
224             return TRUE;
225         default:
226             return FALSE;
227         }
228         break;
229     }
230     default:
231         return FALSE;
232     }
233     return TRUE;
234 }
235
236 /******************************************************************
237  *              WCUSER_FontPreviewProc
238  *
239  * Window proc for font previewer in font property sheet
240  */
241 static LRESULT WINAPI WCUSER_FontPreviewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
242 {
243     switch (msg)
244     {
245     case WM_CREATE:
246         SetWindowLong(hWnd, 0, 0);
247         break;
248     case WM_GETFONT:
249         return GetWindowLong(hWnd, 0);
250     case WM_SETFONT:
251         SetWindowLong(hWnd, 0, wParam);
252         if (LOWORD(lParam))
253         {
254             InvalidateRect(hWnd, NULL, TRUE);
255             UpdateWindow(hWnd);
256         }
257         break;
258     case WM_DESTROY:
259         {
260             HFONT hFont = (HFONT)GetWindowLong(hWnd, 0L);
261             if (hFont) DeleteObject(hFont);
262         }
263         break;
264     case WM_PAINT:
265         {
266             PAINTSTRUCT         ps;
267             int                 font_idx;
268             int                 size_idx;
269             struct dialog_info* di;
270             HFONT               hFont, hOldFont;
271             
272             di = (struct dialog_info*)GetWindowLong(GetParent(hWnd), DWL_USER);
273             BeginPaint(hWnd, &ps);
274
275             font_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
276             size_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
277             
278             hFont = (HFONT)GetWindowLong(hWnd, 0L);
279             if (hFont)
280             {
281                 WCHAR   buf1[256];
282                 WCHAR   buf2[256];
283                 int     len1, len2;
284
285                 len1 = LoadString(GetModuleHandle(NULL), IDS_FNT_PREVIEW_1, 
286                                   buf1, sizeof(buf1) / sizeof(WCHAR));
287                 len2 = LoadString(GetModuleHandle(NULL), IDS_FNT_PREVIEW_2,
288                                   buf2, sizeof(buf2) / sizeof(WCHAR));
289                 buf1[len1] = buf2[len2] = 0;
290                 if (len1) 
291                 {
292                     hOldFont = SelectObject(ps.hdc, hFont);
293                     SetBkColor(ps.hdc, WCUSER_ColorMap[GetWindowLong(GetDlgItem(di->hDlg, IDC_FNT_COLOR_BK), 0)]);
294                     SetTextColor(ps.hdc, WCUSER_ColorMap[GetWindowLong(GetDlgItem(di->hDlg, IDC_FNT_COLOR_FG), 0)]);
295                     TextOut(ps.hdc, 0, 0, buf1, len1);
296                     if (len2)
297                         TextOut(ps.hdc, 0, di->font[size_idx].height, buf2, len2);
298                     SelectObject(ps.hdc, hOldFont);
299                 }
300             }
301             EndPaint(hWnd, &ps);
302         }
303         break;
304     default:
305         return DefWindowProc(hWnd, msg, wParam, lParam);
306     }
307     return 0L;
308 }
309
310 /******************************************************************
311  *              WCUSER_ColorPreviewProc
312  *
313  * Window proc for color previewer in font property sheet
314  */
315 static LRESULT WINAPI WCUSER_ColorPreviewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
316 {
317     switch (msg)
318     {
319     case WM_PAINT:
320         {
321             PAINTSTRUCT     ps;
322             int             i, step;
323             RECT            client, r;
324             HBRUSH          hbr;
325             
326             BeginPaint(hWnd, &ps);
327             GetClientRect(hWnd, &client);
328             step = client.right / 8;
329             
330             for (i = 0; i < 16; i++)
331             {
332                 r.top = (i / 8) * (client.bottom / 2);
333                 r.bottom = r.top + client.bottom / 2;
334                 r.left = (i & 7) * step;
335                 r.right = r.left + step;
336                 hbr = CreateSolidBrush(WCUSER_ColorMap[i]);
337                 FillRect(ps.hdc, &r, hbr);
338                 DeleteObject(hbr);
339                 if (GetWindowLong(hWnd, 0) == i)
340                 {
341                     HPEN        hOldPen;
342                     int         i = 2;
343
344                     hOldPen = SelectObject(ps.hdc, GetStockObject(WHITE_PEN));
345                     r.right--; r.bottom--;
346                     for (;;)
347                     {
348                         MoveToEx(ps.hdc, r.left, r.bottom, NULL);
349                         LineTo(ps.hdc, r.left, r.top);
350                         LineTo(ps.hdc, r.right, r.top);
351                         SelectObject(ps.hdc, GetStockObject(BLACK_PEN));
352                         LineTo(ps.hdc, r.right, r.bottom);
353                         LineTo(ps.hdc, r.left, r.bottom);
354
355                         if (--i == 0) break;
356                         r.left++; r.top++; r.right--; r.bottom--;
357                         SelectObject(ps.hdc, GetStockObject(WHITE_PEN));
358                     }
359                     SelectObject(ps.hdc, hOldPen);
360                 }
361             }
362             EndPaint(hWnd, &ps);
363             break;
364         }
365     case WM_LBUTTONDOWN:
366         {
367             int             i, step;
368             RECT            client;
369             
370             GetClientRect(hWnd, &client);
371             step = client.right / 8;
372             i = (HIWORD(lParam) >= client.bottom / 2) ? 8 : 0;
373             i += LOWORD(lParam) / step;
374             SetWindowLong(hWnd, 0, i);
375             InvalidateRect(GetDlgItem(GetParent(hWnd), IDC_FNT_PREVIEW), NULL, FALSE);
376             InvalidateRect(hWnd, NULL, FALSE);
377         }
378         break;
379     default:
380         return DefWindowProc(hWnd, msg, wParam, lParam);
381     }
382     return 0L;
383 }
384
385 /******************************************************************
386  *              font_enum
387  *
388  * enumerates all the font names with at least one valid font
389  */
390 static int CALLBACK font_enum_size2(const LOGFONT* lf, const TEXTMETRIC* tm, 
391                                     DWORD FontType, LPARAM lParam)
392 {
393     struct dialog_info* di = (struct dialog_info*)lParam;
394
395     if (WCUSER_ValidateFontMetric(di->data, tm, FontType))
396     {
397         di->nFont++;
398     }
399
400     return 1;
401 }
402
403 static int CALLBACK font_enum(const LOGFONT* lf, const TEXTMETRIC* tm, 
404                               DWORD FontType, LPARAM lParam)
405 {
406     struct dialog_info* di = (struct dialog_info*)lParam;
407     HDC hdc;
408
409     if (WCUSER_ValidateFont(di->data, lf) && (hdc = GetDC(di->hDlg)))
410     {
411         if (FontType & RASTER_FONTTYPE)
412         {
413             di->nFont = 0;
414             EnumFontFamilies(hdc, lf->lfFaceName, font_enum_size2, (LPARAM)di);
415         }
416         else
417             di->nFont = 1;
418         
419         if (di->nFont)
420         {
421             SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_ADDSTRING, 
422                                0, (LPARAM)lf->lfFaceName);
423         }
424         ReleaseDC(di->hDlg, hdc);
425     }
426
427     return 1;
428 }
429
430 /******************************************************************
431  *              font_enum_size
432  *
433  *
434  */
435 static int CALLBACK font_enum_size(const LOGFONT* lf, const TEXTMETRIC* tm, 
436                                    DWORD FontType, LPARAM lParam)
437 {
438     struct dialog_info* di = (struct dialog_info*)lParam;
439     WCHAR               buf[32];
440     static const WCHAR  fmt[] = {'%','l','d',0};
441
442     if (di->nFont == 0 && !(FontType & RASTER_FONTTYPE))
443     {
444         static const int sizes[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
445         int i;
446
447         di->nFont = sizeof(sizes) / sizeof(sizes[0]);
448         di->font = HeapAlloc(GetProcessHeap(), 0, di->nFont * sizeof(di->font[0]));
449         for (i = 0; i < di->nFont; i++)
450         {
451             /* drop sizes where window size wouldn't fit on screen */
452             if (sizes[i] * di->data->curcfg.win_height > GetSystemMetrics(SM_CYSCREEN))
453             {
454                 di->nFont = i;
455                 break;
456             }
457             di->font[i].height = sizes[i];
458             di->font[i].weight = 400;
459             lstrcpy(di->font[i].faceName, lf->lfFaceName);
460             wsprintf(buf, fmt, sizes[i]);
461             SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, i, (LPARAM)buf);
462         }
463         /* don't need to enumerate other */
464         return 0;
465     }
466
467     if (WCUSER_ValidateFontMetric(di->data, tm, FontType))
468     {
469         int     idx;
470
471         /* we want the string to be sorted with a numeric order, not a lexicographic...
472          * do the job by hand... get where to insert the new string
473          */
474         for (idx = 0; idx < di->nFont && tm->tmHeight > di->font[idx].height; idx++);
475         while (idx < di->nFont && 
476                tm->tmHeight == di->font[idx].height && 
477                tm->tmWeight > di->font[idx].weight)
478             idx++;
479         if (idx == di->nFont || 
480             tm->tmHeight != di->font[idx].height ||
481             tm->tmWeight < di->font[idx].weight)
482         {
483             /* here we need to add the new entry */
484             wsprintf(buf, fmt, tm->tmHeight);
485             SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, idx, (LPARAM)buf);
486
487             /* now grow our arrays and insert the values at the same index than in the list box */
488             di->font = HeapReAlloc(GetProcessHeap(), 0, di->font, sizeof(*di->font) * (di->nFont + 1));
489             if (idx != di->nFont)
490                 memmove(&di->font[idx + 1], &di->font[idx], (di->nFont - idx) * sizeof(*di->font));
491             di->font[idx].height = tm->tmHeight;
492             di->font[idx].weight = tm->tmWeight;
493             lstrcpy(di->font[idx].faceName, lf->lfFaceName);
494             di->nFont++;
495         }
496     }
497     return 1;
498 }
499
500 /******************************************************************
501  *              select_font
502  *
503  *
504  */
505 static BOOL  select_font(struct dialog_info* di)
506 {
507     int         font_idx, size_idx;
508     WCHAR       buf[256];
509     WCHAR       fmt[128];
510     LOGFONT     lf;
511     HFONT       hFont, hOldFont;
512     struct config_data config;
513
514     font_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
515     size_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
516
517     if (font_idx < 0 || size_idx < 0 || size_idx >= di->nFont)
518         return FALSE;
519     
520     WCUSER_FillLogFont(&lf, di->font[size_idx].faceName, 
521                        di->font[size_idx].height, di->font[size_idx].weight);
522     hFont = WCUSER_CopyFont(&config, PRIVATE(di->data)->hWnd, &lf);
523     if (!hFont) return FALSE;
524
525     if (config.cell_height != di->font[size_idx].height)
526         Trace(0, "select_font: mismatched heights (%u<>%u)\n",
527               config.cell_height, di->font[size_idx].height);
528     hOldFont = (HFONT)SendDlgItemMessage(di->hDlg, IDC_FNT_PREVIEW, WM_GETFONT, 0L, 0L);
529
530     SendDlgItemMessage(di->hDlg, IDC_FNT_PREVIEW, WM_SETFONT, (DWORD)hFont, TRUE);
531     if (hOldFont) DeleteObject(hOldFont);
532
533     LoadString(GetModuleHandle(NULL), IDS_FNT_DISPLAY, fmt, sizeof(fmt) / sizeof(WCHAR));
534     wsprintf(buf, fmt, config.cell_width, config.cell_height);
535
536     SendDlgItemMessage(di->hDlg, IDC_FNT_FONT_INFO, WM_SETTEXT, 0, (LPARAM)buf);
537
538     return TRUE;
539 }
540
541 /******************************************************************
542  *              fill_list_size
543  *
544  * fills the size list box according to selected family in font LB
545  */
546 static BOOL  fill_list_size(struct dialog_info* di, BOOL doInit)
547 {
548     HDC         hdc;
549     int         idx;
550     WCHAR       lfFaceName[LF_FACESIZE];
551
552     idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
553     if (idx < 0) return FALSE;
554     
555     hdc = GetDC(di->hDlg);
556     if (!hdc) return FALSE;
557
558     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETTEXT, idx, (LPARAM)lfFaceName);
559     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_RESETCONTENT, 0L, 0L);
560     if (di->font) HeapFree(GetProcessHeap(), 0, di->font);
561     di->nFont = 0;
562     di->font = NULL;
563
564     EnumFontFamilies(hdc, lfFaceName, font_enum_size, (LPARAM)di);
565     ReleaseDC(di->hDlg, hdc);
566
567     if (doInit)
568     {
569         int     ref = -1;
570
571         for (idx = 0; idx < di->nFont; idx++)
572         {
573             if (!lstrcmp(di->font[idx].faceName, di->config->face_name) &&
574                 di->font[idx].height == di->config->cell_height &&
575                 di->font[idx].weight == di->config->font_weight)
576             {
577                 if (ref == -1) ref = idx;
578                 else Trace(0, "Several matches found: ref=%d idx=%d\n", ref, idx);
579             }
580         }
581         idx = (ref == -1) ? 0 : ref;
582     }
583     else
584         idx = 0;
585     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_SETCURSEL, idx, 0L);
586     select_font(di);
587     return TRUE;
588 }
589
590 /******************************************************************
591  *              fill_list_font
592  *
593  * Fills the font LB
594  */
595 static BOOL fill_list_font(struct dialog_info* di)
596 {
597     HDC hdc;
598
599     hdc = GetDC(di->hDlg);
600     if (!hdc) return FALSE;
601
602     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_RESETCONTENT, 0L, 0L);
603     EnumFontFamilies(hdc, NULL, font_enum, (LPARAM)di);
604     ReleaseDC(di->hDlg, hdc);
605     if (SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SELECTSTRING, 
606                            (WPARAM)-1, (LPARAM)di->config->face_name) == LB_ERR)
607         SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SETCURSEL, 0L, 0L);
608     fill_list_size(di, TRUE);
609     return TRUE;
610 }
611
612 /******************************************************************
613  *              WCUSER_FontDlgProc
614  *
615  * Dialog proc for the Font property sheet
616  */
617 static BOOL WINAPI WCUSER_FontDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
618 {
619     struct dialog_info*         di;
620
621     switch (msg) 
622     {
623     case WM_INITDIALOG:
624         di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
625         di->hDlg = hDlg;
626         SetWindowLong(hDlg, DWL_USER, (DWORD)di);
627         /* remove dialog from this control, font will be reset when listboxes are filled */
628         SendDlgItemMessage(hDlg, IDC_FNT_PREVIEW, WM_SETFONT, 0L, 0L);
629         fill_list_font(di);
630         SetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_BK), 0, (di->config->def_attr >> 4) & 0x0F);
631         SetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_FG), 0, di->config->def_attr & 0x0F);
632         break;
633     case WM_COMMAND:
634         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
635         switch (LOWORD(wParam)) 
636         {
637         case IDC_FNT_LIST_FONT: 
638             if (HIWORD(wParam) == LBN_SELCHANGE)
639             {
640                 fill_list_size(di, FALSE);
641             }
642             break;
643         case IDC_FNT_LIST_SIZE: 
644             if (HIWORD(wParam) == LBN_SELCHANGE)
645             {
646                 select_font(di);
647             }
648             break;
649         }
650         break;
651     case WM_NOTIFY:
652     {
653         NMHDR*  nmhdr = (NMHDR*)lParam;
654         DWORD   val;
655
656         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
657         switch (nmhdr->code) 
658         {
659         case PSN_SETACTIVE:
660             di->hDlg = hDlg;
661             break;
662         case PSN_APPLY:
663             val = SendDlgItemMessage(hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
664
665             if (val < di->nFont) (di->apply)(di, hDlg, WCUSER_ApplyToFont, val);
666
667             (di->apply)(di, hDlg, WCUSER_ApplyToAttribute, 
668                         (GetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_BK), 0) << 4) |
669                         GetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_FG), 0));
670
671             SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
672             return TRUE;
673         default:
674             return FALSE;
675         }
676         break;
677     }
678     default:
679         return FALSE;
680     }
681     return TRUE;
682 }
683
684 /******************************************************************
685  *              WCUSER_ConfigDlgProc
686  *
687  * Dialog proc for the config property sheet
688  */
689 static BOOL WINAPI WCUSER_ConfigDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
690 {
691     struct dialog_info*         di;
692
693     switch (msg) 
694     {
695     case WM_INITDIALOG:
696         di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
697         di->hDlg = hDlg;
698         SetWindowLong(hDlg, DWL_USER, (DWORD)di);
699         SetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH,   di->config->sb_width,   FALSE);
700         SetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT,  di->config->sb_height,  FALSE);
701         SetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH,  di->config->win_width,  FALSE);
702         SetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, di->config->win_height, FALSE);
703         break;
704     case WM_COMMAND:
705         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
706         switch (LOWORD(wParam)) 
707         {
708         }
709         break;
710     case WM_NOTIFY:
711     {
712         NMHDR*          nmhdr = (NMHDR*)lParam;
713         COORD           sb;
714         SMALL_RECT      pos;
715         BOOL            st_w, st_h;
716
717         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
718         switch (nmhdr->code) 
719         {
720         case PSN_SETACTIVE:
721             di->hDlg = hDlg;
722             break;
723         case PSN_APPLY:
724             sb.X = GetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH,  &st_w, FALSE);
725             sb.Y = GetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, &st_h, FALSE);
726             if (st_w && st_h && (sb.X != di->config->sb_width || sb.Y != di->config->sb_height))
727             {
728                 (di->apply)(di, hDlg, WCUSER_ApplyToBufferSize, (DWORD)&sb);
729             }
730             
731             pos.Right  = GetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH,  &st_w, FALSE);
732             pos.Bottom = GetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, &st_h, FALSE);
733             if (st_w && st_h && 
734                 (pos.Right != di->config->win_width || pos.Bottom != di->config->win_height))
735             {
736                 pos.Left = pos.Top = 0;
737                 pos.Right--; pos.Bottom--;
738                 (di->apply)(di, hDlg, WCUSER_ApplyToWindow, (DWORD)&pos);
739             }
740             SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
741             return TRUE;
742         default:
743             return FALSE;
744         }
745         break;
746     }
747     default:
748         return FALSE;
749     }
750     return TRUE;
751 }
752
753 /******************************************************************
754  *              WCUSER_GetProperties
755  *
756  * Runs the dialog box to set up the winconsole options
757  */
758 BOOL WCUSER_GetProperties(struct inner_data* data, BOOL current)
759 {
760     HPROPSHEETPAGE      psPage[3];
761     PROPSHEETPAGE       psp;
762     PROPSHEETHEADER     psHead;
763     WCHAR               buff[256];
764     WNDCLASS            wndclass;
765     static const WCHAR szFntPreview[] = {'W','i','n','e','C','o','n','F','o','n','t','P','r','e','v','i','e','w',0};
766     static const WCHAR szColorPreview[] = {'W','i','n','e','C','o','n','C','o','l','o','r','P','r','e','v','i','e','w',0};
767     struct dialog_info  di;
768
769     InitCommonControls();
770
771     di.data = data;
772     if (current)
773     {
774         di.config = &data->curcfg;
775         di.apply = WCUSER_ApplyCurrent;
776     }
777     else
778     {
779         di.config = &data->defcfg;
780         di.apply = WCUSER_ApplyDefault;
781     }
782     di.nFont = 0;
783     di.font = NULL;
784
785     wndclass.style         = 0;
786     wndclass.lpfnWndProc   = WCUSER_FontPreviewProc;
787     wndclass.cbClsExtra    = 0;
788     wndclass.cbWndExtra    = 4; /* for hFont */
789     wndclass.hInstance     = GetModuleHandle(NULL);
790     wndclass.hIcon         = 0;
791     wndclass.hCursor       = LoadCursor(0, IDC_ARROW);
792     wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
793     wndclass.lpszMenuName  = NULL;
794     wndclass.lpszClassName = szFntPreview;
795     RegisterClass(&wndclass);
796
797     wndclass.style         = 0;
798     wndclass.lpfnWndProc   = WCUSER_ColorPreviewProc;
799     wndclass.cbClsExtra    = 0;
800     wndclass.cbWndExtra    = sizeof(DWORD);
801     wndclass.hInstance     = GetModuleHandle(NULL);
802     wndclass.hIcon         = 0;
803     wndclass.hCursor       = LoadCursor(0, IDC_ARROW);
804     wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
805     wndclass.lpszMenuName  = NULL;
806     wndclass.lpszClassName = szColorPreview;
807     RegisterClass(&wndclass);
808
809     memset(&psp, 0, sizeof(psp));
810     psp.dwSize = sizeof(psp);
811     psp.dwFlags = 0;
812     psp.hInstance = wndclass.hInstance;
813     psp.lParam = (LPARAM)&di;
814
815     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_OPTION);
816     psp.pfnDlgProc = WCUSER_OptionDlgProc;
817     psPage[0] = CreatePropertySheetPage(&psp);
818
819     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_FONT);
820     psp.pfnDlgProc = WCUSER_FontDlgProc;
821     psPage[1] = CreatePropertySheetPage(&psp);
822
823     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG);
824     psp.pfnDlgProc = WCUSER_ConfigDlgProc;
825     psPage[2] = CreatePropertySheetPage(&psp);
826
827     memset(&psHead, 0, sizeof(psHead));
828     psHead.dwSize = sizeof(psHead);
829
830     if (!LoadString(GetModuleHandle(NULL), 
831                     (current) ? IDS_DLG_TIT_CURRENT : IDS_DLG_TIT_DEFAULT, 
832                     buff, sizeof(buff) / sizeof(buff[0])))
833     {
834         buff[0] = 'S';
835         buff[1] = 'e';
836         buff[2] = 't';
837         buff[3] = 'u';
838         buff[4] = 'p';
839         buff[5] = '\0';
840     }
841
842     psHead.pszCaption = buff;
843     psHead.nPages = 3;
844     psHead.hwndParent = PRIVATE(data)->hWnd;
845     psHead.u3.phpage = psPage;
846  
847     PropertySheet(&psHead);
848
849     return TRUE;
850 }
851
852