dialog.c 28.6 KB
Newer Older
1
/* dialog management for wineconsole
2
 * USER32 backend
3
 * Copyright (c) 2001, 2002 Eric Pouech
4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 19 20
 */

#include <stdio.h>
21
#include <stdlib.h>
22
#include <stdarg.h>
23 24

#define NONAMELESSUNION
25

26 27 28 29 30
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
31 32
#include "commctrl.h"
#include "prsht.h"
33
#include "winecon_user.h"
34

35 36 37 38
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(wineconsole);

39
struct dialog_info
40
{
41
    struct config_data  config;         /* configuration used for dialog box */
42 43
    struct inner_data*	data;	        /* pointer to current winecon info */
    HWND		hDlg;		/* handle to active propsheet */
44
    int			nFont;		/* number of font size in size LB */
45
    struct font_info
46
    {
47 48 49
        UINT                    height;
        UINT                    weight;
        WCHAR                   faceName[LF_FACESIZE];
50 51 52 53 54 55 56 57
    } 			*font;		/* array of nFont. index sync'ed with SIZE LB */
};

/******************************************************************
 *		WCUSER_OptionDlgProc
 *
 * Dialog prop for the option property sheet
 */
58
static INT_PTR WINAPI WCUSER_OptionDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
59 60 61
{
    struct dialog_info*		di;
    unsigned 			idc;
62 63

    switch (msg)
64 65 66 67
    {
    case WM_INITDIALOG:
	di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
	di->hDlg = hDlg;
68
        SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)di);
69

70
        SendMessageW(GetDlgItem(hDlg,IDC_OPT_HIST_SIZE_UD), UDM_SETRANGE, 0, MAKELPARAM(500, 0));
71

72 73
	if (di->config.cursor_size <= 25)	idc = IDC_OPT_CURSOR_SMALL;
	else if (di->config.cursor_size <= 50)	idc = IDC_OPT_CURSOR_MEDIUM;
74
	else				        idc = IDC_OPT_CURSOR_LARGE;
75
        SendDlgItemMessageW(hDlg, idc, BM_SETCHECK, BST_CHECKED, 0);
76
	SetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, di->config.history_size,  FALSE);
77 78
        SendDlgItemMessageW(hDlg, IDC_OPT_HIST_NODOUBLE, BM_SETCHECK,
                            (di->config.history_nodup) ? BST_CHECKED : BST_UNCHECKED, 0);
79 80
        SendDlgItemMessageW(hDlg, IDC_OPT_INSERT_MODE, BM_SETCHECK,
                            (di->config.insert_mode) ? BST_CHECKED : BST_UNCHECKED, 0);
81 82 83 84 85 86
        SendDlgItemMessageW(hDlg, IDC_OPT_CONF_CTRL, BM_SETCHECK,
                            (di->config.menu_mask & MK_CONTROL) ? BST_CHECKED : BST_UNCHECKED, 0);
        SendDlgItemMessageW(hDlg, IDC_OPT_CONF_SHIFT, BM_SETCHECK,
                            (di->config.menu_mask & MK_SHIFT) ? BST_CHECKED : BST_UNCHECKED, 0);
        SendDlgItemMessageW(hDlg, IDC_OPT_QUICK_EDIT, BM_SETCHECK,
                            (di->config.quick_edit) ? BST_CHECKED : BST_UNCHECKED, 0);
87 88 89 90 91 92
	return FALSE; /* because we set the focus */
    case WM_COMMAND:
	break;
    case WM_NOTIFY:
    {
	NMHDR*	nmhdr = (NMHDR*)lParam;
93 94
        DWORD   val;
        BOOL	done;
95

96
        di = (struct dialog_info*)GetWindowLongPtrW(hDlg, DWLP_USER);
97

98
	switch (nmhdr->code)
99 100 101 102 103 104
	{
	case PSN_SETACTIVE:
	    /* needed in propsheet to keep properly the selected radio button
	     * otherwise, the focus would be set to the first tab stop in the
	     * propsheet, which would always activate the first radio button
	     */
105
	    if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED)
106 107 108 109 110
		idc = IDC_OPT_CURSOR_SMALL;
	    else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED)
		idc = IDC_OPT_CURSOR_MEDIUM;
	    else
		idc = IDC_OPT_CURSOR_LARGE;
111
            PostMessageW(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, idc), TRUE);
112
            di->hDlg = hDlg;
113 114
	    break;
	case PSN_APPLY:
