PATCH: Inserting an item in a listview sometimes generates incorrect messages

Adam Gundy arg at cyberscience.com
Wed Mar 5 08:28:29 CST 2003


Hi. If an item is inserted in a listview and this causes the focus to
change, we must not send change notifications (Windows doesn't) - this caused
our change handler to fall over because the item information was NULL.

Cyberscience disclaims all copyright and responsibility... ;-)

Changelog:

        * dlls/comctl32/listview.c: Adam Gundy <arg at cyberscience.com>
        When shifting the list's indices, we must not send notify messages
        if we have to refocus. Item modification handlers are not supposed
        to be called here.

diff -u -r wine-20030219/dlls/comctl32/listview.c wine-20030219-new/dlls/comctl32/listview.c
--- wine-20030219/dlls/comctl32/listview.c      Fri Feb 14 23:31:45 2003
+++ wine-20030219-new/dlls/comctl32/listview.c  Wed Mar  5 11:20:35 2003
@@ -374,7 +374,7 @@
 static void LISTVIEW_GetOrigin(LISTVIEW_INFO *, LPPOINT);
 static BOOL LISTVIEW_GetViewRect(LISTVIEW_INFO *, LPRECT);
 static void LISTVIEW_SetGroupSelection(LISTVIEW_INFO *, INT);
-static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *, const LVITEMW *, BOOL);
+static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *, const LVITEMW *, BOOL, BOOL);
 static void LISTVIEW_UpdateScroll(LISTVIEW_INFO *);
 static void LISTVIEW_SetSelection(LISTVIEW_INFO *, INT);
 static void LISTVIEW_UpdateSize(LISTVIEW_INFO *);
@@ -384,7 +384,7 @@
 static INT LISTVIEW_GetStringWidthT(LISTVIEW_INFO *, LPCWSTR, BOOL);
 static BOOL LISTVIEW_KeySelection(LISTVIEW_INFO *, INT);
 static UINT LISTVIEW_GetItemState(LISTVIEW_INFO *, INT, UINT);
-static BOOL LISTVIEW_SetItemState(LISTVIEW_INFO *, INT, const LVITEMW *);
+static BOOL LISTVIEW_SetItemState(LISTVIEW_INFO *, INT, BOOL, const LVITEMW *);
 static LRESULT LISTVIEW_VScroll(LISTVIEW_INFO *, INT, INT, HWND);
 static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *, INT, INT, HWND);
 static INT LISTVIEW_GetTopIndex(LISTVIEW_INFO *);
@@ -2721,7 +2721,7 @@
     if (!(clone = ranges_clone(infoPtr->selectionRanges))) return FALSE;
     iterator_rangesitems(&i, ranges_diff(clone, toSkip));
     while(iterator_next(&i))
-       LISTVIEW_SetItemState(infoPtr, i.nItem, &lvItem);
+       LISTVIEW_SetItemState(infoPtr, i.nItem, TRUE, &lvItem);
     /* note that the iterator destructor will free the cloned range */
     iterator_destroy(&i);
 
@@ -2786,7 +2786,7 @@
  *   TRUE : focused item changed
  *   FALSE : focused item has NOT changed
  */
-static inline BOOL LISTVIEW_SetItemFocus(LISTVIEW_INFO *infoPtr, INT nItem)
+static inline BOOL LISTVIEW_SetItemFocus(LISTVIEW_INFO *infoPtr, INT nItem, BOOL notify)
 {
     INT oldFocus = infoPtr->nFocusedItem;
     LVITEMW lvItem;
@@ -2795,7 +2795,7 @@
     
     lvItem.state =  nItem == -1 ? 0 : LVIS_FOCUSED;
     lvItem.stateMask = LVIS_FOCUSED;
-    LISTVIEW_SetItemState(infoPtr, nItem == -1 ? infoPtr->nFocusedItem : nItem, &lvItem);
+    LISTVIEW_SetItemState(infoPtr, nItem == -1 ? infoPtr->nFocusedItem : nItem, notify, &lvItem);
 
     return oldFocus != infoPtr->nFocusedItem;
 }
@@ -2838,7 +2838,7 @@
 
     nNewFocus = shift_item(infoPtr, infoPtr->nFocusedItem, nItem, direction);
     if (nNewFocus != infoPtr->nFocusedItem)
-        LISTVIEW_SetItemFocus(infoPtr, nNewFocus);
+        LISTVIEW_SetItemFocus(infoPtr, nNewFocus, FALSE);
     
     /* But we are not supposed to modify nHotItem! */
 }
