Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48589 Signed-off=-by: Dirk Niggemann dirk.niggemann@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 );
--- dlls/comdlg32/filedlg31.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/comdlg32/filedlg31.c b/dlls/comdlg32/filedlg31.c index 0e8f316f52..43dbf7f9af 100644 --- a/dlls/comdlg32/filedlg31.c +++ b/dlls/comdlg32/filedlg31.c @@ -300,7 +300,7 @@ 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, int curropen, const DRAWITEMSTRUCT *lpdis) + int savedlg, const DRAWITEMSTRUCT *lpdis) { WCHAR *str; HICON hIcon; @@ -1225,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, lfs->curropen, (DRAWITEMSTRUCT *)lParam ); + return FD31_WMDrawItem( hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam );
case WM_COMMAND: return FD31_WMCommand( hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs );