A new series begins, but this one's a little special, being the last letter of our beloved alphabet. I would like to keep this open until people agree that the listview is _solid_, flicker free, fast, and a pleasure to interact with. Mind you that this series is not meant to solve all problems -- I will defer new features for later. But what it should do is stabilize what we have already. That is to say, after this series is complete, I would like to turn my attention to new features, with the knowladge that the already implemented ones are solid. This will give everybody a sense of progress, as we watch the TODO header get shorter :) So once again, if you have complaints, _please_ let them be heard (or read, or what have you) This one fixes the refresh problem in Xnews reported by Paul Rupe. It also eliminates some potential flicker, and tries to solve world hunger. ChangeLog Rewrite of the SetItemCount: bugs got squashed, LVSICF_{NOSCROLL,NOINVALIDATEALL} implemented. Index: dlls/comctl32/listview.c =================================================================== RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v retrieving revision 1.312 diff -u -r1.312 listview.c --- dlls/comctl32/listview.c 25 Oct 2002 03:21:25 -0000 1.312 +++ dlls/comctl32/listview.c 25 Oct 2002 05:37:46 -0000 @@ -53,7 +53,6 @@ * -- LISTVIEW_StyleChanged doesn't handle some changes too well * * Speedups - * -- LISTVIEW_SetItemCount is too invalidation happy * -- LISTVIEW_Size invalidates too much * -- in sorted mode, LISTVIEW_InsertItemT sorts the array, * instead of inserting in the right spot @@ -6521,46 +6520,79 @@ */ static BOOL LISTVIEW_SetItemCount(LISTVIEW_INFO *infoPtr, INT nItems, DWORD dwFlags) { - TRACE("(nItems=%d, dwFlags=%lx)\n", nItems, dwFlags); + TRACE("(nItems=%d, dwFlags=%lx)\n", nItems, dwFlags); - if (infoPtr->dwStyle & LVS_OWNERDATA) - { - int precount,topvisible; - - TRACE("LVS_OWNERDATA is set!\n"); - if (dwFlags & (LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL)) - FIXME("flags %s %s not implemented\n", - (dwFlags & LVSICF_NOINVALIDATEALL) ? "LVSICF_NOINVALIDATEALL" - : "", - (dwFlags & LVSICF_NOSCROLL) ? "LVSICF_NOSCROLL" : ""); + if (infoPtr->dwStyle & LVS_OWNERDATA) + { + UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; + INT nOldCount = infoPtr->nItemCount; - LISTVIEW_DeselectAll(infoPtr); + LISTVIEW_DeselectAll(infoPtr); + infoPtr->nItemCount = nItems; + LISTVIEW_UpdateScroll(infoPtr); - precount = infoPtr->nItemCount; - topvisible = LISTVIEW_GetTopIndex(infoPtr) + - LISTVIEW_GetCountPerColumn(infoPtr) + 1; + /* the flags are valid only in ownerdata report and list modes */ + if (uView == LVS_ICON || uView == LVS_SMALLICON) dwFlags = 0; - infoPtr->nItemCount = nItems; - LISTVIEW_UpdateItemSize(infoPtr); + if (!(dwFlags & LVSICF_NOSCROLL)) + LISTVIEW_EnsureVisible(infoPtr, nItems - 1, FALSE); - LISTVIEW_UpdateSize(infoPtr); - LISTVIEW_UpdateScroll(infoPtr); + if (!(dwFlags & LVSICF_NOINVALIDATEALL)) + LISTVIEW_InvalidateList(infoPtr); + else + { + INT nFrom, nTo; + POINT Origin; + RECT rcErase; + + LISTVIEW_GetOrigin(infoPtr, &Origin); + nFrom = min(nOldCount, nItems); + nTo = max(nOldCount, nItems); + + if (uView == LVS_REPORT) + { + rcErase.left = 0; + rcErase.top = nFrom * infoPtr->nItemHeight; + rcErase.right = infoPtr->nItemWidth; + rcErase.bottom = nTo * infoPtr->nItemHeight; + OffsetRect(&rcErase, Origin.x, Origin.y); + if (IntersectRect(&rcErase, &rcErase, &infoPtr->rcList)) + LISTVIEW_InvalidateRect(infoPtr, &rcErase); + } + else /* LVS_LIST */ + { + INT nPerCol = LISTVIEW_GetCountPerColumn(infoPtr); - if (min(precount,infoPtr->nItemCount) < topvisible) - LISTVIEW_InvalidateList(infoPtr); /* FIXME: optimize */ - } - else - { - /* According to MSDN for non-LVS_OWNERDATA this is just - * a performance issue. The control allocates its internal - * data structures for the number of items specified. It - * cuts down on the number of memory allocations. Therefore - * we will just issue a WARN here - */ - WARN("for non-ownerdata performance option not implemented.\n"); - } + rcErase.left = (nFrom / nPerCol) * infoPtr->nItemWidth; + rcErase.top = (nFrom % nPerCol) * infoPtr->nItemHeight; + rcErase.right = rcErase.left + infoPtr->nItemWidth; + rcErase.bottom = nPerCol * infoPtr->nItemHeight; + OffsetRect(&rcErase, Origin.x, Origin.y); + if (IntersectRect(&rcErase, &rcErase, &infoPtr->rcList)) + LISTVIEW_InvalidateRect(infoPtr, &rcErase); + + rcErase.left = (nFrom / nPerCol + 1) * infoPtr->nItemWidth; + rcErase.top = 0; + rcErase.right = (nTo / nPerCol + 1) * infoPtr->nItemWidth; + rcErase.bottom = nPerCol * infoPtr->nItemHeight; + OffsetRect(&rcErase, Origin.x, Origin.y); + if (IntersectRect(&rcErase, &rcErase, &infoPtr->rcList)) + LISTVIEW_InvalidateRect(infoPtr, &rcErase); + } + } + } + else + { + /* According to MSDN for non-LVS_OWNERDATA this is just + * a performance issue. The control allocates its internal + * data structures for the number of items specified. It + * cuts down on the number of memory allocations. Therefore + * we will just issue a WARN here + */ + WARN("for non-ownerdata performance option not implemented.\n"); + } - return TRUE; + return TRUE; } /*** -- Dimi.