shell32/shellview: Get rid of intermediate pointer array when filling ListView.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2017-01-25 22:51:30 +03:00 committed by Alexandre Julliard
parent 970029bb9b
commit a26d6e375e
1 changed files with 34 additions and 57 deletions

View File

@ -110,6 +110,7 @@ typedef struct
LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */ LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */ UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
POINT ptLastMousePos; /* Mouse position at last DragOver call */ POINT ptLastMousePos; /* Mouse position at last DragOver call */
UINT columns; /* Number of shell folder columns */
} IShellViewImpl; } IShellViewImpl;
static inline IShellViewImpl *impl_from_IShellView3(IShellView3 *iface) static inline IShellViewImpl *impl_from_IShellView3(IShellView3 *iface)
@ -383,7 +384,6 @@ static void ShellView_InitList(IShellViewImpl *This)
SHELLDETAILS sd; SHELLDETAILS sd;
WCHAR nameW[50]; WCHAR nameW[50];
HRESULT hr; HRESULT hr;
INT i;
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
@ -405,39 +405,36 @@ static void ShellView_InitList(IShellViewImpl *This)
} }
} }
for (i = 0; 1; i++) for (This->columns = 0;; This->columns++)
{ {
if (This->pSF2Parent) if (This->pSF2Parent)
hr = IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd); hr = IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, This->columns, &sd);
else else
hr = IShellDetails_GetDetailsOf(details, NULL, i, &sd); hr = IShellDetails_GetDetailsOf(details, NULL, This->columns, &sd);
if (FAILED(hr)) break; if (FAILED(hr)) break;
lvColumn.fmt = sd.fmt; lvColumn.fmt = sd.fmt;
lvColumn.cx = sd.cxChar*8; /* chars->pixel */ lvColumn.cx = sd.cxChar*8; /* chars->pixel */
StrRetToStrNW(nameW, sizeof(nameW)/sizeof(WCHAR), &sd.str, NULL); StrRetToStrNW(nameW, sizeof(nameW)/sizeof(WCHAR), &sd.str, NULL);
SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn); SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, This->columns, (LPARAM)&lvColumn);
} }
if (details) IShellDetails_Release(details); if (details) IShellDetails_Release(details);
} }
/********************************************************** /* LVM_SORTITEMS callback used when initially inserting items */
* ShellView_CompareItems() static INT CALLBACK ShellView_CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
*
* NOTES
* internal, CALLBACK for DSA_Sort
*/
static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
{ {
int ret; LPITEMIDLIST pidl1 = (LPITEMIDLIST)lParam1;
TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData); LPITEMIDLIST pidl2 = (LPITEMIDLIST)lParam2;
IShellFolder *folder = (IShellFolder *)lpData;
int ret;
if(!lpData) return 0; TRACE("pidl1=%p, pidl2=%p, shellfolder=%p\n", pidl1, pidl2, folder);
ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2)); ret = (SHORT)HRESULT_CODE(IShellFolder_CompareIDs(folder, 0, pidl1, pidl2));
TRACE("ret=%i\n",ret); TRACE("ret=%i\n", ret);
return ret; return ret;
} }
/************************************************************************* /*************************************************************************
@ -568,19 +565,19 @@ static int LV_FindItemByPidl(
/********************************************************** /**********************************************************
* LV_AddItem() * LV_AddItem()
*/ */
static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl) static void shellview_add_item(IShellViewImpl * This, LPCITEMIDLIST pidl)
{ {
LVITEMW lvItem; LVITEMW lvItem;
TRACE("(%p)(pidl=%p)\n", This, pidl); TRACE("(%p)(pidl=%p)\n", This, pidl);
lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/ lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
lvItem.iItem = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0); /*add the item to the end of the list*/ lvItem.iItem = 0;
lvItem.iSubItem = 0; lvItem.iSubItem = 0;
lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/ lvItem.lParam = (LPARAM)pidl;
lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/ lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
return ListView_InsertItemW(This->hWndList, &lvItem) != -1; ListView_InsertItemW(This->hWndList, &lvItem);
} }
/********************************************************** /**********************************************************
@ -618,16 +615,6 @@ static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCIT
* - fills the list into the view * - fills the list into the view
*/ */
static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
{
LPITEMIDLIST pidl = ptr;
IShellViewImpl *This = arg;
/* in a commdlg This works as a filemask*/
if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
SHFree(pidl);
return TRUE;
}
static HRESULT ShellView_FillList(IShellViewImpl *This) static HRESULT ShellView_FillList(IShellViewImpl *This)
{ {
IFolderView2 *folderview = &This->IFolderView2_iface; IFolderView2 *folderview = &This->IFolderView2_iface;
@ -635,40 +622,28 @@ static HRESULT ShellView_FillList(IShellViewImpl *This)
LPITEMIDLIST pidl; LPITEMIDLIST pidl;
DWORD fetched; DWORD fetched;
HRESULT hr; HRESULT hr;
HDPA hdpa;
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
/* get the itemlist from the shfolder*/ /* get the itemlist from the shfolder*/
hr = IShellFolder_EnumObjects(This->pSFParent, This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList); hr = IShellFolder_EnumObjects(This->pSFParent, This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
if (hr != S_OK) return hr; if (hr != S_OK)
return hr;
/* create a pointer array */
hdpa = DPA_Create(16);
if (!hdpa)
{
IEnumIDList_Release(pEnumIDList);
return E_OUTOFMEMORY;
}
/* copy the items into the array*/
while((S_OK == IEnumIDList_Next(pEnumIDList, 1, &pidl, &fetched)) && fetched)
{
if (DPA_InsertPtr(hdpa, DPA_GetPtrCount(hdpa), pidl) == -1)
{
SHFree(pidl);
}
}
/* sort the array */
DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
IFolderView2_SetRedraw(folderview, FALSE); IFolderView2_SetRedraw(folderview, FALSE);
DPA_DestroyCallback(hdpa, fill_list, This);
/* copy the items into the array */
while ((S_OK == IEnumIDList_Next(pEnumIDList, 1, &pidl, &fetched)) && fetched)
{
if (IncludeObject(This, pidl) == S_OK)
shellview_add_item(This, pidl);
}
SendMessageW(This->hWndList, LVM_SORTITEMS, (WPARAM)This->pSFParent, (LPARAM)ShellView_CompareItems);
IFolderView2_SetRedraw(folderview, TRUE); IFolderView2_SetRedraw(folderview, TRUE);
IEnumIDList_Release(pEnumIDList); IEnumIDList_Release(pEnumIDList);
return S_OK; return S_OK;
} }
@ -1626,6 +1601,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST *pidls, LONG event) static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST *pidls, LONG event)
{ {
LPCITEMIDLIST pidl;
BOOL ret = TRUE; BOOL ret = TRUE;
TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pidls[0], pidls[1], event); TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pidls[0], pidls[1], event);
@ -1634,7 +1610,8 @@ static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST *pi
{ {
case SHCNE_MKDIR: case SHCNE_MKDIR:
case SHCNE_CREATE: case SHCNE_CREATE:
LV_AddItem(This, pidls[0]); pidl = ILClone(ILFindLastID(pidls[0]));
shellview_add_item(This, pidl);
break; break;
case SHCNE_RMDIR: case SHCNE_RMDIR:
case SHCNE_DELETE: case SHCNE_DELETE: