Improved header control performance by maintaining an internal order

array.
This commit is contained in:
Phil Krylov 2005-08-29 12:17:42 +00:00 committed by Alexandre Julliard
parent c486949985
commit 682dd707c8
1 changed files with 98 additions and 21 deletions

View File

@ -87,6 +87,7 @@ typedef struct
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_OrderToIndex(HWND hwnd, WPARAM wParam)
{
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 @@ HEADER_DeleteItem (HWND hwnd, WPARAM wParam)
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 @@ HEADER_DeleteItem (HWND hwnd, WPARAM wParam)
}
/* 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 @@ HEADER_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_SetOrderArray(HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
}
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 @@ HEADER_InsertItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_InsertItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
}
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 @@ HEADER_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_SetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 @@ HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
Free (infoPtr->items);
}
if (infoPtr->order)
Free(infoPtr->order);
if (infoPtr->himl)
ImageList_Destroy (infoPtr->himl);
@ -1505,6 +1579,9 @@ HEADER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
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 */