115 116
	    if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED) val = 25;
	    else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED) val = 50;
117 118
	    else val = 100;
            di->config.cursor_size = val;
119 120

 	    val = GetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, &done, FALSE);
121
	    if (done) di->config.history_size = val;
122

123
            val = (IsDlgButtonChecked(hDlg, IDC_OPT_HIST_NODOUBLE) & BST_CHECKED) != 0;
124
            di->config.history_nodup = val;
125

126 127 128
            val = (IsDlgButtonChecked(hDlg, IDC_OPT_INSERT_MODE) & BST_CHECKED) != 0;
            di->config.insert_mode = val;

129 130 131
            val = 0;
            if (IsDlgButtonChecked(hDlg, IDC_OPT_CONF_CTRL) & BST_CHECKED)  val |= MK_CONTROL;
            if (IsDlgButtonChecked(hDlg, IDC_OPT_CONF_SHIFT) & BST_CHECKED) val |= MK_SHIFT;
132
            di->config.menu_mask = val;
133

134
            val = (IsDlgButtonChecked(hDlg, IDC_OPT_QUICK_EDIT) & BST_CHECKED) != 0;
135
            di->config.quick_edit = val;
136

137
            SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
138 139 140 141 142 143 144 145 146 147 148 149
	    return TRUE;
	default:
	    return FALSE;
	}
	break;
    }
    default:
	return FALSE;
    }
    return TRUE;
}

150 151 152 153 154 155 156 157
static COLORREF get_color(struct dialog_info *di, unsigned int idc)
{
    LONG_PTR index;

    index = GetWindowLongPtrW(GetDlgItem(di->hDlg, idc), 0);
    return di->config.color_map[index];
}

158 159 160 161 162 163 164 165 166
/******************************************************************
 *		WCUSER_FontPreviewProc
 *
 * Window proc for font previewer in font property sheet
 */
static LRESULT WINAPI WCUSER_FontPreviewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
167
    case WM_CREATE:
168
        SetWindowLongPtrW(hWnd, 0, 0);
169 170
        break;
    case WM_GETFONT:
171
        return GetWindowLongPtrW(hWnd, 0);
172
    case WM_SETFONT:
173
        SetWindowLongPtrW(hWnd, 0, wParam);
174 175 176 177 178 179 180 181
        if (LOWORD(lParam))
        {
            InvalidateRect(hWnd, NULL, TRUE);
            UpdateWindow(hWnd);
        }
        break;
    case WM_DESTROY:
        {
182
            HFONT hFont = (HFONT)GetWindowLongPtrW(hWnd, 0);
183 184 185
            if (hFont) DeleteObject(hFont);
        }
        break;
186
    case WM_PAINT:
187 188 189 190
        {
            PAINTSTRUCT	        ps;
            int		        size_idx;
            struct dialog_info*	di;
191
            HFONT	        hFont, hOldFont;
192

193
            di = (struct dialog_info*)GetWindowLongPtrW(GetParent(hWnd), DWLP_USER);
194 195
            BeginPaint(hWnd, &ps);

196
            size_idx = SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0, 0);
197

198
            hFont = (HFONT)GetWindowLongPtrW(hWnd, 0);
199
            if (hFont)
200
            {
201
                COLORREF bkcolor;
202 203 204 205 206
                WCHAR ascii[] = {'A','S','C','I','I',':',' ','a','b','c','X','Y','Z','\0'};
                WCHAR buf[256];
                int   len;

                hOldFont = SelectObject(ps.hdc, hFont);
207
                bkcolor = get_color(di, IDC_FNT_COLOR_BK);
208 209
                FillRect(ps.hdc, &ps.rcPaint, CreateSolidBrush(bkcolor));
                SetBkColor(ps.hdc, bkcolor);
210
                SetTextColor(ps.hdc, get_color(di, IDC_FNT_COLOR_FG));
211
                len = LoadStringW(GetModuleHandleW(NULL), IDS_FNT_PREVIEW, buf, ARRAY_SIZE(buf));
212
                if (len)
213
                    TextOutW(ps.hdc, 0, 0, buf, len);
214
                TextOutW(ps.hdc, 0, di->font[size_idx].height, ascii, ARRAY_SIZE(ascii) - 1);
215
                SelectObject(ps.hdc, hOldFont);
216 217 218 219 220
            }
            EndPaint(hWnd, &ps);
        }
        break;
    default:
