Listview L7

Dimitrie O. Paun dpaun at rogers.com
Mon Oct 7 01:12:32 CDT 2002


This one should make ICON and SMALLICON work in OWNERDATA case.

ChangeLog
  Maintain the item position in {,SMALL}ICON mode separataly
  from the item, so that we have it even in LVS_OWNERDATA.

--- dlls/comctl32/listview.c.L6	Mon Oct  7 01:02:40 2002
+++ dlls/comctl32/listview.c	Mon Oct  7 02:07:24 2002
@@ -100,7 +100,6 @@
   UINT state;
   LPARAM lParam;
   INT iIndent;
-  POINT ptPosition;
   BOOL valid;
 } LISTVIEW_ITEM;
 
@@ -153,8 +152,10 @@
   RECT rcFocus;
   DWORD dwStyle;		/* the cached window GWL_STYLE */
   DWORD dwLvExStyle;		/* extended listview style */
-  HDPA hdpaItems;
   UINT nItemCount;
+  HDPA hdpaItems;
+  HDPA hdpaPosX;		/* maintains the (X, Y) coordinates of the */
+  HDPA hdpaPosY;		/* items in LVS_ICON, and LVS_SMALLICON modes */
   PFNLVCOMPARE pfnCompare;
   LPARAM lParamSort;
   HWND hwndEdit;
@@ -1297,11 +1298,8 @@
     /************************************************************/
     if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
     {
-	/* FIXME: what about virtual listview? */
-	HDPA hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-	LISTVIEW_ITEM * lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-	if (!lpItem) return FALSE;
-	TopLeft = lpItem->ptPosition;
+	TopLeft.x = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, nItem);
+	TopLeft.y = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, nItem);
     }
     else if (uView == LVS_LIST)
     {
@@ -1347,6 +1345,7 @@
 	        TopLeft.x -= scrollInfo.nPos;
         }
     }
+    TRACE("TopLeft=%s\n", debugpoint(&TopLeft));
 
     /************************************************************/
     /* compute position point (ala LVM_GETITEMPOSITION)         */
@@ -3901,6 +3900,8 @@
     /* reinitialize listview memory */
     bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems);
     infoPtr->nItemCount = 0;
+    DPA_DeleteAllPtrs(infoPtr->hdpaPosX);
+    DPA_DeleteAllPtrs(infoPtr->hdpaPosY);
 
     /* align items (set position of each item) */
     if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
@@ -4105,6 +4106,8 @@
       }
 
       bResult = DPA_Destroy(hdpaSubItems);
+      DPA_DeletePtr(infoPtr->hdpaPosX, nItem);
+      DPA_DeletePtr(infoPtr->hdpaPosY, nItem);
     }
 
     LISTVIEW_ShiftIndices(infoPtr,nItem,-1);
@@ -6052,11 +6055,7 @@
     infoPtr->nItemCount++;
    
     if (!LISTVIEW_SetItemT(infoPtr, lpLVItem, isW))
-    {
-	DPA_DeletePtr(infoPtr->hdpaItems, nItem);
-	infoPtr->nItemCount--;
-	goto fail;
-    }
+	goto undo;
 
     /* if we're sorted, sort the list, and update the index */
     if (is_sorted)
@@ -6072,6 +6071,18 @@
 	}
     }
 
+    /* make room for the position, if we are in the right mode */
+    if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+    {
+        if (DPA_InsertPtr(infoPtr->hdpaPosX, nItem, 0) == -1)
+	    goto undo;
+        if (DPA_InsertPtr(infoPtr->hdpaPosY, nItem, 0) == -1)
+	{
+	    DPA_DeletePtr(infoPtr->hdpaPosX, nItem);
+	    goto undo;
+	}
+    }
+    
     /* Add the subitem list to the items array. Do this last in case we go to
      * fail during the above.
      */
@@ -6099,6 +6110,9 @@
     TRACE("    <- %d\n", nItem);
     return nItem;
 
+undo:
+    DPA_DeletePtr(infoPtr->hdpaItems, nItem);
+    infoPtr->nItemCount--;
 fail:
     DPA_DeletePtr(hdpaSubItems, 0);
     DPA_Destroy (hdpaSubItems);
