Fixed make install target to work even when nothing has been compiled
[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
413     WCUSER_DumpLogFont("DlgFamily: ", lf, FontType);
414     if (WCUSER_ValidateFont(di->data, lf))
415     {
416         if (FontType & RASTER_FONTTYPE)
417         {
418             di->nFont = 0;
419             EnumFontFamilies(PRIVATE(di->data)->hMemDC, lf->lfFaceName, font_enum_size2, (LPARAM)di);
420         }
421         else
422             di->nFont = 1;
423
424         if (di->nFont)
425         {
426             SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_ADDSTRING,
427                                0, (LPARAM)lf->lfFaceName);
428         }
429     }
430
431     return 1;
432 }
433
434 /******************************************************************
435  *              font_enum_size
436  *
437  *
438  */
439 static int CALLBACK font_enum_size(const LOGFONT* lf, const TEXTMETRIC* tm,
440                                    DWORD FontType, LPARAM lParam)
441 {
442     struct dialog_info* di = (struct dialog_info*)lParam;
443     WCHAR               buf[32];
444     static const WCHAR  fmt[] = {'%','l','d',0};
445
446     WCUSER_DumpTextMetric(tm, FontType);
447     if (di->nFont == 0 && !(FontType & RASTER_FONTTYPE))
448     {
449         static const int sizes[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
450         int i;
451
452         di->nFont = sizeof(sizes) / sizeof(sizes[0]);
453         di->font = HeapAlloc(GetProcessHeap(), 0, di->nFont * sizeof(di->font[0]));
454         for (i = 0; i < di->nFont; i++)
455         {
456             /* drop sizes where window size wouldn't fit on screen */
457             if (sizes[i] * di->data->curcfg.win_height > GetSystemMetrics(SM_CYSCREEN))
458             {
459                 di->nFont = i;
460                 break;
461             }
462             di->font[i].height = sizes[i];
463             di->font[i].weight = 400;
464             lstrcpy(di->font[i].faceName, lf->lfFaceName);
465             wsprintf(buf, fmt, sizes[i]);
466             SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, i, (LPARAM)buf);
467         }
468         /* don't need to enumerate other */
469         return 0;
470     }
471
472     if (WCUSER_ValidateFontMetric(di->data, tm, FontType))
473     {
474         int     idx;
475
476         /* we want the string to be sorted with a numeric order, not a lexicographic...
477          * do the job by hand... get where to insert the new string
478          */
479         for (idx = 0; idx < di->nFont && tm->tmHeight > di->font[idx].height; idx++);
480         while (idx < di->nFont &&
481                tm->tmHeight == di->font[idx].height &&
482                tm->tmWeight > di->font[idx].weight)
483             idx++;
484         if (idx == di->nFont ||
485             tm->tmHeight != di->font[idx].height ||
486             tm->tmWeight < di->font[idx].weight)
487         {
488             /* here we need to add the new entry */
489             wsprintf(buf, fmt, tm->tmHeight);
490             SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, idx, (LPARAM)buf);
491
492             /* now grow our arrays and insert the values at the same index than in the list box */
493             di->font = HeapReAlloc(GetProcessHeap(), 0, di->font, sizeof(*di->font) * (di->nFont + 1));
494             if (idx != di->nFont)
495                 memmove(&di->font[idx + 1], &di->font[idx], (di->nFont - idx) * sizeof(*di->font));
496             di->font[idx].height = tm->tmHeight;
497             di->font[idx].weight = tm->tmWeight;
498             lstrcpy(di->font[idx].faceName, lf->lfFaceName);
499             di->nFont++;
500         }
501     }
502     return 1;
503 }
504
505 /******************************************************************
506  *              select_font
507  *
508  *
509  */
510 static BOOL  select_font(struct dialog_info* di)
511 {
512     int         font_idx, size_idx;
513     WCHAR       buf[256];
514     WCHAR       fmt[128];
515     LOGFONT     lf;
516     HFONT       hFont, hOldFont;
517     struct config_data config;
518
519     font_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
520     size_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
521
522     if (font_idx < 0 || size_idx < 0 || size_idx >= di->nFont)
523         return FALSE;
524
525     WCUSER_FillLogFont(&lf, di->font[size_idx].faceName,
526                        di->font[size_idx].height, di->font[size_idx].weight);
527     hFont = WCUSER_CopyFont(&config, PRIVATE(di->data)->hWnd, &lf);
528     if (!hFont) return FALSE;
529
530     if (config.cell_height != di->font[size_idx].height)
531         WINE_TRACE("select_font: mismatched heights (%u<>%u)\n",
532                    config.cell_height, di->font[size_idx].height);
533     hOldFont = (HFONT)SendDlgItemMessage(di->hDlg, IDC_FNT_PREVIEW, WM_GETFONT, 0L, 0L);
534
535     SendDlgItemMessage(di->hDlg, IDC_FNT_PREVIEW, WM_SETFONT, (DWORD)hFont, TRUE);
536     if (hOldFont) DeleteObject(hOldFont);
537
538     LoadString(GetModuleHandle(NULL), IDS_FNT_DISPLAY, fmt, sizeof(fmt) / sizeof(WCHAR));
539     wsprintf(buf, fmt, config.cell_width, config.cell_height);
540
541     SendDlgItemMessage(di->hDlg, IDC_FNT_FONT_INFO, WM_SETTEXT, 0, (LPARAM)buf);
542
543     return TRUE;
544 }
545
546 /******************************************************************
547  *              fill_list_size
548  *
549  * fills the size list box according to selected family in font LB
550  */
551 static BOOL  fill_list_size(struct dialog_info* di, BOOL doInit)
552 {
553     int         idx;
554     WCHAR       lfFaceName[LF_FACESIZE];
555
556     idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
557     if (idx < 0) return FALSE;
558
559     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETTEXT, idx, (LPARAM)lfFaceName);
560     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_RESETCONTENT, 0L, 0L);
561     if (di->font) HeapFree(GetProcessHeap(), 0, di->font);
562     di->nFont = 0;
563     di->font = NULL;
564
565     EnumFontFamilies(PRIVATE(di->data)->hMemDC, lfFaceName, font_enum_size, (LPARAM)di);
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 WINE_TRACE("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     SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_RESETCONTENT, 0L, 0L);
598     EnumFontFamilies(PRIVATE(di->data)->hMemDC, NULL, font_enum, (LPARAM)di);
599     if (SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SELECTSTRING,
600                            (WPARAM)-1, (LPARAM)di->config->face_name) == LB_ERR)
601         SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SETCURSEL, 0L, 0L);
602     fill_list_size(di, TRUE);
603     return TRUE;
604 }
605
606 /******************************************************************
607  *              WCUSER_FontDlgProc
608  *
609  * Dialog proc for the Font property sheet
610  */
611 static BOOL WINAPI WCUSER_FontDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
612 {
613     struct dialog_info*         di;
614
615     switch (msg)
616     {
617     case WM_INITDIALOG:
618         di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
619         di->hDlg = hDlg;
620         SetWindowLong(hDlg, DWL_USER, (DWORD)di);
621         /* remove dialog from this control, font will be reset when listboxes are filled */
622         SendDlgItemMessage(hDlg, IDC_FNT_PREVIEW, WM_SETFONT, 0L, 0L);
623         fill_list_font(di);
624         SetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_BK), 0, (di->config->def_attr >> 4) & 0x0F);
625         SetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_FG), 0, di->config->def_attr & 0x0F);
626         break;
627     case WM_COMMAND:
628         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
629         switch (LOWORD(wParam))
630         {
631         case IDC_FNT_LIST_FONT:
632             if (HIWORD(wParam) == LBN_SELCHANGE)
633             {
634                 fill_list_size(di, FALSE);
635             }
636             break;
637         case IDC_FNT_LIST_SIZE:
638             if (HIWORD(wParam) == LBN_SELCHANGE)
639             {
640                 select_font(di);
641             }
642             break;
643         }
644         break;
645     case WM_NOTIFY:
646     {
647         NMHDR*  nmhdr = (NMHDR*)lParam;
648         DWORD   val;
649
650         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
651         switch (nmhdr->code)
652         {
653         case PSN_SETACTIVE:
654             di->hDlg = hDlg;
655             break;
656         case PSN_APPLY:
657             val = SendDlgItemMessage(hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
658
659             if (val < di->nFont) (di->apply)(di, hDlg, WCUSER_ApplyToFont, val);
660
661             (di->apply)(di, hDlg, WCUSER_ApplyToAttribute,
662                         (GetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_BK), 0) << 4) |
663                         GetWindowLong(GetDlgItem(hDlg, IDC_FNT_COLOR_FG), 0));
664
665             SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
666             return TRUE;
667         default:
668             return FALSE;
669         }
670         break;
671     }
672     default:
673         return FALSE;
674     }
675     return TRUE;
676 }
677
678 /******************************************************************
679  *              WCUSER_ConfigDlgProc
680  *
681  * Dialog proc for the config property sheet
682  */
683 static BOOL WINAPI WCUSER_ConfigDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
684 {
685     struct dialog_info*         di;
686
687     switch (msg)
688     {
689     case WM_INITDIALOG:
690         di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
691         di->hDlg = hDlg;
692         SetWindowLong(hDlg, DWL_USER, (DWORD)di);
693         SetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH,   di->config->sb_width,   FALSE);
694         SetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT,  di->config->sb_height,  FALSE);
695         SetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH,  di->config->win_width,  FALSE);
696         SetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, di->config->win_height, FALSE);
697         break;
698     case WM_COMMAND:
699         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
700         switch (LOWORD(wParam))
701         {
702         }
703         break;
704     case WM_NOTIFY:
705     {
706         NMHDR*          nmhdr = (NMHDR*)lParam;
707         COORD           sb;
708         SMALL_RECT      pos;
709         BOOL            st_w, st_h;
710
711         di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
712         switch (nmhdr->code)
713         {
714         case PSN_SETACTIVE:
715             di->hDlg = hDlg;
716             break;
717         case PSN_APPLY:
718             sb.X = GetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH,  &st_w, FALSE);
719             sb.Y = GetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, &st_h, FALSE);
720             if (st_w && st_h && (sb.X != di->config->sb_width || sb.Y != di->config->sb_height))
721             {
722                 (di->apply)(di, hDlg, WCUSER_ApplyToBufferSize, (DWORD)&sb);
723             }
724
725             pos.Right  = GetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH,  &st_w, FALSE);
726             pos.Bottom = GetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, &st_h, FALSE);
727             if (st_w && st_h &&
728                 (pos.Right != di->config->win_width || pos.Bottom != di->config->win_height))
729             {
730                 pos.Left = pos.Top = 0;
731                 pos.Right--; pos.Bottom--;
732                 (di->apply)(di, hDlg, WCUSER_ApplyToWindow, (DWORD)&pos);
733             }
734             SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
735             return TRUE;
736         default:
737             return FALSE;
738         }
739         break;
740     }
741     default:
742         return FALSE;
743     }
744     return TRUE;
745 }
746
747 /******************************************************************
748  *              WCUSER_GetProperties
749  *
750  * Runs the dialog box to set up the winconsole options
751  */
752 BOOL WCUSER_GetProperties(struct inner_data* data, BOOL current)
753 {
754     HPROPSHEETPAGE      psPage[3];
755     PROPSHEETPAGE       psp;
756     PROPSHEETHEADER     psHead;
757     WCHAR               buff[256];
758     WNDCLASS            wndclass;
759     static const WCHAR szFntPreview[] = {'W','i','n','e','C','o','n','F','o','n','t','P','r','e','v','i','e','w',0};
760     static const WCHAR szColorPreview[] = {'W','i','n','e','C','o','n','C','o','l','o','r','P','r','e','v','i','e','w',0};
761     struct dialog_info  di;
762
763     InitCommonControls();
764
765     di.data = data;
766     if (current)
767     {
768         di.config = &data->curcfg;
769         di.apply = WCUSER_ApplyCurrent;
770     }
771     else
772     {
773         di.config = &data->defcfg;
774         di.apply = WCUSER_ApplyDefault;
775     }
776     di.nFont = 0;
777     di.font = NULL;
778
779     wndclass.style         = 0;
780     wndclass.lpfnWndProc   = WCUSER_FontPreviewProc;
781     wndclass.cbClsExtra    = 0;
782     wndclass.cbWndExtra    = 4; /* for hFont */
783     wndclass.hInstance     = GetModuleHandle(NULL);
784     wndclass.hIcon         = 0;
785     wndclass.hCursor       = LoadCursor(0, IDC_ARROW);
786     wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
787     wndclass.lpszMenuName  = NULL;
788     wndclass.lpszClassName = szFntPreview;
789     RegisterClass(&wndclass);
790
791     wndclass.style         = 0;
792     wndclass.lpfnWndProc   = WCUSER_ColorPreviewProc;
793     wndclass.cbClsExtra    = 0;
794     wndclass.cbWndExtra    = sizeof(DWORD);
795     wndclass.hInstance     = GetModuleHandle(NULL);
796     wndclass.hIcon         = 0;
797     wndclass.hCursor       = LoadCursor(0, IDC_ARROW);
798     wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
799     wndclass.lpszMenuName  = NULL;
800     wndclass.lpszClassName = szColorPreview;
801     RegisterClass(&wndclass);
802
803     memset(&psp, 0, sizeof(psp));
804     psp.dwSize = sizeof(psp);
805     psp.dwFlags = 0;
806     psp.hInstance = wndclass.hInstance;
807     psp.lParam = (LPARAM)&di;
808
809     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_OPTION);
810     psp.pfnDlgProc = WCUSER_OptionDlgProc;
811     psPage[0] = CreatePropertySheetPage(&psp);
812
813     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_FONT);
814     psp.pfnDlgProc = WCUSER_FontDlgProc;
815     psPage[1] = CreatePropertySheetPage(&psp);
816
817     psp.u.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG);
818     psp.pfnDlgProc = WCUSER_ConfigDlgProc;
819     psPage[2] = CreatePropertySheetPage(&psp);
820
821     memset(&psHead, 0, sizeof(psHead));
822     psHead.dwSize = sizeof(psHead);
823
824     if (!LoadString(GetModuleHandle(NULL),
825                     (current) ? IDS_DLG_TIT_CURRENT : IDS_DLG_TIT_DEFAULT,
826                     buff, sizeof(buff) / sizeof(buff[0])))
827     {
828         buff[0] = 'S';
829         buff[1] = 'e';
830         buff[2] = 't';
831         buff[3] = 'u';
832         buff[4] = 'p';
833         buff[5] = '\0';
834     }
835
836     psHead.pszCaption = buff;
837     psHead.nPages = 3;
838     psHead.hwndParent = PRIVATE(data)->hWnd;
839     psHead.u3.phpage = psPage;
840
841     PropertySheet(&psHead);
842
843     return TRUE;
844 }
845
846