Added patch with multiple fixes for owner-drawn and sorted listbox.

This commit is contained in:
Sebastian Lackner 2017-03-20 16:49:38 +01:00
parent e92999d7d5
commit a47000e41c
6 changed files with 344 additions and 0 deletions

View File

@ -371,6 +371,7 @@ patch_enable_all ()
enable_user32_PNG_Support="$1"
enable_user32_Refresh_MDI_Menus="$1"
enable_user32_ScrollWindowEx="$1"
enable_user32_Sorted_Listbox="$1"
enable_user32_WM_MEASUREITEM="$1"
enable_user32_lpCreateParams="$1"
enable_uxtheme_CloseThemeClass="$1"
@ -1335,6 +1336,9 @@ patch_enable ()
user32-ScrollWindowEx)
enable_user32_ScrollWindowEx="$2"
;;
user32-Sorted_Listbox)
enable_user32_Sorted_Listbox="$2"
;;
user32-WM_MEASUREITEM)
enable_user32_WM_MEASUREITEM="$2"
;;
@ -2106,6 +2110,13 @@ if test "$enable_uxtheme_GTK_Theming" -eq 1; then
enable_ntdll_DllRedirects=1
fi
if test "$enable_user32_Sorted_Listbox" -eq 1; then
if test "$enable_user32_WM_MEASUREITEM" -gt 1; then
abort "Patchset user32-WM_MEASUREITEM disabled, but user32-Sorted_Listbox depends on that."
fi
enable_user32_WM_MEASUREITEM=1
fi
if test "$enable_user32_MessageBox_WS_EX_TOPMOST" -eq 1; then
if test "$enable_user32_lpCreateParams" -gt 1; then
abort "Patchset user32-lpCreateParams disabled, but user32-MessageBox_WS_EX_TOPMOST depends on that."
@ -7779,6 +7790,30 @@ if test "$enable_user32_WM_MEASUREITEM" -eq 1; then
) >> "$patchlist"
fi
# Patchset user32-Sorted_Listbox
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * user32-WM_MEASUREITEM
# |
# | This patchset fixes the following Wine bugs:
# | * [#42602] Multiple fixes for owner-drawn and sorted listbox
# |
# | Modified files:
# | * dlls/user32/listbox.c, dlls/user32/tests/msg.c
# |
if test "$enable_user32_Sorted_Listbox" -eq 1; then
patch_apply user32-Sorted_Listbox/0001-user32-tests-Add-a-message-test-for-an-owner-drawn-s.patch
patch_apply user32-Sorted_Listbox/0002-user32-Fix-order-of-items-passed-in-WM_COMPAREITEM-d.patch
patch_apply user32-Sorted_Listbox/0003-user32-Fix-the-listbox-sorting-algorithm.patch
patch_apply user32-Sorted_Listbox/0004-user32-For-an-owner-drawn-listbox-without-strings-WM.patch
(
printf '%s\n' '+ { "Dmitry Timoshkov", "user32/tests: Add a message test for an owner-drawn sorted listbox.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "user32: Fix order of items passed in WM_COMPAREITEM data.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "user32: Fix the listbox sorting algorithm.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "user32: For an owner-drawn listbox without strings WM_MEASUREITEM still needs correct itemData.", 1 },';
) >> "$patchlist"
fi
# Patchset uxtheme-CloseThemeClass
# |
# | This patchset fixes the following Wine bugs:

View File

