blob: 04220ac40f527b2233165837b90fd516c925fa1e [file] [log] [blame]
Eric Pouech0b83d4c2001-11-23 23:04:58 +00001/* dialog management for wineconsole
2 * (c) 2001 Eric Pouech
3 */
4
5#include <stdio.h>
6#include "winecon_private.h"
7#include "commctrl.h"
8#include "prsht.h"
9
10/* FIXME: so far, part of the code is made in ASCII because the Uncode property sheet functions
11 * are not implemented yet
12 */
13struct dialog_info
14{
15 struct inner_data* data; /* pointer to current winecon info */
16 HWND hDlg; /* handle to window dialog */
17 int nFont; /* number of font size in size LB */
18 struct font_info
19 {
20 TEXTMETRIC tm;
21 LOGFONT lf;
22 } *font; /* array of nFont. index sync'ed with SIZE LB */
23};
24
25/******************************************************************
26 * WCUSER_OptionDlgProc
27 *
28 * Dialog prop for the option property sheet
29 */
30static BOOL WINAPI WCUSER_OptionDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
31{
32 struct dialog_info* di;
33 unsigned idc;
34
35 switch (msg)
36 {
37 case WM_INITDIALOG:
38 di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
39 di->hDlg = hDlg;
40 SetWindowLongA(hDlg, DWL_USER, (DWORD)di);
41 if (di->data->cursor_size < 33) idc = IDC_OPT_CURSOR_SMALL;
42 else if (di->data->cursor_size < 66) idc = IDC_OPT_CURSOR_MEDIUM;
43 else idc = IDC_OPT_CURSOR_LARGE;
44 SendDlgItemMessage(hDlg, idc, BM_SETCHECK, BST_CHECKED, 0L);
45 SetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, WINECON_GetHistorySize(di->data->hConIn), FALSE);
46 if (WINECON_GetHistoryMode(di->data->hConIn))
47 SendDlgItemMessage(hDlg, IDC_OPT_HIST_DOUBLE, BM_SETCHECK, BST_CHECKED, 0L);
48 return FALSE; /* because we set the focus */
49 case WM_COMMAND:
50 break;
51 case WM_NOTIFY:
52 {
53 NMHDR* nmhdr = (NMHDR*)lParam;
54
55 di = (struct dialog_info*)GetWindowLongA(hDlg, DWL_USER);
56 switch (nmhdr->code)
57 {
58 case PSN_SETACTIVE:
59 /* needed in propsheet to keep properly the selected radio button
60 * otherwise, the focus would be set to the first tab stop in the
61 * propsheet, which would always activate the first radio button
62 */
63 if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED)
64 idc = IDC_OPT_CURSOR_SMALL;
65 else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED)
66 idc = IDC_OPT_CURSOR_MEDIUM;
67 else
68 idc = IDC_OPT_CURSOR_LARGE;
69 PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, idc), TRUE);
70 break;
71 case PSN_APPLY:
72 {
73 int curs_size;
74 int hist_size;
75 BOOL done;
76
77 if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED) curs_size = 33;
78 else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED) curs_size = 66;
79 else curs_size = 99;
80 if (curs_size != di->data->cursor_size)
81 {
82 CONSOLE_CURSOR_INFO cinfo;
83 cinfo.dwSize = curs_size;
84 cinfo.bVisible = di->data->cursor_visible;
85 SetConsoleCursorInfo(di->data->hConOut, &cinfo);
86 }
87 hist_size = GetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, &done, FALSE);
88 if (done) WINECON_SetHistorySize(di->data->hConIn, hist_size);
89 SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
90 WINECON_SetHistoryMode(di->data->hConIn,
91 IsDlgButtonChecked(hDlg, IDC_OPT_HIST_DOUBLE) & BST_CHECKED);
92 return TRUE;
93 }
94 default:
95 return FALSE;
96 }
97 break;
98 }
99 default:
100 return FALSE;
101 }
102 return TRUE;
103}
104
105/******************************************************************
106 * WCUSER_FontPreviewProc
107 *
108 * Window proc for font previewer in font property sheet
109 */
110static LRESULT WINAPI WCUSER_FontPreviewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
111{
112 switch (msg)
113 {
114 case WM_PAINT:
115 {
116 PAINTSTRUCT ps;
117 int font_idx;
118 int size_idx;
119 struct dialog_info* di;
120
121 di = (struct dialog_info*)GetWindowLong(GetParent(hWnd), DWL_USER);
122 BeginPaint(hWnd, &ps);
123
124 font_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
125 size_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
126
127 if (font_idx >= 0 && size_idx >= 0 && size_idx < di->nFont)
128 {
129 HFONT hFont, hOldFont;
130 WCHAR buf1[256];
131 WCHAR buf2[256];
132 int len1, len2;
133
134 hFont = CreateFontIndirect(&di->font[size_idx].lf);
135 len1 = LoadString(GetModuleHandle(NULL), IDS_FNT_PREVIEW_1,
136 buf1, sizeof(buf1) / sizeof(WCHAR));
137 len2 = LoadString(GetModuleHandle(NULL), IDS_FNT_PREVIEW_2,
138 buf2, sizeof(buf2) / sizeof(WCHAR));
139 if (hFont && len1)
140 {
141 hOldFont = SelectObject(ps.hdc, hFont);
142 SetBkColor(ps.hdc, RGB(0x00, 0x00, 0x00));
143 SetTextColor(ps.hdc, RGB(0xFF, 0xFF, 0xFF));
144 TextOut(ps.hdc, 0, 0, buf1, len1);
145 if (len2)
146 TextOut(ps.hdc, 0, di->font[size_idx].tm.tmHeight, buf2, len2);
147 SelectObject(ps.hdc, hOldFont);
148 DeleteObject(hFont);
149 }
150 }
151 EndPaint(hWnd, &ps);
152 break;
153 }
154 default:
155 return DefWindowProc(hWnd, msg, wParam, lParam);
156 }
157 return 0L;
158}
159
160/******************************************************************
161 * font_enum
162 *
163 *
164 */
165static int CALLBACK font_enum_size2(const LOGFONT* lf, const TEXTMETRIC* tm,
166 DWORD FontType, LPARAM lParam)
167{
168 struct dialog_info* di = (struct dialog_info*)lParam;
169
170 if (WCUSER_ValidateFontMetric(di->data, tm))
171 {
172 di->nFont++;
173 }
174 return 1;
175}
176
177static int CALLBACK font_enum(const LOGFONT* lf, const TEXTMETRIC* tm,
178 DWORD FontType, LPARAM lParam)
179{
180 struct dialog_info* di = (struct dialog_info*)lParam;
181 HDC hdc;
182
183 if (WCUSER_ValidateFont(di->data, lf) && (hdc = GetDC(di->hDlg)))
184 {
185 di->nFont = 0;
186 EnumFontFamilies(hdc, lf->lfFaceName, font_enum_size2, (LPARAM)di);
187 if (di->nFont)
188 {
189 int idx;
190 idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_ADDSTRING,
191 0, (LPARAM)lf->lfFaceName);
192 }
193 ReleaseDC(di->hDlg, hdc);
194 }
195 return 1;
196}
197
198/******************************************************************
199 * font_enum_size
200 *
201 *
202 */
203static int CALLBACK font_enum_size(const LOGFONT* lf, const TEXTMETRIC* tm,
204 DWORD FontType, LPARAM lParam)
205{
206 struct dialog_info* di = (struct dialog_info*)lParam;
207
208 if (WCUSER_ValidateFontMetric(di->data, tm))
209 {
210 WCHAR buf[32];
211 WCHAR fmt[] = {'%','l','d',0};
212 int idx;
213
214 /* we want the string to be sorted with a numeric order, not a lexicographic...
215 * do the job by hand... get where to insert the new string
216 */
217 for (idx = 0; idx < di->nFont && tm->tmHeight > di->font[idx].tm.tmHeight; idx++);
218 wsprintfW(buf, fmt, tm->tmHeight);
219 SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, idx, (LPARAM)buf);
220
221 /* now grow our arrays and insert to values at the same index than in the list box */
222 di->font = HeapReAlloc(GetProcessHeap(), 0, di->font, sizeof(*di->font) * (di->nFont + 1));
223 if (idx != di->nFont)
224 memmove(&di->font[idx + 1], &di->font[idx], (di->nFont - idx) * sizeof(*di->font));
225 di->font[idx].tm = *tm;
226 di->font[idx].lf = *lf;
227 di->nFont++;
228
229 }
230 return 1;
231}
232
233/******************************************************************
234 * select_font
235 *
236 *
237 */
238static BOOL select_font(struct dialog_info* di)
239{
240 int idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
241 WCHAR buf[256];
242 WCHAR fmt[128];
243
244 if (idx < 0 || idx >= di->nFont)
245 return FALSE;
246
247 LoadString(GetModuleHandle(NULL), IDS_FNT_DISPLAY, fmt, sizeof(fmt) / sizeof(WCHAR));
248 wsprintfW(buf, fmt, di->font[idx].tm.tmMaxCharWidth, di->font[idx].tm.tmHeight);
249
250 SendDlgItemMessage(di->hDlg, IDC_FNT_FONT_INFO, WM_SETTEXT, 0, (LPARAM)buf);
251 InvalidateRect(GetDlgItem(di->hDlg, IDC_FNT_PREVIEW), NULL, TRUE);
252 UpdateWindow(GetDlgItem(di->hDlg, IDC_FNT_PREVIEW));
253 return TRUE;
254}
255
256/******************************************************************
257 * fill_list_size
258 *
259 * fills the size list box according to selected family in font LB
260 */
261static BOOL fill_list_size(struct dialog_info* di, BOOL doInit)
262{
263 HDC hdc;
264 int idx;
265 WCHAR lfFaceName[LF_FACESIZE];
266
267 idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
268 if (idx < 0) return FALSE;
269
270 hdc = GetDC(di->hDlg);
271 if (!hdc) return FALSE;
272
273 SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETTEXT, idx, (LPARAM)lfFaceName);
274 SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_RESETCONTENT, 0L, 0L);
275 if (di->font) HeapFree(GetProcessHeap(), 0, di->font);
276 di->nFont = 0;
277 di->font = NULL;
278
279 EnumFontFamilies(hdc, lfFaceName, font_enum_size, (LPARAM)di);
280 ReleaseDC(di->hDlg, hdc);
281
282 if (doInit)
283 {
284 for (idx = 0; idx < di->nFont; idx++)
285 {
286 if (memcmp(&di->data->logFont, &di->font[idx].lf, sizeof(LOGFONT)) == 0)
287 break;
288 }
289 if (idx == di->nFont) idx = 0;
290 }
291 else
292 idx = 0;
293 SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_SETCURSEL, idx, 0L);
294 select_font(di);
295 return TRUE;
296}
297
298/******************************************************************
299 * fill_list_font
300 *
301 * Fills the font LB
302 */
303static BOOL fill_list_font(struct dialog_info* di)
304{
305 HDC hdc;
306
307 hdc = GetDC(di->hDlg);
308 if (!hdc) return FALSE;
309
310 SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_RESETCONTENT, 0L, 0L);
311 EnumFontFamilies(hdc, NULL, font_enum, (LPARAM)di);
312 ReleaseDC(di->hDlg, hdc);
313 if (SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SELECTSTRING,
314 (WPARAM)-1, (LPARAM)di->data->logFont.lfFaceName) == LB_ERR)
315 SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SETCURSEL, 0L, 0L);
316 fill_list_size(di, TRUE);
317 return TRUE;
318}
319
320/******************************************************************
321 * WCUSER_FontDlgProc
322 *
323 * Dialog proc for the Font property sheet
324 */
325static BOOL WINAPI WCUSER_FontDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
326{
327 struct dialog_info* di;
328
329 switch (msg)
330 {
331 case WM_INITDIALOG:
332 di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
333 di->hDlg = hDlg;
334 SetWindowLong(hDlg, DWL_USER, (DWORD)di);
335 fill_list_font(di);
336 break;
337 case WM_COMMAND:
338 di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
339 switch (LOWORD(wParam))
340 {
341 case IDC_FNT_LIST_FONT:
342 if (HIWORD(wParam) == LBN_SELCHANGE)
343 {
344 fill_list_size(di, FALSE);
345 }
346 break;
347 case IDC_FNT_LIST_SIZE:
348 if (HIWORD(wParam) == LBN_SELCHANGE)
349 {
350 select_font(di);
351 }
352 break;
353 }
354 break;
355 case WM_NOTIFY:
356 {
357 NMHDR* nmhdr = (NMHDR*)lParam;
358
359 di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
360 switch (nmhdr->code)
361 {
362 case PSN_APPLY:
363 {
364 int idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
365
366 if (idx >= 0 && idx < di->nFont)
367 {
368 WCUSER_SetFont(di->data, &di->font[idx].lf, &di->font[idx].tm);
369 }
370 SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
371 return TRUE;
372 }
373 default:
374 return FALSE;
375 }
376 break;
377 }
378 default:
379 return FALSE;
380 }
381 return TRUE;
382}
383
384/******************************************************************
385 * WCUSER_ConfigDlgProc
386 *
387 * Dialog proc for the config property sheet
388 */
389static BOOL WINAPI WCUSER_ConfigDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
390{
391 struct dialog_info* di;
392
393 switch (msg)
394 {
395 case WM_INITDIALOG:
396 di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
397 di->hDlg = hDlg;
398 SetWindowLong(hDlg, DWL_USER, (DWORD)di);
399 SetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH, di->data->sb_width, FALSE);
400 SetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, di->data->sb_height, FALSE);
401 SetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH, di->data->win_width, FALSE);
402 SetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, di->data->win_height, FALSE);
403 break;
404 case WM_COMMAND:
405 di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
406 switch (LOWORD(wParam))
407 {
408 }
409 break;
410 case WM_NOTIFY:
411 {
412 NMHDR* nmhdr = (NMHDR*)lParam;
413
414 di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
415 switch (nmhdr->code)
416 {
417 case PSN_APPLY:
418 {
419 COORD sb;
420 SMALL_RECT pos;
421 BOOL st_w, st_h;
422
423 sb.X = GetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH, &st_w, FALSE);
424 sb.Y = GetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, &st_h, FALSE);
425 if (st_w && st_h && (sb.X != di->data->sb_width || sb.Y != di->data->sb_height))
426 {
427 SetConsoleScreenBufferSize(di->data->hConOut, sb);
428 }
429
430 pos.Right = GetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH, &st_w, FALSE);
431 pos.Bottom = GetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, &st_h, FALSE);
432 if (st_w && st_h &&
433 (pos.Right != di->data->win_width || pos.Bottom != di->data->win_height))
434 {
435 pos.Left = pos.Top = 0;
436 pos.Right--; pos.Bottom--;
437 SetConsoleWindowInfo(di->data->hConOut, FALSE, &pos);
438 }
439
440 SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
441 return TRUE;
442 }
443 default:
444 return FALSE;
445 }
446 break;
447 }
448 default:
449 return FALSE;
450 }
451 return TRUE;
452}
453
454/******************************************************************
455 * WCUSER_GetProperties
456 *
457 * Runs the dialog box to set up the winconsole options
458 */
459BOOL WCUSER_GetProperties(struct inner_data* data)
460{
461 HPROPSHEETPAGE psPage[3];
462 PROPSHEETPAGEA psp;
463 PROPSHEETHEADERA psHead;
464 WNDCLASS wndclass;
465 static WCHAR szFntPreview[] = {'W','i','n','e','C','o','n','F','o','n','t','P','r','e','v','i','e','w',0};
466 struct dialog_info di;
467
468 InitCommonControls();
469
470 di.data = data;
471 di.nFont = 0;
472 di.font = NULL;
473
474 wndclass.style = 0;
475 wndclass.lpfnWndProc = WCUSER_FontPreviewProc;
476 wndclass.cbClsExtra = 0;
477 wndclass.cbWndExtra = 0;
478 wndclass.hInstance = GetModuleHandle(NULL);
479 wndclass.hIcon = 0;
480 wndclass.hCursor = LoadCursor(0, IDC_ARROW);
481 wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
482 wndclass.lpszMenuName = NULL;
483 wndclass.lpszClassName = szFntPreview;
484 RegisterClass(&wndclass);
485
486 memset(&psp, 0, sizeof(psp));
487 psp.dwSize = sizeof(psp);
488 psp.dwFlags = 0;
489 psp.hInstance = wndclass.hInstance;
490 psp.lParam = (LPARAM)&di;
491
492 psp.u.pszTemplate = MAKEINTRESOURCEA(IDD_OPTION);
493 psp.pfnDlgProc = WCUSER_OptionDlgProc;
494 psPage[0] = CreatePropertySheetPageA(&psp);
495
496 psp.u.pszTemplate = MAKEINTRESOURCEA(IDD_FONT);
497 psp.pfnDlgProc = WCUSER_FontDlgProc;
498 psPage[1] = CreatePropertySheetPageA(&psp);
499
500 psp.u.pszTemplate = MAKEINTRESOURCEA(IDD_CONFIG);
501 psp.pfnDlgProc = WCUSER_ConfigDlgProc;
502 psPage[2] = CreatePropertySheetPageA(&psp);
503
504 memset(&psHead, 0, sizeof(psHead));
505 psHead.dwSize = sizeof(psHead);
506 psHead.pszCaption = "Setup";
507 psHead.nPages = 3;
508 psHead.hwndParent = data->hWnd;
509 psHead.u3.phpage = psPage;
510
511 PropertySheetA(&psHead);
512
513 return TRUE;
514}
515