[2/3] comctl32/listview: Handle LVIF_NORECOMPUTE in LVM_GETITEM[A,W]

Nikolay Sivov bunglehead at gmail.com
Tue Apr 28 14:34:00 CDT 2009


Changelog:
    - Handle LVIF_NORECOMPUTE in LVM_GETITEM[A,W]

>From 0ecaf2cafb3ae5f1191c2381403114ae18e0f894 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Tue, 28 Apr 2009 22:26:38 +0400
Subject: Handle LVIF_NORECOMPUTE in LVM_GETITEM[A,W]

---
 dlls/comctl32/listview.c       |   69 ++++++++++++++++++++++++++-------------
 dlls/comctl32/tests/listview.c |    6 +--
 2 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index b6c6c2d..b225730 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -72,7 +72,6 @@
  * Flags
  *   -- LVIF_COLUMNS
  *   -- LVIF_GROUPID
- *   -- LVIF_NORECOMPUTE
  *
  * States
  *   -- LVIS_ACTIVATING (not currently supported by comctl32.dll version 6.0)
@@ -5558,6 +5557,8 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
 	/* apparently, we should not callback for lParam in LVS_OWNERDATA */
 	if ((lpLVItem->mask & ~(LVIF_STATE | LVIF_PARAM)) || infoPtr->uCallbackMask)
 	{
+	    UINT mask = lpLVItem->mask;
+
 	    /* NOTE: copy only fields which we _know_ are initialized, some apps
 	     *       depend on the uninitialized fields being 0 */
 	    dispInfo.item.mask = lpLVItem->mask & ~LVIF_PARAM;
@@ -5565,34 +5566,49 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
 	    dispInfo.item.iSubItem = isubitem;
 	    if (lpLVItem->mask & LVIF_TEXT)
 	    {
-		dispInfo.item.pszText = lpLVItem->pszText;
-		dispInfo.item.cchTextMax = lpLVItem->cchTextMax;		
+		if (lpLVItem->mask & LVIF_NORECOMPUTE)
+		    /* reset mask */
+		    dispInfo.item.mask &= ~(LVIF_TEXT | LVIF_NORECOMPUTE);
+		else
+		{
+		    dispInfo.item.pszText = lpLVItem->pszText;
+		    dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
+		}
 	    }
 	    if (lpLVItem->mask & LVIF_STATE)
 	        dispInfo.item.stateMask = lpLVItem->stateMask & infoPtr->uCallbackMask;
-	    notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
-	    dispInfo.item.stateMask = lpLVItem->stateMask;
-	    if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS))
+	    /* could be zeroed on LVIF_NORECOMPUTE case */
+	    if (dispInfo.item.mask != 0)
 	    {
-	        /* full size structure expected - _WIN32IE >= 0x560 */
-	        *lpLVItem = dispInfo.item;
+	        notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
+	        dispInfo.item.stateMask = lpLVItem->stateMask;
+	        if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS))
+	        {
+	            /* full size structure expected - _WIN32IE >= 0x560 */
+	            *lpLVItem = dispInfo.item;
+	        }
+	        else if (lpLVItem->mask & LVIF_INDENT)
+	        {
+	            /* indent member expected - _WIN32IE >= 0x300 */
+	            memcpy(lpLVItem, &dispInfo.item, offsetof( LVITEMW, iGroupId ));
+	        }
+	        else
+	        {
+	            /* minimal structure expected */
+	            memcpy(lpLVItem, &dispInfo.item, offsetof( LVITEMW, iIndent ));
+	        }
+	        lpLVItem->mask = mask;
+	        TRACE("   getdispinfo(1):lpLVItem=%s\n", debuglvitem_t(lpLVItem, isW));
 	    }
-	    else if (lpLVItem->mask & LVIF_INDENT)
-	    {
-	        /* indent member expected - _WIN32IE >= 0x300 */
-	        memcpy(lpLVItem, &dispInfo.item, offsetof( LVITEMW, iGroupId ));
-	    }
-	    else
-	    {
-	        /* minimal structure expected */
-	        memcpy(lpLVItem, &dispInfo.item, offsetof( LVITEMW, iIndent ));
-	    }
-	    TRACE("   getdispinfo(1):lpLVItem=%s\n", debuglvitem_t(lpLVItem, isW));
 	}
 	
 	/* make sure lParam is zeroed out */
 	if (lpLVItem->mask & LVIF_PARAM) lpLVItem->lParam = 0;
-	
+
+	/* callback marked pointer required here */
+	if ((lpLVItem->mask & LVIF_TEXT) && (lpLVItem->mask & LVIF_NORECOMPUTE))
+	    lpLVItem->pszText = LPSTR_TEXTCALLBACKW;
+
 	/* we store only a little state, so if we're not asked, we're done */
 	if (!(lpLVItem->mask & LVIF_STATE) || isubitem) return TRUE;
 
@@ -5649,7 +5665,8 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
     }
 
     /* Apps depend on calling back for text if it is NULL or LPSTR_TEXTCALLBACKW */
-    if ((lpLVItem->mask & LVIF_TEXT) && !is_textW(pItemHdr->pszText))
+    if ((lpLVItem->mask & LVIF_TEXT) && !(lpLVItem->mask & LVIF_NORECOMPUTE) &&
+        !is_textW(pItemHdr->pszText))
     {
 	dispInfo.item.mask |= LVIF_TEXT;
 	dispInfo.item.pszText = lpLVItem->pszText;
@@ -5696,7 +5713,8 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
     }
     else if (lpLVItem->mask & LVIF_TEXT)
     {
-	if (isW) lpLVItem->pszText = pItemHdr->pszText;
+	/* if LVN_GETDISPINFO's disabled with LVIF_NORECOMPUTE return callback placeholder */
+	if (isW || !is_textW(pItemHdr->pszText)) lpLVItem->pszText = pItemHdr->pszText;
 	else textcpynT(lpLVItem->pszText, isW, pItemHdr->pszText, TRUE, lpLVItem->cchTextMax);
     }
 
@@ -5772,7 +5790,12 @@ static BOOL LISTVIEW_GetItemExtT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVIte
     pszText = lpLVItem->pszText;
     bResult = LISTVIEW_GetItemT(infoPtr, lpLVItem, isW);
     if (bResult && lpLVItem->pszText != pszText)
-	textcpynT(pszText, isW, lpLVItem->pszText, isW, lpLVItem->cchTextMax);
+    {
+	if (lpLVItem->pszText != LPSTR_TEXTCALLBACKW)
+	    textcpynT(pszText, isW, lpLVItem->pszText, isW, lpLVItem->cchTextMax);
+	else
+	    pszText = LPSTR_TEXTCALLBACKW;
+    }
     lpLVItem->pszText = pszText;
 
     return bResult;
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index cde7a25..0ad3175 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -1881,10 +1881,9 @@ static void test_norecompute(void)
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
     expect(TRUE, res);
-todo_wine
     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
-    ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", TRUE);
+    ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
 
     DestroyWindow(hwnd);
 
@@ -1906,10 +1905,9 @@ todo_wine
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
     expect(TRUE, res);
-todo_wine
     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
-    ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", TRUE);
+    ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
 
     DestroyWindow(hwnd);
 }
-- 
1.5.6.5





More information about the wine-patches mailing list