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