Listview V17

Dimitrie O. Paun dpaun at rogers.com
Mon Oct 21 13:28:55 CDT 2002


ChangeLog
  Complete rewrite of the rcView implementation
  Lots of bugs fixed in rcView computation
  Assorted cleanups, and simplifications.

--- dlls/comctl32/listview.c.V16	Mon Oct 21 12:10:30 2002
+++ dlls/comctl32/listview.c	Mon Oct 21 14:25:37 2002
@@ -211,7 +211,6 @@
 				* LISTVIEW_UpdateSize. This rectangle offset
 				* by the LISTVIEW_GetOrigin value is in
 				* client coordinates   */
-  RECT rcView;                 /* This rectangle contains all items */ 
   SIZE iconSize;
   SIZE iconSpacing;
   SIZE iconStateSize;
@@ -319,17 +318,13 @@
   TRACE("hwndSelf=%08x, clrBk=0x%06lx, clrText=0x%06lx, clrTextBk=0x%06lx, ItemHeight=%d, ItemWidth=%d, Style=0x%08lx\n", \
         iP->hwndSelf, iP->clrBk, iP->clrText, iP->clrTextBk, \
         iP->nItemHeight, iP->nItemWidth, infoPtr->dwStyle); \
-  TRACE("hwndSelf=%08x, himlNor=%p, himlSml=%p, himlState=%p, Focused=%d, Hot=%d, exStyle=0x%08lx, Focus=%s\n", \
+  TRACE("hwndSelf=%08x, himlNor=%p, himlSml=%p, himlState=%p, Focused=%d, Hot=%d, exStyle=0x%08lx, Focus=%d\n", \
         iP->hwndSelf, iP->himlNormal, iP->himlSmall, iP->himlState, \
-        iP->nFocusedItem, iP->nHotItem, iP->dwLvExStyle, \
-        (iP->bFocus) ? "true" : "false"); \
+        iP->nFocusedItem, iP->nHotItem, iP->dwLvExStyle, iP->bFocus ); \
   TRACE("hwndSelf=%08x, ntmH=%d, icSz.cx=%ld, icSz.cy=%ld, icSp.cx=%ld, icSp.cy=%ld, notifyFmt=%d\n", \
         iP->hwndSelf, iP->ntmHeight, iP->iconSize.cx, iP->iconSize.cy, \
         iP->iconSpacing.cx, iP->iconSpacing.cy, iP->notifyFormat); \
-  TRACE("hwndSelf=%08x, rcList=(%d,%d)-(%d,%d), rcView=(%d,%d)-(%d,%d)\n", \
-        iP->hwndSelf, \
-	iP->rcList.left, iP->rcList.top, iP->rcList.right, iP->rcList.bottom, \
-	iP->rcView.left, iP->rcView.top, iP->rcView.right, iP->rcView.bottom); \
+  TRACE("hwndSelf=%08x, rcList=%s\n", iP->hwndSelf, debugrect(&iP->rcList)); \
 } while(0)
 
 
@@ -338,7 +333,6 @@
  */
 static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL);
 static void LISTVIEW_GetItemBox(LISTVIEW_INFO *, INT, LPRECT);
-static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *, INT);
 static void LISTVIEW_GetItemOrigin(LISTVIEW_INFO *, INT, LPPOINT);
 static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *, INT, LPPOINT);
 static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *, INT, LPRECT);
@@ -351,7 +345,6 @@
 static void LISTVIEW_UpdateScroll(LISTVIEW_INFO *);
 static void LISTVIEW_SetSelection(LISTVIEW_INFO *, INT);
 static BOOL LISTVIEW_UpdateSize(LISTVIEW_INFO *);
-static void LISTVIEW_UnsupportedStyles(LONG);
 static HWND LISTVIEW_EditLabelT(LISTVIEW_INFO *, INT, BOOL);
 static LRESULT LISTVIEW_Command(LISTVIEW_INFO *, WPARAM, LPARAM);
 static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *, PFNLVCOMPARE, LPARAM);
