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