Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56873
-- v7: comctl32/edit: Fix incorrect size for format rect when it is smaller than text.
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/user32/tests/edit.c | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/dlls/user32/tests/edit.c b/dlls/user32/tests/edit.c index bbde9b16616..47472ea4634 100644 --- a/dlls/user32/tests/edit.c +++ b/dlls/user32/tests/edit.c @@ -3426,6 +3426,55 @@ static void test_dbcs_WM_CHAR(void) } }
+static void test_format_rect(void) +{ + HWND edit; + RECT rect, expected_rect; + + struct state_tests + { + int style; + int style_ex; + RECT input; + RECT expected; + } + tests[] = + { + {ES_MULTILINE | WS_VISIBLE, 0, {0, 0, 0, 0}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {0, 0, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 10, 250}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 250, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 10, 1000}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 1000, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 1000, 1000}, {2, 2, 999, 994}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {0, 0, 0, 0}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {0, 0, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 10, 250}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 250, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 10, 1000}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 1000, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 1000, 1000}, {2, 2, 999, 994}} + }; + + for (int i = 0; i < ARRAY_SIZE(tests); i++) + { + edit = create_editcontrol(tests[i].style, tests[i].style_ex); + if (IsRectEmpty(&tests[i].expected)) + SendMessageA(edit, EM_GETRECT, 0, (LPARAM)&expected_rect); + else + expected_rect = tests[i].expected; + SetWindowTextA(edit, "Test Test Test\r\n\r\nTest Test Test Test Test Test Test Test Test Test Test Test\r\n\r\nTest Test Test"); + SendMessageA(edit, EM_SETRECT, 0, (LPARAM)&tests[i].input); + SendMessageA(edit, EM_GETRECT, 0, (LPARAM)&rect); + todo_wine ok (EqualRect(&expected_rect, &rect), "Expected rect {%ld, %ld, %ld, %ld}, but got {%ld, %ld, %ld, %ld}.\n", + expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom, + rect.left, rect.top, rect.right, rect.bottom); + DestroyWindow(edit); + } +} + START_TEST(edit) { BOOL b; @@ -3464,6 +3513,7 @@ START_TEST(edit) test_EM_GETLINE(); test_wordbreak_proc(); test_dbcs_WM_CHAR(); + test_format_rect();
UnregisterWindowClasses(); }
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56873 --- dlls/user32/edit.c | 51 ++++++++++++++++++++++++++++++++++------ dlls/user32/tests/edit.c | 2 +- 2 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index 39f429813d6..c59783463cf 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -2297,9 +2297,12 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) /* Windows doesn't care to fix text placement for SL controls */ es->format_rect.bottom = es->format_rect.top + es->line_height;
- /* Always stay within the client area */ - GetClientRect(es->hwndSelf, &ClientRect); - es->format_rect.bottom = min(es->format_rect.bottom, ClientRect.bottom); + if (!(es->style & ES_MULTILINE)) + { + /* Always stay within the client area */ + GetClientRect(es->hwndSelf, &ClientRect); + es->format_rect.bottom = min(es->format_rect.bottom, ClientRect.bottom); + }
if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) EDIT_BuildLineDefs_ML(es, 0, get_text_length(es), 0, NULL); @@ -2307,6 +2310,24 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP); }
+static int EDIT_is_valid_format_rect(EDITSTATE *es, const RECT *rc) +{ + RECT edit_rect; + int text_height = es->line_height * es->line_count; + + GetClientRect(es->hwndSelf, &edit_rect); + if (rc->top >= rc->bottom) + return 0; + if (rc->left >= rc->right) + return 0; + if (text_height > (rc->bottom - rc->top)) + return 0; + if (es->text_width > (rc->right - rc->left)) + return 0; + if ((rc->bottom - rc->top) > (edit_rect.bottom - edit_rect.top)) + return -1; + return 1; +}
/********************************************************************* * @@ -2319,12 +2340,28 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc) { LONG_PTR ExStyle; - INT bw, bh; + INT bw, bh, res; ExStyle = GetWindowLongPtrW(es->hwndSelf, GWL_EXSTYLE); + + res = EDIT_is_valid_format_rect(es, rc); + if (res == 0) + { + GetClientRect(es->hwndSelf, &es->format_rect); + } + else if (res == -1) + { + CopyRect(&es->format_rect, rc); + es->format_rect.left += 1; + es->format_rect.top += 1; + es->format_rect.right -= 1; + es->format_rect.bottom += 1; + } + else + { + CopyRect(&es->format_rect, rc); + } - CopyRect(&es->format_rect, rc); - - if (ExStyle & WS_EX_CLIENTEDGE) { + if (ExStyle & WS_EX_CLIENTEDGE && res != -1) { es->format_rect.left++; es->format_rect.right--; diff --git a/dlls/user32/tests/edit.c b/dlls/user32/tests/edit.c index 47472ea4634..a5cfd7f0d82 100644 --- a/dlls/user32/tests/edit.c +++ b/dlls/user32/tests/edit.c @@ -3468,7 +3468,7 @@ static void test_format_rect(void) SetWindowTextA(edit, "Test Test Test\r\n\r\nTest Test Test Test Test Test Test Test Test Test Test Test\r\n\r\nTest Test Test"); SendMessageA(edit, EM_SETRECT, 0, (LPARAM)&tests[i].input); SendMessageA(edit, EM_GETRECT, 0, (LPARAM)&rect); - todo_wine ok (EqualRect(&expected_rect, &rect), "Expected rect {%ld, %ld, %ld, %ld}, but got {%ld, %ld, %ld, %ld}.\n", + ok (EqualRect(&expected_rect, &rect), "Expected rect {%ld, %ld, %ld, %ld}, but got {%ld, %ld, %ld, %ld}.\n", expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom, rect.left, rect.top, rect.right, rect.bottom); DestroyWindow(edit);
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Debug: https://bugs.winehq.org/show_bug.cgi?id=56873 --- dlls/comctl32/tests/edit.c | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/dlls/comctl32/tests/edit.c b/dlls/comctl32/tests/edit.c index bce0215ef19..e32c8aa0fd9 100644 --- a/dlls/comctl32/tests/edit.c +++ b/dlls/comctl32/tests/edit.c @@ -3791,6 +3791,55 @@ static void test_ime(void) DestroyWindow(hwnd); }
+static void test_format_rect(void) +{ + HWND edit; + RECT rect, expected_rect; + + struct state_tests + { + int style; + int style_ex; + RECT input; + RECT expected; + } + tests[] = + { + {ES_MULTILINE | WS_VISIBLE, 0, {0, 0, 0, 0}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {0, 0, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 10, 250}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 250, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 10, 1000}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 1000, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, 0, {1, 1, 1000, 1000}, {2, 2, 999, 999}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {0, 0, 0, 0}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {0, 0, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 10, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 10, 250}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 250, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 10, 1000}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 1000, 10}, {0}}, + {ES_MULTILINE | WS_VISIBLE, WS_EX_CLIENTEDGE, {1, 1, 1000, 1000}, {2, 2, 999, 999}} + }; + + for (int i = 0; i < ARRAY_SIZE(tests); i++) + { + edit = create_editcontrol(tests[i].style, tests[i].style_ex); + if (IsRectEmpty(&tests[i].expected)) + SendMessageA(edit, EM_GETRECT, 0, (LPARAM)&expected_rect); + else + expected_rect = tests[i].expected; + SetWindowTextA(edit, "Test Test Test\r\n\r\nTest Test Test Test Test Test Test Test Test Test Test Test\r\n\r\nTest Test Test"); + SendMessageA(edit, EM_SETRECT, 0, (LPARAM)&tests[i].input); + SendMessageA(edit, EM_GETRECT, 0, (LPARAM)&rect); + todo_wine ok (EqualRect(&expected_rect, &rect), "Expected rect {%ld, %ld, %ld, %ld}, but got {%ld, %ld, %ld, %ld}.\n", + expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom, + rect.left, rect.top, rect.right, rect.bottom); + DestroyWindow(edit); + } +} + START_TEST(edit) { ULONG_PTR ctx_cookie; @@ -3838,6 +3887,7 @@ START_TEST(edit) test_change_focus(); test_cue_banner(); test_ime(); + test_format_rect();
UnregisterWindowClasses();
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56873 --- dlls/comctl32/edit.c | 55 +++++++++++++++++++++++++++++++++----- dlls/comctl32/tests/edit.c | 2 +- 2 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/dlls/comctl32/edit.c b/dlls/comctl32/edit.c index 4b950412617..68aa649f6dc 100644 --- a/dlls/comctl32/edit.c +++ b/dlls/comctl32/edit.c @@ -126,6 +126,7 @@ typedef struct INT wheelDeltaRemainder; /* scroll wheel delta left over after scrolling whole lines */ WCHAR *cue_banner_text; BOOL cue_banner_draw_focused; + INT valid_format_rect;
/* * only for multi line controls @@ -2200,7 +2201,8 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) INT fw, vlc, max_x_offset, max_y_offset;
vlc = get_vertical_line_count(es); - es->format_rect.bottom = es->format_rect.top + vlc * es->line_height; + if (es->valid_format_rect != -1) + es->format_rect.bottom = es->format_rect.top + vlc * es->line_height;
/* correct es->x_offset */ fw = es->format_rect.right - es->format_rect.left; @@ -2222,9 +2224,12 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) /* Windows doesn't care to fix text placement for SL controls */ es->format_rect.bottom = es->format_rect.top + es->line_height;
- /* Always stay within the client area */ - GetClientRect(es->hwndSelf, &ClientRect); - es->format_rect.bottom = min(es->format_rect.bottom, ClientRect.bottom); + if (!(es->style & ES_MULTILINE)) + { + /* Always stay within the client area */ + GetClientRect(es->hwndSelf, &ClientRect); + es->format_rect.bottom = min(es->format_rect.bottom, ClientRect.bottom); + }
if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) EDIT_BuildLineDefs_ML(es, 0, get_text_length(es), 0, NULL); @@ -2232,6 +2237,24 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP); }
+static int EDIT_is_valid_format_rect(EDITSTATE *es, const RECT *rc) +{ + RECT edit_rect; + int text_height = es->line_height * es->line_count; + + GetClientRect(es->hwndSelf, &edit_rect); + if (rc->top >= rc->bottom) + return 0; + if (rc->left >= rc->right) + return 0; + if (text_height > (rc->bottom - rc->top)) + return 0; + if (es->text_width > (rc->right - rc->left)) + return 0; + if ((rc->bottom - rc->top) > (edit_rect.bottom - edit_rect.top)) + return -1; + return 1; +}
/********************************************************************* * @@ -2244,12 +2267,29 @@ static void EDIT_AdjustFormatRect(EDITSTATE *es) static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc) { LONG_PTR ExStyle; - INT bw, bh; + INT bw, bh, res; ExStyle = GetWindowLongPtrW(es->hwndSelf, GWL_EXSTYLE);
- CopyRect(&es->format_rect, rc); + res = EDIT_is_valid_format_rect(es, rc); + if (res == 0) + { + GetClientRect(es->hwndSelf, &es->format_rect); + } + else if (res == -1) + { + CopyRect(&es->format_rect, rc); + es->format_rect.left += 1; + es->format_rect.top += 1; + es->format_rect.right -= 1; + es->format_rect.bottom -= 1; + } + else + { + CopyRect(&es->format_rect, rc); + } + es->valid_format_rect = res;
- if (ExStyle & WS_EX_CLIENTEDGE) { + if (ExStyle & WS_EX_CLIENTEDGE && res != -1) { es->format_rect.left++; es->format_rect.right--;
@@ -4381,6 +4421,7 @@ static LRESULT EDIT_WM_Create(EDITSTATE *es, const WCHAR *name) RECT clientRect;
TRACE("%s\n", debugstr_w(name)); + es->valid_format_rect = 1;
/* * To initialize some final structure members, we call some helper diff --git a/dlls/comctl32/tests/edit.c b/dlls/comctl32/tests/edit.c index e32c8aa0fd9..26d7b6aeb06 100644 --- a/dlls/comctl32/tests/edit.c +++ b/dlls/comctl32/tests/edit.c @@ -3833,7 +3833,7 @@ static void test_format_rect(void) SetWindowTextA(edit, "Test Test Test\r\n\r\nTest Test Test Test Test Test Test Test Test Test Test Test\r\n\r\nTest Test Test"); SendMessageA(edit, EM_SETRECT, 0, (LPARAM)&tests[i].input); SendMessageA(edit, EM_GETRECT, 0, (LPARAM)&rect); - todo_wine ok (EqualRect(&expected_rect, &rect), "Expected rect {%ld, %ld, %ld, %ld}, but got {%ld, %ld, %ld, %ld}.\n", + ok (EqualRect(&expected_rect, &rect), "Expected rect {%ld, %ld, %ld, %ld}, but got {%ld, %ld, %ld, %ld}.\n", expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom, rect.left, rect.top, rect.right, rect.bottom); DestroyWindow(edit);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147902
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w7u_adm (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w7u_el (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w8 (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w8adm (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w864 (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w1064v1507 (32 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w7pro64 (64 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w864 (64 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w1064v1507 (64 bit report) ===
comctl32: edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}. edit.c:3836: Test failed: Expected rect {2, 2, 999, 999}, but got {2, 2, 999, 994}.
=== w10pro64_ja (64 bit report) ===
user32: edit.c:3471: Test failed: Expected rect {2, 2, 999, 994}, but got {2, 2, 999, 992}. edit.c:3471: Test failed: Expected rect {2, 2, 999, 994}, but got {2, 2, 999, 992}.
=== debian11 (32 bit ja:JP report) ===
user32: edit.c:3471: Test failed: Expected rect {2, 2, 999, 994}, but got {2, 2, 999, 992}. edit.c:3471: Test failed: Expected rect {2, 2, 999, 994}, but got {2, 2, 999, 992}.
Still has test failures. See https://testbot.winehq.org/JobDetails.pl?Key=147902
Also ``` warning: 1 line adds whitespace errors. ```