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