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

This commit is contained in:
Nikolay Sivov 2009-04-28 22:26:38 +04:00 committed by Alexandre Julliard
parent 43dcbdeb70
commit cd8b91f1bb
2 changed files with 48 additions and 27 deletions

View File

@ -72,7 +72,6 @@
* Flags * Flags
* -- LVIF_COLUMNS * -- LVIF_COLUMNS
* -- LVIF_GROUPID * -- LVIF_GROUPID
* -- LVIF_NORECOMPUTE
* *
* States * States
* -- LVIS_ACTIVATING (not currently supported by comctl32.dll version 6.0) * -- LVIS_ACTIVATING (not currently supported by comctl32.dll version 6.0)
@ -5560,6 +5559,8 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
/* apparently, we should not callback for lParam in LVS_OWNERDATA */ /* apparently, we should not callback for lParam in LVS_OWNERDATA */
if ((lpLVItem->mask & ~(LVIF_STATE | LVIF_PARAM)) || infoPtr->uCallbackMask) if ((lpLVItem->mask & ~(LVIF_STATE | LVIF_PARAM)) || infoPtr->uCallbackMask)
{ {
UINT mask = lpLVItem->mask;
/* NOTE: copy only fields which we _know_ are initialized, some apps /* NOTE: copy only fields which we _know_ are initialized, some apps
* depend on the uninitialized fields being 0 */ * depend on the uninitialized fields being 0 */
dispInfo.item.mask = lpLVItem->mask & ~LVIF_PARAM; dispInfo.item.mask = lpLVItem->mask & ~LVIF_PARAM;
@ -5567,34 +5568,49 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
dispInfo.item.iSubItem = isubitem; dispInfo.item.iSubItem = isubitem;
if (lpLVItem->mask & LVIF_TEXT) if (lpLVItem->mask & LVIF_TEXT)
{ {
dispInfo.item.pszText = lpLVItem->pszText; if (lpLVItem->mask & LVIF_NORECOMPUTE)
dispInfo.item.cchTextMax = lpLVItem->cchTextMax; /* 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) if (lpLVItem->mask & LVIF_STATE)
dispInfo.item.stateMask = lpLVItem->stateMask & infoPtr->uCallbackMask; dispInfo.item.stateMask = lpLVItem->stateMask & infoPtr->uCallbackMask;
notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW); /* could be zeroed on LVIF_NORECOMPUTE case */
dispInfo.item.stateMask = lpLVItem->stateMask; if (dispInfo.item.mask != 0)
if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS))
{ {
/* full size structure expected - _WIN32IE >= 0x560 */ notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
*lpLVItem = dispInfo.item; 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 */ /* make sure lParam is zeroed out */
if (lpLVItem->mask & LVIF_PARAM) lpLVItem->lParam = 0; 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 */ /* we store only a little state, so if we're not asked, we're done */
if (!(lpLVItem->mask & LVIF_STATE) || isubitem) return TRUE; if (!(lpLVItem->mask & LVIF_STATE) || isubitem) return TRUE;
@ -5651,7 +5667,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 */ /* 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.mask |= LVIF_TEXT;
dispInfo.item.pszText = lpLVItem->pszText; dispInfo.item.pszText = lpLVItem->pszText;
@ -5698,7 +5715,8 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
} }
else if (lpLVItem->mask & LVIF_TEXT) 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); else textcpynT(lpLVItem->pszText, isW, pItemHdr->pszText, TRUE, lpLVItem->cchTextMax);
} }
@ -5774,7 +5792,12 @@ static BOOL LISTVIEW_GetItemExtT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVIte
pszText = lpLVItem->pszText; pszText = lpLVItem->pszText;
bResult = LISTVIEW_GetItemT(infoPtr, lpLVItem, isW); bResult = LISTVIEW_GetItemT(infoPtr, lpLVItem, isW);
if (bResult && lpLVItem->pszText != pszText) 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; lpLVItem->pszText = pszText;
return bResult; return bResult;

View File

@ -1881,10 +1881,9 @@ static void test_norecompute(void)
flush_sequences(sequences, NUM_MSG_SEQUENCES); flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item); res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
expect(TRUE, res); expect(TRUE, res);
todo_wine
ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n", ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
LPSTR_TEXTCALLBACK, (VOID*)item.pszText); 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); DestroyWindow(hwnd);
@ -1906,10 +1905,9 @@ todo_wine
flush_sequences(sequences, NUM_MSG_SEQUENCES); flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item); res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
expect(TRUE, res); expect(TRUE, res);
todo_wine
ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n", ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
LPSTR_TEXTCALLBACK, (VOID*)item.pszText); 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); DestroyWindow(hwnd);
} }