221
        return DefWindowProcW(hWnd, msg, wParam, lParam);
222
    }
223 224 225 226 227 228 229 230 231 232 233 234 235 236
    return 0L;
}

/******************************************************************
 *		WCUSER_ColorPreviewProc
 *
 * Window proc for color previewer in font property sheet
 */
static LRESULT WINAPI WCUSER_ColorPreviewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_PAINT:
        {
237 238 239 240 241
            PAINTSTRUCT ps;
            int i, step;
            RECT client, r;
            struct dialog_info *di;
            HBRUSH hbr;
242

243 244 245
            BeginPaint(hWnd, &ps);
            GetClientRect(hWnd, &client);
            step = client.right / 8;
246

247 248
            di = (struct dialog_info *)GetWindowLongPtrW(GetParent(hWnd), DWLP_USER);

249 250 251 252 253 254
            for (i = 0; i < 16; i++)
            {
                r.top = (i / 8) * (client.bottom / 2);
                r.bottom = r.top + client.bottom / 2;
                r.left = (i & 7) * step;
                r.right = r.left + step;
255
                hbr = CreateSolidBrush(di->config.color_map[i]);
256 257
                FillRect(ps.hdc, &r, hbr);
                DeleteObject(hbr);
258
                if (GetWindowLongW(hWnd, 0) == i)
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
                {
                    HPEN        hOldPen;
                    int         i = 2;

                    hOldPen = SelectObject(ps.hdc, GetStockObject(WHITE_PEN));
                    r.right--; r.bottom--;
                    for (;;)
                    {
                        MoveToEx(ps.hdc, r.left, r.bottom, NULL);
                        LineTo(ps.hdc, r.left, r.top);
                        LineTo(ps.hdc, r.right, r.top);
                        SelectObject(ps.hdc, GetStockObject(BLACK_PEN));
                        LineTo(ps.hdc, r.right, r.bottom);
                        LineTo(ps.hdc, r.left, r.bottom);

                        if (--i == 0) break;
                        r.left++; r.top++; r.right--; r.bottom--;
                        SelectObject(ps.hdc, GetStockObject(WHITE_PEN));
                    }
                    SelectObject(ps.hdc, hOldPen);
                }
            }
            EndPaint(hWnd, &ps);
            break;
        }
    case WM_LBUTTONDOWN:
        {
            int             i, step;
            RECT            client;
288

289 290 291 292
            GetClientRect(hWnd, &client);
            step = client.right / 8;
            i = (HIWORD(lParam) >= client.bottom / 2) ? 8 : 0;
            i += LOWORD(lParam) / step;
293
            SetWindowLongW(hWnd, 0, i);
294 295 296 297
            InvalidateRect(GetDlgItem(GetParent(hWnd), IDC_FNT_PREVIEW), NULL, FALSE);
            InvalidateRect(hWnd, NULL, FALSE);
        }
        break;
298
    default:
299
        return DefWindowProcW(hWnd, msg, wParam, lParam);
300 301 302 303 304 305 306
    }
    return 0L;
}

/******************************************************************
 *		font_enum
 *
307
 * enumerates all the font names with at least one valid font
308
 */
309 310
static int CALLBACK font_enum_size2(const LOGFONTW* lf, const TEXTMETRICW* tm,
                                    DWORD FontType, LPARAM lParam)
311 312 313
{
    struct dialog_info*	di = (struct dialog_info*)lParam;

314
    WCUSER_DumpTextMetric(tm, FontType);
315
    if (WCUSER_ValidateFontMetric(di->data, tm, FontType, 0))
316 317 318
    {
	di->nFont++;
    }
319

320 321 322
    return 1;
}

323 324
static int CALLBACK font_enum(const LOGFONTW* lf, const TEXTMETRICW* tm,
                              DWORD FontType, LPARAM lParam)
325 326 327
{
    struct dialog_info*	di = (struct dialog_info*)lParam;

328
    WCUSER_DumpLogFont("DlgFamily: ", lf, FontType);
329
    if (WCUSER_ValidateFont(di->data, lf, 0))
330
    {
331 332 333
        if (FontType & RASTER_FONTTYPE)
        {
            di->nFont = 0;
334
            EnumFontFamiliesW(PRIVATE(di->data)->hMemDC, lf->lfFaceName, font_enum_size2, (LPARAM)di);
335 336 337
        }
        else
            di->nFont = 1;
338

339
        if (di->nFont)
340
	{
341 342
            SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_ADDSTRING,
                                0, (LPARAM)lf->lfFaceName);
343
        }
344
    }
