Remove all lines containing cvs/svn "$Id$" keyword.
[wxWidgets.git] / src / os2 / dir.cpp
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
49 static inline FIND_DATA InitFindData() { return ERROR_INVALID_HANDLE; }
50
51 static inline bool IsFindDataOk(
52 FIND_DATA vFd
53 )
54 {
55 return vFd != ERROR_INVALID_HANDLE;
56 }
57
58 static inline void FreeFindData(
59 FIND_DATA vFd
60 )
61 {
62 if (!::DosFindClose(vFd))
63 {
64 wxLogLastError(wxT("DosFindClose"));
65 }
66 }
67
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
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
104 static const wxChar* GetNameFromFindData(
105 FIND_STRUCT* pFinddata
106 )
107 {
108 return (wxChar*)pFinddata->achName;
109 }
110
111 static const FIND_ATTR GetAttrFromFindData(
112 FIND_STRUCT* pFinddata
113 )
114 {
115 return pFinddata->attrFile;
116 }
117
118 static inline bool IsDir(
119 FIND_ATTR vAttr
120 )
121 {
122 return (vAttr & FILE_DIRECTORY) != 0;
123 }
124
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
157 void SetFileSpec(const wxString& rsFilespec) { m_sFilespec = rsFilespec; }
158 void SetFlags(int nFlags) { m_nFlags = nFlags; }
159
160 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
180 wxDirData::wxDirData(
181 const wxString& rsDirname
182 )
183 : m_sDirname(rsDirname)
184 {
185 m_vFinddata = InitFindData();
186 } // end of wxDirData::wxDirData
187
188 wxDirData::~wxDirData()
189 {
190 Close();
191 } // end of wxDirData::~wxDirData
192
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
202 void wxDirData::Rewind()
203 {
204 Close();
205 } // end of wxDirData::Rewind
206
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
314 wxDir::wxDir(
315 const wxString& rsDirname
316 )
317 {
318 m_data = NULL;
319
320 (void)Open(rsDirname);
321 } // end of wxDir::wxDir
322
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
332 bool wxDir::IsOpened() const
333 {
334 return m_data != NULL;
335 } // end of wxDir::IsOpen
336
337 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
359 wxDir::~wxDir()
360 {
361 delete M_DIR;
362 } // end of wxDir::~wxDir
363
364 // ----------------------------------------------------------------------------
365 // wxDir enumerating
366 // ----------------------------------------------------------------------------
367
368 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
381 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