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