345

346 347 348 349 350 351 352 353
    return 1;
}

/******************************************************************
 *		font_enum_size
 *
 *
 */
354 355
static int CALLBACK font_enum_size(const LOGFONTW* lf, const TEXTMETRICW* tm,
                                   DWORD FontType, LPARAM lParam)
356 357
{
    struct dialog_info*	di = (struct dialog_info*)lParam;
358 359
    WCHAR	        buf[32];
    static const WCHAR  fmt[] = {'%','l','d',0};
360

361
    WCUSER_DumpTextMetric(tm, FontType);
362
    if (di->nFont == 0 && !(FontType & RASTER_FONTTYPE))
363
    {
364 365
        static const int sizes[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
        int i;
366

367
        di->nFont = ARRAY_SIZE(sizes);
368 369
        di->font = HeapAlloc(GetProcessHeap(), 0, di->nFont * sizeof(di->font[0]));
        for (i = 0; i < di->nFont; i++)
370
        {
371 372
            /* drop sizes where window size wouldn't fit on screen */
            if (sizes[i] * di->data->curcfg.win_height > GetSystemMetrics(SM_CYSCREEN))
373
            {
374 375
                di->nFont = i;
                break;
376
            }
377 378
            di->font[i].height = sizes[i];
            di->font[i].weight = 400;
379 380 381
            lstrcpyW(di->font[i].faceName, lf->lfFaceName);
            wsprintfW(buf, fmt, sizes[i]);
            SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, i, (LPARAM)buf);
382
        }
383 384 385 386
        /* don't need to enumerate other */
        return 0;
    }

387
    if (WCUSER_ValidateFontMetric(di->data, tm, FontType, 0))
388
    {
389
	int	idx = 0;
390 391 392 393

	/* we want the string to be sorted with a numeric order, not a lexicographic...
	 * do the job by hand... get where to insert the new string
	 */
394 395
	while (idx < di->nFont && tm->tmHeight > di->font[idx].height)
            idx++;
396 397
        while (idx < di->nFont &&
               tm->tmHeight == di->font[idx].height &&
398 399
               tm->tmWeight > di->font[idx].weight)
            idx++;
400
        if (idx == di->nFont ||
401 402
            tm->tmHeight != di->font[idx].height ||
            tm->tmWeight < di->font[idx].weight)
403 404
        {
            /* here we need to add the new entry */
405 406
            wsprintfW(buf, fmt, tm->tmHeight);
            SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, idx, (LPARAM)buf);
407

408
            /* now grow our arrays and insert the values at the same index than in the list box */
409 410 411 412 413 414 415 416
            if (di->nFont)
            {
                di->font = HeapReAlloc(GetProcessHeap(), 0, di->font, sizeof(*di->font) * (di->nFont + 1));
                if (idx != di->nFont)
                    memmove(&di->font[idx + 1], &di->font[idx], (di->nFont - idx) * sizeof(*di->font));
            }
            else
                di->font = HeapAlloc(GetProcessHeap(), 0, sizeof(*di->font));
417 418
            di->font[idx].height = tm->tmHeight;
            di->font[idx].weight = tm->tmWeight;
419
            lstrcpyW(di->font[idx].faceName, lf->lfFaceName);
420 421
            di->nFont++;
        }
422 423 424 425 426 427 428 429 430 431 432
    }
    return 1;
}

/******************************************************************
 *		select_font
 *
 *
 */
static BOOL  select_font(struct dialog_info* di)
{
433
    int		font_idx, size_idx;
434 435
    WCHAR	buf[256];
    WCHAR	fmt[128];
436
    DWORD_PTR   args[2];
437
    LOGFONTW    lf;
438 439 440
    HFONT       hFont, hOldFont;
    struct config_data config;

441 442
    font_idx = SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0, 0);
    size_idx = SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0, 0);
443

444
    if (font_idx < 0 || size_idx < 0 || size_idx >= di->nFont)
445
	return FALSE;
446 447

    WCUSER_FillLogFont(&lf, di->font[size_idx].faceName,
448
                       di->font[size_idx].height, di->font[size_idx].weight);
449
    hFont = WCUSER_CopyFont(&config, di->data->hWnd, &lf, NULL);
450 451 452
    if (!hFont) return FALSE;

    if (config.cell_height != di->font[size_idx].height)
