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