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