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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@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.



[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux