1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/os2/dir.cpp
3 // Purpose:     wxDir implementation for OS/2
4 // Author:      Vadim Zeitlin
5 // Modified by: Stefan Neis
6 // Created:     08.12.99
7 // Copyright:   (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifndef WX_PRECOMP
23     #include "wx/os2/private.h"
24     #include "wx/intl.h"
25     #include "wx/log.h"
26 #endif // PCH
27 
28 #include "wx/dir.h"
29 #include "wx/filefn.h"          // for wxMatchWild
30 
31 #include <sys/types.h>
32 
33 #define INCL_DOSFILEMGR
34 #define INCL_DOSERRORS
35 #include <os2.h>
36 
37 #ifdef __EMX__
38 #include <dirent.h>
39 #endif
40 
41 // ----------------------------------------------------------------------------
42 // define the types and functions used for file searching
43 // ----------------------------------------------------------------------------
44 
45 typedef FILEFINDBUF3                FIND_STRUCT;
46 typedef HDIR                        FIND_DATA;
47 typedef ULONG                       FIND_ATTR;
48 
InitFindData()49 static inline FIND_DATA InitFindData() { return ERROR_INVALID_HANDLE; }
50 
IsFindDataOk(FIND_DATA vFd)51 static inline bool IsFindDataOk(
52   FIND_DATA                     vFd
53 )
54 {
55     return vFd != ERROR_INVALID_HANDLE;
56 }
57 
FreeFindData(FIND_DATA vFd)58 static inline void FreeFindData(
59   FIND_DATA                     vFd
60 )
61 {
62     if (!::DosFindClose(vFd))
63     {
64         wxLogLastError(wxT("DosFindClose"));
65     }
66 }
67 
FindFirst(const wxString & rsSpec,FIND_STRUCT * pFinddata)68 static inline FIND_DATA FindFirst(
69   const wxString&               rsSpec
70 , FIND_STRUCT*                  pFinddata
71 )
72 {
73     ULONG                       ulFindCount = 1;
74     FIND_DATA                   hDir = HDIR_CREATE;
75     FIND_ATTR                   rc;
76 
77     rc = ::DosFindFirst( rsSpec.c_str()
78                         ,&hDir
79                         ,0x37 // was: FILE_NORMAL
80                         ,pFinddata
81                         ,sizeof(FILEFINDBUF3)
82                         ,&ulFindCount
83                         ,FIL_STANDARD
84                        );
85     if (rc != 0)
86         return InitFindData();
87     return hDir;
88 }
89 
FindNext(FIND_DATA vFd,FIND_STRUCT * pFinddata)90 static inline bool FindNext(
91   FIND_DATA                         vFd
92 , FIND_STRUCT*                      pFinddata
93 )
94 {
95     ULONG                           ulFindCount = 1;
96 
97     return ::DosFindNext( vFd
98                          ,pFinddata
99                          ,sizeof(FILEFINDBUF3)
100                          ,&ulFindCount
101                          ) == 0;
102 }
103 
GetNameFromFindData(FIND_STRUCT * pFinddata)104 static const wxChar* GetNameFromFindData(
105   FIND_STRUCT*                      pFinddata
106 )
107 {
108     return (wxChar*)pFinddata->achName;
109 }
110 
GetAttrFromFindData(FIND_STRUCT * pFinddata)111 static const FIND_ATTR GetAttrFromFindData(
112   FIND_STRUCT*                      pFinddata
113 )
114 {
115     return pFinddata->attrFile;
116 }
117 
IsDir(FIND_ATTR vAttr)118 static inline bool IsDir(
119   FIND_ATTR                         vAttr
120 )
121 {
122     return (vAttr & FILE_DIRECTORY) != 0;
123 }
124 
IsHidden(FIND_ATTR vAttr)125 static inline bool IsHidden(
126   FIND_ATTR                         vAttr
127 )
128 {
129     return (vAttr & (FILE_HIDDEN | FILE_SYSTEM)) != 0;
130 }
131 
132 // ----------------------------------------------------------------------------
133 // constants
134 // ----------------------------------------------------------------------------
135 
136 #ifndef MAX_PATH
137     #define MAX_PATH 260        // from PM++ headers
138 #endif
139 
140 // ----------------------------------------------------------------------------
141 // macros
142 // ----------------------------------------------------------------------------
143 
144 #define M_DIR       ((wxDirData *)m_data)
145 
146 // ----------------------------------------------------------------------------
147 // private classes
148 // ----------------------------------------------------------------------------
149 
150 // this class stores everything we need to enumerate the files
151 class wxDirData
152 {
153 public:
154     wxDirData(const wxString& rsDirname);
155     ~wxDirData();
156 
SetFileSpec(const wxString & rsFilespec)157     void SetFileSpec(const wxString& rsFilespec) { m_sFilespec = rsFilespec; }
SetFlags(int nFlags)158     void SetFlags(int nFlags) { m_nFlags = nFlags; }
159 
GetName() const160     const wxString& GetName() const { return m_sDirname; }
161     void Close();
162     void Rewind();
163     bool Read(wxString* rsFilename);
164 
165 private:
166     FIND_DATA                       m_vFinddata;
167     wxString                        m_sDirname;
168     wxString                        m_sFilespec;
169     int                             m_nFlags;
170 }; // end of CLASS wxDirData
171 
172 // ============================================================================
173 // implementation
174 // ============================================================================
175 
176 // ----------------------------------------------------------------------------
177 // wxDirData
178 // ----------------------------------------------------------------------------
179 
wxDirData(const wxString & rsDirname)180 wxDirData::wxDirData(
181   const wxString&                   rsDirname
182 )
183 : m_sDirname(rsDirname)
184 {
185     m_vFinddata = InitFindData();
186 } // end of wxDirData::wxDirData
187 
~wxDirData()188 wxDirData::~wxDirData()
189 {
190     Close();
191 } // end of wxDirData::~wxDirData
192 
Close()193 void wxDirData::Close()
194 {
195     if ( IsFindDataOk(m_vFinddata) )
196     {
197         FreeFindData(m_vFinddata);
198         m_vFinddata = InitFindData();
199     }
200 } // end of wxDirData::Close
201 
Rewind()202 void wxDirData::Rewind()
203 {
204     Close();
205 } // end of wxDirData::Rewind
206 
Read(wxString * psFilename)207 bool wxDirData::Read(
208   wxString*                         psFilename
209 )
210 {
211     bool                            bFirst = false;
212 
213     FILEFINDBUF3                    vFinddata;
214     #define PTR_TO_FINDDATA (&vFinddata)
215 
216     if (!IsFindDataOk(m_vFinddata))
217     {
218         //
219         // Open first
220         //
221         wxString                    sFilespec = m_sDirname;
222 
223         if ( !wxEndsWithPathSeparator(sFilespec) )
224         {
225             sFilespec += wxT('\\');
226         }
227         sFilespec += (!m_sFilespec ? wxT("*.*") : m_sFilespec.c_str());
228 
229         m_vFinddata = FindFirst( sFilespec
230                                 ,PTR_TO_FINDDATA
231                                );
232         bFirst = true;
233     }
234 
235     if ( !IsFindDataOk(m_vFinddata) )
236     {
237         return false;
238     }
239 
240     const wxChar*                   zName;
241     FIND_ATTR                       vAttr;
242 
243     for ( ;; )
244     {
245         if (bFirst)
246         {
247             bFirst = false;
248         }
249         else
250         {
251             if (!FindNext( m_vFinddata
252                           ,PTR_TO_FINDDATA
253                          ))
254             {
255                 return false;
256             }
257         }
258 
259         zName = GetNameFromFindData(PTR_TO_FINDDATA);
260         vAttr = GetAttrFromFindData(PTR_TO_FINDDATA);
261 
262         //
263         // Don't return "." and ".." unless asked for
264         //
265         if ( zName[0] == wxT('.') &&
266              ((zName[1] == wxT('.') && zName[2] == wxT('\0')) ||
267               (zName[1] == wxT('\0'))) )
268         {
269             if (!(m_nFlags & wxDIR_DOTDOT))
270                 continue;
271         }
272 
273         //
274         // Check the type now
275         //
276         if (!(m_nFlags & wxDIR_FILES) && !IsDir(vAttr))
277         {
278             //
279             // It's a file, but we don't want them
280             //
281             continue;
282         }
283         else if (!(m_nFlags & wxDIR_DIRS) && IsDir(vAttr) )
284         {
285             //
286             // It's a dir, and we don't want it
287             //
288             continue;
289         }
290 
291         //
292         // Finally, check whether it's a hidden file
293         //
294         if (!(m_nFlags & wxDIR_HIDDEN))
295         {
296             if (IsHidden(vAttr))
297             {
298                 //
299                 // It's a hidden file, skip it
300                 //
301                 continue;
302             }
303         }
304         *psFilename = zName;
305         break;
306     }
307     return true;
308 } // end of wxDirData::Read
309 
310 // ----------------------------------------------------------------------------
311 // wxDir construction/destruction
312 // ----------------------------------------------------------------------------
313 
wxDir(const wxString & rsDirname)314 wxDir::wxDir(
315   const wxString&                   rsDirname
316 )
317 {
318     m_data = NULL;
319 
320     (void)Open(rsDirname);
321 } // end of wxDir::wxDir
322 
Open(const wxString & rsDirname)323 bool wxDir::Open(
324   const wxString&                   rsDirname
325 )
326 {
327     delete M_DIR;
328     m_data = new wxDirData(rsDirname);
329     return true;
330 } // end of wxDir::Open
331 
IsOpened() const332 bool wxDir::IsOpened() const
333 {
334     return m_data != NULL;
335 } // end of wxDir::IsOpen
336 
GetName() const337 wxString wxDir::GetName() const
338 {
339     wxString name;
340     if ( m_data )
341     {
342         name = M_DIR->GetName();
343         if ( !name.empty() )
344         {
345             // bring to canonical Windows form
346             name.Replace(wxT("/"), wxT("\\"));
347 
348             if ( name.Last() == wxT('\\') )
349             {
350                 // chop off the last (back)slash
351                 name.Truncate(name.length() - 1);
352             }
353         }
354     }
355 
356     return name;
357 }
358 
~wxDir()359 wxDir::~wxDir()
360 {
361     delete M_DIR;
362 } // end of wxDir::~wxDir
363 
364 // ----------------------------------------------------------------------------
365 // wxDir enumerating
366 // ----------------------------------------------------------------------------
367 
GetFirst(wxString * psFilename,const wxString & rsFilespec,int nFlags) const368 bool wxDir::GetFirst(
369   wxString*                         psFilename
370 , const wxString&                   rsFilespec
371 , int                               nFlags
372 ) const
373 {
374     wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
375     M_DIR->Rewind();
376     M_DIR->SetFileSpec(rsFilespec);
377     M_DIR->SetFlags(nFlags);
378     return GetNext(psFilename);
379 } // end of wxDir::GetFirst
380 
GetNext(wxString * psFilename) const381 bool wxDir::GetNext(
382   wxString*                         psFilename
383 ) const
384 {
385     wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
386     wxCHECK_MSG( psFilename, false, wxT("bad pointer in wxDir::GetNext()") );
387     return M_DIR->Read(psFilename);
388 } // end of wxDir::GetNext
389 
390