@@ -1581,33 +1574,6 @@
 
 	    
 /***
- * DESCRIPTION:
- * Prints a message for unsupported window styles.
- * A kind of TODO list for window styles.
- *
- * PARAMETER(S):
- * [I] lStyle : window style
- *
- * RETURN:
- * None
- */
-static void LISTVIEW_UnsupportedStyles(LONG lStyle)
-{
-  if ((LVS_TYPESTYLEMASK & lStyle) == LVS_NOSCROLL)
-    FIXME("  LVS_NOSCROLL\n");
-
-  if (lStyle & LVS_NOLABELWRAP)
-    FIXME("  LVS_NOLABELWRAP\n");
-
-  if (lStyle & LVS_SORTASCENDING)
-    FIXME("  LVS_SORTASCENDING\n");
-
-  if (lStyle & LVS_SORTDESCENDING)
-    FIXME("  LVS_SORTDESCENDING\n");
-}
-
-
-/***
  * DESCRIPTION:            [INTERNAL]
  * Computes an item's (left,top) corner, relative to rcView.
  * That is, the position has NOT been made relative to the Origin.
@@ -1949,7 +1915,6 @@
   UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
   INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
   POINT ptItem;
-  RECT rcView;
   INT i, off_x=0, off_y=0;
 
   if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
@@ -1963,7 +1928,6 @@
     }
     ptItem.x = off_x;
     ptItem.y = off_y;
-    ZeroMemory(&rcView, sizeof(RECT));
     TRACE("Icon  off.x=%d, off.y=%d, left=%d, right=%d\n",
 	  off_x, off_y,
 	  infoPtr->rcList.left, infoPtr->rcList.right);
@@ -1980,11 +1944,7 @@
 
         LISTVIEW_SetItemPosition(infoPtr, i, ptItem);
         ptItem.x += infoPtr->nItemWidth;
-        rcView.right = max(rcView.right, ptItem.x);
       }
-
-      rcView.right -= off_x;
-      rcView.bottom = (ptItem.y-off_y) + infoPtr->nItemHeight;
     }
     else
     {
@@ -1993,12 +1953,7 @@
         LISTVIEW_SetItemPosition(infoPtr, i, ptItem);
         ptItem.y += infoPtr->nItemHeight;
       }
-
-      rcView.right = infoPtr->nItemWidth;
-      rcView.bottom = ptItem.y-off_y;
     }
-
-    infoPtr->rcView = rcView;
   }
 }
 
@@ -2017,7 +1972,6 @@
   UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
   INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
   POINT ptItem;
-  RECT rcView;
   INT i, off_x=0, off_y=0;
 
   if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
@@ -2031,7 +1985,6 @@
     }
     ptItem.x = off_x;
     ptItem.y = off_y;
-    ZeroMemory(&rcView, sizeof(RECT));
     TRACE("Icon  off.x=%d, off.y=%d\n", off_x, off_y);
 
     if (nListHeight > infoPtr->nItemHeight)
@@ -2046,10 +1999,7 @@
 
         LISTVIEW_SetItemPosition(infoPtr, i, ptItem);
         ptItem.y += infoPtr->nItemHeight;
-        rcView.bottom = max(rcView.bottom, ptItem.y);
       }
-
-      rcView.right = ptItem.x + infoPtr->nItemWidth;
     }
     else
     {
@@ -2058,18 +2008,64 @@
         LISTVIEW_SetItemPosition(infoPtr, i, ptItem);
         ptItem.x += infoPtr->nItemWidth;
       }
-
-      rcView.bottom = infoPtr->nItemHeight;
-      rcView.right = ptItem.x;
     }
-
-    infoPtr->rcView = rcView;
   }
 }
 
 
 /***
  * DESCRIPTION:
+ * Retrieves the bounding rectangle of all the items, not offset by Origin.
+ *
+ * PARAMETER(S):
+ * [I] infoPtr : valid pointer to the listview structure
+ * [O] lprcView : bounding rectangle
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static void LISTVIEW_GetAreaRect(LISTVIEW_INFO *infoPtr, LPRECT lprcView)
+{
+    INT i, x, y;
+
+    SetRectEmpty(lprcView);
+
+    switch (infoPtr->dwStyle & LVS_TYPEMASK)
+    {
+    case LVS_ICON:
+    case LVS_SMALLICON:
+	for (i = 0; i < infoPtr->nItemCount; i++)
+	{
+	    x = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, i);
+	    y = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, i);
+	    lprcView->right = max(lprcView->right, x);
+	    lprcView->bottom = max(lprcView->bottom, y);
+	}
+	if (infoPtr->nItemCount > 0)
+	{
+	    lprcView->right += infoPtr->nItemWidth;
+	    lprcView->bottom += infoPtr->nItemHeight;
+	}
+	break;
+
+    case LVS_LIST:
+	y = LISTVIEW_GetCountPerColumn(infoPtr);
+	x = infoPtr->nItemCount / y;
+	if (infoPtr->nItemCount % y) x++;
+	lprcView->right = x * infoPtr->nItemWidth;
+	lprcView->bottom = y * infoPtr->nItemHeight;
+	break;
+	
+    case LVS_REPORT:	    
+    	lprcView->right = infoPtr->nItemWidth;
+	lprcView->bottom = infoPtr->nItemCount * infoPtr->nItemHeight;
+	break;
+    }
+}
+
+/***
+ * DESCRIPTION:
  * Retrieves the bounding rectangle of all the items.
  *
  * PARAMETER(S):
@@ -2087,10 +2083,9 @@
     TRACE("(lprcView=%p)\n", lprcView);
 
     if (!lprcView) return FALSE;
-  
+ 
     LISTVIEW_GetOrigin(infoPtr, &ptOrigin);
-   
-    *lprcView = infoPtr->rcView;
+    LISTVIEW_GetAreaRect(infoPtr, lprcView); 
     OffsetRect(lprcView, ptOrigin.x, ptOrigin.y); 
 
     TRACE("lprcView=%s\n", debugrect(lprcView));
@@ -2736,26 +2731,24 @@
  */
 static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *infoPtr, INT nItem)
 {
-  INT nFirst = min(infoPtr->nSelectionMark, nItem);
-  INT nLast = max(infoPtr->nSelectionMark, nItem);
-  INT i;
-  LVITEMW item;
-
-  if (nFirst == -1)
-    nFirst = nItem;
-
-  item.state = LVIS_SELECTED;
-  item.stateMask = LVIS_SELECTED;
-
-  /* FIXME: this is not correct LVS_OWNERDATA
-   * See docu for LVN_ITEMCHANGED. Is there something similar for
-   * RemoveGroupSelection (is there such a thing?)?
-   */
-  for (i = nFirst; i <= nLast; i++)
-    LISTVIEW_SetItemState(infoPtr,i,&item);
+    INT nFirst = min(infoPtr->nSelectionMark, nItem);
+    INT nLast = max(infoPtr->nSelectionMark, nItem);
+    INT i;
+    LVITEMW item;
+
+    if (nFirst == -1) nFirst = nItem;
+
+    item.state = LVIS_SELECTED;
+    item.stateMask = LVIS_SELECTED;
 
-  LISTVIEW_SetItemFocus(infoPtr, nItem);
-  infoPtr->nSelectionMark = nItem;
+    /* FIXME: this is not correct LVS_OWNERDATA
+     * setting the item states individually will generate
+     * a LVN_ITEMCHANGED notification for each one. Instead,
+     * we have to send a LVN_ODSTATECHANGED notification.
+     * See MSDN documentation for LVN_ITEMCHANGED.
+     */
+    for (i = nFirst; i <= nLast; i++)
+	LISTVIEW_SetItemState(infoPtr,i,&item);
 }
 
 
