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

Roman Pišl rpisl at seznam.cz
Thu Mar 26 10:54:29 CDT 2020


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();
-- 
2.20.1




More information about the wine-devel mailing list