Listview Q5

Dimitrie O. Paun dpaun at rogers.com
Mon Oct 14 23:22:55 CDT 2002


This one removes the updating of the max item lenght when setting
an item's text. AFAICS, that's not used right now, but I'm curious
if this breaks anything for anyone.

Rein, does this one fix the color of the item in your news reader?

Alexandre, I'm done with the Q-series, commit at will! ;)

ChangeLog
  Fix iterator creation for LVS_LIST mode
  Do not update the infoPtr->nItemWidth in set_main_item
  Better handling of text bk colour in custom draw
  Rename GetItemListOrigin to GetItemOrigin
  A bunch of code cleanups, simplifications, etc.

--- dlls/comctl32/listview.c.Q4	Mon Oct 14 22:59:14 2002
+++ dlls/comctl32/listview.c	Tue Oct 15 00:07:38 2002
@@ -123,6 +123,7 @@
   COLORREF clrBk;
   COLORREF clrText;
   COLORREF clrTextBk;
+  COLORREF clrTextBkDefault;
   HIMAGELIST himlNormal;
   HIMAGELIST himlSmall;
   HIMAGELIST himlState;
@@ -153,7 +154,6 @@
   HCURSOR hHotCursor;
   HFONT hFont;
   INT ntmHeight;		/*  from GetTextMetrics from above font */
-  INT ntmAveCharWidth;		/*  from GetTextMetrics from above font */
   BOOL bRedraw;
   BOOL bFocus;
   INT nFocusedItem;
@@ -275,7 +275,7 @@
 static void LISTVIEW_AlignTop(LISTVIEW_INFO *);
 static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *, INT);
 static INT LISTVIEW_CalculateMaxHeight(LISTVIEW_INFO *);
-static BOOL LISTVIEW_GetItemListOrigin(LISTVIEW_INFO *, INT, LPPOINT);
+static BOOL LISTVIEW_GetItemOrigin(LISTVIEW_INFO *, INT, LPPOINT);
 static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *, INT, LPPOINT);
 static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *, INT, LPRECT);
 static INT LISTVIEW_CalculateMaxWidth(LISTVIEW_INFO *);
@@ -947,7 +947,7 @@
 	if (nLastCol < nFirstCol || nLastRow < nFirstRow) return TRUE;
 
 	if (!(i->ranges = DPA_Create(nLastCol - nFirstCol + 1))) return FALSE;
-	for (nCol = nFirstCol; nCol < nLastCol; nCol++)
+	for (nCol = nFirstCol; nCol <= nLastCol; nCol++)
 	{
 	    item_range.lower = nCol * nPerCol + nFirstRow;
 	    if(item_range.lower >= infoPtr->nItemCount) break;
@@ -994,7 +994,7 @@
     /* now delete the invisible items from the list */
     while(iterator_next(i))
     {
-	if (!LISTVIEW_GetItemListOrigin(infoPtr, i->nItem, &Position)) continue;
+	if (!LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position)) continue;
 	rcItem.left = Position.x + Origin.x;
 	rcItem.top = Position.y + Origin.y;
 	rcItem.right = rcItem.left + infoPtr->nItemWidth;
@@ -1038,7 +1038,7 @@
     POINT Origin, Position; \
     RECT rcBox; \
     if (LISTVIEW_GetOrigin(infoPtr, &Origin) && \
-	LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position) && \
+	LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position) && \
         Header_GetItemRect(infoPtr->hwndHeader, nSubItem, &rcBox)) { \
 	OffsetRect(&rcBox, Origin.x + Position.x, Origin.y + Position.y); \
 	LISTVIEW_InvalidateRect(infoPtr, &rcBox); \
@@ -1510,7 +1510,7 @@
  *   TRUE if computations OK
  *   FALSE otherwise
  */
-static BOOL LISTVIEW_GetItemListOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lpptPosition)
+static BOOL LISTVIEW_GetItemOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lpptPosition)
 {
     UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
 
@@ -1787,7 +1787,6 @@
  * [I] infoPtr : valid pointer to the listview structure
  * [I] nItem : item number
  * [O] lprcBox : ptr to Box rectangle
- *                The internal LVIR_BOX rectangle
  *
  * RETURN:
  *   TRUE if computations OK
@@ -1800,7 +1799,7 @@
     POINT Position, Origin;
     LVITEMW lvItem;
 
-    if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE;
+    if (!LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position)) return FALSE;
     if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
 
     /* Be smart and try to figure out the minimum we have to do */
@@ -2001,8 +2000,7 @@
  *   SUCCESS : subitem pointer
  *   FAILURE : NULL
  */
-static LISTVIEW_SUBITEM* LISTVIEW_GetSubItemPtr(HDPA hdpaSubItems,
-                                                INT nSubItem)
+static LISTVIEW_SUBITEM* LISTVIEW_GetSubItemPtr(HDPA hdpaSubItems, INT nSubItem)
 {
     LISTVIEW_SUBITEM *lpSubItem;
     INT i;
@@ -2102,22 +2100,17 @@
  */
 static void LISTVIEW_SaveTextMetrics(LISTVIEW_INFO *infoPtr)
 {
-  TEXTMETRICW tm;
-  HDC hdc = GetDC(infoPtr->hwndSelf);
-  HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
-  INT oldHeight, oldACW;
-
-  GetTextMetricsW(hdc, &tm);
-
-  oldHeight = infoPtr->ntmHeight;
-  oldACW = infoPtr->ntmAveCharWidth;
-  infoPtr->ntmHeight = tm.tmHeight;
-  infoPtr->ntmAveCharWidth = tm.tmAveCharWidth;
-
-  SelectObject(hdc, hOldFont);
-  ReleaseDC(infoPtr->hwndSelf, hdc);
-  TRACE("tmHeight old=%d,new=%d; tmAveCharWidth old=%d,new=%d\n",
-        oldHeight, infoPtr->ntmHeight, oldACW, infoPtr->ntmAveCharWidth);
+    HDC hdc = GetDC(infoPtr->hwndSelf);
+    HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
+    HFONT hOldFont = SelectObject(hdc, hFont);
+    TEXTMETRICW tm;
+
+    if (GetTextMetricsW(hdc, &tm))
+	infoPtr->ntmHeight = tm.tmHeight;
+    SelectObject(hdc, hOldFont);
+    ReleaseDC(infoPtr->hwndSelf, hdc);
+    
+    TRACE("tmHeight=%d\n", infoPtr->ntmHeight);
 }
 
 
@@ -2531,6 +2524,18 @@
     return oldFocus != infoPtr->nFocusedItem;
 }
 
+/* Helper function for LISTVIEW_ShiftIndices *only* */
+static INT shift_item(LISTVIEW_INFO *infoPtr, INT nShiftItem, INT nItem, INT direction)
+{
+    if (nShiftItem < nItem) return nShiftItem;
+
+    if (nShiftItem > nItem) return nShiftItem + direction;
+
+    if (direction > 0) return nShiftItem + direction;
+
+    return min(nShiftItem, infoPtr->nItemCount - 1);
+}
+
 /**
 * DESCRIPTION:
 * Updates the various indices after an item has been inserted or deleted.
@@ -2545,36 +2550,21 @@
 */
 static void LISTVIEW_ShiftIndices(LISTVIEW_INFO *infoPtr, INT nItem, INT direction)
 {
-  TRACE("Shifting %iu, %i steps\n", nItem, direction);
+    INT nNewFocus;
+    
+    TRACE("Shifting %iu, %i steps\n", nItem, direction);
 
-  ranges_shift(infoPtr->hdpaSelectionRanges, nItem, direction);
+    ranges_shift(infoPtr->hdpaSelectionRanges, nItem, direction);
 
-  /* Note that the following will fail if direction != +1 and -1 */
-  if (infoPtr->nSelectionMark > nItem)
-      infoPtr->nSelectionMark += direction;
-  else if (infoPtr->nSelectionMark == nItem)
-  {
-    if (direction > 0)
-      infoPtr->nSelectionMark += direction;
-    else if (infoPtr->nSelectionMark >= infoPtr->nItemCount)
-      infoPtr->nSelectionMark = infoPtr->nItemCount - 1;
-  }
+    assert(abs(direction) == 1);
 
-  if (infoPtr->nFocusedItem > nItem)
-    infoPtr->nFocusedItem += direction;
-  else if (infoPtr->nFocusedItem == nItem)
-  {
-    if (direction > 0)
-      infoPtr->nFocusedItem += direction;
-    else
-    {
-      if (infoPtr->nFocusedItem >= infoPtr->nItemCount)
-        infoPtr->nFocusedItem = infoPtr->nItemCount - 1;
-      if (infoPtr->nFocusedItem >= 0)
-        LISTVIEW_SetItemFocus(infoPtr, infoPtr->nFocusedItem);
-    }
-  }
-  /* But we are not supposed to modify nHotItem! */
+    infoPtr->nSelectionMark = shift_item(infoPtr, infoPtr->nSelectionMark, nItem, direction);
+
+    nNewFocus = shift_item(infoPtr, infoPtr->nFocusedItem, nItem, direction);
+    if (nNewFocus != infoPtr->nFocusedItem)
+        LISTVIEW_SetItemFocus(infoPtr, nNewFocus);
+    
+    /* But we are not supposed to modify nHotItem! */
 }
 
 