@ -0,0 +1,160 @@
From 726802175f5249d2313620f488a55ffa391c56ce Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 8 Mar 2017 16:33:41 +0800
Subject: user32/tests: Add a message test for an owner-drawn sorted listbox.
---
dlls/user32/tests/msg.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 88 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index a742f670ab..3a492b37bd 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -2232,18 +2232,61 @@ static void add_message_(int line, const struct recvd_message *msg)
{
MEASURE_ITEM_STRUCT mi;
MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam;
+ BOOL is_unicode_data = TRUE;
sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx",
msg->descr, msg->hwnd, mis->CtlType, mis->CtlID,
mis->itemID, mis->itemData);
+ if (mis->CtlType == ODT_LISTBOX)
+ {
+ HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID);
+ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
+ }
+
mi.u.wp = 0;
mi.u.item.CtlType = mis->CtlType;
mi.u.item.CtlID = mis->CtlID;
mi.u.item.itemID = mis->itemID;
mi.u.item.wParam = msg->wParam;
seq->wParam = mi.u.wp;
- seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0;
+ if (is_unicode_data)
+ seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0;
+ else
+ seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0;
+ break;
+ }
+
+ case WM_COMPAREITEM:
+ {
+ COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam;
+ HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID);
+ BOOL is_unicode_data = TRUE;
+
+ ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam);
+ ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
+todo_wine
+ ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
+todo_wine
+ ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
+
+ sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx",
+ msg->descr, msg->hwnd, cis->CtlType, cis->CtlID,
+ cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2);
+
+ if (cis->CtlType == ODT_LISTBOX)
+ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
+
+ if (is_unicode_data)
+ {
+ seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0;
+ seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0;
+ }
+ else
+ {
+ seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0;
+ seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0;
+ }
break;
}
@@ -9261,7 +9304,7 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam
message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
message == WM_SETFOCUS || message == WM_KILLFOCUS ||
message == WM_ENABLE || message == WM_ENTERIDLE ||
- message == WM_DRAWITEM || message == WM_MEASUREITEM ||
+ message == WM_DRAWITEM || message == WM_MEASUREITEM || message == WM_COMPAREITEM ||
message == WM_COMMAND || message == WM_IME_SETCONTEXT)
{
switch (message)
@@ -9309,7 +9352,7 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam
ret = DefWindowProcA(hwnd, message, wParam, lParam);
defwndproc_counter--;
- return ret;
+ return message == WM_COMPAREITEM ? -1 : ret;
}
static INT_PTR CALLBACK StopQuitMsgCheckProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
@@ -14430,6 +14473,19 @@ static const struct message wm_lb_addstring[] =
{ WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef },
{ 0 }
};
+static const struct message wm_lb_addstring_sort[] =
+{
+ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed },
+ { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed },
+ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee },
+ { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ee },
+ { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee },
+ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef },
+ { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ef },
+ { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ee, 0xf30604ef },
+ { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef },
+ { 0 }
+};
#define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
@@ -14495,6 +14551,7 @@ static void test_listbox_messages(void)
parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 200, 200, 0, 0, 0, NULL);
+ /* with LBS_HASSTRINGS */
listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL,
WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE,
10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
@@ -14576,6 +14633,34 @@ static void test_listbox_messages(void)
log_all_parent_messages--;
DestroyWindow(listbox);
+
+ /* with LBS_SORT and without LBS_HASSTRINGS */
+ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL,
+ WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE,
+ 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
+ listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc);
+
+ check_lb_state(listbox, 0, LB_ERR, 0, 0);
+
+ flush_sequence();
+
+ log_all_parent_messages++;
+
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
+ ok(ret == 0, "expected 0, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
+todo_wine
+ ok(ret == 1, "expected 1, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
+todo_wine
+ ok(ret == 2, "expected 2, got %ld\n", ret);
+
+ ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", TRUE);
+ check_lb_state(listbox, 3, LB_ERR, 0, 0);
+
+ log_all_parent_messages--;
+
+ DestroyWindow(listbox);
DestroyWindow(parent);
}
--
2.11.0

View File

@ -0,0 +1,63 @@
From 25f564b7d279386c882c144fd6591d012049dcb7 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 8 Mar 2017 16:48:26 +0800
Subject: user32: Fix order of items passed in WM_COMPAREITEM data.
---
dlls/user32/listbox.c | 10 +++++-----
dlls/user32/tests/msg.c | 4 ----
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index 689cb106c4..4269ef0717 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -858,15 +858,15 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
cis.hwndItem = descr->self;
/* note that some application (MetaStock) expects the second item
* to be in the listbox */
- cis.itemID1 = -1;
- cis.itemData1 = (ULONG_PTR)str;
- cis.itemID2 = index;
- cis.itemData2 = descr->items[index].data;
+ cis.itemID1 = index;
+ cis.itemData1 = descr->items[index].data;
+ cis.itemID2 = -1;
+ cis.itemData2 = (ULONG_PTR)str;
cis.dwLocaleId = descr->locale;
res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis );
}
if (!res) return index;
- if (res < 0) max = index;
+ if (res > 0) max = index;
else min = index + 1;
}
return exact ? -1 : max;
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 3a492b37bd..f806e5366e 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -2265,9 +2265,7 @@ static void add_message_(int line, const struct recvd_message *msg)
ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam);
ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
-todo_wine
ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
-todo_wine
ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx",
@@ -14649,10 +14647,8 @@ static void test_listbox_messages(void)
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
ok(ret == 0, "expected 0, got %ld\n", ret);
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
-todo_wine
ok(ret == 1, "expected 1, got %ld\n", ret);
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
-todo_wine
ok(ret == 2, "expected 2, got %ld\n", ret);
ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", TRUE);
--
2.11.0

View File

@ -0,0 +1,44 @@
From 29128bbe18f85edc8f7760262c6b598bd789ffb0 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 8 Mar 2017 17:48:58 +0800
Subject: user32: Fix the listbox sorting algorithm.
---
dlls/user32/listbox.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index 4269ef0717..5eb266b15a 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -840,10 +840,11 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
{
INT index, min, max, res;
- if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */
+ if (!descr->nb_items || !(descr->style & LBS_SORT)) return -1; /* Add it at the end */
+
min = 0;
- max = descr->nb_items;
- while (min != max)
+ max = descr->nb_items - 1;
+ while (min <= max)
{
index = (min + max) / 2;
if (HAS_STRINGS(descr))
@@ -866,10 +867,10 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis );
}
if (!res) return index;
- if (res > 0) max = index;
+ if (res > 0) max = index - 1;
else min = index + 1;
}
- return exact ? -1 : max;
+ return exact ? -1 : min;
}
--
2.11.0

View File

@ -0,0 +1,40 @@
From 3a44891b4f5f206363492fc3ff91e8a97a70857d Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 8 Mar 2017 17:52:10 +0800
Subject: user32: For an owner-drawn listbox without strings WM_MEASUREITEM
still needs correct itemData.
---
dlls/user32/listbox.c | 2 +-
dlls/user32/tests/msg.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index 5eb266b15a..4572b81bf3 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -1566,7 +1566,7 @@ static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index,
mis.CtlType = ODT_LISTBOX;
mis.CtlID = id;
mis.itemID = index;
- mis.itemData = (ULONG_PTR)str;
+ mis.itemData = str ? (ULONG_PTR)str : data;
mis.itemHeight = descr->item_height;
TRACE("owner=%p CtlID=%08x, itemID=%08x, itemData=%08lx\n",
descr->owner, mis.CtlID, mis.itemID, mis.itemData);
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index f806e5366e..34385bd266 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -14651,7 +14651,7 @@ static void test_listbox_messages(void)
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
ok(ret == 2, "expected 2, got %ld\n", ret);
- ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", TRUE);
+ ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", FALSE);
check_lb_state(listbox, 3, LB_ERR, 0, 0);
log_all_parent_messages--;
--
2.11.0

View File

@ -0,0 +1,2 @@
Fixes: [42602] Multiple fixes for owner-drawn and sorted listbox
Depends: user32-WM_MEASUREITEM