[PATCH 1/3] comdlg32.dll - Make old-style OpenFileName() function display directory tree in the directory listbox, without square brackets around directory names. This matches the functionality for this listbox in winXP, 7 and 10. Also display open folder icon for selected folder.
Dirk Niggemann
dirk.niggemann at gmail.com
Sun Feb 23 17:16:50 CST 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48589
Signed-off=-by: Dirk Niggemann <dirk.niggemann at gmail.com>
---
dlls/comdlg32/filedlg31.c | 155 ++++++++++++++++++++++++++++++++------
1 file changed, 131 insertions(+), 24 deletions(-)
diff --git a/dlls/comdlg32/filedlg31.c b/dlls/comdlg32/filedlg31.c
index 53ef3eeb48..0e8f316f52 100644
--- a/dlls/comdlg32/filedlg31.c
+++ b/dlls/comdlg32/filedlg31.c
@@ -48,6 +48,7 @@ static const WCHAR FILE_bslash[] = {'\\', 0};
static const WCHAR FILE_specc[] = {'%','c',':', 0};
static const int fldrHeight = 16;
static const int fldrWidth = 20;
+static const int indentWidth = 5;
static HICON hFolder = 0;
static HICON hFolder2 = 0;
@@ -70,6 +71,7 @@ typedef struct tagFD31_DATA
LPOPENFILENAMEW ofnW; /* pointer either to the original structure or
a W copy for A/16 API */
LPOPENFILENAMEA ofnA; /* original structure if 32bits ansi dialog */
+ UINT curropen; /* position of currenly open folder */
} FD31_DATA, *PFD31_DATA;
/***********************************************************************
@@ -170,12 +172,60 @@ static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
return FILE_star; /* FIXME */
}
+
+/***********************************************************************
+ * FD31_Directory
+ */
+static LRESULT FD31_Directory( HWND hdlg, LPCWSTR filespec, int pos, int indent, int curropen, BOOL long_names )
+{
+ HANDLE handle;
+ LRESULT ret = LB_OKAY;
+ WIN32_FIND_DATAW entry;
+ LRESULT maxinsert = LB_ERR;
+ int n = 0;
+
+ /* scan directory */
+ if ((handle = FindFirstFileW(filespec, &entry)) == INVALID_HANDLE_VALUE)
+ {
+ int le = GetLastError();
+ if ((le != ERROR_NO_MORE_FILES) && (le != ERROR_FILE_NOT_FOUND)) return LB_ERR;
+ }
+ else
+ {
+ do
+ {
+ WCHAR buffer[270];
+ if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ static const WCHAR dotW[] = { '.',0 };
+ static const WCHAR dotdotW[] = { '.', '.', 0 };
+ if ( !lstrcmpW( entry.cFileName, dotW ) ) continue;
+ if ( !lstrcmpW( entry.cFileName, dotdotW ) ) continue;
+ if (!long_names && entry.cAlternateFileName[0])
+ lstrcpyW( buffer, entry.cAlternateFileName );
+ else
+ lstrcpyW( buffer , entry.cFileName );
+ if (!long_names) CharLowerW( buffer );
+ /* pos = LISTBOX_FindFileStrPos( descr, buffer ); */
+ SendMessageW(hdlg, LB_INSERTSTRING, pos+n, (LPARAM)buffer);
+ SendMessageW(hdlg, LB_SETITEMDATA, pos+n, curropen == (pos+n) ? indent | 0x10000 : indent);
+ if (ret <= maxinsert) maxinsert++; else maxinsert = ret;
+ n++;
+ }
+ } while (FindNextFileW( handle, &entry ));
+ FindClose( handle );
+ }
+ return ret;
+}
+
/***********************************************************************
* FD31_ScanDir [internal]
*/
-static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
+static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath,
+ int curropen)
{
WCHAR buffer[BUFFILE];
+ WCHAR currpath[BUFFILE];
HWND hdlg;
LRESULT lRet = TRUE;
HCURSOR hCursorWait, oldCursor;
@@ -183,6 +233,7 @@ static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
TRACE("Trying to change to %s\n", debugstr_w(newPath));
if ( newPath[0] && !SetCurrentDirectoryW( newPath ))
return FALSE;
+ GetCurrentDirectoryW(BUFFILE, currpath);
/* get the list of spec files */
lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter,
@@ -211,9 +262,35 @@ static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
/* list of directories */
lstrcpyW(buffer, FILE_star);
-
- if (GetDlgItem(hWnd, lst2) != 0) {
- lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
+ if ((hdlg = GetDlgItem(hWnd, lst2)) != 0) {
+ WCHAR * dir = currpath;
+ WCHAR * sepptr;
+ UINT n = 0;
+ WCHAR pathcomp[BUFFILE];
+ SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
+ while (dir)
+ {
+ sepptr = wcschr(dir, FILE_bslash[0]);
+ if (sepptr) *sepptr = 0;
+ if (!*dir)
+ {
+ dir = (sepptr) ? (sepptr + 1) : 0;
+ continue;
+ }
+ lstrcpyW(pathcomp, dir);
+ if( dir[lstrlenW(dir) -1] == ':' )
+ lstrcatW(pathcomp, FILE_bslash);
+ TRACE("Using path comp %s\n", debugstr_w(pathcomp));
+ SendMessageW(hdlg, LB_INSERTSTRING, n, (LPARAM)pathcomp);
+ dir = (sepptr) ? (sepptr + 1) : 0;
+ /* last entry sets open folder if -1 */
+ if (curropen == -1 && !dir)
+ SendMessageW(hdlg, LB_SETITEMDATA, n, n | 0x10000 );
+ else
+ SendMessageW(hdlg, LB_SETITEMDATA, n,n == curropen ? n | 0x10000 : n);
+ n++;
+ }
+ FD31_Directory(hdlg, buffer, n, n, curropen, TRUE);
}
SetCursor(oldCursor);
return lRet;
@@ -223,12 +300,17 @@ static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
* FD31_WMDrawItem [internal]
*/
static LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
- int savedlg, const DRAWITEMSTRUCT *lpdis)
+ int savedlg, int curropen, const DRAWITEMSTRUCT *lpdis)
{
WCHAR *str;
HICON hIcon;
COLORREF oldText = 0, oldBk = 0;
+ ULONG indent = 0;
+ if (lpdis->itemData)
+ {
+ indent = lpdis->itemData & 0xffff;
+ }
if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
{
if (!(str = heap_alloc(BUFFILEALLOC))) return FALSE;
@@ -271,7 +353,7 @@ static LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
- ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
+ ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth + indent*indentWidth,
lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
&(lpdis->rcItem), str, lstrlenW(str), NULL);
@@ -283,7 +365,10 @@ static LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
SetBkColor( lpdis->hDC, oldBk );
SetTextColor( lpdis->hDC, oldText );
}
- DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
+ if (lpdis->itemData & 0x10000)
+ DrawIconEx( lpdis->hDC, lpdis->rcItem.left + indent*indentWidth, lpdis->rcItem.top, hFolder2, 16, 16, 0, 0, DI_NORMAL );
+ else
+ DrawIconEx( lpdis->hDC, lpdis->rcItem.left + indent*indentWidth, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
heap_free(str);
return TRUE;
}
@@ -408,30 +493,50 @@ static void FD31_UpdateFileTitle(const FD31_DATA *lfs)
/***********************************************************************
* FD31_DirListDblClick [internal]
*/
-static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs )
+static LRESULT FD31_DirListDblClick( FD31_DATA *lfs )
{
LONG lRet;
+ LONG currindent;
HWND hWnd = lfs->hwnd;
LPWSTR pstr;
WCHAR tmpstr[BUFFILE];
+ WCHAR tmpstr2[BUFFILE];
+ int n, indent;
/* get the raw string (with brackets) */
lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
if (lRet == LB_ERR) return TRUE;
pstr = heap_alloc(BUFFILEALLOC);
- SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
- (LPARAM)pstr);
+ SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet, (LPARAM)pstr);
+ currindent = SendDlgItemMessageW(hWnd, lst2, LB_GETITEMDATA, lRet, 0) & 0xffff;
+ lfs->curropen = currindent;
lstrcpyW( tmpstr, pstr );
- heap_free(pstr);
/* get the selected directory in tmpstr */
if (tmpstr[0] == '[')
{
tmpstr[lstrlenW(tmpstr) - 1] = 0;
lstrcpyW(tmpstr,tmpstr+1);
}
+ n = lRet -1;
+ while (n >= 0)
+ {
+ SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, n, (LPARAM)pstr);
+ indent = SendDlgItemMessageW(hWnd, lst2, LB_GETITEMDATA, n, 0) & 0xffff;
+ if (indent < currindent)
+ {
+ lstrcpyW(tmpstr2, pstr);
+ lstrcatW(tmpstr2, FILE_bslash);
+ lstrcatW(tmpstr2, tmpstr);
+ lstrcpyW(tmpstr, tmpstr2);
+ currindent = indent;
+ }
+ n--;
+ }
+ heap_free(pstr);
lstrcatW(tmpstr, FILE_bslash);
+ TRACE("%s\n",debugstr_w(tmpstr));
- FD31_ScanDir(lfs->ofnW, hWnd, tmpstr);
+ FD31_ScanDir(lfs->ofnW, hWnd, tmpstr, lfs->curropen);
/* notify the app */
if (lfs->hook)
{
@@ -485,7 +590,8 @@ static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
LPWSTR pBeginFileName, pstr2;
WCHAR tmpstr2[BUFFILE];
- pBeginFileName = wcsrchr(path, '\\');
+ TRACE("initial path=%s\n", debugstr_w(path));
+ pBeginFileName = wcsrchr(path, FILE_bslash[0]);
if (pBeginFileName == NULL)
pBeginFileName = wcsrchr(path, ':');
@@ -506,19 +612,18 @@ static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
SetDlgItemTextW( hWnd, edt1, tmpstr2 );
- FD31_ScanDir(lfs->ofnW, hWnd, path);
+ FD31_ScanDir(lfs->ofnW, hWnd, path, lfs->curropen);
return (lfs->ofnW->Flags & OFN_NOVALIDATE) != 0;
}
/* no wildcards, we might have a directory or a filename */
/* try appending a wildcard and reading the directory */
-
pstr2 = path + lstrlenW(path);
if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
lstrcatW(path, FILE_bslash);
/* if ScanDir succeeds, we have changed the directory */
- if (FD31_ScanDir(lfs->ofnW, hWnd, path))
+ if (FD31_ScanDir(lfs->ofnW, hWnd, path, lfs->curropen))
return FALSE; /* and path is not a valid file name */
/* if not, this must be a filename */
@@ -533,7 +638,7 @@ static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
lstrcpynW(tmpstr2, pBeginFileName + 1, ARRAY_SIZE(tmpstr2));
/* Should we MessageBox() if this fails? */
- if (!FD31_ScanDir(lfs->ofnW, hWnd, path))
+ if (!FD31_ScanDir(lfs->ofnW, hWnd, path, lfs->curropen))
{
return FALSE;
}
@@ -571,7 +676,10 @@ static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control,
if (control != lst1)
{
if (!FD31_TestPath( lfs, filename) )
+ {
+ TRACE ("not in file list %s\n", debugstr_w(filename));
return FALSE;
+ }
}
FD31_UpdateResult(lfs, filename);
@@ -658,7 +766,7 @@ static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs )
* FD31_WMCommand [internal]
*/
static LRESULT FD31_WMCommand( HWND hWnd, LPARAM lParam, UINT notification,
- UINT control, const FD31_DATA *lfs )
+ UINT control, FD31_DATA *lfs )
{
switch (control)
{
@@ -951,7 +1059,7 @@ static PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode)
}
lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
-
+ lfs->curropen = 0;
return lfs;
}
@@ -972,7 +1080,6 @@ static LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
ofn = lfs->ofnW;
TRACE("flags=%x initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
-
SetWindowTextW( hWnd, ofn->lpstrTitle );
/* read custom filter information */
if (ofn->lpstrCustomFilter)
@@ -1048,9 +1155,9 @@ static LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
}
else
*tmpstr = 0;
- if (!FD31_ScanDir(ofn, hWnd, tmpstr)) {
+ if (!FD31_ScanDir(ofn, hWnd, tmpstr, -1)) {
*tmpstr = 0;
- if (!FD31_ScanDir(ofn, hWnd, tmpstr))
+ if (!FD31_ScanDir(ofn, hWnd, tmpstr, -1))
WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
}
/* select current drive in combo 2, omit missing drives */
@@ -1071,7 +1178,7 @@ static LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
if (ofn->Flags & OFN_HIDEREADONLY)
ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
if (lfs->hook)
- return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
+ return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
return TRUE;
}
@@ -1118,7 +1225,7 @@ static INT_PTR CALLBACK FD31_FileOpenDlgProc(HWND hWnd, UINT wMsg,
return FD31_WMMeasureItem( lParam );
case WM_DRAWITEM:
- return FD31_WMDrawItem( hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam );
+ return FD31_WMDrawItem( hWnd, wParam, lParam, !lfs->open, lfs->curropen, (DRAWITEMSTRUCT *)lParam );
case WM_COMMAND:
return FD31_WMCommand( hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs );
--
2.17.2 (Apple Git-113)
More information about the wine-devel
mailing list