The listview bug is caused by passing the incorrect index to the LISTVIEW_SortItems callers custom compare function. If we pass the copied array indices, which are different because of the sorting, the caller is going to use those indices for their unsorted array which don't match.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56140
-- v7: comctl32: Fix sorting for listview.
From: Jacob Czekalla jczekalla@codeweavers.com
--- dlls/comctl32/tests/listview.c | 74 ++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+)
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 1081a045cde..df892753b54 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -3028,6 +3028,79 @@ static void test_subitem_rect(void) DestroyWindow(hwnd); }
+static INT WINAPI test_CallBackCompareEx(LPARAM first, LPARAM second, LPARAM lParam) +{ + HWND list_view = (HWND)lParam; + CHAR buffer1[256], buffer2[256]; + int itm1, itm2; + + ListView_GetItemTextA(list_view, first, 0, buffer1, sizeof(buffer1)); + ListView_GetItemTextA(list_view, second, 0, buffer2, sizeof(buffer2)); + + itm1 = atoi(buffer1); + itm2 = atoi(buffer2); + + return (itm1 - itm2); +} + +static void test_custom_sort(void) +{ + int prev_value; + int sorted; + LVITEMA lvi = {0}; + LV_COLUMNA lvc = {0}; + RECT rcClient; + CHAR buffer[256]; + CHAR col_names[][2] = { "1", "2" }; + HWND list_view = create_listview_control(LVS_REPORT); + + lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + lvc.pszText = col_names[0]; + lvc.iSubItem = 0; + SendMessageA(list_view, LVM_INSERTCOLUMNA, 0, (LPARAM) &lvc); + + lvc.pszText = col_names[1]; + lvc.iSubItem = 1; + SendMessageA(list_view, LVM_INSERTCOLUMNA, 1, (LPARAM) &lvc); + + srand(1234); + + for (int i = 0; i < 100; i++) + { + lvi.mask = LVIF_TEXT; + lvi.iItem = i; + lvi.iSubItem = 0; + lvi.pszText = buffer; + sprintf(buffer, "%d", rand() % 100); + SendMessageA(list_view, LVM_INSERTITEMA, 0, (LPARAM) &lvi); + + lvi.iSubItem = 1; + sprintf(buffer, "%d", rand() % 100); + SendMessageA(list_view, LVM_SETITEMTEXTA, i, (LPARAM) &lvi); + } + + SendMessageA(list_view, LVM_SORTITEMSEX, (WPARAM) list_view, (LPARAM) test_CallBackCompareEx); + + for (int i = 1; i < 100; i++) + { + ListView_GetItemTextA(list_view, i - 1, 0, buffer, sizeof(buffer)); + prev_value = atoi(buffer); + + ListView_GetItemTextA(list_view, i, 0, buffer, sizeof(buffer)); + + if (atoi(buffer) < prev_value) + { + sorted = 0; + break; + } + sorted = 1; + } + + todo_wine ok(sorted, "ListView not sorted correctly.\n"); + + DestroyWindow(list_view); +} + /* comparison callback for test_sorting */ static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam) { @@ -7227,6 +7300,7 @@ START_TEST(listview) test_LVM_GETCOUNTPERPAGE(); test_item_state_change(); test_LVM_SETBKIMAGE(FALSE); + test_custom_sort();
if (!load_v6_module(&ctx_cookie, &hCtx)) {
From: Jacob Czekalla jczekalla@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56140 --- dlls/comctl32/listview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index c82473b6205..0302e3e19a0 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -9396,7 +9396,7 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare, if (infoPtr->nFocusedItem >= 0) focusedItem = DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nFocusedItem);
- context.items = hdpaItems; + context.items = infoPtr->hdpaItems; context.compare_func = pfnCompare; context.lParam = lParamSort; if (IsEx)
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=147463
Your paranoid android.
=== debian11 (32 bit report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit ar:MA report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit de report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit fr report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit he:IL report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit hi:IN report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit ja:JP report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11 (32 bit zh:CN report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11b (32 bit WoW report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
=== debian11b (64 bit WoW report) ===
comctl32: listview.c:3099: Test succeeded inside todo block: ListView not sorted correctly.
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/listview.c:
- for (int i = 0; i < 100; i++)
- {
lvi.mask = LVIF_TEXT;
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.pszText = buffer;
sprintf(buffer, "%d", rand() % 100);
SendMessageA(list_view, LVM_INSERTITEMA, 0, (LPARAM) &lvi);
lvi.iSubItem = 1;
sprintf(buffer, "%d", rand() % 100);
SendMessageA(list_view, LVM_SETITEMTEXTA, i, (LPARAM) &lvi);
- }
- SendMessageA(list_view, LVM_SORTITEMSEX, (WPARAM) list_view, (LPARAM) test_CallBackCompareEx);
Let's remove the space after (WPARAM) and (LPARAM).
Zhiyi Zhang (@zhiyi) commented about dlls/comctl32/tests/listview.c:
sprintf(buffer, "%d", rand() % 100);
SendMessageA(list_view, LVM_INSERTITEMA, 0, (LPARAM) &lvi);
lvi.iSubItem = 1;
sprintf(buffer, "%d", rand() % 100);
SendMessageA(list_view, LVM_SETITEMTEXTA, i, (LPARAM) &lvi);
- }
- SendMessageA(list_view, LVM_SORTITEMSEX, (WPARAM) list_view, (LPARAM) test_CallBackCompareEx);
- for (int i = 1; i < 100; i++)
- {
ListView_GetItemTextA(list_view, i - 1, 0, buffer, sizeof(buffer));
prev_value = atoi(buffer);
ListView_GetItemTextA(list_view, i, 0, buffer, sizeof(buffer));
There are two spaces before sizeof(buffer).
Otherwise, it looks good. Thanks for your work.