@@ -2874,7 +2874,7 @@
      * See MSDN documentation for LVN_ITEMCHANGED.
      */
     for (i = nFirst; i <= nLast; i++)
-       LISTVIEW_SetItemState(infoPtr,i,&item);
+       LISTVIEW_SetItemState(infoPtr,i,TRUE,&item);
 }
 
 
@@ -2939,11 +2939,11 @@
     LISTVIEW_DeselectAllSkipItems(infoPtr, selection);
     iterator_rangesitems(&i, selection);
     while(iterator_next(&i))
-       LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
+       LISTVIEW_SetItemState(infoPtr, i.nItem, TRUE, &item);
     /* this will also destroy the selection */
     iterator_destroy(&i);
     
-    LISTVIEW_SetItemFocus(infoPtr, nItem);
+    LISTVIEW_SetItemFocus(infoPtr, nItem, TRUE);
 }
 
 /***
@@ -2967,7 +2967,7 @@
 
     lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
     lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
-    LISTVIEW_SetItemState(infoPtr, nItem, &lvItem);
+    LISTVIEW_SetItemState(infoPtr, nItem, TRUE, &lvItem);
 
     infoPtr->nSelectionMark = nItem;
 }
@@ -3007,7 +3007,7 @@
       }
       else if (wCtrl)
       {
-        bResult = LISTVIEW_SetItemFocus(infoPtr, nItem);
+        bResult = LISTVIEW_SetItemFocus(infoPtr, nItem, TRUE);
       }
       else
       {
@@ -3220,7 +3220,7 @@
        {
            if (lpLVItem->state & LVIS_FOCUSED)
            {
-               LISTVIEW_SetItemFocus(infoPtr, -1);
+               LISTVIEW_SetItemFocus(infoPtr, -1, !isNew);
                infoPtr->nFocusedItem = lpLVItem->iItem;
                LISTVIEW_EnsureVisible(infoPtr, lpLVItem->iItem, uView == LVS_LIST);
            }
@@ -3325,7 +3325,7 @@
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL isW)
+static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL notify, BOOL isW)
 {
     UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
     LPWSTR pszText = NULL;
@@ -3349,7 +3349,7 @@
     if (lpLVItem->iSubItem)
        bResult = set_sub_item(infoPtr, lpLVItem, TRUE, &bChanged);
     else
-       bResult = set_main_item(infoPtr, lpLVItem, FALSE, TRUE, &bChanged);
+       bResult = set_main_item(infoPtr, lpLVItem, !notify, TRUE, &bChanged);
 
     /* redraw item, if necessary */
     if (bChanged && !infoPtr->bIsDrawing)
@@ -4224,7 +4224,7 @@
     /* remove selection, and focus */
     item.state = 0;
     item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-    LISTVIEW_SetItemState(infoPtr, nItem, &item);
+    LISTVIEW_SetItemState(infoPtr, nItem, TRUE, &item);
            
     /* send LVN_DELETEITEM notification. */
     notify_deleteitem(infoPtr, nItem);
@@ -4304,7 +4304,7 @@
     dispInfo.item.iSubItem = 0;
     dispInfo.item.pszText = pszText;
     dispInfo.item.cchTextMax = textlenT(pszText, isW);
-    return LISTVIEW_SetItemT(infoPtr, &dispInfo.item, isW);
+    return LISTVIEW_SetItemT(infoPtr, &dispInfo.item, TRUE, isW);
 }
 
 /***
@@ -4341,7 +4341,7 @@
     }
 
     LISTVIEW_SetSelection(infoPtr, nItem);
-    LISTVIEW_SetItemFocus(infoPtr, nItem);
+    LISTVIEW_SetItemFocus(infoPtr, nItem, TRUE);
     LISTVIEW_InvalidateItem(infoPtr, nItem);
 
     rect.left = LVIR_LABEL;
@@ -6742,7 +6742,7 @@
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static BOOL LISTVIEW_SetItemState(LISTVIEW_INFO *infoPtr, INT nItem, const LVITEMW *lpLVItem)
+static BOOL LISTVIEW_SetItemState(LISTVIEW_INFO *infoPtr, INT nItem, BOOL notify, const LVITEMW *lpLVItem)
 {
     BOOL bResult = TRUE;
     LVITEMW lvItem;
@@ -6758,10 +6758,10 @@
     {
        /* apply to all items */
        for (lvItem.iItem = 0; lvItem.iItem < infoPtr->nItemCount; lvItem.iItem++)
