[PATCH 1/3] comdlg32: Optimize FILEDLG95_FILENAME_FillFromSelection.
Lauri Kenttä
lauri.kentta at gmail.com
Thu Jun 23 06:29:54 CDT 2016
Related to bug 26803.
Previously the function would loop the files twice, first to count,
then to create a string from the names. This patch removes the
first pass and instead allocates a buffer that is always big enough.
This trades some memory for speed, but since currently selecting
1000 files takes over a minute but the required memory for those
1000 filenames is only 262 kB (worst case), this seems a reasonable
trade-off.
This gives 20% speed-up for selecting 253 files with shift-click.
Signed-off-by: Lauri Kenttä <lauri.kentta at gmail.com>
---
dlls/comdlg32/filedlg.c | 114 +++++++++++++++++++-----------------------------
1 file changed, 44 insertions(+), 70 deletions(-)
diff --git a/dlls/comdlg32/filedlg.c b/dlls/comdlg32/filedlg.c
index 282582b..8e64c1e 100644
--- a/dlls/comdlg32/filedlg.c
+++ b/dlls/comdlg32/filedlg.c
@@ -3626,86 +3626,60 @@ static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
*/
void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd)
{
- FileOpenDlgInfos *fodInfos;
- LPITEMIDLIST pidl;
- UINT nFiles = 0, nFileToOpen, nFileSelected, nLength = 0;
- WCHAR lpstrTemp[MAX_PATH];
- LPWSTR lpstrAllFile, lpstrCurrFile;
+ FileOpenDlgInfos *fodInfos;
+ LPITEMIDLIST pidl;
+ UINT nFiles = 0, nFileToOpen, nFileSelected, nLength = 0, nTempLength;
+ WCHAR lpstrTemp[MAX_PATH];
+ LPWSTR lpstrAllFiles;
- TRACE("\n");
- fodInfos = GetPropA(hwnd,FileOpenDlgInfosStr);
+ TRACE("\n");
+ fodInfos = GetPropA(hwnd,FileOpenDlgInfosStr);
- /* Count how many files we have */
- nFileSelected = GetNumSelected( fodInfos->Shell.FOIDataObject );
+ /* Count how many files we have */
+ nFileSelected = GetNumSelected( fodInfos->Shell.FOIDataObject );
- /* calculate the string length, count files */
- if (nFileSelected >= 1)
+ /* Allocate a buffer that is surely big enough; n * (MAX_PATH + quotes) + extra space at the end */
+ lpstrAllFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nFileSelected * (MAX_PATH + 2) + 1) * sizeof(WCHAR));
+ if (!lpstrAllFiles)
+ return;
+
+ /* Loop through the selection, handle only files (not folders) */
+ for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
+ {
+ pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
+ if (pidl)
{
- nLength += 3; /* first and last quotes, trailing \0 */
- for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
+ if (!IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl))
{
- pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
-
- if (pidl)
- {
- /* get the total length of the selected file names */
- lpstrTemp[0] = '\0';
- GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER|SHGDN_FORPARSING, lpstrTemp );
-
- if ( ! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl) ) /* Ignore folders */
- {
- nLength += lstrlenW( lpstrTemp ) + 3;
- nFiles++;
- }
- COMDLG32_SHFree( pidl );
- }
+ nFiles += 1;
+ lpstrTemp[0] = '\0';
+ GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER|SHGDN_FORPARSING, lpstrTemp );
+ nTempLength = lstrlenW( lpstrTemp );
+
+ lpstrAllFiles[nLength++] = '"';
+ lstrcpyW( lpstrAllFiles + nLength, lpstrTemp );
+ nLength += nTempLength;
+ lpstrAllFiles[nLength++] = '"';
+ lpstrAllFiles[nLength++] = ' ';
+ lpstrAllFiles[nLength] = 0;
}
+ COMDLG32_SHFree( pidl );
}
+ }
- /* allocate the buffer */
- if (nFiles <= 1) nLength = MAX_PATH;
- lpstrAllFile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(WCHAR));
-
- /* Generate the string for the edit control */
- if(nFiles >= 1)
- {
- lpstrCurrFile = lpstrAllFile;
- for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
- {
- pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
+ /* If there's only one file, use the name as-is without quotes */
+ if (nFiles == 1)
+ lstrcpyW( lpstrAllFiles, lpstrTemp );
- if (pidl)
- {
- /* get the file name */
- lpstrTemp[0] = '\0';
- GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER|SHGDN_FORPARSING, lpstrTemp );
+ if (nFiles != 0)
+ {
+ SetWindowTextW( fodInfos->DlgInfos.hwndFileName, lpstrAllFiles );
+ /* Select the file name like Windows does */
+ if (filename_is_edit( fodInfos ))
+ SendMessageW(fodInfos->DlgInfos.hwndFileName, EM_SETSEL, 0, -1);
+ }
- if (! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl)) /* Ignore folders */
- {
- if ( nFiles > 1)
- {
- *lpstrCurrFile++ = '\"';
- lstrcpyW( lpstrCurrFile, lpstrTemp );
- lpstrCurrFile += lstrlenW( lpstrTemp );
- *lpstrCurrFile++ = '\"';
- *lpstrCurrFile++ = ' ';
- *lpstrCurrFile = 0;
- }
- else
- {
- lstrcpyW( lpstrAllFile, lpstrTemp );
- }
- }
- COMDLG32_SHFree( pidl );
- }
- }
- SetWindowTextW( fodInfos->DlgInfos.hwndFileName, lpstrAllFile );
-
- /* Select the file name like Windows does */
- if (filename_is_edit( fodInfos ))
- SendMessageW(fodInfos->DlgInfos.hwndFileName, EM_SETSEL, 0, -1);
- }
- HeapFree(GetProcessHeap(),0, lpstrAllFile );
+ HeapFree(GetProcessHeap(), 0, lpstrAllFiles);
}
--
2.9.0
More information about the wine-patches
mailing list