@@ -2914,7 +2904,6 @@
 static BOOL set_main_item(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW)
 {
     LONG lStyle = infoPtr->dwStyle;
-    UINT uView = lStyle & LVS_TYPEMASK;
     HDPA hdpaSubItems;
     LISTVIEW_ITEM *lpItem;
     NMLISTVIEW nmlv;
@@ -2994,13 +2983,6 @@
 	}
     }
 
-    /* if LVS_LIST or LVS_SMALLICON, update the width of the items */
-    if((uChanged & LVIF_TEXT) && ((uView == LVS_LIST) || (uView == LVS_SMALLICON)))
-    {
-	int item_width = LISTVIEW_CalculateItemWidth(infoPtr, lpLVItem->iItem);
-	if(item_width > infoPtr->nItemWidth) infoPtr->nItemWidth = item_width;
-    }
-
     /* if we're inserting the item, we're done */
     if (!lpItem->valid) return TRUE;
     
@@ -3196,19 +3178,6 @@
     return nItem;
 }
 
-/* helper function for the drawing code */
-static void select_text_attr(LISTVIEW_INFO *infoPtr, HDC hdc, NMLVCUSTOMDRAW *lpnmlvcd)
-{
-    if ( (lpnmlvcd->clrTextBk != CLR_DEFAULT) && (lpnmlvcd->clrTextBk != CLR_NONE) )
-    {
-	SetBkMode(hdc, OPAQUE);
-	SetBkColor(hdc, lpnmlvcd->clrTextBk);
-    }
-    else
-	SetBkMode(hdc, TRANSPARENT);
-
-    SetTextColor(hdc, lpnmlvcd->clrText);
-}
 
 /***
  * DESCRIPTION:
@@ -3306,7 +3275,11 @@
     /* Don't bother painting item being edited */
     if (infoPtr->bEditing && lprcFocus && nSubItem == 0) goto postpaint;
 
-    select_text_attr(infoPtr, hdc, &nmlvcd);
+    /* Set the text attributes */
+    SetBkMode(hdc, nmlvcd.clrTextBk == CLR_NONE ? TRANSPARENT : OPAQUE);
+    if (nmlvcd.clrTextBk != CLR_NONE)
+	SetBkColor(hdc, nmlvcd.clrTextBk == CLR_DEFAULT ? infoPtr->clrTextBkDefault : nmlvcd.clrTextBk);
+    SetTextColor(hdc, nmlvcd.clrText);
 
     /* draw the selection background, if we're drawing the main item */
     if (nSubItem == 0)
@@ -3407,7 +3380,7 @@
 	if (infoPtr->bFocus && (item.state & LVIS_FOCUSED)) dis.itemState |= ODS_FOCUS;
 	dis.hwndItem = infoPtr->hwndSelf;
 	dis.hDC = hdc;
-	if (!LISTVIEW_GetItemListOrigin(infoPtr, dis.itemID, &Position)) continue;
+	if (!LISTVIEW_GetItemOrigin(infoPtr, dis.itemID, &Position)) continue;
 	dis.rcItem.left = Position.x + Origin.x;
 	dis.rcItem.right = dis.rcItem.left + infoPtr->nItemWidth;
 	dis.rcItem.top = Position.y + Origin.y;
