Listview S8
Dimitrie O. Paun
dpaun at rogers.com
Thu Oct 17 10:55:39 CDT 2002
This one unifies setting of item attributes between
LVS_OWNERDATA, and normal. It also fixes a few
potential bugs lurking in there.
I don't have a OWNERDATA testcase, so testing from
people with such beast is needed. Both positive, and
negative feedback is appreciated.
ChangeLog
Unify set_{owner,main}_item functions
Fix {old,new}state and lParam reporting in LVN_ITEMCHANG{ING,ED}
Fix sanity check conditions for LVS_OWNERDATA.
--- dlls/comctl32/listview.c.S7 Thu Oct 17 10:57:24 2002
+++ dlls/comctl32/listview.c Thu Oct 17 11:50:37 2002
@@ -2868,6 +2868,7 @@
return TRUE;
}
+
/***
* DESCRIPTION:
* Helper for LISTVIEW_SetItemT *only*: sets item attributes.
@@ -2882,101 +2883,39 @@
* SUCCESS : TRUE
* FAILURE : FALSE
*/
-static BOOL set_owner_item(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW, BOOL *bChanged)
+static BOOL set_main_item(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW, BOOL *bChanged)
{
- LONG lStyle = infoPtr->dwStyle;
+ LISTVIEW_ITEM *lpItem;
NMLISTVIEW nmlv;
- INT oldState;
+ UINT uChanged = 0;
+ LVITEMW item;
TRACE("()\n");
- /* a virtual listview stores only the state for the main item */
- if (lpLVItem->iSubItem || !(lpLVItem->mask & LVIF_STATE)) return FALSE;
-
- oldState = (LVIS_FOCUSED | LVIS_SELECTED) & ~infoPtr->uCallbackMask;
- if (oldState) oldState = LISTVIEW_GetItemState(infoPtr, lpLVItem->iItem, oldState);
- TRACE("oldState=%x, newState=%x\n", oldState, lpLVItem->state);
-
- /* we're done if we don't need to change anything we handle */
- if ( !((oldState ^ lpLVItem->state) & lpLVItem->stateMask &
- ~infoPtr->uCallbackMask & (LVIS_FOCUSED | LVIS_SELECTED))) return TRUE;
-
- *bChanged = TRUE;
-
- /*
- * As per MSDN LVN_ITEMCHANGING notifications are _NOT_ sent for
- * by LVS_OWERNDATA list controls
- */
-
- /* if we handle the focus, and we're asked to change it, do it now */
- if ( lpLVItem->stateMask & LVIS_FOCUSED )
+ if (infoPtr->dwStyle & LVS_OWNERDATA)
{
- if (lpLVItem->state & LVIS_FOCUSED)
- infoPtr->nFocusedItem = lpLVItem->iItem;
- else if (infoPtr->nFocusedItem == lpLVItem->iItem)
- infoPtr->nFocusedItem = -1;
+ /* a virtual listview we stores only selection and focus */
+ if ((lpLVItem->mask & ~LVIF_STATE) || (lpLVItem->stateMask & ~(LVIS_FOCUSED | LVIS_SELECTED)))
+ return FALSE;
+ lpItem = NULL;
}
-
- /* and the selection is the only other state a virtual list may hold */
- if (lpLVItem->stateMask & LVIS_SELECTED)
+ else
{
- if (lpLVItem->state & LVIS_SELECTED)
- {
- if (lStyle & LVS_SINGLESEL) LISTVIEW_DeselectAllSkipItem(infoPtr, lpLVItem->iItem);
- ranges_additem(infoPtr->selectionRanges, lpLVItem->iItem);
- }
- else
- ranges_delitem(infoPtr->selectionRanges, lpLVItem->iItem);
+ HDPA hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
+ if (!hdpaSubItems) return FALSE;
+ if (!(lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0))) return FALSE;
}
- /* notify the parent now that things have changed */
- ZeroMemory(&nmlv, sizeof(nmlv));
- nmlv.iItem = lpLVItem->iItem;
- nmlv.uNewState = lpLVItem->state;
- nmlv.uOldState = oldState;
- nmlv.uChanged = LVIF_STATE;
- notify_listview(infoPtr, LVN_ITEMCHANGED, &nmlv);
-
- return TRUE;
-}
-
-/***
- * DESCRIPTION:
- * Helper for LISTVIEW_SetItemT *only*: sets item attributes.
- *
- * PARAMETER(S):
- * [I] infoPtr : valid pointer to the listview structure
- * [I] lpLVItem : valid pointer to new item atttributes
- * [I] isW : TRUE if lpLVItem is Unicode, FALSE if it's ANSI
- * [O] bChanged : will be set to TRUE if the item really changed
- *
- * RETURN:
- * SUCCESS : TRUE
- * FAILURE : FALSE
- */
-static BOOL set_main_item(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW, BOOL *bChanged)
-{
- LONG lStyle = infoPtr->dwStyle;
- HDPA hdpaSubItems;
- LISTVIEW_ITEM *lpItem;
- NMLISTVIEW nmlv;
- UINT uChanged = 0, oldState;
-
- TRACE("()\n");
-
- hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
- if (!hdpaSubItems && hdpaSubItems != (HDPA)-1) return FALSE;
-
- lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
- if (!lpItem) return FALSE;
-
/* we need to handle the focus, and selection differently */
- oldState = (LVIS_FOCUSED | LVIS_SELECTED) & ~infoPtr->uCallbackMask;
- if (oldState) oldState = LISTVIEW_GetItemState(infoPtr, lpLVItem->iItem, oldState);
+ item.iItem = lpLVItem->iItem;
+ item.iSubItem = lpLVItem->iSubItem;
+ item.mask = LVIF_STATE | LVIF_PARAM;
+ item.stateMask = ~0;
+ if (!LISTVIEW_GetItemT(infoPtr, &item, TRUE)) return FALSE;
- TRACE("oldState=%x, newState=%x\n", oldState, lpLVItem->state);
+ TRACE("oldState=%x, newState=%x\n", item.state, lpLVItem->state);
/* determine what fields will change */
- if ((lpLVItem->mask & LVIF_STATE) && ((oldState ^ lpLVItem->state) & lpLVItem->stateMask & ~infoPtr->uCallbackMask))
+ if ((lpLVItem->mask & LVIF_STATE) && ((item.state ^ lpLVItem->state) & lpLVItem->stateMask & ~infoPtr->uCallbackMask))
uChanged |= LVIF_STATE;
if ((lpLVItem->mask & LVIF_IMAGE) && (lpItem->hdr.iImage != lpLVItem->iImage))
@@ -2997,13 +2936,14 @@
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
nmlv.iItem = lpLVItem->iItem;
- nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask;
- nmlv.uOldState = lpItem->state & lpLVItem->stateMask;
+ nmlv.uNewState = (item.state & ~lpLVItem->stateMask) | (lpLVItem->state & lpLVItem->stateMask);
+ nmlv.uOldState = item.state;
nmlv.uChanged = uChanged;
- nmlv.lParam = lpItem->lParam;
+ nmlv.lParam = item.lParam;
/* send LVN_ITEMCHANGING notification, if the item is not being inserted */
- if(lpItem->valid && notify_listview(infoPtr, LVN_ITEMCHANGING, &nmlv))
+ /* and we are _NOT_ virtual (LVS_OWERNDATA) */
+ if(lpItem && lpItem->valid && notify_listview(infoPtr, LVN_ITEMCHANGING, &nmlv))
return FALSE;
/* copy information */
@@ -3021,11 +2961,14 @@
if (uChanged & LVIF_STATE)
{
- lpItem->state &= ~lpLVItem->stateMask;
- lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
+ if (lpLVItem->stateMask & ~infoPtr->uCallbackMask & ~(LVIS_FOCUSED | LVIS_SELECTED))
+ {
+ lpItem->state &= ~lpLVItem->stateMask;
+ lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
+ }
if (lpLVItem->state & lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED)
{
- if (lStyle & LVS_SINGLESEL) LISTVIEW_DeselectAllSkipItem(infoPtr, lpLVItem->iItem);
+ if (infoPtr->dwStyle & LVS_SINGLESEL) LISTVIEW_DeselectAllSkipItem(infoPtr, lpLVItem->iItem);
ranges_additem(infoPtr->selectionRanges, lpLVItem->iItem);
}
else if (lpLVItem->stateMask & LVIS_SELECTED)
@@ -3045,10 +2988,10 @@
}
/* if we're inserting the item, we're done */
- if (!lpItem->valid) return TRUE;
+ if (lpItem && !lpItem->valid) return TRUE;
/* send LVN_ITEMCHANGED notification */
- nmlv.lParam = lpItem->lParam;
+ if (lpLVItem->mask & LVIF_PARAM) nmlv.lParam = lpLVItem->lParam;
notify_listview(infoPtr, LVN_ITEMCHANGED, &nmlv);
return TRUE;
@@ -3073,6 +3016,9 @@
HDPA hdpaSubItems;
LISTVIEW_SUBITEM *lpSubItem;
+ /* we do not support subitems for virtual listviews */
+ if (infoPtr->dwStyle & LVS_OWNERDATA) return FALSE;
+
/* set subitem only if column is present */
if (Header_GetItemCount(infoPtr->hwndHeader) <= lpLVItem->iSubItem)
return FALSE;
@@ -3149,7 +3095,9 @@
if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iItem >= infoPtr->nItemCount)
return FALSE;
-
+
+ if (lpLVItem->mask == 0) return TRUE;
+
/* For efficiency, we transform the lpLVItem->pszText to Unicode here */
if ((lpLVItem->mask & LVIF_TEXT) && is_textW(lpLVItem->pszText))
{
@@ -3158,18 +3106,12 @@
}
/* actually set the fields */
- if (infoPtr->dwStyle & LVS_OWNERDATA)
- bResult = set_owner_item(infoPtr, lpLVItem, TRUE, &bChanged);
- else
- {
- /* sanity checks first */
- if (!is_assignable_item(lpLVItem, infoPtr->dwStyle)) return FALSE;
+ if (!is_assignable_item(lpLVItem, infoPtr->dwStyle)) return FALSE;
- if (lpLVItem->iSubItem)
- bResult = set_sub_item(infoPtr, lpLVItem, TRUE, &bChanged);
- else
- bResult = set_main_item(infoPtr, lpLVItem, TRUE, &bChanged);
- }
+ if (lpLVItem->iSubItem)
+ bResult = set_sub_item(infoPtr, lpLVItem, TRUE, &bChanged);
+ else
+ bResult = set_main_item(infoPtr, lpLVItem, TRUE, &bChanged);
/* redraw item, if necessary */
if (bChanged && !infoPtr->bIsDrawing)
More information about the wine-patches
mailing list