comctl32/listview: State mask should be ignored on LVM_INSERTITEM

Nikolay Sivov bunglehead at gmail.com
Thu Apr 9 16:31:30 CDT 2009


http://bugs.winehq.org/show_bug.cgi?id=17564

7-zip Filemanager uses this to add selected item to list:
---
        item.mask |= LVIF_STATE;
        item.state = LVIS_SELECTED;
        item.stateMask = 0; /* during memset() initialisation */
---

Changelog:
    - State mask should be ignored on LVM_INSERTITEM

>From d14793b0920d1950445227ff1d14efa45f3882db Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Thu, 9 Apr 2009 17:23:01 -0400
Subject: State mask should be ignored on LVM_INSERTITEM

---
 dlls/comctl32/listview.c       |   18 ++++++-----
 dlls/comctl32/tests/listview.c |   66 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index f06095b..e571f33 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -3478,6 +3478,8 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
     NMLISTVIEW nmlv;
     UINT uChanged = 0;
     LVITEMW item;
+    /* stateMask is ignored for LVM_INSERTITEM */
+    UINT stateMask = isNew ? ~0 : lpLVItem->stateMask;
 
     TRACE("()\n");
 
@@ -3510,7 +3512,7 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
 
     TRACE("oldState=%x, newState=%x\n", item.state, lpLVItem->state);
     /* determine what fields will change */    
-    if ((lpLVItem->mask & LVIF_STATE) && ((item.state ^ lpLVItem->state) & lpLVItem->stateMask & ~infoPtr->uCallbackMask))
+    if ((lpLVItem->mask & LVIF_STATE) && ((item.state ^ lpLVItem->state) & stateMask & ~infoPtr->uCallbackMask))
 	uChanged |= LVIF_STATE;
 
     if ((lpLVItem->mask & LVIF_IMAGE) && (lpItem->hdr.iImage != lpLVItem->iImage))
@@ -3531,7 +3533,7 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
     
     ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
     nmlv.iItem = lpLVItem->iItem;
-    nmlv.uNewState = (item.state & ~lpLVItem->stateMask) | (lpLVItem->state & lpLVItem->stateMask);
+    nmlv.uNewState = (item.state & ~stateMask) | (lpLVItem->state & stateMask);
     nmlv.uOldState = item.state;
     nmlv.uChanged = uChanged;
     nmlv.lParam = item.lParam;
@@ -3564,21 +3566,21 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
 
     if (uChanged & LVIF_STATE)
     {
-	if (lpItem && (lpLVItem->stateMask & ~infoPtr->uCallbackMask & ~(LVIS_FOCUSED | LVIS_SELECTED)))
+	if (lpItem && (stateMask & ~infoPtr->uCallbackMask & ~(LVIS_FOCUSED | LVIS_SELECTED)))
 	{
-	    lpItem->state &= ~lpLVItem->stateMask;
-	    lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
+	    lpItem->state &= ~stateMask;
+	    lpItem->state |= (lpLVItem->state & stateMask);
 	}
-	if (lpLVItem->state & lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED)
+	if (lpLVItem->state & stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED)
 	{
 	    if (infoPtr->dwStyle & LVS_SINGLESEL) LISTVIEW_DeselectAllSkipItem(infoPtr, lpLVItem->iItem);
 	    ranges_additem(infoPtr->selectionRanges, lpLVItem->iItem);
 	}
-	else if (lpLVItem->stateMask & LVIS_SELECTED)
+	else if (stateMask & LVIS_SELECTED)
 	    ranges_delitem(infoPtr->selectionRanges, lpLVItem->iItem);
 	
 	/* if we are asked to change focus, and we manage it, do it */
-	if (lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED)
+	if (stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED)
 	{
 	    if (lpLVItem->state & LVIS_FOCUSED)
 	    {
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index 6f3524b..914be42 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -634,6 +634,72 @@ static void test_items(void)
     insert_column(hwnd, 0);
     insert_column(hwnd, 1);
 
+    /* LVIS_SELECTED with zero stateMask */
+    /* set */
+    memset (&item, 0, sizeof (item));
+    item.mask = LVIF_STATE;
+    item.state = LVIS_SELECTED;
+    item.stateMask = 0;
+    item.iItem = 0;
+    item.iSubItem = 0;
+    r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
+    ok(r == 0, "ret %d\n", r);
+    /* get */
+    memset (&item, 0xcc, sizeof (item));
+    item.mask = LVIF_STATE;
+    item.stateMask = LVIS_SELECTED;
+    item.state = 0;
+    item.iItem = 0;
+    item.iSubItem = 0;
+    r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+    ok(r != 0, "ret %d\n", r);
+    ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
+    SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
+
+    /* LVIS_SELECTED with zero stateMask */
+    /* set */
+    memset (&item, 0, sizeof (item));
+    item.mask = LVIF_STATE;
+    item.state = LVIS_FOCUSED;
+    item.stateMask = 0;
+    item.iItem = 0;
+    item.iSubItem = 0;
+    r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
+    ok(r == 0, "ret %d\n", r);
+    /* get */
+    memset (&item, 0xcc, sizeof (item));
+    item.mask = LVIF_STATE;
+    item.stateMask = LVIS_FOCUSED;
+    item.state = 0;
+    item.iItem = 0;
+    item.iSubItem = 0;
+    r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+    ok(r != 0, "ret %d\n", r);
+    ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
+    SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
+
+    /* LVIS_CUT with LVIS_FOCUSED stateMask */
+    /* set */
+    memset (&item, 0, sizeof (item));
+    item.mask = LVIF_STATE;
+    item.state = LVIS_CUT;
+    item.stateMask = LVIS_FOCUSED;
+    item.iItem = 0;
+    item.iSubItem = 0;
+    r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
+    ok(r == 0, "ret %d\n", r);
+    /* get */
+    memset (&item, 0xcc, sizeof (item));
+    item.mask = LVIF_STATE;
+    item.stateMask = LVIS_CUT;
+    item.state = 0;
+    item.iItem = 0;
+    item.iSubItem = 0;
+    r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+    ok(r != 0, "ret %d\n", r);
+    ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
+    SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
+
     /* Insert an item with just a param */
     memset (&item, 0xcc, sizeof (item));
     item.mask = LVIF_PARAM;
-- 
1.5.6.5





More information about the wine-patches mailing list