X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1944c6bdd0daa0a9793e9a57f0800c169fec958b..69d31e313035d5e22d9400ec946f6007f710910c:/src/unix/dir.cpp?ds=sidebyside diff --git a/src/unix/dir.cpp b/src/unix/dir.cpp index 188e93c6e5..31270d04a5 100644 --- a/src/unix/dir.cpp +++ b/src/unix/dir.cpp @@ -6,7 +6,7 @@ // Created: 08.12.99 // RCS-ID: $Id$ // Copyright: (c) 1999 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "dir.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -37,6 +33,8 @@ #include "wx/filefn.h" // for wxMatchWild #include +#include +#include #include @@ -65,6 +63,8 @@ public: void Rewind() { rewinddir(m_dir); } bool Read(wxString *filename); + const wxString& GetName() const { return m_dirname; } + private: DIR *m_dir; @@ -91,7 +91,7 @@ wxDirData::wxDirData(const wxString& dirname) // throw away the trailing slashes size_t n = m_dirname.length(); - wxCHECK_RET( n, _T("empty dir name in wxDir") ); + wxCHECK_RET( n, wxT("empty dir name in wxDir") ); while ( n > 0 && m_dirname[--n] == '/' ) ; @@ -108,21 +108,34 @@ wxDirData::~wxDirData() { if ( closedir(m_dir) != 0 ) { - wxLogLastError(_T("closedir")); + wxLogLastError(wxT("closedir")); } } } bool wxDirData::Read(wxString *filename) { - dirent *de; - bool matches = FALSE; + dirent *de = NULL; // just to silence compiler warnings + bool matches = false; + + // speed up string concatenation in the loop a bit + wxString path = m_dirname; + path += wxT('/'); + path.reserve(path.length() + 255); + + wxString de_d_name; while ( !matches ) { de = readdir(m_dir); if ( !de ) - return FALSE; + return false; + +#if wxUSE_UNICODE + de_d_name = wxString(de->d_name, *wxConvFileName); +#else + de_d_name = de->d_name; +#endif // don't return "." and ".." unless asked for if ( de->d_name[0] == '.' && @@ -131,45 +144,46 @@ bool wxDirData::Read(wxString *filename) { if ( !(m_flags & wxDIR_DOTDOT) ) continue; + + // we found a valid match + break; } // check the type now - if ( !(m_flags & wxDIR_FILES) && - !wxDir::Exists(m_dirname + _T('/') + de->d_name) ) + if ( !(m_flags & wxDIR_FILES) && !wxDir::Exists(path + de_d_name) ) { // it's a file, but we don't want them continue; } - else if ( !(m_flags & wxDIR_DIRS) && - wxDir::Exists(m_dirname + _T('/') + de->d_name) ) + else if ( !(m_flags & wxDIR_DIRS) && wxDir::Exists(path + de_d_name) ) { // it's a dir, and we don't want it continue; } // finally, check the name - if ( !m_filespec ) + if ( m_filespec.empty() ) { - matches = m_flags & wxDIR_HIDDEN ? TRUE : de->d_name[0] != '.'; + matches = m_flags & wxDIR_HIDDEN ? true : de->d_name[0] != '.'; } else { // test against the pattern - matches = wxMatchWild(m_filespec, de->d_name, + matches = wxMatchWild(m_filespec, de_d_name, !(m_flags & wxDIR_HIDDEN)); } } - *filename = de->d_name; + *filename = de_d_name; - return TRUE; + return true; } #else // old VMS (TODO) wxDirData::wxDirData(const wxString& WXUNUSED(dirname)) { - wxFAIL_MSG(_T("not implemented")); + wxFAIL_MSG(wxT("not implemented")); } wxDirData::~wxDirData() @@ -178,7 +192,7 @@ wxDirData::~wxDirData() bool wxDirData::Read(wxString * WXUNUSED(filename)) { - return FALSE; + return false; } #endif // not or new VMS/old VMS @@ -190,7 +204,7 @@ bool wxDirData::Read(wxString * WXUNUSED(filename)) /* static */ bool wxDir::Exists(const wxString& dir) { - return wxPathExists(dir); + return wxDirExists(dir); } // ---------------------------------------------------------------------------- @@ -211,16 +225,13 @@ bool wxDir::Open(const wxString& dirname) if ( !M_DIR->IsOk() ) { - wxLogSysError(_("Can not enumerate files in directory '%s'"), - dirname.c_str()); - delete M_DIR; m_data = NULL; - return FALSE; + return false; } - return TRUE; + return true; } bool wxDir::IsOpened() const @@ -228,6 +239,22 @@ bool wxDir::IsOpened() const return m_data != NULL; } +wxString wxDir::GetName() const +{ + wxString name; + if ( m_data ) + { + name = M_DIR->GetName(); + if ( !name.empty() && (name.Last() == wxT('/')) ) + { + // chop off the last (back)slash + name.Truncate(name.length() - 1); + } + } + + return name; +} + wxDir::~wxDir() { delete M_DIR; @@ -241,7 +268,7 @@ bool wxDir::GetFirst(wxString *filename, const wxString& filespec, int flags) const { - wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") ); + wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") ); M_DIR->Rewind(); @@ -253,9 +280,55 @@ bool wxDir::GetFirst(wxString *filename, bool wxDir::GetNext(wxString *filename) const { - wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") ); + wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") ); - wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") ); + wxCHECK_MSG( filename, false, wxT("bad pointer in wxDir::GetNext()") ); return M_DIR->Read(filename); } + +bool wxDir::HasSubDirs(const wxString& spec) const +{ + wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") ); + + if ( spec.empty() ) + { + // faster check for presence of any subdirectory: normally each subdir + // has a hard link to the parent directory and so, knowing that there + // are at least "." and "..", we have a subdirectory if and only if + // links number is > 2 - this is just a guess but it works fairly well + // in practice + // + // note that we may guess wrongly in one direction only: i.e. we may + // return true when there are no subdirectories but this is ok as the + // caller will learn it soon enough when it calls GetFirst(wxDIR) + // anyhow + wxStructStat stBuf; + if ( wxStat(M_DIR->GetName().c_str(), &stBuf) == 0 ) + { + switch ( stBuf.st_nlink ) + { + case 2: + // just "." and ".." + return false; + + case 0: + case 1: + // weird filesystem, don't try to guess for it, use dumb + // method below + break; + + default: + // assume we have subdirs - may turn out to be wrong if we + // have other hard links to this directory but it's not + // that bad as explained above + return true; + } + } + } + + // just try to find first directory + wxString s; + return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN); +} +