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