@@ -4378,6 +4371,7 @@
 	(uView == LVS_ICON || uView ==LVS_SMALLICON))
     {
 	POINT Origin;
+	RECT rcArea;
 	
 	FIXME("LVFI_NEARESTXY is slow.\n");
         LISTVIEW_GetOrigin(infoPtr, &Origin);
@@ -4390,9 +4384,13 @@
 	case VK_RIGHT: Destination.x += infoPtr->nItemWidth; break;
 	case VK_LEFT:  Destination.x -= infoPtr->nItemWidth; break;
 	case VK_HOME:  Destination.x = Destination.y = 0; break;
-	case VK_END:   Destination.x = infoPtr->rcView.right; Destination.y = infoPtr->rcView.bottom; break;
 	case VK_NEXT:  Destination.y += infoPtr->rcList.bottom - infoPtr->rcList.top; break;
 	case VK_PRIOR: Destination.y -= infoPtr->rcList.bottom - infoPtr->rcList.top; break;
+	case VK_END:
+	    LISTVIEW_GetAreaRect(infoPtr, &rcArea);
+	    Destination.x = rcArea.right; 
+	    Destination.y = rcArea.bottom; 
+	    break;
 	default: ERR("Unknown vkDirection=%d\n", lpFindInfo->vkDirection);
 	}
 	bNearest = TRUE;
