[PATCH 2/4] Process input order array more accurately
Nikolay Sivov
bunglehead at gmail.com
Sun Oct 18 06:21:00 CDT 2009
---
dlls/comctl32/header.c | 58 ++++++++++++++++++---
dlls/comctl32/tests/header.c | 121 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 172 insertions(+), 7 deletions(-)
diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index d84965c..dce1d8c 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -1214,20 +1214,64 @@ HEADER_GetOrderArray(const HEADER_INFO *infoPtr, INT size, LPINT order)
return TRUE;
}
+/* Returns index of first duplicate 'value' from [0,to) range,
+ or -1 if there isn't any */
+static INT has_duplicate(INT *array, INT to, INT value)
+{
+ INT i;
+ for(i = 0; i < to; i++)
+ if (array[i] == value) return i;
+ return -1;
+}
+
+/* returns next available value from [0,max] not to duplicate in [0,to) */
+static INT get_nextvalue(INT *array, INT to, INT max)
+{
+ INT i;
+ for(i = 0; i < max; i++)
+ if (has_duplicate(array, to, i) == -1) return i;
+ return 0;
+}
+
static LRESULT
HEADER_SetOrderArray(HEADER_INFO *infoPtr, INT size, const INT *order)
{
- INT i;
HEADER_ITEM *lpItem;
+ INT i;
- if ((UINT)size <infoPtr->uNumItem)
+ if ((UINT)size != infoPtr->uNumItem)
return FALSE;
- memcpy(infoPtr->order, order, infoPtr->uNumItem * sizeof(INT));
+
+ for (i=0; i<size; i++)
+ {
+ if (order[i] >= size || order[i] < 0)
+ /* on invalid index get next available */
+ /* FIXME: if i==0 array item is out of range behaviour is
+ different, see tests */
+ infoPtr->order[i] = get_nextvalue(infoPtr->order, i, size);
+ else
+ {
+ INT j, dup;
+
+ infoPtr->order[i] = order[i];
+ j = i;
+ /* remove duplicates */
+ while ((dup = has_duplicate(infoPtr->order, j, order[j])) != -1)
+ {
+ INT next;
+
+ next = get_nextvalue(infoPtr->order, j, size);
+ infoPtr->order[dup] = next;
+ j--;
+ }
+ }
+ }
+ /* sync with item data */
for (i=0; i<size; i++)
- {
- lpItem = &infoPtr->items[*order++];
- lpItem->iOrder=i;
- }
+ {
+ lpItem = &infoPtr->items[infoPtr->order[i]];
+ lpItem->iOrder = i;
+ }
HEADER_SetItemBounds(infoPtr);
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
diff --git a/dlls/comctl32/tests/header.c b/dlls/comctl32/tests/header.c
index 2fecaee..283c568 100644
--- a/dlls/comctl32/tests/header.c
+++ b/dlls/comctl32/tests/header.c
@@ -1689,6 +1689,126 @@ static int init(void)
return 1;
}
+/* maximum 8 items allowed */
+static void check_orderarray(HWND hwnd, DWORD start, DWORD set, DWORD expected,
+ int todo, int line)
+{
+ int count, i;
+ INT order[8];
+ DWORD ret, array = 0;
+
+ count = SendMessage(hwnd, HDM_GETITEMCOUNT, 0, 0);
+
+ /* initial order */
+ for(i = 1; i<=count; i++)
+ order[i-1] = start>>(4*(count-i)) & 0xf;
+
+ ret = SendMessage(hwnd, HDM_SETORDERARRAY, count, (LPARAM)order);
+ ok_(__FILE__, line)(ret, "Expected HDM_SETORDERARAY to succeed, got %d\n", ret);
+
+ /* new order */
+ for(i = 1; i<=count; i++)
+ order[i-1] = set>>(4*(count-i)) & 0xf;
+ ret = SendMessage(hwnd, HDM_SETORDERARRAY, count, (LPARAM)order);
+ ok_(__FILE__, line)(ret, "Expected HDM_SETORDERARAY to succeed, got %d\n", ret);
+
+ /* check actual order */
+ ret = SendMessage(hwnd, HDM_GETORDERARRAY, count, (LPARAM)order);
+ ok_(__FILE__, line)(ret, "Expected HDM_GETORDERARAY to succeed, got %d\n", ret);
+ for(i = 1; i<=count; i++)
+ array |= order[i-1]<<(4*(count-i));
+
+ if (todo) {
+ todo_wine
+ ok_(__FILE__, line)(array == expected, "Expected %x, got %x\n", expected, array);
+ }
+ else
+ ok_(__FILE__, line)(array == expected, "Expected %x, got %x\n", expected, array);
+}
+
+static void test_hdm_orderarray(void)
+{
+ HWND hwnd;
+ INT order[5];
+ DWORD ret;
+
+ hwnd = create_header_control();
+
+ /* three items */
+ addItem(hwnd, 0, NULL);
+ addItem(hwnd, 1, NULL);
+ addItem(hwnd, 2, NULL);
+
+ ret = SendMessage(hwnd, HDM_GETORDERARRAY, 3, (LPARAM)order);
+ if (!ret)
+ {
+ win_skip("HDM_GETORDERARRAY not implemented.\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ expect(0, order[0]);
+ expect(1, order[1]);
+ expect(2, order[2]);
+
+if (0)
+{
+ /* null pointer, crashes native */
+ ret = SendMessage(hwnd, HDM_SETORDERARRAY, 3, (LPARAM)NULL);
+ expect(FALSE, ret);
+}
+ /* count out of limits */
+ ret = SendMessage(hwnd, HDM_SETORDERARRAY, 5, (LPARAM)order);
+ expect(FALSE, ret);
+ /* count out of limits */
+ ret = SendMessage(hwnd, HDM_SETORDERARRAY, 2, (LPARAM)order);
+ expect(FALSE, ret);
+
+ /* try with out of range item index */
+ /* (0,1,2)->(1,0,3) => (1,0,2) */
+ check_orderarray(hwnd, 0x120, 0x103, 0x102, FALSE, __LINE__);
+ /* (1,0,2)->(3,0,1) => (0,2,1) */
+ check_orderarray(hwnd, 0x102, 0x301, 0x021, TRUE, __LINE__);
+ /* (0,2,1)->(2,3,1) => (2,0,1) */
+ check_orderarray(hwnd, 0x021, 0x231, 0x201, FALSE, __LINE__);
+
+ /* (0,1,2)->(0,2,2) => (0,1,2) */
+ check_orderarray(hwnd, 0x012, 0x022, 0x012, FALSE, __LINE__);
+
+ addItem(hwnd, 3, NULL);
+
+ /* (0,1,2,3)->(0,1,2,2) => (0,1,3,2) */
+ check_orderarray(hwnd, 0x0123, 0x0122, 0x0132, FALSE, __LINE__);
+ /* (0,1,2,3)->(0,1,3,3) => (0,1,2,3) */
+ check_orderarray(hwnd, 0x0123, 0x0133, 0x0123, FALSE, __LINE__);
+ /* (0,1,2,3)->(0,4,2,3) => (0,1,2,3) */
+ check_orderarray(hwnd, 0x0123, 0x0423, 0x0123, FALSE, __LINE__);
+ /* (0,1,2,3)->(4,0,1,2) => (0,1,3,2) */
+ check_orderarray(hwnd, 0x0123, 0x4012, 0x0132, TRUE, __LINE__);
+ /* (0,1,3,2)->(4,0,1,4) => (0,3,1,2) */
+ check_orderarray(hwnd, 0x0132, 0x4014, 0x0312, TRUE, __LINE__);
+ /* (0,1,2,3)->(4,1,0,2) => (1,0,3,2) */
+ check_orderarray(hwnd, 0x0123, 0x4102, 0x1032, TRUE, __LINE__);
+ /* (0,1,2,3)->(0,1,4,2) => (0,1,2,3) */
+ check_orderarray(hwnd, 0x0123, 0x0142, 0x0132, FALSE, __LINE__);
+ /* (0,1,2,3)->(4,4,4,4) => (0,1,2,3) */
+ check_orderarray(hwnd, 0x0123, 0x4444, 0x0123, FALSE, __LINE__);
+ /* (0,1,2,3)->(4,4,1,2) => (0,1,3,2) */
+ check_orderarray(hwnd, 0x0123, 0x4412, 0x0132, TRUE, __LINE__);
+ /* (0,1,2,3)->(4,4,4,1) => (0,2,3,1) */
+ check_orderarray(hwnd, 0x0123, 0x4441, 0x0231, TRUE, __LINE__);
+ /* (0,1,2,3)->(1,4,4,4) => (1,0,2,3) */
+ check_orderarray(hwnd, 0x0123, 0x1444, 0x1023, FALSE, __LINE__);
+ /* (0,1,2,3)->(4,2,4,1) => (0,2,3,1) */
+ check_orderarray(hwnd, 0x0123, 0x4241, 0x0231, FALSE, __LINE__);
+ /* (0,1,2,3)->(4,2,0,1) => (2,0,3,1) */
+ check_orderarray(hwnd, 0x0123, 0x4201, 0x2031, TRUE, __LINE__);
+ /* (3,2,1,0)->(4,2,0,1) => (3,2,0,1) */
+ check_orderarray(hwnd, 0x3210, 0x4201, 0x3201, FALSE, __LINE__);
+
+ DestroyWindow(hwnd);
+}
+
START_TEST(header)
{
HWND parent_hwnd;
@@ -1700,6 +1820,7 @@ START_TEST(header)
test_header_control();
test_header_order();
+ test_hdm_orderarray();
test_customdraw();
DestroyWindow(hHeaderParentWnd);
--
1.5.6.5
--=-0A+yxRmQ4EU+v7Q+ojl5--
More information about the wine-patches
mailing list