comctl32/header: Process input order array more accurately.
This commit is contained in:
parent
76859b0f47
commit
5517209a24
|
@ -1214,18 +1214,62 @@ HEADER_GetOrderArray(const HEADER_INFO *infoPtr, INT size, LPINT order)
|
||||||
return TRUE;
|
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
|
static LRESULT
|
||||||
HEADER_SetOrderArray(HEADER_INFO *infoPtr, INT size, const INT *order)
|
HEADER_SetOrderArray(HEADER_INFO *infoPtr, INT size, const INT *order)
|
||||||
{
|
{
|
||||||
INT i;
|
|
||||||
HEADER_ITEM *lpItem;
|
HEADER_ITEM *lpItem;
|
||||||
|
INT i;
|
||||||
|
|
||||||
if ((UINT)size <infoPtr->uNumItem)
|
if ((UINT)size != infoPtr->uNumItem)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
memcpy(infoPtr->order, order, infoPtr->uNumItem * sizeof(INT));
|
|
||||||
for (i=0; i<size; i++)
|
for (i=0; i<size; i++)
|
||||||
{
|
{
|
||||||
lpItem = &infoPtr->items[*order++];
|
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[infoPtr->order[i]];
|
||||||
lpItem->iOrder = i;
|
lpItem->iOrder = i;
|
||||||
}
|
}
|
||||||
HEADER_SetItemBounds(infoPtr);
|
HEADER_SetItemBounds(infoPtr);
|
||||||
|
|
|
@ -1689,6 +1689,126 @@ static int init(void)
|
||||||
return 1;
|
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)
|
START_TEST(header)
|
||||||
{
|
{
|
||||||
HWND parent_hwnd;
|
HWND parent_hwnd;
|
||||||
|
@ -1700,6 +1820,7 @@ START_TEST(header)
|
||||||
|
|
||||||
test_header_control();
|
test_header_control();
|
||||||
test_header_order();
|
test_header_order();
|
||||||
|
test_hdm_orderarray();
|
||||||
test_customdraw();
|
test_customdraw();
|
||||||
|
|
||||||
DestroyWindow(hHeaderParentWnd);
|
DestroyWindow(hHeaderParentWnd);
|
||||||
|
|
Loading…
Reference in New Issue