@@ -3478,7 +3451,7 @@
 	/* iterate through the invalidated columns */
 	for (nCol = nFirstCol; nCol <= nLastCol; nCol++)
 	{
-	    if (!LISTVIEW_GetItemListOrigin(infoPtr, i.nItem, &Position)) continue;
+	    if (!LISTVIEW_GetItemOrigin(infoPtr, i.nItem, &Position)) continue;
 	    Position.x += Origin.x;
 	    Position.y += Origin.y;
 
@@ -3526,7 +3499,7 @@
     
     while(iterator_prev(&i))
     {
-	if (!LISTVIEW_GetItemListOrigin(infoPtr, i.nItem, &Position)) continue;
+	if (!LISTVIEW_GetItemOrigin(infoPtr, i.nItem, &Position)) continue;
 	Position.x += Origin.x;
 	Position.y += Origin.y;
 
@@ -3550,7 +3523,7 @@
 static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc)
 {
     UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
-    COLORREF oldBkColor, oldTextColor;
+    COLORREF oldTextColor;
     NMLVCUSTOMDRAW nmlvcd;
     HFONT hOldFont;
     DWORD cdmode;
@@ -3564,7 +3537,7 @@
     /* save dc values we're gonna trash while drawing */
     hOldFont = SelectObject(hdc, infoPtr->hFont);
     oldBkMode = GetBkMode(hdc);
-    oldBkColor = GetBkColor(hdc);
+    infoPtr->clrTextBkDefault = GetBkColor(hdc);
     oldTextColor = GetTextColor(hdc);
    
     GetClientRect(infoPtr->hwndSelf, &rcClient);
@@ -3596,7 +3569,7 @@
     /* unselect objects */
     SelectObject(hdc, hOldFont);
     SetBkMode(hdc, oldBkMode);
-    SetBkColor(hdc, oldBkColor);
+    SetBkColor(hdc, infoPtr->clrTextBkDefault);
     SetTextColor(hdc, oldTextColor);
     infoPtr->bIsDrawing = FALSE;
 }
@@ -4018,7 +3991,7 @@
       DPA_DeletePtr(infoPtr->hdpaPosY, nItem);
     }
 
-    LISTVIEW_ShiftIndices(infoPtr,nItem,-1);
+    LISTVIEW_ShiftIndices(infoPtr, nItem, -1);
 
     /* align items (set position of each item) */
     if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
@@ -4330,7 +4303,7 @@
 	
 	/* This is very inefficient. To do a good job here,
 	 * we need a sorted array of (x,y) item positions */
-	if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) continue;
+	if (!LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position)) continue;
 
 	/* compute the distance^2 to the destination */
 	xdist = Destination.x - Position.x;
@@ -4894,7 +4867,7 @@
     TRACE("(nItem=%d, lpptPosition=%p)\n", nItem, lpptPosition);
 
     if (!lpptPosition || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE;
-    if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, lpptPosition)) return FALSE;
+    if (!LISTVIEW_GetItemOrigin(infoPtr, nItem, lpptPosition)) return FALSE;
     if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
 
     if (uView == LVS_ICON)
@@ -4984,7 +4957,7 @@
 
     if (!lprc || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE;
     if (!LISTVIEW_GetOrigin(infoPtr, &Origin)) return FALSE;
-    if (!LISTVIEW_GetItemListOrigin(infoPtr, nItem, &Position)) return FALSE;
+    if (!LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position)) return FALSE;
 
     /* Be smart and try to figure out the minimum we have to do */
     if (lprc->left == LVIR_ICON) doLabel = FALSE;
@@ -5057,6 +5030,7 @@
  * 
  * NOTE: for subItem = 0, we should return the bounds of the _entire_ item,
  *       not only those of the first column.
+ *       Fortunately, LISTVIEW_GetItemMetrics does the right thing.
  * 
  * RETURN:
  *     TRUE: success
@@ -5523,7 +5497,7 @@
     if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return -1;
     
     if (!LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, &rcState, &rcIcon, &rcLabel)) return -1;
-    if (!LISTVIEW_GetItemListOrigin(infoPtr, lpht->iItem, &Position)) return -1;
+    if (!LISTVIEW_GetItemOrigin(infoPtr, lpht->iItem, &Position)) return -1;
     opt.x = lpht->pt.x - Position.x - Origin.x;
     opt.y = lpht->pt.y - Position.y - Origin.y;
     




More information about the wine-patches mailing list