-           if (!LISTVIEW_SetItemT(infoPtr, &lvItem, TRUE)) bResult = FALSE;
+           if (!LISTVIEW_SetItemT(infoPtr, &lvItem, notify, TRUE)) bResult = FALSE;
     }
     else
-       bResult = LISTVIEW_SetItemT(infoPtr, &lvItem, TRUE);
+       bResult = LISTVIEW_SetItemT(infoPtr, &lvItem, notify, TRUE);
 
     return bResult;
 }
@@ -6794,7 +6794,7 @@
     
     TRACE("(nItem=%d, lpLVItem=%s, isW=%d)\n", nItem, debuglvitem_t(&lvItem, isW), isW);
 
-    return LISTVIEW_SetItemT(infoPtr, &lvItem, isW); 
+    return LISTVIEW_SetItemT(infoPtr, &lvItem, TRUE, isW);
 }
 
 /***
@@ -6957,7 +6957,7 @@
        {
            item.state = LVIS_SELECTED;
            item.stateMask = LVIS_SELECTED;
-           LISTVIEW_SetItemState(infoPtr, i, &item);
+           LISTVIEW_SetItemState(infoPtr, i, TRUE, &item);
        }
        if (lpItem->state & LVIS_FOCUSED)
        {
@@ -7614,7 +7614,7 @@
         if (bGroupSelect)
        {
           LISTVIEW_AddGroupSelection(infoPtr, nItem);
-         LISTVIEW_SetItemFocus(infoPtr, nItem);
+         LISTVIEW_SetItemFocus(infoPtr, nItem, TRUE);
           infoPtr->nSelectionMark = nItem;
        }
         else
@@ -7624,7 +7624,7 @@
          item.state = LVIS_SELECTED | LVIS_FOCUSED;
          item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
 
-         LISTVIEW_SetItemState(infoPtr,nItem,&item);
+         LISTVIEW_SetItemState(infoPtr,nItem,TRUE,&item);
          infoPtr->nSelectionMark = nItem;
        }
       }
@@ -7636,7 +7636,7 @@
        
        item.state = (bGroupSelect ? LVIS_SELECTED : 0) | LVIS_FOCUSED;
         item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-       LISTVIEW_SetItemState(infoPtr, nItem, &item);
+       LISTVIEW_SetItemState(infoPtr, nItem, TRUE, &item);
         infoPtr->nSelectionMark = nItem;
       }
       else  if (wKey & MK_SHIFT)
@@ -7959,7 +7959,7 @@
   
     if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
     {
-       LISTVIEW_SetItemFocus(infoPtr, nItem);
+       LISTVIEW_SetItemFocus(infoPtr, nItem, TRUE);
        if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL)) &&
             !LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED))
            LISTVIEW_SetSelection(infoPtr, nItem);
@@ -8621,10 +8621,10 @@
   /* case LVM_SETINSERTMARKCOLOR: */
 
   case LVM_SETITEMA:
-    return LISTVIEW_SetItemT(infoPtr, (LPLVITEMW)lParam, FALSE);
+    return LISTVIEW_SetItemT(infoPtr, (LPLVITEMW)lParam, TRUE, FALSE);
 
   case LVM_SETITEMW:
-    return LISTVIEW_SetItemT(infoPtr, (LPLVITEMW)lParam, TRUE);
+    return LISTVIEW_SetItemT(infoPtr, (LPLVITEMW)lParam, TRUE, TRUE);
 
   case LVM_SETITEMCOUNT:
     return LISTVIEW_SetItemCount(infoPtr, (INT)wParam, (DWORD)lParam);
@@ -8640,7 +8640,7 @@
     return LISTVIEW_SetItemPosition(infoPtr, (INT)wParam, *((POINT*)lParam));
 
   case LVM_SETITEMSTATE:
-    return LISTVIEW_SetItemState(infoPtr, (INT)wParam, (LPLVITEMW)lParam);
+    return LISTVIEW_SetItemState(infoPtr, (INT)wParam, TRUE, (LPLVITEMW)lParam);
 
   case LVM_SETITEMTEXTA:
     return LISTVIEW_SetItemTextT(infoPtr, (INT)wParam, (LPLVITEMW)lParam, FALSE);


Seeya,
 Adam
--
Real Programmers don't comment their code. If it was hard to write,
it should be hard to read, and even harder to modify.
These are all my own opinions.




More information about the wine-patches mailing list