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