453
        WINE_TRACE("mismatched heights (%u<>%u)\n",
454
                   config.cell_height, di->font[size_idx].height);
455
    hOldFont = (HFONT)SendDlgItemMessageW(di->hDlg, IDC_FNT_PREVIEW, WM_GETFONT, 0, 0);
456

457
    SendDlgItemMessageW(di->hDlg, IDC_FNT_PREVIEW, WM_SETFONT, (WPARAM)hFont, TRUE);
458
    if (hOldFont) DeleteObject(hOldFont);
459

460
    LoadStringW(GetModuleHandleW(NULL), IDS_FNT_DISPLAY, fmt, ARRAY_SIZE(fmt));
461 462 463
    args[0] = config.cell_width;
    args[1] = config.cell_height;
    FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
464
                   fmt, 0, 0, buf, ARRAY_SIZE(buf), (__ms_va_list*)args);
465

466
    SendDlgItemMessageW(di->hDlg, IDC_FNT_FONT_INFO, WM_SETTEXT, 0, (LPARAM)buf);
467

468 469 470 471 472 473 474 475 476 477 478 479 480
    return TRUE;
}

/******************************************************************
 *		fill_list_size
 *
 * fills the size list box according to selected family in font LB
 */
static BOOL  fill_list_size(struct dialog_info* di, BOOL doInit)
{
    int		idx;
    WCHAR	lfFaceName[LF_FACESIZE];

481
    idx = SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0, 0);
482
    if (idx < 0) return FALSE;
483

484 485
    SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_GETTEXT, idx, (LPARAM)lfFaceName);
    SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_SIZE, LB_RESETCONTENT, 0, 0);
486
    HeapFree(GetProcessHeap(), 0, di->font);
487 488 489
    di->nFont = 0;
    di->font = NULL;

490
    EnumFontFamiliesW(PRIVATE(di->data)->hMemDC, lfFaceName, font_enum_size, (LPARAM)di);
491 492 493

    if (doInit)
    {
494 495
        int     ref = -1;

496 497
	for (idx = 0; idx < di->nFont; idx++)
	{
498
            if (!lstrcmpW(di->font[idx].faceName, di->config.face_name) &&
499 500
                di->font[idx].height == di->config.cell_height &&
                di->font[idx].weight == di->config.font_weight)
501 502
            {
                if (ref == -1) ref = idx;
503
                else WINE_TRACE("Several matches found: ref=%d idx=%d\n", ref, idx);
504
            }
505
	}
506
	idx = (ref == -1) ? 0 : ref;
507 508 509
    }
    else
	idx = 0;
510
    SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_SIZE, LB_SETCURSEL, idx, 0);
511 512 513 514 515 516 517 518 519 520 521
    select_font(di);
    return TRUE;
}

/******************************************************************
 *		fill_list_font
 *
 * Fills the font LB
 */
static BOOL fill_list_font(struct dialog_info* di)
{
522 523 524 525 526
    SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_RESETCONTENT, 0, 0);
    EnumFontFamiliesW(PRIVATE(di->data)->hMemDC, NULL, font_enum, (LPARAM)di);
    if (SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_SELECTSTRING,
                            -1, (LPARAM)di->config.face_name) == LB_ERR)
        SendDlgItemMessageW(di->hDlg, IDC_FNT_LIST_FONT, LB_SETCURSEL, 0, 0);
527 528 529 530 531 532 533 534 535
    fill_list_size(di, TRUE);
    return TRUE;
}

/******************************************************************
 *		WCUSER_FontDlgProc
 *
 * Dialog proc for the Font property sheet
 */
