home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / unix / dir.cpp < prev    next >
C/C++ Source or Header  |  2002-10-08  |  9KB  |  342 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        unix/dir.cpp
  3. // Purpose:     wxDir implementation for Unix/POSIX systems
  4. // Author:      Vadim Zeitlin
  5. // Modified by:
  6. // Created:     08.12.99
  7. // RCS-ID:      $Id: dir.cpp,v 1.8.2.1 2002/09/30 16:56:13 RR Exp $
  8. // Copyright:   (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "dir.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.     #include "wx/intl.h"
  33.     #include "wx/log.h"
  34. #endif // PCH
  35.  
  36. #include "wx/dir.h"
  37. #include "wx/filefn.h"          // for wxMatchWild
  38.  
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41. #include <unistd.h>
  42.  
  43. #include <dirent.h>
  44.  
  45. // ----------------------------------------------------------------------------
  46. // macros
  47. // ----------------------------------------------------------------------------
  48.  
  49. #define M_DIR       ((wxDirData *)m_data)
  50.  
  51. // ----------------------------------------------------------------------------
  52. // private classes
  53. // ----------------------------------------------------------------------------
  54.  
  55. // this class stores everything we need to enumerate the files
  56. class wxDirData
  57. {
  58. public:
  59.     wxDirData(const wxString& dirname);
  60.     ~wxDirData();
  61.  
  62.     bool IsOk() const { return m_dir != NULL; }
  63.  
  64.     void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
  65.     void SetFlags(int flags) { m_flags = flags; }
  66.  
  67.     void Rewind() { rewinddir(m_dir); }
  68.     bool Read(wxString *filename);
  69.  
  70.     const wxString& GetName() const { return m_dirname; }
  71.  
  72. private:
  73.     DIR     *m_dir;
  74.  
  75.     wxString m_dirname;
  76.     wxString m_filespec;
  77.  
  78.     int      m_flags;
  79. };
  80.  
  81. // ============================================================================
  82. // implementation
  83. // ============================================================================
  84.  
  85. // ----------------------------------------------------------------------------
  86. // wxDirData
  87. // ----------------------------------------------------------------------------
  88.  
  89. #if !defined( __VMS__ ) || ( __VMS_VER >= 70000000 )
  90.  
  91. wxDirData::wxDirData(const wxString& dirname)
  92.          : m_dirname(dirname)
  93. {
  94.     m_dir = NULL;
  95.  
  96.     // throw away the trailing slashes
  97.     size_t n = m_dirname.length();
  98.     wxCHECK_RET( n, _T("empty dir name in wxDir") );
  99.  
  100.     while ( n > 0 && m_dirname[--n] == '/' )
  101.         ;
  102.  
  103.     m_dirname.Truncate(n + 1);
  104.  
  105.     // do open the dir
  106.     m_dir = opendir(m_dirname.fn_str());
  107. }
  108.  
  109. wxDirData::~wxDirData()
  110. {
  111.     if ( m_dir )
  112.     {
  113.         if ( closedir(m_dir) != 0 )
  114.         {
  115.             wxLogLastError(_T("closedir"));
  116.         }
  117.     }
  118. }
  119.  
  120. bool wxDirData::Read(wxString *filename)
  121. {
  122.     dirent *de = (dirent *)NULL;    // just to silence compiler warnings
  123.     bool matches = FALSE;
  124.  
  125.     // speed up string concatenation in the loop a bit
  126.     wxString path = m_dirname;
  127.     path += _T('/');
  128.     path.reserve(path.length() + 255);
  129.     
  130.     wxString de_d_name;
  131.  
  132.     while ( !matches )
  133.     {
  134.         de = readdir(m_dir);
  135.         if ( !de )
  136.             return FALSE;
  137.             
  138. #if wxUSE_UNICODE
  139.         de_d_name = wxConvLibc.cMB2WC( de->d_name );
  140. #else
  141.         de_d_name = de->d_name;
  142. #endif            
  143.  
  144.         // don't return "." and ".." unless asked for
  145.         if ( de->d_name[0] == '.' &&
  146.              ((de->d_name[1] == '.' && de->d_name[2] == '\0') ||
  147.               (de->d_name[1] == '\0')) )
  148.         {
  149.             if ( !(m_flags & wxDIR_DOTDOT) )
  150.                 continue;
  151.  
  152.             // we found a valid match
  153.             break;
  154.         }
  155.  
  156.         // check the type now
  157.         if ( !(m_flags & wxDIR_FILES) && !wxDir::Exists(path + de_d_name) )
  158.         {
  159.             // it's a file, but we don't want them
  160.             continue;
  161.         }
  162.         else if ( !(m_flags & wxDIR_DIRS) && wxDir::Exists(path + de_d_name) )
  163.         {
  164.             // it's a dir, and we don't want it
  165.             continue;
  166.         }
  167.  
  168.         // finally, check the name
  169.         if ( m_filespec.empty() )
  170.         {
  171.             matches = m_flags & wxDIR_HIDDEN ? TRUE : de->d_name[0] != '.';
  172.         }
  173.         else
  174.         {
  175.             // test against the pattern
  176.             matches = wxMatchWild(m_filespec, de_d_name,
  177.                                   !(m_flags & wxDIR_HIDDEN));
  178.         }
  179.     }
  180.  
  181.     *filename = de_d_name;
  182.  
  183.     return TRUE;
  184. }
  185.  
  186. #else // old VMS (TODO)
  187.  
  188. wxDirData::wxDirData(const wxString& WXUNUSED(dirname))
  189. {
  190.     wxFAIL_MSG(_T("not implemented"));
  191. }
  192.  
  193. wxDirData::~wxDirData()
  194. {
  195. }
  196.  
  197. bool wxDirData::Read(wxString * WXUNUSED(filename))
  198. {
  199.     return FALSE;
  200. }
  201.  
  202. #endif // not or new VMS/old VMS
  203.  
  204. // ----------------------------------------------------------------------------
  205. // wxDir helpers
  206. // ----------------------------------------------------------------------------
  207.  
  208. /* static */
  209. bool wxDir::Exists(const wxString& dir)
  210. {
  211.     return wxPathExists(dir);
  212. }
  213.  
  214. // ----------------------------------------------------------------------------
  215. // wxDir construction/destruction
  216. // ----------------------------------------------------------------------------
  217.  
  218. wxDir::wxDir(const wxString& dirname)
  219. {
  220.     m_data = NULL;
  221.  
  222.     (void)Open(dirname);
  223. }
  224.  
  225. bool wxDir::Open(const wxString& dirname)
  226. {
  227.     delete M_DIR;
  228.     m_data = new wxDirData(dirname);
  229.  
  230.     if ( !M_DIR->IsOk() )
  231.     {
  232.         wxLogSysError(_("Can not enumerate files in directory '%s'"),
  233.                       dirname.c_str());
  234.  
  235.         delete M_DIR;
  236.         m_data = NULL;
  237.  
  238.         return FALSE;
  239.     }
  240.  
  241.     return TRUE;
  242. }
  243.  
  244. bool wxDir::IsOpened() const
  245. {
  246.     return m_data != NULL;
  247. }
  248.  
  249. wxString wxDir::GetName() const
  250. {
  251.     wxString name;
  252.     if ( m_data )
  253.     {
  254.         name = M_DIR->GetName();
  255.         if ( !name.empty() && (name.Last() == _T('/')) )
  256.         {
  257.             // chop off the last (back)slash
  258.             name.Truncate(name.length() - 1);
  259.         }
  260.     }
  261.  
  262.     return name;
  263. }
  264.  
  265. wxDir::~wxDir()
  266. {
  267.     delete M_DIR;
  268. }
  269.  
  270. // ----------------------------------------------------------------------------
  271. // wxDir enumerating
  272. // ----------------------------------------------------------------------------
  273.  
  274. bool wxDir::GetFirst(wxString *filename,
  275.                      const wxString& filespec,
  276.                      int flags) const
  277. {
  278.     wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
  279.  
  280.     M_DIR->Rewind();
  281.  
  282.     M_DIR->SetFileSpec(filespec);
  283.     M_DIR->SetFlags(flags);
  284.  
  285.     return GetNext(filename);
  286. }
  287.  
  288. bool wxDir::GetNext(wxString *filename) const
  289. {
  290.     wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
  291.  
  292.     wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
  293.  
  294.     return M_DIR->Read(filename);
  295. }
  296.  
  297. bool wxDir::HasSubDirs(const wxString& spec)
  298. {
  299.     wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
  300.  
  301.     if ( spec.empty() )
  302.     {
  303.         // faster check for presence of any subdirectory: normally each subdir
  304.         // has a hard link to the parent directory and so, knowing that there
  305.         // are at least "." and "..", we have a subdirectory if and only if
  306.         // links number is > 2 - this is just a guess but it works fairly well
  307.         // in practice
  308.         //
  309.         // note that we may guess wrongly in one direction only: i.e. we may
  310.         // return true when there are no subdirectories but this is ok as the
  311.         // caller will learn it soon enough when it calls GetFirst(wxDIR)
  312.         // anyhow
  313.         wxStructStat stBuf;
  314.         if ( wxStat(M_DIR->GetName().c_str(), &stBuf) == 0 )
  315.         {
  316.             switch ( stBuf.st_nlink )
  317.             {
  318.                 case 2:
  319.                     // just "." and ".."
  320.                     return FALSE;
  321.  
  322.                 case 0:
  323.                 case 1:
  324.                     // weird filesystem, don't try to guess for it, use dumb
  325.                     // method below
  326.                     break;
  327.  
  328.                 default:
  329.                     // assume we have subdirs - may turn out to be wrong if we
  330.                     // have other hard links to this directory but it's not
  331.                     // that bad as explained above
  332.                     return TRUE;
  333.             }
  334.         }
  335.     }
  336.  
  337.     // just try to find first directory
  338.     wxString s;
  339.     return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
  340. }
  341.  
  342.