Some app inserts textual items in listview with CR/LF in them. These are not displayed on Windows, while Wine draws an empty square box for each CR or LF.
Manual testing on Windows show that CR or LF are not displayed, while other characters < 32 are displayed.
A couple of tests in this MR show that: - the CR / LF are stored in listview (as they can be retrieved) - the CR / LF are somehow accounted in string width
So, try to fix this by not passing CR nor LF to DrawText().
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/comctl32/tests/listview.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 1a9831bbaec..f0c90a9009a 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -1310,10 +1310,12 @@ static void test_items(void) { const LPARAM lparamTest = 0x42; static CHAR text[] = "Text"; + static CHAR textnl[] = "T\re\nxt"; char buffA[5]; + char buffB[7]; HWND hwnd; LVITEMA item; - DWORD r; + DWORD r, r2;
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); @@ -1432,6 +1434,29 @@ static void test_items(void) expect(1, r); ok(!memcmp(item.pszText, text, sizeof(text)), "got text %s, expected %s\n", item.pszText, text);
+ /* Set up a subitem with special characters */ + memset (&item, 0xcc, sizeof (item)); + item.mask = LVIF_TEXT; + item.iItem = 0; + item.iSubItem = 1; + item.pszText = textnl; + r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); + expect(1, r); + + item.mask = LVIF_TEXT; + item.iItem = 0; + item.iSubItem = 1; + item.pszText = buffB; + item.cchTextMax = sizeof(buffB); + r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); + expect(1, r); + ok(!memcmp(item.pszText, textnl, sizeof(textnl)), "got text %s, expected %s\n", item.pszText, textnl); + + r = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, 0, (LPARAM) text); + ok(r > 0, "Expected non null width\n"); + r2 = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, 0, (LPARAM) textnl); + ok(r2 > r, "Expected a greater width\n"); + /* set up with extra flag */ /* 1. reset subitem text */ item.mask = LVIF_TEXT;
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/comctl32/listview.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index 9191aef1c3f..ad58eb2c1ab 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -2282,7 +2282,30 @@ static void LISTVIEW_GetItemOrigin(const LISTVIEW_INFO *infoPtr, INT nItem, LPPO lpptPosition->y = nItem * infoPtr->nItemHeight; } } - + +/* wrapper for DrawTextW, so that we remove the characters that native doesn't display (Win10) */ +static INT LISTVIEW_draw_text(HDC hdc, WCHAR *text, RECT *rect, unsigned format) +{ + static const WCHAR *totrim = L"\r\n"; + WCHAR *buffer; + WCHAR *src, *dst; + INT ret; + + if (!wcspbrk(text, totrim)) + return DrawTextW(hdc, text, -1, rect, format); + + buffer = wcsdup(text); + if (!buffer) return 0; + for (src = text, dst = buffer; *src; src++) + { + if (!wcschr(totrim, *src)) + *dst++ = *src; + } + ret = DrawTextW(hdc, buffer, dst - buffer, rect, format); + free(buffer); + return ret; +} + /*** * DESCRIPTION: [INTERNAL] * Compute the rectangles of an item. This is to localize all @@ -2474,8 +2497,8 @@ static void LISTVIEW_GetItemMetrics(const LISTVIEW_INFO *infoPtr, const LVITEMW uFormat = oversizedBox ? LV_FL_DT_FLAGS : LV_ML_DT_FLAGS; else uFormat = LV_SL_DT_FLAGS; - - DrawTextW (hdc, lpLVItem->pszText, -1, &rcText, uFormat | DT_CALCRECT); + + LISTVIEW_draw_text(hdc, lpLVItem->pszText, &rcText, uFormat | DT_CALCRECT);
if (rcText.right != rcText.left) labelSize.cx = min(rcText.right - rcText.left + TRAILING_LABEL_PADDING, infoPtr->nItemWidth); @@ -4752,7 +4775,7 @@ static void LISTVIEW_DrawItemPart(LISTVIEW_INFO *infoPtr, LVITEMW *item, const N if (infoPtr->uView == LV_VIEW_DETAILS && infoPtr->dwLvExStyle & LVS_EX_GRIDLINES) rcLabel.bottom--;
- DrawTextW(nmlvcd->nmcd.hdc, item->pszText, -1, &rcLabel, format); + LISTVIEW_draw_text(nmlvcd->nmcd.hdc, item->pszText, &rcLabel, format); }
/***
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=150406
Your paranoid android.
=== w10pro64_ja (64 bit report) ===
comctl32: listview.c:1458: Test failed: Expected a greater width listview.c:1458: Test failed: Expected a greater width
=== w10pro64_zh_CN (64 bit report) ===
comctl32: listview.c:1458: Test failed: Expected a greater width listview.c:1458: Test failed: Expected a greater width
=== debian11b (64 bit WoW report) ===
user32: input.c:733: Test failed: peek: raw_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x46, lparam 0x10001 input.c:733: Test failed: peek: raw_legacy: 0: test->expect 2 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x66, lparam 0x10001 input.c:734: Test failed: peek: raw_legacy: 0: got F: 0 input.c:733: Test failed: peek: raw_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: peek: raw_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x46, lparam 0xffffffffc0020001 input.c:733: Test failed: peek: raw_vk_packet_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_vk_packet_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0xe7, lparam 0x10001 input.c:734: Test failed: peek: raw_vk_packet_legacy: 0: got 0xe7: 0 input.c:733: Test failed: peek: raw_vk_packet_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0 input.c:733: Test failed: peek: raw_vk_packet_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0xe7, lparam 0xffffffffc0020001 input.c:733: Test failed: peek: raw_unicode_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x3c0, lparam 0x1 input.c:734: Test failed: peek: raw_unicode_legacy: 0: got 0xe7: 0 input.c:733: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 0: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x11, lparam 0xc00001 input.c:734: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 0: got VK_CONTROL: 0 input.c:734: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 0: got VK_LCONTROL: 0 input.c:733: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 1: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x11, lparam 0xffffffffc0c00001 input.c:733: Test failed: peek: raw_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: peek: raw_vk_packet_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_vk_packet_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x46, lparam 0x10001 input.c:733: Test failed: receive: raw_legacy: 0: test->expect 2 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x66, lparam 0x10001 input.c:734: Test failed: receive: raw_legacy: 0: got F: 0 input.c:733: Test failed: receive: raw_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x46, lparam 0xffffffffc0020001 input.c:733: Test failed: receive: raw_vk_packet_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_vk_packet_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0xe7, lparam 0x10001 input.c:734: Test failed: receive: raw_vk_packet_legacy: 0: got 0xe7: 0 input.c:733: Test failed: receive: raw_vk_packet_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_vk_packet_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0xe7, lparam 0xffffffffc0020001 input.c:733: Test failed: receive: raw_unicode_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x3c0, lparam 0x1 input.c:734: Test failed: receive: raw_unicode_legacy: 0: got 0xe7: 0 input.c:733: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 0: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x11, lparam 0xc00001 input.c:734: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 0: got VK_CONTROL: 0 input.c:734: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 0: got VK_LCONTROL: 0 input.c:733: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 1: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x11, lparam 0xffffffffc0c00001 input.c:733: Test failed: receive: raw_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_vk_packet_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_vk_packet_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0
It's unlikely that this belongs to listview at all. I remember seeing null glyphs in tooltips too. What we need to compare is DrawText() output, and fix that. Note that it has to use the same font, otherwise it's an additional variable factor.
To keep in mind:
* on modern Windows version, last time I checked, cr/lf glyphs are in fact present in fonts like Tahoma, and they have zero width set in the font itself; * regardless of the font, a common approach is to zero control characters advances during text shaping. We do that for directwrite; * results could differ between DrawText(), uniscribe, and directwrite, for common controls it's enough to check just DrawText(), and then maybe some Indic text too so that complex shaping kicks in.