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