@@ -6785,68 +6799,33 @@
  */
 static BOOL LISTVIEW_SetItemPosition(LISTVIEW_INFO *infoPtr, INT nItem, POINT pt)
 {
-  UINT lStyle = infoPtr->dwStyle;
-  UINT uView = lStyle & LVS_TYPEMASK;
-  LISTVIEW_ITEM *lpItem;
-  HDPA hdpaSubItems;
-  BOOL bResult = FALSE;
-
-  TRACE("(nItem=%d, &pt=%s\n", nItem, debugpoint(&pt));
-
-  if (lStyle & LVS_OWNERDATA)
-    return FALSE;
+    UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
 
-  if ((nItem >= 0) || (nItem < infoPtr->nItemCount))
-  {
-    if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
-    {
-      if ( (hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem)) )
-      {
-        if ( (lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0)) )
-        {
-	  POINT orig = lpItem->ptPosition;
-          bResult = TRUE;
-          if ((pt.x == -1) && (pt.y == -1))
-          {
-            /* This point value seems to be an undocumented feature. The
-             * best guess is that it means either at the origin, or at
-             * the true beginning of the list. I will assume the origin.
-             */
-            if (!LISTVIEW_GetOrigin(infoPtr, &pt))
-              pt.x = pt.y = 0;
-            if (uView == LVS_ICON)
-            {
-              pt.x += (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2;
-              pt.y += ICON_TOP_PADDING;
-            }
-            TRACE("requested special (-1,-1), set to origin %s\n", debugpoint(&pt));
-          }
+    TRACE("(nItem=%d, &pt=%s\n", nItem, debugpoint(&pt));
 
-          lpItem->ptPosition = *&pt;
-	  if (uView == LVS_ICON)
-	  {
-	    lpItem->ptPosition.y -= ICON_TOP_PADDING;
-              lpItem->ptPosition.x -= (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2;
-              if ((lpItem->ptPosition.y < 0) || (lpItem->ptPosition.x < 0))
-              {
-                  FIXME("failed orig=%s, intent=%s, is %s, setting neg to 0\n", 
-			debugpoint(&orig), debugpoint(&pt), debugpoint(&lpItem->ptPosition));
-                  /*
-                  if (lpItem->ptPosition.x < 0) lpItem->ptPosition.x = 0;
-                  if (lpItem->ptPosition.y < 0) lpItem->ptPosition.y = 0;
-                  */
-              }
-              else
-              {
-                  TRACE("orig=%s, intent=%s, is %s\n", debugpoint(&orig), debugpoint(&pt), debugpoint(&lpItem->ptPosition));
-              }
-	  }
-        }
-      }
-    }
-  }
+    if (nItem < 0 || nItem >= infoPtr->nItemCount ||
+	!(uView == LVS_ICON || uView == LVS_SMALLICON)) return FALSE;
 
-  return bResult;
+    /* This point value seems to be an undocumented feature.
+     * The best guess is that it means either at the origin, 
+     * or at true beginning of the list. I will assume the origin. */
+    if ((pt.x == -1) && (pt.y == -1))
+	LISTVIEW_GetOrigin(infoPtr, &pt);
+    else if (uView == LVS_ICON)
+    {
+	pt.x -= (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2;
+	pt.y -= ICON_TOP_PADDING;
+    }
+
+    /* Allocating a POINTER for every item is too resource intensive,
+     * so we'll keep the (x,y) in different arrays */
+    if (DPA_InsertPtr(infoPtr->hdpaPosX, nItem, (void *)pt.x) == nItem &&
+        DPA_InsertPtr(infoPtr->hdpaPosY, nItem, (void *)pt.y) == nItem )
+	return TRUE;
+    
+    ERR("We should never fail here (nItem=%d, pt=%s), please report.\n", 
+	nItem, debugpoint(&pt));
+    return FALSE;
 }
 
 /***
@@ -7224,6 +7203,8 @@
 
   /* allocate memory for the data structure */
   infoPtr->hdpaItems = DPA_Create(10);
+  infoPtr->hdpaPosX  = DPA_Create(10);
+  infoPtr->hdpaPosY  = DPA_Create(10);
 
   /* allocate memory for the selection ranges */
   infoPtr->hdpaSelectionRanges = DPA_Create(10);




More information about the wine-patches mailing list