[PATCH v3] comctl32: Initialize early font metrics in edit control.

Roman Pišl rpisl at seznam.cz
Thu Mar 26 14:07:05 CDT 2020


Hello,
I just tested all affected applications from bugzilla and just setting 
es->line_height = 1 and es->char_width = 1 in NCCreate is sufficient, 
since all other content is zero anyway and proper value is set during 
WM_CREATE.

So a less intrusive change is possible..

Roman

Dne 26. 03. 20 v 16:54 Roman Pišl napsal(a):
> v2: Introduced helper function.
> v3: Improved helper function (I really didn't like the previous).
> 
> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48803
> Signed-off-by: Roman Pišl <rpisl at seznam.cz>
> ---
>   dlls/comctl32/edit.c       | 38 ++++++++++++++++--------
>   dlls/comctl32/tests/edit.c | 59 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 85 insertions(+), 12 deletions(-)
> 
> diff --git a/dlls/comctl32/edit.c b/dlls/comctl32/edit.c
> index d02d7af7b9..e7a3f9b7f9 100644
> --- a/dlls/comctl32/edit.c
> +++ b/dlls/comctl32/edit.c
> @@ -3724,25 +3724,14 @@ static DWORD get_font_margins(HDC hdc, const TEXTMETRICW *tm)
>   	return MAKELONG(left, right);
>   }
>   
> -/*********************************************************************
> - *
> - *	WM_SETFONT
> - *
> - * With Win95 look the margins are set to default font value unless
> - * the system font (font == 0) is being set, in which case they are left
> - * unchanged.
> - *
> - */
> -static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
> +static DWORD set_font(EDITSTATE *es, HFONT font)
>   {
>   	TEXTMETRICW tm;
>   	HDC dc;
>   	HFONT old_font = 0;
> -	RECT clientRect;
>   	DWORD margins;
>   
>   	es->font = font;
> -	EDIT_InvalidateUniscribeData(es);
>   	dc = GetDC(es->hwndSelf);
>   	if (font)
>   		old_font = SelectObject(dc, font);
> @@ -3754,6 +3743,26 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
>   		SelectObject(dc, old_font);
>   	ReleaseDC(es->hwndSelf, dc);
>   
> +	return margins;
> +}
> +
> +/*********************************************************************
> + *
> + *	WM_SETFONT
> + *
> + * With Win95 look the margins are set to default font value unless
> + * the system font (font == 0) is being set, in which case they are left
> + * unchanged.
> + *
> + */
> +static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
> +{
> +	RECT clientRect;
> +	DWORD margins;
> +
> +	EDIT_InvalidateUniscribeData(es);
> +	margins = set_font(es, font);
> +
>   	/* Reset the format rect and the margins */
>   	GetClientRect(es->hwndSelf, &clientRect);
>   	EDIT_SetRectNP(es, &clientRect);
> @@ -4488,6 +4497,11 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs)
>           else if (es->style & WS_BORDER)
>   		SetWindowLongW(hwnd, GWL_STYLE, es->style & ~WS_BORDER);
>   
> +	/*
> +	 * Initialize font metrics - line_height and char_width so that
> +	 * early messages before WM_CREATE don't lead to division by zero.
> +	 */
> +	set_font(es, 0);
>   	return TRUE;
>   
>   cleanup:
> diff --git a/dlls/comctl32/tests/edit.c b/dlls/comctl32/tests/edit.c
> index cec6025077..3bfbee4ddd 100644
> --- a/dlls/comctl32/tests/edit.c
> +++ b/dlls/comctl32/tests/edit.c
> @@ -1768,6 +1768,64 @@ static BOOL is_font_installed(const char*name)
>       return ret;
>   }
>   
> +static WNDPROC orig_class_proc;
> +
> +static LRESULT CALLBACK test_class_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
> +{
> +    RECT rect;
> +    LRESULT result;
> +
> +    switch (message)
> +    {
> +        case WM_NCCREATE:
> +            result = CallWindowProcA(orig_class_proc, hwnd, message, wParam, lParam);
> +
> +            memset(&rect, 0, sizeof(rect));
> +            SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rect);
> +            ok(!rect.right && !rect.bottom, "Invalid size after NCCREATE: %d x %d\n", rect.right, rect.bottom);
> +
> +            /* test that early messages don't crash or cause unexpected behavior */
> +            SendMessageA(hwnd, EM_SETSEL, 0, 0);
> +            SendMessageA(hwnd, WM_SIZE, 0, 0);
> +
> +            return result;
> +
> +        case WM_CREATE:
> +            /* test that early messages don't crash or cause unexpected behavior */
> +            SendMessageA(hwnd, EM_SETSEL, 0, 0);
> +            SendMessageA(hwnd, WM_SIZE, 0, 0);
> +
> +            break;
> +    }
> +
> +    return CallWindowProcA(orig_class_proc, hwnd, message, wParam, lParam);
> +}
> +
> +static void test_early_messages(void)
> +{
> +    BOOL ret;
> +    ATOM atom;
> +    HWND hwEdit;
> +    WNDCLASSA cls;
> +
> +    ret = GetClassInfoA(NULL, "Edit", &cls);
> +    ok(ret, "Failed to get class info.\n");
> +
> +    orig_class_proc = cls.lpfnWndProc;
> +    cls.lpfnWndProc = test_class_proc;
> +    cls.lpszClassName = "TestClassName";
> +
> +    atom = RegisterClassA(&cls);
> +    ok(atom != 0, "Failed to register class.\n");
> +
> +    hwEdit = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atom), "Text Text", ES_MULTILINE | WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
> +        10, 10, 300, 300, NULL, NULL, hinst, NULL);
> +    ok(hwEdit != NULL, "Failed to create a window.\n");
> +
> +    DestroyWindow(hwEdit);
> +    UnregisterClassA((LPCSTR)MAKEINTATOM(atom), hinst);
> +}
> +
>   static void test_margins(void)
>   {
>       DWORD old_margins, new_margins;
> @@ -3393,6 +3451,7 @@ START_TEST(edit)
>       test_edit_control_6();
>       test_edit_control_limittext();
>       test_edit_control_scroll();
> +    test_early_messages();
>       test_margins();
>       test_margins_font_change();
>       test_text_position();
> 



More information about the wine-devel mailing list