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.