diff --git a/src/msw/dir.cpp b/src/msw/dir.cpp index 5b05d23d48..f406a91281 100644 --- a/src/msw/dir.cpp +++ b/src/msw/dir.cpp @@ -27,8 +27,11 @@ #include "wx/dir.h" -#ifdef __WINDOWS__ - #include "wx/msw/private.h" +#include "wx/msw/private.h" +#include + +#ifdef __VISUALC__ + #pragma comment(lib, "shlwapi") #endif // ---------------------------------------------------------------------------- @@ -60,11 +63,6 @@ inline void FreeFindData(FIND_DATA fd) } } -const wxChar *GetNameFromFindData(const FIND_STRUCT *finddata) -{ - return finddata->cFileName; -} - // Helper function checking that the contents of the given FIND_STRUCT really // match our filter. We need to do it ourselves as native Windows functions // apply the filter to both the long and the short names of the file, so @@ -78,17 +76,7 @@ CheckFoundMatch(const FIND_STRUCT* finddata, const wxString& filter) if ( filter.empty() ) return true; - // Otherwise do check the match validity. Notice that we must do it - // case-insensitively because the case of the file names is not supposed to - // matter under Windows. - wxString fn(GetNameFromFindData(finddata)); - - // However if the filter contains only special characters (which is a - // common case), we can skip the case conversion. - if ( filter.find_first_not_of(wxS("*?.")) == wxString::npos ) - return fn.Matches(filter); - - return fn.MakeUpper().Matches(filter.Upper()); + return ::PathMatchSpec(finddata->cFileName, filter) == TRUE; } inline bool @@ -130,11 +118,6 @@ FindFirst(const wxString& spec, return fd; } -inline FIND_ATTR GetAttrFromFindData(FIND_STRUCT *finddata) -{ - return finddata->dwFileAttributes; -} - inline bool IsDir(FIND_ATTR attr) { return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; @@ -231,7 +214,6 @@ bool wxDirData::Read(wxString *filename) bool first = false; WIN32_FIND_DATA finddata; - #define PTR_TO_FINDDATA (&finddata) if ( !IsFindDataOk(m_finddata) ) { @@ -246,7 +228,7 @@ bool wxDirData::Read(wxString *filename) else filespec += m_filespec; - m_finddata = FindFirst(filespec, m_filespec, PTR_TO_FINDDATA); + m_finddata = FindFirst(filespec, m_filespec, &finddata); first = true; } @@ -265,9 +247,6 @@ bool wxDirData::Read(wxString *filename) return false; } - const wxChar *name; - FIND_ATTR attr; - for ( ;; ) { if ( first ) @@ -276,7 +255,7 @@ bool wxDirData::Read(wxString *filename) } else { - if ( !FindNext(m_finddata, m_filespec, PTR_TO_FINDDATA) ) + if ( !FindNext(m_finddata, m_filespec, &finddata) ) { DWORD err = ::GetLastError(); @@ -290,8 +269,8 @@ bool wxDirData::Read(wxString *filename) } } - name = GetNameFromFindData(PTR_TO_FINDDATA); - attr = GetAttrFromFindData(PTR_TO_FINDDATA); + const wxChar* const name = finddata.cFileName; + const FIND_ATTR attr = finddata.dwFileAttributes; // don't return "." and ".." unless asked for if ( name[0] == wxT('.') && diff --git a/tests/file/dir.cpp b/tests/file/dir.cpp index ae5b81c5d5..fa2b836900 100644 --- a/tests/file/dir.cpp +++ b/tests/file/dir.cpp @@ -20,6 +20,16 @@ #define DIRTEST_FOLDER wxString("dirTest_folder") #define SEP wxFileName::GetPathSeparator() +// We can't use wxFileSelectorDefaultWildcardStr from wxCore here, so define +// our own. +const wxString WILDCARD_ALL = +#if defined(__WXMSW__) +"*.*" +#else // Unix/Mac +"*" +#endif +; + // ---------------------------------------------------------------------------- // test fixture // ---------------------------------------------------------------------------- @@ -145,6 +155,21 @@ TEST_CASE_METHOD(DirTestCase, "Dir::Traverse", "[dir]") wxArrayString files; CHECK( wxDir::GetAllFiles(DIRTEST_FOLDER, &files) == 4 ); + // enum all files using an explicit wildcard + CHECK(wxDir::GetAllFiles(DIRTEST_FOLDER, &files, WILDCARD_ALL) == 4); + + // enum all files using an explicit wildcard different from WILDCARD_ALL + // + // broken under Wine, see https://bugs.winehq.org/show_bug.cgi?id=55677 + if ( !wxIsRunningUnderWine() ) + { + CHECK(wxDir::GetAllFiles(DIRTEST_FOLDER, &files, "d" + WILDCARD_ALL) == 4); + } + else if (wxDir::GetAllFiles(DIRTEST_FOLDER, &files, "d" + WILDCARD_ALL) == 4) + { + WARN("PathMatchSpec() seems to work under Wine now"); + } + // enum all files according to the filter CHECK( wxDir::GetAllFiles(DIRTEST_FOLDER, &files, "*.foo") == 1 ); @@ -232,3 +257,45 @@ TEST_CASE_METHOD(DirTestCase, "Dir::GetName", "[dir]") CHECK( d.GetNameWithSep() == "/" ); #endif } + +// Disabled by default test allowing to check the result of matching against +// the given filter. +#ifdef __WXMSW__ + +#include "wx/msw/wrapwin.h" +#include +#ifdef __VISUALC__ + #pragma comment(lib, "shlwapi") +#endif + +#include "wx/crt.h" +#include "wx/filefn.h" + +TEST_CASE("Dir::Match", "[.]") +{ + wxString filter; + REQUIRE( wxGetEnv("WX_TEST_DIR_FILTER", &filter) ); + + static const wxString filenames[] = + { + "foo", + "foo.bar", + "foo.bar.baz", + ".hidden", + ".hidden.ext", + }; + + // Show the results of matching the pattern using various functions. + wxPrintf("%-15s %20s %20s %20s\n", + "File", "wxString::Matches", "wxMatchWild", "PathMatchSpec"); + for ( const auto& fn : filenames ) + { + wxPrintf("%-15s %20d %20d %20d\n", + fn, + fn.Matches(filter), + wxMatchWild(filter, fn), + PathMatchSpec(fn.wc_str(), filter.wc_str()) == TRUE); + } +} + +#endif // __WXMSW__