536
static INT_PTR WINAPI WCUSER_FontDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
537 538 539
{
    struct dialog_info*		di;

540
    switch (msg)
541 542 543 544
    {
    case WM_INITDIALOG:
	di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
	di->hDlg = hDlg;
545
        SetWindowLongPtrW(hDlg, DWLP_USER, (DWORD_PTR)di);
546
        /* remove dialog from this control, font will be reset when listboxes are filled */
547
        SendDlgItemMessageW(hDlg, IDC_FNT_PREVIEW, WM_SETFONT, 0, 0);
548
	fill_list_font(di);
549 550
        SetWindowLongW(GetDlgItem(hDlg, IDC_FNT_COLOR_BK), 0, (di->config.def_attr >> 4) & 0x0F);
        SetWindowLongW(GetDlgItem(hDlg, IDC_FNT_COLOR_FG), 0, di->config.def_attr & 0x0F);
551 552
	break;
    case WM_COMMAND:
553
        di = (struct dialog_info*)GetWindowLongPtrW(hDlg, DWLP_USER);
554
	switch (LOWORD(wParam))
555
	{
556
	case IDC_FNT_LIST_FONT:
557 558 559 560 561
	    if (HIWORD(wParam) == LBN_SELCHANGE)
	    {
		fill_list_size(di, FALSE);
	    }
	    break;
562
	case IDC_FNT_LIST_SIZE:
563 564 565 566 567 568 569 570 571 572
	    if (HIWORD(wParam) == LBN_SELCHANGE)
	    {
		select_font(di);
	    }
	    break;
	}
	break;
    case WM_NOTIFY:
    {
	NMHDR*	nmhdr = (NMHDR*)lParam;
573
        DWORD   val;
574

575
        di = (struct dialog_info*)GetWindowLongPtrW(hDlg, DWLP_USER);
576
	switch (nmhdr->code)
577
	{
578 579 580
        case PSN_SETACTIVE:
            di->hDlg = hDlg;
            break;
581
	case PSN_APPLY:
582
            val = SendDlgItemMessageW(hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0, 0);
583

584 585
	    if (val < di->nFont)
            {
586
                LOGFONTW lf;
587

588 589 590
                WCUSER_FillLogFont(&lf, di->font[val].faceName,
                                   di->font[val].height, di->font[val].weight);
                DeleteObject(WCUSER_CopyFont(&di->config,
591
                                             di->data->hWnd, &lf, NULL));
592 593
            }

594 595
            val = (GetWindowLongW(GetDlgItem(hDlg, IDC_FNT_COLOR_BK), 0) << 4) |
                   GetWindowLongW(GetDlgItem(hDlg, IDC_FNT_COLOR_FG), 0);
596
            di->config.def_attr = val;
597

598
            SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
	    return TRUE;
	default:
	    return FALSE;
	}
	break;
    }
    default:
	return FALSE;
    }
    return TRUE;
}

/******************************************************************
 *		WCUSER_ConfigDlgProc
 *
 * Dialog proc for the config property sheet
 */
616
static INT_PTR WINAPI WCUSER_ConfigDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
617 618
{
    struct dialog_info*		di;
619
    int                     nMaxUD = 2000;
620

621
    switch (msg)
622 623
    {
    case WM_INITDIALOG:
624 625 626
        di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
        di->hDlg = hDlg;

627
        SetWindowLongPtrW(hDlg, DWLP_USER, (DWORD_PTR)di);
628 629 630 631 632
        SetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH,   di->config.sb_width,   FALSE);
        SetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT,  di->config.sb_height,  FALSE);
        SetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH,  di->config.win_width,  FALSE);
        SetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, di->config.win_height, FALSE);

633 634 635 636
        SendMessageW(GetDlgItem(hDlg,IDC_CNF_WIN_HEIGHT_UD), UDM_SETRANGE, 0, MAKELPARAM(nMaxUD, 0));
        SendMessageW(GetDlgItem(hDlg,IDC_CNF_WIN_WIDTH_UD), UDM_SETRANGE, 0, MAKELPARAM(nMaxUD, 0));
        SendMessageW(GetDlgItem(hDlg,IDC_CNF_SB_HEIGHT_UD), UDM_SETRANGE, 0, MAKELPARAM(nMaxUD, 0));
        SendMessageW(GetDlgItem(hDlg,IDC_CNF_SB_WIDTH_UD), UDM_SETRANGE, 0, MAKELPARAM(nMaxUD, 0));
637

638 639
        SendDlgItemMessageW(hDlg, IDC_CNF_CLOSE_EXIT, BM_SETCHECK,
                            (di->config.exit_on_die) ? BST_CHECKED : BST_UNCHECKED, 0);
640
        {
641 642
            static const WCHAR s1[] = {'W','i','n','3','2',0};
            static const WCHAR s2[] = {'E','m','a','c','s',0};
643

644 645 646
            SendDlgItemMessageW(hDlg, IDC_CNF_EDITION_MODE, CB_ADDSTRING, 0, (LPARAM)s1);
            SendDlgItemMessageW(hDlg, IDC_CNF_EDITION_MODE, CB_ADDSTRING, 0, (LPARAM)s2);
            SendDlgItemMessageW(hDlg, IDC_CNF_EDITION_MODE, CB_SETCURSEL, di->config.edition_mode, 0);
647 648
    	}

