Avoid events when implicitly selecting first wxBookCtrl page.
[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(wxT("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 += wxT('\\');
227 }
228 sFilespec += (!m_sFilespec ? wxT("*.*") : 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] == wxT('.') &&
267 ((zName[1] == wxT('.') && zName[2] == wxT('\0')) ||
268 (zName[1] == wxT('\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 construction/destruction
313 // ----------------------------------------------------------------------------
314
315 wxDir::wxDir(
316 const wxString& rsDirname
317 )
318 {
319 m_data = NULL;
320
321 (void)Open(rsDirname);
322 } // end of wxDir::wxDir
323
324 bool wxDir::Open(
325 const wxString& rsDirname
326 )
327 {
328 delete M_DIR;
329 m_data = new wxDirData(rsDirname);
330 return true;
331 } // end of wxDir::Open
332
333 bool wxDir::IsOpened() const
334 {
335 return m_data != NULL;
336 } // end of wxDir::IsOpen
337
338 wxString wxDir::GetName() const
339 {
340 wxString name;
341 if ( m_data )
342 {
343 name = M_DIR->GetName();
344 if ( !name.empty() )
345 {
346 // bring to canonical Windows form
347 name.Replace(wxT("/"), wxT("\\"));
348
349 if ( name.Last() == wxT('\\') )
350 {
351 // chop off the last (back)slash
352 name.Truncate(name.length() - 1);
353 }
354 }
355 }
356
357 return name;
358 }
359
360 wxDir::~wxDir()
361 {
362 delete M_DIR;
363 } // end of wxDir::~wxDir
364
365 // ----------------------------------------------------------------------------
366 // wxDir enumerating
367 // ----------------------------------------------------------------------------
368
369 bool wxDir::GetFirst(
370 wxString* psFilename
371 , const wxString& rsFilespec
372 , int nFlags
373 ) const
374 {
375 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
376 M_DIR->Rewind();
377 M_DIR->SetFileSpec(rsFilespec);
378 M_DIR->SetFlags(nFlags);
379 return GetNext(psFilename);
380 } // end of wxDir::GetFirst
381
382 bool wxDir::GetNext(
383 wxString* psFilename
384 ) const
385 {
386 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
387 wxCHECK_MSG( psFilename, false, wxT("bad pointer in wxDir::GetNext()") );
388 return M_DIR->Read(psFilename);
389 } // end of wxDir::GetNext
390