Improved header control performance by maintaining an internal order
array.
diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index ab3ebce..5ef8447 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -87,6 +87,7 @@
HIMAGELIST himl; /* handle to an image list (may be 0) */
HEADER_ITEM *items; /* pointer to array of HEADER_ITEM's */
+ INT *order; /* array of item IDs indexed by order */
BOOL bRectsValid; /* validity flag for bounding rectangles */
} HEADER_INFO;
@@ -113,14 +114,10 @@
{
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
INT iorder = (INT)wParam;
- UINT i;
- if ((iorder <0) || iorder >infoPtr->uNumItem)
+ if ((iorder <0) || iorder >= infoPtr->uNumItem)
return iorder;
- for (i=0; i<infoPtr->uNumItem; i++)
- if (HEADER_IndexToOrder(hwnd,i) == iorder)
- return i;
- return iorder;
+ return infoPtr->order[iorder];
}
static void
@@ -647,16 +644,19 @@
if (infoPtr->items[0].pszText)
Free (infoPtr->items[0].pszText);
Free (infoPtr->items);
+ Free(infoPtr->order);
infoPtr->items = 0;
+ infoPtr->order = 0;
infoPtr->uNumItem = 0;
}
else {
HEADER_ITEM *oldItems = infoPtr->items;
- HEADER_ITEM *pItem;
INT i;
INT iOrder;
TRACE("Complex delete! [iItem=%d]\n", iItem);
+ for (i = 0; i < infoPtr->uNumItem; i++)
+ TRACE("%d: order=%d, iOrder=%d, ->iOrder=%d\n", i, infoPtr->order[i], infoPtr->items[i].iOrder, infoPtr->items[infoPtr->order[i]].iOrder);
if (infoPtr->items[iItem].pszText)
Free (infoPtr->items[iItem].pszText);
iOrder = infoPtr->items[iItem].iOrder;
@@ -676,11 +676,21 @@
}
/* Correct the orders */
- for (i=infoPtr->uNumItem, pItem = infoPtr->items; i; i--, pItem++)
+ if (iOrder < infoPtr->uNumItem)
{
- if (pItem->iOrder > iOrder)
- pItem->iOrder--;
+ memmove(&infoPtr->order[iOrder], &infoPtr->order[iOrder + 1],
+ (infoPtr->uNumItem - iOrder) * sizeof(INT));
+ for (i = 0; i < infoPtr->uNumItem; i++)
+ {
+ if (infoPtr->order[i] > iItem)
+ infoPtr->order[i]--;
+ if (i >= iOrder)
+ infoPtr->items[infoPtr->order[i]].iOrder = infoPtr->order[i];
+ }
}
+
+ for (i = 0; i < infoPtr->uNumItem; i++)
+ TRACE("%d: order=%d, iOrder=%d, ->iOrder=%d\n", i, infoPtr->order[i], infoPtr->items[i].iOrder, infoPtr->items[infoPtr->order[i]].iOrder);
Free (oldItems);
}
@@ -850,14 +860,13 @@
static LRESULT
HEADER_GetOrderArray(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
- int i;
LPINT order = (LPINT) lParam;
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
if ((unsigned int)wParam <infoPtr->uNumItem)
return FALSE;
- for (i=0; i<(int)wParam; i++)
- *order++=HEADER_OrderToIndex(hwnd,i);
+
+ memcpy(order, infoPtr->order, infoPtr->uNumItem * sizeof(INT));
return TRUE;
}
@@ -871,6 +880,7 @@
if ((unsigned int)wParam <infoPtr->uNumItem)
return FALSE;
+ memcpy(infoPtr->order, order, infoPtr->uNumItem * sizeof(INT));
for (i=0; i<(int)wParam; i++)
{
lpItem = &infoPtr->items[*order++];
@@ -923,10 +933,12 @@
if (infoPtr->uNumItem == 0) {
infoPtr->items = Alloc (sizeof (HEADER_ITEM));
+ infoPtr->order = Alloc(sizeof(INT));
infoPtr->uNumItem++;
}
else {
HEADER_ITEM *oldItems = infoPtr->items;
+ INT *oldOrder = infoPtr->order;
infoPtr->uNumItem++;
infoPtr->items = Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
@@ -949,13 +961,21 @@
}
}
+ infoPtr->order = Alloc(sizeof(INT) * infoPtr->uNumItem);
+ memcpy(infoPtr->order, oldOrder, iOrder * sizeof(INT));
+ infoPtr->order[iOrder] = nItem;
+ memcpy(&infoPtr->order[iOrder + 1], &oldOrder[iOrder],
+ (infoPtr->uNumItem - iOrder - 1) * sizeof(INT));
+
Free (oldItems);
+ Free(oldOrder);
}
- for (i=0; i < infoPtr->uNumItem; i++)
+ for (i = 0; i < infoPtr->uNumItem; i++)
{
- if (infoPtr->items[i].iOrder >= iOrder)
- infoPtr->items[i].iOrder++;
+ if (i != iOrder && infoPtr->order[i] >= nItem)
+ infoPtr->order[i]++;
+ infoPtr->items[infoPtr->order[i]].iOrder = infoPtr->order[i];
}
lpItem = &infoPtr->items[nItem];
@@ -1025,10 +1045,12 @@
if (infoPtr->uNumItem == 0) {
infoPtr->items = Alloc (sizeof (HEADER_ITEM));
+ infoPtr->order = Alloc(sizeof(INT));
infoPtr->uNumItem++;
}
else {
HEADER_ITEM *oldItems = infoPtr->items;
+ INT *oldOrder = infoPtr->order;
infoPtr->uNumItem++;
infoPtr->items = Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
@@ -1051,13 +1073,21 @@
}
}
+ infoPtr->order = Alloc(infoPtr->uNumItem * sizeof(INT));
+ memcpy(infoPtr->order, oldOrder, iOrder * sizeof(INT));
+ infoPtr->order[iOrder] = nItem;
+ memcpy(&infoPtr->order[iOrder + 1], &oldOrder[iOrder],
+ (infoPtr->uNumItem - iOrder - 1) * sizeof(INT));
+
Free (oldItems);
+ Free(oldOrder);
}
- for (i=0; i < infoPtr->uNumItem; i++)
+ for (i = 0; i < infoPtr->uNumItem; i++)
{
- if (infoPtr->items[i].iOrder >= iOrder)
- infoPtr->items[i].iOrder++;
+ if (i != iOrder && infoPtr->order[i] >= nItem)
+ infoPtr->order[i]++;
+ infoPtr->items[infoPtr->order[i]].iOrder = infoPtr->order[i];
}
lpItem = &infoPtr->items[nItem];
@@ -1224,7 +1254,27 @@
if (phdi->mask & HDI_ORDER)
{
- lpItem->iOrder = phdi->iOrder;
+ INT i, nMin, nMax;
+
+ if (lpItem->iOrder < phdi->iOrder)
+ {
+ memmove(&infoPtr->order[lpItem->iOrder],
+ &infoPtr->order[lpItem->iOrder + 1],
+ (phdi->iOrder - lpItem->iOrder) * sizeof(INT));
+ }
+ if (phdi->iOrder < lpItem->iOrder)
+ {
+ memmove(&infoPtr->order[phdi->iOrder + 1],
+ &infoPtr->order[phdi->iOrder],
+ (lpItem->iOrder - phdi->iOrder) * sizeof(INT));
+ }
+ infoPtr->order[phdi->iOrder] = nItem;
+ nMin = min(lpItem->iOrder, phdi->iOrder);
+ nMax = max(lpItem->iOrder, phdi->iOrder);
+ for (i = nMin; i <= nMax; i++)
+ {
+ infoPtr->items[infoPtr->order[i]].iOrder = infoPtr->order[i];
+ }
}
HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, nItem, phdi->mask);
@@ -1289,7 +1339,27 @@
if (phdi->mask & HDI_ORDER)
{
- lpItem->iOrder = phdi->iOrder;
+ INT i, nMin, nMax;
+
+ if (lpItem->iOrder < phdi->iOrder)
+ {
+ memmove(&infoPtr->order[lpItem->iOrder],
+ &infoPtr->order[lpItem->iOrder + 1],
+ (phdi->iOrder - lpItem->iOrder) * sizeof(INT));
+ }
+ if (phdi->iOrder < lpItem->iOrder)
+ {
+ memmove(&infoPtr->order[phdi->iOrder + 1],
+ &infoPtr->order[phdi->iOrder],
+ (lpItem->iOrder - phdi->iOrder) * sizeof(INT));
+ }
+ infoPtr->order[phdi->iOrder] = nItem;
+ nMin = min(lpItem->iOrder, phdi->iOrder);
+ nMax = max(lpItem->iOrder, phdi->iOrder);
+ for (i = nMin; i <= nMax; i++)
+ {
+ infoPtr->items[infoPtr->order[i]].iOrder = infoPtr->order[i];
+ }
}
HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGEDW, nItem, phdi->mask);
@@ -1328,6 +1398,7 @@
infoPtr->uNumItem = 0;
infoPtr->hFont = 0;
infoPtr->items = 0;
+ infoPtr->order = 0;
infoPtr->bRectsValid = FALSE;
infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
infoPtr->hcurDivider = LoadCursorW (COMCTL32_hModule, MAKEINTRESOURCEW(IDC_DIVIDER));
@@ -1372,6 +1443,9 @@
Free (infoPtr->items);
}
+ if (infoPtr->order)
+ Free(infoPtr->order);
+
if (infoPtr->himl)
ImageList_Destroy (infoPtr->himl);
@@ -1505,6 +1579,9 @@
lpItem= &infoPtr->items[infoPtr->iMoveItem];
lpItem->iOrder = newindex;
+ infoPtr->order[oldindex] = nItem;
+ infoPtr->order[newindex] = infoPtr->iMoveItem;
+
infoPtr->bRectsValid = FALSE;
InvalidateRect(hwnd, NULL, FALSE);
/* FIXME: Should some WM_NOTIFY be sent */