649 650
	break;
    case WM_COMMAND:
651
        di = (struct dialog_info*)GetWindowLongPtrW(hDlg, DWLP_USER);
652
	switch (LOWORD(wParam))
653 654 655 656 657
	{
	}
	break;
    case WM_NOTIFY:
    {
658
	NMHDR*	        nmhdr = (NMHDR*)lParam;
659
        int             win_w, win_h, sb_w, sb_h;
660
        BOOL            st1, st2;
661

662
        di = (struct dialog_info*)GetWindowLongPtrW(hDlg, DWLP_USER);
663
	switch (nmhdr->code)
664
	{
665 666 667
        case PSN_SETACTIVE:
            di->hDlg = hDlg;
            break;
668
	case PSN_APPLY:
669 670 671
            sb_w = GetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH,  &st1, FALSE);
            sb_h = GetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, &st2, FALSE);
            if (!st1 || ! st2)
672
            {
673
                SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
674
                return TRUE;
675
            }
676 677 678 679
            win_w = GetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH,  &st1, FALSE);
            win_h = GetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, &st2, FALSE);
            if (!st1 || !st2)
            {
680
                SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
681 682 683
                return TRUE;
            }
            if (win_w > sb_w || win_h > sb_h)
684
            {
685 686 687
                WCHAR   cap[256];
                WCHAR   txt[256];

688 689
                LoadStringW(GetModuleHandleW(NULL), IDS_DLG_TIT_ERROR, cap, ARRAY_SIZE(cap));
                LoadStringW(GetModuleHandleW(NULL), IDS_DLG_ERR_SBWINSIZE, txt, ARRAY_SIZE(txt));
690 691 692

                MessageBoxW(hDlg, txt, cap, MB_OK);
                SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
693
                return TRUE;
694
            }
695 696 697 698 699
            di->config.win_width  = win_w;
            di->config.win_height = win_h;
            di->config.sb_width  = sb_w;
            di->config.sb_height = sb_h;

700
            di->config.exit_on_die = IsDlgButtonChecked(hDlg, IDC_CNF_CLOSE_EXIT) ? 1 : 0;
701 702 703
            di->config.edition_mode = SendDlgItemMessageW(hDlg, IDC_CNF_EDITION_MODE,
                                                          CB_GETCURSEL, 0, 0);
            SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
704 705 706 707 708 709 710 711 712 713 714 715
	    return TRUE;
	default:
	    return FALSE;
	}
	break;
    }
    default:
	return FALSE;
    }
    return TRUE;
}

716 717 718 719 720 721
/******************************************************************
 *		WCUSER_SaveDlgProc
 *
 *      Dialog Procedure for choosing how to handle modification to the
 * console settings.
 */
722
static INT_PTR WINAPI WCUSER_SaveDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
723 724 725 726
{
    switch (msg)
    {
    case WM_INITDIALOG:
727
        SendDlgItemMessageW(hDlg, IDC_SAV_SESSION, BM_SETCHECK, BST_CHECKED, 0);
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
	break;
    case WM_COMMAND:
	switch (LOWORD(wParam))
	{
        case IDOK:
            EndDialog(hDlg,
                      (IsDlgButtonChecked(hDlg, IDC_SAV_SAVE) == BST_CHECKED) ?
                      IDC_SAV_SAVE : IDC_SAV_SESSION);
            break;
        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL); break;
	}
        break;
    default:
        return FALSE;
    }
    return TRUE;
}

747 748 749
/******************************************************************
 *		WCUSER_GetProperties
 *
750
 * Runs the dialog box to set up the wineconsole options
751
 */
