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