Piotr Caban : comctl32: Improve LISTVIEW_MarqueeHighlight performance.
Alexandre Julliard
julliard at winehq.org
Tue Jun 7 12:02:34 CDT 2011
Module: wine
Branch: master
Commit: a87e726d6b2a7ec4b86cb01a3267237fb366427b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a87e726d6b2a7ec4b86cb01a3267237fb366427b
Author: Piotr Caban <piotr at codeweavers.com>
Date: Mon Jun 6 20:52:34 2011 +0200
comctl32: Improve LISTVIEW_MarqueeHighlight performance.
---
dlls/comctl32/listview.c | 74 +++++++++++++++++++++++++++++++++-------------
1 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 86c3f76..2f20f8e 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -1497,6 +1497,37 @@ static BOOL iterator_visibleitems(ITERATOR *i, const LISTVIEW_INFO *infoPtr, HDC
return TRUE;
}
+/* Remove common elements from two iterators */
+/* Passed iterators have to point on the first elements */
+static BOOL iterator_remove_common_items(ITERATOR *iter1, ITERATOR *iter2)
+{
+ iterator_next(iter1);
+ iterator_next(iter2);
+
+ while(1) {
+ if(iter1->nItem==-1 || iter2->nItem==-1)
+ break;
+
+ if(iter1->nItem == iter2->nItem) {
+ int delete = iter1->nItem;
+
+ iterator_prev(iter1);
+ iterator_prev(iter2);
+ ranges_delitem(iter1->ranges, delete);
+ ranges_delitem(iter2->ranges, delete);
+ iterator_next(iter1);
+ iterator_next(iter2);
+ } else if(iter1->nItem > iter2->nItem)
+ iterator_next(iter2);
+ else
+ iterator_next(iter1);
+ }
+
+ iter1->nItem = iter1->range.lower = iter1->range.upper = -1;
+ iter2->nItem = iter2->range.lower = iter2->range.upper = -1;
+ return TRUE;
+}
+
/******** Misc helper functions ************************************/
static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg,
@@ -3733,7 +3764,7 @@ static void LISTVIEW_MarqueeHighlight(LISTVIEW_INFO *infoPtr, const POINT *coord
{
BOOL controlDown = FALSE;
LVITEMW item;
- ITERATOR i;
+ ITERATOR old_elems, new_elems;
RECT rect;
if (coords_offs->x > infoPtr->marqueeOrigin.x)
@@ -3776,54 +3807,55 @@ static void LISTVIEW_MarqueeHighlight(LISTVIEW_INFO *infoPtr, const POINT *coord
if ((scroll & SCROLL_DOWN) && (coords_orig->y >= infoPtr->rcList.bottom))
LISTVIEW_Scroll(infoPtr, 0, (coords_orig->y - infoPtr->rcList.bottom));
- /* Invert the items in the old marquee rectangle */
- iterator_frameditems_absolute(&i, infoPtr, &infoPtr->marqueeRect);
+ iterator_frameditems_absolute(&old_elems, infoPtr, &infoPtr->marqueeRect);
+
+ CopyRect(&infoPtr->marqueeRect, &rect);
- while (iterator_next(&i))
+ CopyRect(&infoPtr->marqueeDrawRect, &rect);
+ OffsetRect(&infoPtr->marqueeDrawRect, offset->x, offset->y);
+
+ iterator_frameditems_absolute(&new_elems, infoPtr, &infoPtr->marqueeRect);
+ iterator_remove_common_items(&old_elems, &new_elems);
+
+ /* Iterate over no longer selected items */
+ while (iterator_next(&old_elems))
{
- if (i.nItem > -1)
+ if (old_elems.nItem > -1)
{
- if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED) == LVIS_SELECTED)
+ if (LISTVIEW_GetItemState(infoPtr, old_elems.nItem, LVIS_SELECTED) == LVIS_SELECTED)
item.state = 0;
else
item.state = LVIS_SELECTED;
item.stateMask = LVIS_SELECTED;
- LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
+ LISTVIEW_SetItemState(infoPtr, old_elems.nItem, &item);
}
}
+ iterator_destroy(&old_elems);
- iterator_destroy(&i);
-
- CopyRect(&infoPtr->marqueeRect, &rect);
-
- CopyRect(&infoPtr->marqueeDrawRect, &rect);
- OffsetRect(&infoPtr->marqueeDrawRect, offset->x, offset->y);
-
- /* Iterate over the items within our marquee rectangle */
- iterator_frameditems_absolute(&i, infoPtr, &infoPtr->marqueeRect);
+ /* Iterate over newly selected items */
if (GetKeyState(VK_CONTROL) & 0x8000)
controlDown = TRUE;
- while (iterator_next(&i))
+ while (iterator_next(&new_elems))
{
- if (i.nItem > -1)
+ if (new_elems.nItem > -1)
{
/* If CTRL is pressed, invert. If not, always select the item. */
- if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED)))
+ if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, new_elems.nItem, LVIS_SELECTED)))
item.state = 0;
else
item.state = LVIS_SELECTED;
item.stateMask = LVIS_SELECTED;
- LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
+ LISTVIEW_SetItemState(infoPtr, new_elems.nItem, &item);
}
}
+ iterator_destroy(&new_elems);
- iterator_destroy(&i);
LISTVIEW_InvalidateRect(infoPtr, &rect);
}
More information about the wine-cvs
mailing list