752
BOOL WCUSER_GetProperties(struct inner_data* data, BOOL current)
753
{
754 755 756 757 758
    HPROPSHEETPAGE   psPage[3];
    PROPSHEETPAGEW   psp;
    PROPSHEETHEADERW psHead;
    WCHAR            buff[256];
    WNDCLASSW        wndclass;
759 760
    static const WCHAR szFntPreview[] = {'W','i','n','e','C','o','n','F','o','n','t','P','r','e','v','i','e','w',0};
    static const WCHAR szColorPreview[] = {'W','i','n','e','C','o','n','C','o','l','o','r','P','r','e','v','i','e','w',0};
761
    struct dialog_info	di;
762 763 764
    struct config_data  defcfg;
    struct config_data* refcfg;
    BOOL                save, modify_session;
765 766 767 768

    InitCommonControls();

    di.data = data;
769 770
    if (current)
    {
771 772
        refcfg = &data->curcfg;
        save = FALSE;
773 774 775
    }
    else
    {
776 777
        WINECON_RegLoad(NULL, refcfg = &defcfg);
        save = TRUE;
778
    }
779
    di.config = *refcfg;
780 781 782
    di.nFont = 0;
    di.font = NULL;

783 784
    modify_session = FALSE;

785 786 787
    wndclass.style         = 0;
    wndclass.lpfnWndProc   = WCUSER_FontPreviewProc;
    wndclass.cbClsExtra    = 0;
788
    wndclass.cbWndExtra    = sizeof (DWORD_PTR); /* for hFont */
789
    wndclass.hInstance     = GetModuleHandleW(NULL);
790
    wndclass.hIcon         = 0;
791
    wndclass.hCursor       = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
792 793 794
    wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szFntPreview;
795
    RegisterClassW(&wndclass);
796

797 798 799 800
    wndclass.style         = 0;
    wndclass.lpfnWndProc   = WCUSER_ColorPreviewProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = sizeof(DWORD);
801
    wndclass.hInstance     = GetModuleHandleW(NULL);
802
    wndclass.hIcon         = 0;
803
    wndclass.hCursor       = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
804 805 806
    wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szColorPreview;
807
    RegisterClassW(&wndclass);
808

809 810 811 812 813 814
    memset(&psp, 0, sizeof(psp));
    psp.dwSize = sizeof(psp);
    psp.dwFlags = 0;
    psp.hInstance = wndclass.hInstance;
    psp.lParam = (LPARAM)&di;

815
    psp.u.pszTemplate = MAKEINTRESOURCEW(IDD_OPTION);
816
    psp.pfnDlgProc = WCUSER_OptionDlgProc;
817
    psPage[0] = CreatePropertySheetPageW(&psp);
818

819
    psp.u.pszTemplate = MAKEINTRESOURCEW(IDD_FONT);
820
    psp.pfnDlgProc = WCUSER_FontDlgProc;
821
    psPage[1] = CreatePropertySheetPageW(&psp);
822

823
    psp.u.pszTemplate = MAKEINTRESOURCEW(IDD_CONFIG);
824
    psp.pfnDlgProc = WCUSER_ConfigDlgProc;
825
    psPage[2] = CreatePropertySheetPageW(&psp);
826 827 828

    memset(&psHead, 0, sizeof(psHead));
    psHead.dwSize = sizeof(psHead);
829

830 831
    if (!LoadStringW(GetModuleHandleW(NULL), (current) ? IDS_DLG_TIT_CURRENT : IDS_DLG_TIT_DEFAULT,
                     buff, ARRAY_SIZE(buff)))
832 833 834 835 836 837 838 839 840
    {
        buff[0] = 'S';
        buff[1] = 'e';
        buff[2] = 't';
        buff[3] = 'u';
        buff[4] = 'p';
        buff[5] = '\0';
    }

841
    psHead.pszCaption = buff;
842
    psHead.nPages = 3;
843
    psHead.hwndParent = data->hWnd;
844
    psHead.u3.phpage = psPage;
845
    psHead.dwFlags = PSH_NOAPPLYNOW;
846

847 848
    WINECON_DumpConfig("init", refcfg);

849
    PropertySheetW(&psHead);
850

851 852 853 854 855 856 857
    if (memcmp(refcfg, &di.config, sizeof(*refcfg)) == 0)
        return TRUE;

    WINECON_DumpConfig("ref", refcfg);
    WINECON_DumpConfig("cur", &di.config);
    if (refcfg == &data->curcfg)
    {
858 859
        switch (DialogBoxW(GetModuleHandleW(NULL), MAKEINTRESOURCEW(IDD_SAVE_SETTINGS),
                           data->hWnd, WCUSER_SaveDlgProc))
860 861 862 863 864 865 866 867
        {
        case IDC_SAV_SAVE:      save = TRUE; modify_session = TRUE; break;
        case IDC_SAV_SESSION:   modify_session = TRUE; break;
        case IDCANCEL:          break;
        default: WINE_ERR("ooch\n");
        }
    }

868
    if (modify_session) WINECON_SetConfig(data, &di.config);
869 870
    if (save)           WINECON_RegSave(&di.config);

871 872
    return TRUE;
}