Listview K8
Dimitrie O. Paun
dpaun at rogers.com
Fri Oct 4 13:38:55 CDT 2002
ChangeLog
Streamline the GetItem usage.
Fix fatal bug for ICON mode in LVS_ONWERDATA.
Update documentation.
--- dlls/comctl32/listview.c.K7 Fri Oct 4 12:29:55 2002
+++ dlls/comctl32/listview.c Fri Oct 4 14:30:45 2002
@@ -261,7 +261,7 @@
/*
* forward declarations
*/
-static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL, BOOL);
+static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL);
static INT LISTVIEW_SuperHitTestItem(LISTVIEW_INFO *, LPLVHITTESTINFO, BOOL, BOOL);
static void LISTVIEW_AlignLeft(LISTVIEW_INFO *);
static void LISTVIEW_AlignTop(LISTVIEW_INFO *);
@@ -677,7 +677,7 @@
item.iItem = iItem;
item.iSubItem = 0;
item.mask = LVIF_PARAM;
- if (!LISTVIEW_GetItemT(infoPtr, &item, TRUE, TRUE)) return FALSE;
+ if (!LISTVIEW_GetItemT(infoPtr, &item, TRUE)) return FALSE;
uItemState = 0;
@@ -737,9 +737,9 @@
#define LISTVIEW_InvalidateList(infoPtr)\
LISTVIEW_InvalidateRect(infoPtr, &infoPtr->rcList)
-static inline BOOL LISTVIEW_GetItemW(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL internal)
+static inline BOOL LISTVIEW_GetItemW(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem)
{
- return LISTVIEW_GetItemT(infoPtr, lpLVItem, internal, TRUE);
+ return LISTVIEW_GetItemT(infoPtr, lpLVItem, TRUE);
}
static inline int LISTVIEW_GetType(LISTVIEW_INFO *infoPtr)
@@ -955,7 +955,7 @@
item.iSubItem = 0;
item.pszText = buffer;
item.cchTextMax = COUNTOF(buffer);
- if (!LISTVIEW_GetItemW(infoPtr, &item, TRUE)) return 0;
+ if (!LISTVIEW_GetItemW(infoPtr, &item)) return 0;
/* check for a match */
if (lstrncmpiW(item.pszText,infoPtr->szSearchParam,infoPtr->nSearchParamLength) == 0) {
@@ -1248,7 +1248,7 @@
lvItem.mask = LVIF_INDENT;
lvItem.iItem = nItem;
lvItem.iSubItem = 0;
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE)) return FALSE;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
/* do indent */
nIndent = infoPtr->iconSize.cx * lvItem.iIndent;
@@ -2915,7 +2915,7 @@
lvItem.cchTextMax = COUNTOF(szDispText);
lvItem.pszText = szDispText;
*lvItem.pszText = '\0';
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE)) return FALSE;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE));
@@ -2960,7 +2960,7 @@
lvItem.cchTextMax = DISP_TEXT_SIZE;
lvItem.pszText = szDispText;
*lvItem.pszText = '\0';
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE)) return FALSE;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE));
/* now check if we need to update the focus rectangle */
@@ -3055,7 +3055,7 @@
lvItem.cchTextMax = DISP_TEXT_SIZE;
lvItem.pszText = szDispText;
*lvItem.pszText = '\0';
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, FALSE)) return FALSE;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE));
/* now check if we need to update the focus rectangle */
@@ -3311,7 +3311,7 @@
item.iSubItem = 0;
item.mask = LVIF_PARAM | LVIF_STATE;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
- if (!LISTVIEW_GetItemW(infoPtr, &item, TRUE)) continue;
+ if (!LISTVIEW_GetItemW(infoPtr, &item)) continue;
ZeroMemory(&dis, sizeof(dis));
dis.hwndItem = infoPtr->hwndSelf;
@@ -3341,7 +3341,7 @@
item.stateMask = LVIS_SELECTED;
item.iItem = nItem;
item.iSubItem = 0;
- if (!LISTVIEW_GetItemW(infoPtr, &item, TRUE)) continue;
+ if (!LISTVIEW_GetItemW(infoPtr, &item)) continue;
rcFullSelect.left = lpCols[0].rc.left + REPORT_MARGINX +
infoPtr->iconSize.cx * item.iIndent +
@@ -4068,7 +4068,7 @@
dispInfo.item.iItem = infoPtr->nEditLabelItem;
dispInfo.item.iSubItem = 0;
dispInfo.item.stateMask = ~0;
- if (!LISTVIEW_GetItemW(infoPtr, &dispInfo.item, TRUE)) return FALSE;
+ if (!LISTVIEW_GetItemW(infoPtr, &dispInfo.item)) return FALSE;
dispInfo.item.pszText = pszText;
dispInfo.item.cchTextMax = textlenT(pszText, isW);
@@ -4130,7 +4130,7 @@
dispInfo.item.stateMask = ~0;
dispInfo.item.pszText = szDispText;
dispInfo.item.cchTextMax = DISP_TEXT_SIZE;
- if (!LISTVIEW_GetItemT(infoPtr, &dispInfo.item, FALSE, isW)) return 0;
+ if (!LISTVIEW_GetItemT(infoPtr, &dispInfo.item, isW)) return 0;
infoPtr->hwndEdit = CreateEditLabelT(infoPtr, dispInfo.item.pszText, WS_VISIBLE,
rect.left-2, rect.top-1, 0, rect.bottom - rect.top+2, isW);
@@ -4348,7 +4348,7 @@
lvItem.iItem = nItem;
lvItem.iSubItem = 0;
- if (LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE))
+ if (LISTVIEW_GetItemW(infoPtr, &lvItem))
{
if (lvItem.mask & LVIF_TEXT)
{
@@ -4666,28 +4666,33 @@
* PARAMETER(S):
* [I] hwnd : window handle
* [IO] lpLVItem : item info
- * [I] internal : if true then we will use tricks that avoid copies
- * but are not compatible with the regular interface
* [I] isW : if TRUE, then lpLVItem is a LPLVITEMW,
* if FALSE, the lpLVItem is a LPLVITEMA.
*
+ * NOTE:
+ * This is the internal 'GetItem' interface -- it tries to
+ * be smart, and avoids text copies, if possible, by modifing
+ * lpLVItem->pszText to point to the text string. Please note
+ * that this is not always possible (e.g. OWNERDATA), so on
+ * entry you *must* supply valid values for pszText, and cchTextMax.
+ * The only difference to the documented interface is that upon
+ * return, you should use *only* the lpLVItem->pszText, rather than
+ * the buffer pointer you provided on input. Most code already does
+ * that, so it's not a problem.
+ * For the two cases when the text must be copied (that is,
+ * for LVM_GETITEM, and LVMGETITEMTEXT), use LISTVIEW_GetItemExtT.
+ *
* RETURN:
* SUCCESS : TRUE
* FAILURE : FALSE
*/
-static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL internal, BOOL isW)
+static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW)
{
NMLVDISPINFOW dispInfo;
LISTVIEW_ITEM *lpItem;
ITEMHDR* pItemHdr;
HDPA hdpaSubItems;
- if (internal && !isW)
- {
- ERR("We can't have internal non-Unicode GetItem!\n");
- return FALSE;
- }
-
/* In the following:
* lpLVItem describes the information requested by the user
* lpItem is what we have
@@ -4695,7 +4700,7 @@
* information from the application
*/
- TRACE("(lpLVItem=%s, internal=%d, isW=%d)\n", debuglvitem_t(lpLVItem, isW), internal, isW);
+ TRACE("(lpLVItem=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW);
if (!lpLVItem || (lpLVItem->iItem < 0) ||
(lpLVItem->iItem >= GETITEMCOUNT(infoPtr)))
@@ -4826,14 +4831,11 @@
if ((dispInfo.item.mask & LVIF_DI_SETITEM) && pItemHdr->pszText)
textsetptrT(&pItemHdr->pszText, dispInfo.item.pszText, isW);
- /* If lpLVItem->pszText==dispInfo.item.pszText a copy is unnecessary, but */
- /* some apps give a new pointer in ListView_Notify so we can't be sure. */
- if (lpLVItem->pszText != dispInfo.item.pszText)
- textcpynT(lpLVItem->pszText, isW, dispInfo.item.pszText, isW, lpLVItem->cchTextMax);
+ lpLVItem->pszText = dispInfo.item.pszText;
}
else if (lpLVItem->mask & LVIF_TEXT)
{
- if (internal) lpLVItem->pszText = pItemHdr->pszText;
+ if (isW) lpLVItem->pszText = pItemHdr->pszText;
else textcpynT(lpLVItem->pszText, isW, pItemHdr->pszText, TRUE, lpLVItem->cchTextMax);
}
@@ -4881,6 +4883,42 @@
return TRUE;
}
+/***
+ * DESCRIPTION:
+ * Retrieves item attributes.
+ *
+ * PARAMETER(S):
+ * [I] hwnd : window handle
+ * [IO] lpLVItem : item info
+ * [I] isW : if TRUE, then lpLVItem is a LPLVITEMW,
+ * if FALSE, the lpLVItem is a LPLVITEMA.
+ *
+ * NOTE:
+ * This is the external 'GetItem' interface -- it properly copies
+ * the text in the provided buffer.
+ *
+ * RETURN:
+ * SUCCESS : TRUE
+ * FAILURE : FALSE
+ */
+static BOOL LISTVIEW_GetItemExtT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW)
+{
+ LPWSTR pszText;
+ BOOL bResult;
+
+ if (!lpLVItem || (lpLVItem->iItem < 0) ||
+ (lpLVItem->iItem >= GETITEMCOUNT(infoPtr)))
+ return FALSE;
+
+ pszText = lpLVItem->pszText;
+ bResult = LISTVIEW_GetItemT(infoPtr, lpLVItem, isW);
+ if (bResult && lpLVItem->pszText != pszText)
+ textcpynT(pszText, isW, lpLVItem->pszText, isW, lpLVItem->cchTextMax);
+ lpLVItem->pszText = pszText;
+
+ return bResult;
+}
+
/***
* DESCRIPTION:
@@ -4955,6 +4993,7 @@
HDC hdc = GetDC (infoPtr->hwndSelf);
HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
UINT uFormat = LISTVIEW_DTFLAGS | DT_CALCRECT;
+ WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
RECT rcText = *rect;
RECT rcBack = *rect;
BOOL focused, selected;
@@ -4984,11 +5023,9 @@
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nItem;
lvItem.iSubItem = 0;
- /* We will specify INTERNAL and so will receive back a const
- * pointer to the text, rather than specifying a buffer to which
- * to copy it. FIXME: what about OWNERDRAW???
- */
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE)) return FALSE;
+ lvItem.pszText = szDispText;
+ lvItem.cchTextMax = DISP_TEXT_SIZE;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE;
InflateRect(&rcText, -2, 0);
DrawTextW (hdc, lvItem.pszText, -1, &rcText, uFormat);
@@ -5176,9 +5213,9 @@
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nItem;
lvItem.iSubItem = 0;
- lvItem.cchTextMax = DISP_TEXT_SIZE;
lvItem.pszText = szDispText;
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE)) return 0;
+ lvItem.cchTextMax = DISP_TEXT_SIZE;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return 0;
/* FIXME: is this right? What if the label is very long? */
return LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE);
@@ -5235,7 +5272,7 @@
lvItem.iSubItem = 0;
lvItem.mask = LVIF_STATE;
lvItem.stateMask = uMask;
- if (!LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE)) return 0;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return 0;
return lvItem.state & uMask;
}
@@ -5260,7 +5297,7 @@
lpLVItem->mask = LVIF_TEXT;
lpLVItem->iItem = nItem;
- if (!LISTVIEW_GetItemT(infoPtr, lpLVItem, FALSE, isW)) return 0;
+ if (!LISTVIEW_GetItemExtT(infoPtr, lpLVItem, isW)) return 0;
return textlenT(lpLVItem->pszText, isW);
}
@@ -6263,7 +6300,7 @@
INT nLabelWidth;
RECT rcHeader;
LVITEMW lvItem;
- WCHAR szDispText[DISP_TEXT_SIZE];
+ WCHAR szDispText[DISP_TEXT_SIZE] = { 0 };
if (!infoPtr->hwndHeader) /* make sure we have a header */
return (FALSE);
@@ -6306,14 +6343,13 @@
{
lvItem.iSubItem = iCol;
lvItem.mask = LVIF_TEXT;
- lvItem.cchTextMax = DISP_TEXT_SIZE;
lvItem.pszText = szDispText;
- *lvItem.pszText = '\0';
+ lvItem.cchTextMax = DISP_TEXT_SIZE;
cx = 0;
for(item_index = 0; item_index < GETITEMCOUNT(infoPtr); item_index++)
{
lvItem.iItem = item_index;
- if (!LISTVIEW_GetItemT(infoPtr, &lvItem, FALSE, TRUE)) continue;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue;
nLabelWidth = LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE);
cx = (nLabelWidth>cx)?nLabelWidth:cx;
}
@@ -6370,14 +6406,13 @@
lvItem.iSubItem = iCol;
lvItem.mask = LVIF_TEXT;
- lvItem.cchTextMax = DISP_TEXT_SIZE;
lvItem.pszText = szDispText;
- *lvItem.pszText = '\0';
+ lvItem.cchTextMax = DISP_TEXT_SIZE;
cx = size.cx;
for(item_index = 0; item_index < GETITEMCOUNT(infoPtr); item_index++)
{
lvItem.iItem = item_index;
- if (!LISTVIEW_GetItemT(infoPtr, &lvItem, FALSE, TRUE)) continue;
+ if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue;
nLabelWidth = LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE);
nLabelWidth += TRAILING_PADDING;
/* While it is possible for subitems to have icons, even MS messes
@@ -8520,10 +8555,10 @@
return FALSE;
case LVM_GETITEMA:
- return LISTVIEW_GetItemT(infoPtr, (LPLVITEMW)lParam, FALSE, FALSE);
+ return LISTVIEW_GetItemExtT(infoPtr, (LPLVITEMW)lParam, FALSE);
case LVM_GETITEMW:
- return LISTVIEW_GetItemT(infoPtr, (LPLVITEMW)lParam, FALSE, TRUE);
+ return LISTVIEW_GetItemExtT(infoPtr, (LPLVITEMW)lParam, TRUE);
case LVM_GETITEMCOUNT:
return GETITEMCOUNT(infoPtr);
More information about the wine-patches
mailing list