@@ -4474,15 +4472,15 @@
 static INT LISTVIEW_FindItemA(LISTVIEW_INFO *infoPtr, INT nStart,
                               LPLVFINDINFOA lpFindInfo)
 {
-  BOOL hasText = lpFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL);
-  LVFINDINFOW fiw;
-  INT res;
-
-  memcpy(&fiw, lpFindInfo, sizeof(fiw));
-  if (hasText) fiw.psz = textdupTtoW((LPCWSTR)lpFindInfo->psz, FALSE);
-  res = LISTVIEW_FindItemW(infoPtr, nStart, &fiw);
-  if (hasText) textfreeT((LPWSTR)fiw.psz, FALSE);
-  return res;
+    BOOL hasText = lpFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL);
+    LVFINDINFOW fiw;
+    INT res;
+
+    memcpy(&fiw, lpFindInfo, sizeof(fiw));
+    if (hasText) fiw.psz = textdupTtoW((LPCWSTR)lpFindInfo->psz, FALSE);
+    res = LISTVIEW_FindItemW(infoPtr, nStart, &fiw);
+    if (hasText) textfreeT((LPWSTR)fiw.psz, FALSE);
+    return res;
 }
 
 /***
@@ -4624,30 +4622,19 @@
  */
 static INT LISTVIEW_GetCountPerPage(LISTVIEW_INFO *infoPtr)
 {
-  UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
-  INT nItemCount = 0;
-
-  if (uView == LVS_LIST)
-  {
-    if (infoPtr->rcList.right > infoPtr->nItemWidth)
+    switch (infoPtr->dwStyle & LVS_TYPEMASK)
     {
-      nItemCount = LISTVIEW_GetCountPerRow(infoPtr) *
-                   LISTVIEW_GetCountPerColumn(infoPtr);
+    case LVS_ICON:
+    case LVS_SMALLICON:
+	return infoPtr->nItemCount;
+    case LVS_REPORT:
+	return LISTVIEW_GetCountPerColumn(infoPtr);
+    case LVS_LIST:
+	return LISTVIEW_GetCountPerRow(infoPtr) * LISTVIEW_GetCountPerColumn(infoPtr);
     }
-  }
-  else if (uView == LVS_REPORT)
-  {
-    nItemCount = LISTVIEW_GetCountPerColumn(infoPtr);
-  }
-  else
-  {
-    nItemCount = infoPtr->nItemCount;
-  }
-
-  return nItemCount;
+    assert(FALSE);
 }
 
-
 /***
  * DESCRIPTION:
  * Retrieves an image list handle.
@@ -6945,9 +6932,6 @@
   infoPtr->iconStateSize.cx = GetSystemMetrics(SM_CXSMICON);
   infoPtr->iconStateSize.cy = GetSystemMetrics(SM_CYSMICON);
 
-  /* display unsupported listview window styles */
-  LISTVIEW_UnsupportedStyles(lpcs->style);
-
   /* allocate memory for the data structure */
   infoPtr->hdpaItems = DPA_Create(10);
   infoPtr->hdpaPosX  = DPA_Create(10);
@@ -7465,7 +7449,11 @@
       if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
       {
         if (bGroupSelect)
+	{
           LISTVIEW_AddGroupSelection(infoPtr, nItem);
+    	  LISTVIEW_SetItemFocus(infoPtr, nItem);
+          infoPtr->nSelectionMark = nItem;
+	}
         else
 	{
           LVITEMW item;
@@ -8135,9 +8123,6 @@
     /* invalidate client area + erase background */
     LISTVIEW_InvalidateList(infoPtr);
 
-    /* print the list of unsupported window styles */
-    LISTVIEW_UnsupportedStyles(lpss->styleNew);
-
     return 0;
 }
 




More information about the wine-patches mailing list