home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / unix / dir.cpp < prev    next >
C/C++ Source or Header  |  2002-08-12  |  9KB  |  346 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 2002/08/10 11:54:51 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. #if wxUSE_UNICODE
  176.             matches = TRUE;  // FIXME
  177. #else
  178.             // test against the pattern
  179.             matches = wxMatchWild(m_filespec, de_d_name,
  180.                                   !(m_flags & wxDIR_HIDDEN));
  181. #endif
  182.         }
  183.     }
  184.  
  185.     *filename = de_d_name;
  186.  
  187.     return TRUE;
  188. }
  189.  
  190. #else // old VMS (TODO)
  191.  
  192. wxDirData::wxDirData(const wxString& WXUNUSED(dirname))
  193. {
  194.     wxFAIL_MSG(_T("not implemented"));
  195. }
  196.  
  197. wxDirData::~wxDirData()
  198. {
  199. }
  200.  
  201. bool wxDirData::Read(wxString * WXUNUSED(filename))
  202. {
  203.     return FALSE;
  204. }
  205.  
  206. #endif // not or new VMS/old VMS
  207.  
  208. // ----------------------------------------------------------------------------
  209. // wxDir helpers
  210. // ----------------------------------------------------------------------------
  211.  
  212. /* static */
  213. bool wxDir::Exists(const wxString& dir)
  214. {
  215.     return wxPathExists(dir);
  216. }
  217.  
  218. // ----------------------------------------------------------------------------
  219. // wxDir construction/destruction
  220. // ----------------------------------------------------------------------------
  221.  
  222. wxDir::wxDir(const wxString& dirname)
  223. {
  224.     m_data = NULL;
  225.  
  226.     (void)Open(dirname);
  227. }
  228.  
  229. bool wxDir::Open(const wxString& dirname)
  230. {
  231.     delete M_DIR;
  232.     m_data = new wxDirData(dirname);
  233.  
  234.     if ( !M_DIR->IsOk() )
  235.     {
  236.         wxLogSysError(_("Can not enumerate files in directory '%s'"),
  237.                       dirname.c_str());
  238.  
  239.         delete M_DIR;
  240.         m_data = NULL;
  241.  
  242.         return FALSE;
  243.     }
  244.  
  245.     return TRUE;
  246. }
  247.  
  248. bool wxDir::IsOpened() const
  249. {
  250.     return m_data != NULL;
  251. }
  252.  
  253. wxString wxDir::GetName() const
  254. {
  255.     wxString name;
  256.     if ( m_data )
  257.     {
  258.         name = M_DIR->GetName();
  259.         if ( !name.empty() && (name.Last() == _T('/')) )
  260.         {
  261.             // chop off the last (back)slash
  262.             name.Truncate(name.length() - 1);
  263.         }
  264.     }
  265.  
  266.     return name;
  267. }
  268.  
  269. wxDir::~wxDir()
  270. {
  271.     delete M_DIR;
  272. }
  273.  
  274. // ----------------------------------------------------------------------------
  275. // wxDir enumerating
  276. // ----------------------------------------------------------------------------
  277.  
  278. bool wxDir::GetFirst(wxString *filename,
  279.                      const wxString& filespec,
  280.                      int flags) const
  281. {
  282.     wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
  283.  
  284.     M_DIR->Rewind();
  285.  
  286.     M_DIR->SetFileSpec(filespec);
  287.     M_DIR->SetFlags(flags);
  288.  
  289.     return GetNext(filename);
  290. }
  291.  
  292. bool wxDir::GetNext(wxString *filename) const
  293. {
  294.     wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
  295.  
  296.     wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
  297.  
  298.     return M_DIR->Read(filename);
  299. }
  300.  
  301. bool wxDir::HasSubDirs(const wxString& spec)
  302. {
  303.     wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
  304.  
  305.     if ( spec.empty() )
  306.     {
  307.         // faster check for presence of any subdirectory: normally each subdir
  308.         // has a hard link to the parent directory and so, knowing that there
  309.         // are at least "." and "..", we have a subdirectory if and only if
  310.         // links number is > 2 - this is just a guess but it works fairly well
  311.         // in practice
  312.         //
  313.         // note that we may guess wrongly in one direction only: i.e. we may
  314.         // return true when there are no subdirectories but this is ok as the
  315.         // caller will learn it soon enough when it calls GetFirst(wxDIR)
  316.         // anyhow
  317.         wxStructStat stBuf;
  318.         if ( wxStat(M_DIR->GetName().c_str(), &stBuf) == 0 )
  319.         {
  320.             switch ( stBuf.st_nlink )
  321.             {
  322.                 case 2:
  323.                     // just "." and ".."
  324.                     return FALSE;
  325.  
  326.                 case 0:
  327.                 case 1:
  328.                     // weird filesystem, don't try to guess for it, use dumb
  329.                     // method below
  330.                     break;
  331.  
  332.                 default:
  333.                     // assume we have subdirs - may turn out to be wrong if we
  334.                     // have other hard links to this directory but it's not
  335.                     // that bad as explained above
  336.                     return TRUE;
  337.             }
  338.         }
  339.     }
  340.  
  341.     // just try to find first directory
  342.     wxString s;
  343.     return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
  344. }
  345.  
  346.