]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dir.cpp
2ed4f0e02e3c6671bd79b24a5e77c88ae78bc2a6
[wxWidgets.git] / src / msw / dir.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/dir.cpp
3 // Purpose: wxDir implementation for Win32
4 // Author: Vadim Zeitlin
5 // Modified by:
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 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34 #endif // PCH
35
36 #include "wx/dir.h"
37 #include "wx/filefn.h" // for wxPathExists()
38
39 // ----------------------------------------------------------------------------
40 // define the types and functions used for file searching
41 // ----------------------------------------------------------------------------
42
43 // under Win16 use compiler-specific functions
44 #ifdef __WIN16__
45 #ifdef __VISUALC__
46 #include <dos.h>
47 #include <errno.h>
48
49 typedef struct _find_t FIND_STRUCT;
50 #elif defined(__BORLANDC__)
51 #include <dir.h>
52
53 typedef struct ffblk FIND_STRUCT;
54 #else
55 #error "No directory searching functions for this compiler"
56 #endif
57
58 typedef FIND_STRUCT *FIND_DATA;
59 typedef char FIND_ATTR;
60
61 static inline FIND_DATA InitFindData() { return (FIND_DATA)NULL; }
62 static inline bool IsFindDataOk(FIND_DATA fd) { return fd != NULL; }
63 static inline void FreeFindData(FIND_DATA fd) { free(fd); }
64
65 static inline FIND_DATA FindFirst(const wxString& spec,
66 FIND_STRUCT * WXUNUSED(finddata))
67 {
68 // attribute to find all files
69 static const FIND_ATTR attr = 0x3F;
70
71 FIND_DATA fd = (FIND_DATA)malloc(sizeof(FIND_STRUCT));
72
73 if (
74 #ifdef __VISUALC__
75 _dos_findfirst(spec, attr, fd) == 0
76 #else // Borland
77 findfirst(spec, fd, attr) == 0
78 #endif
79 )
80 {
81 return fd;
82 }
83 else
84 {
85 free(fd);
86
87 return NULL;
88 }
89 }
90
91 static inline bool FindNext(FIND_DATA fd, FIND_STRUCT * WXUNUSED(finddata))
92 {
93 #ifdef __VISUALC__
94 return _dos_findnext(fd) == 0;
95 #else // Borland
96 return findnext(fd) == 0;
97 #endif
98 }
99
100 static const wxChar *GetNameFromFindData(FIND_STRUCT *finddata)
101 {
102 #ifdef __VISUALC__
103 return finddata->name;
104 #else // Borland
105 return finddata->ff_name;
106 #endif
107 }
108
109 static const FIND_ATTR GetAttrFromFindData(FIND_STRUCT *finddata)
110 {
111 #ifdef __VISUALC__
112 return finddata->attrib;
113 #else // Borland
114 return finddata->ff_attrib;
115 #endif
116 }
117
118 static inline bool IsDir(FIND_ATTR attr)
119 {
120 return (attr & _A_SUBDIR) != 0;
121 }
122
123 static inline bool IsHidden(FIND_ATTR attr)
124 {
125 return (attr & (_A_SYSTEM | _A_HIDDEN)) != 0;
126 }
127 #else // Win32
128 #include <windows.h>
129
130 typedef WIN32_FIND_DATA FIND_STRUCT;
131 typedef HANDLE FIND_DATA;
132 typedef DWORD FIND_ATTR;
133
134 static inline FIND_DATA InitFindData() { return INVALID_HANDLE_VALUE; }
135
136 static inline bool IsFindDataOk(FIND_DATA fd)
137 {
138 return fd != INVALID_HANDLE_VALUE;
139 }
140
141 static inline void FreeFindData(FIND_DATA fd)
142 {
143 if ( !::FindClose(fd) )
144 {
145 wxLogLastError(_T("FindClose"));
146 }
147 }
148
149 static inline FIND_DATA FindFirst(const wxString& spec,
150 FIND_STRUCT *finddata)
151 {
152 return ::FindFirstFile(filespec, &finddata);
153 }
154
155 static inline bool FindNext(FIND_DATA fd, FIND_STRUCT *finddata)
156 {
157 return ::FindNextFile(fd, finddata) != 0;
158 }
159
160 static const wxChar *GetNameFromFindData(FIND_STRUCT *finddata)
161 {
162 return finddata->cFileName;
163 }
164
165 static const FIND_ATTR GetAttrFromFindData(FIND_STRUCT *finddata)
166 {
167 return finddata->dwFileAttributes;
168 }
169
170 static inline bool IsDir(FIND_ATTR attr)
171 {
172 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
173 }
174
175 static inline bool IsHidden(FIND_ATTR attr)
176 {
177 return (attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
178 }
179 #endif // __WIN16__
180
181 // ----------------------------------------------------------------------------
182 // constants
183 // ----------------------------------------------------------------------------
184
185 #ifndef MAX_PATH
186 #define MAX_PATH 260 // from VC++ headers
187 #endif
188
189 // ----------------------------------------------------------------------------
190 // macros
191 // ----------------------------------------------------------------------------
192
193 #define M_DIR ((wxDirData *)m_data)
194
195 // ----------------------------------------------------------------------------
196 // private classes
197 // ----------------------------------------------------------------------------
198
199 // this class stores everything we need to enumerate the files
200 class wxDirData
201 {
202 public:
203 wxDirData(const wxString& dirname);
204 ~wxDirData();
205
206 void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
207 void SetFlags(int flags) { m_flags = flags; }
208
209 void Close();
210 void Rewind();
211 bool Read(wxString *filename);
212
213 private:
214 FIND_DATA m_finddata;
215
216 wxString m_dirname;
217 wxString m_filespec;
218
219 int m_flags;
220 };
221
222 // ============================================================================
223 // implementation
224 // ============================================================================
225
226 // ----------------------------------------------------------------------------
227 // wxDirData
228 // ----------------------------------------------------------------------------
229
230 wxDirData::wxDirData(const wxString& dirname)
231 : m_dirname(dirname)
232 {
233 m_finddata = InitFindData();
234 }
235
236 wxDirData::~wxDirData()
237 {
238 Close();
239 }
240
241 void wxDirData::Close()
242 {
243 if ( IsFindDataOk(m_finddata) )
244 {
245 FreeFindData(m_finddata);
246
247 m_finddata = InitFindData();
248 }
249 }
250
251 void wxDirData::Rewind()
252 {
253 Close();
254 }
255
256 bool wxDirData::Read(wxString *filename)
257 {
258 bool first = FALSE;
259
260 #ifdef __WIN32__
261 WIN32_FIND_DATA finddata;
262 #define PTR_TO_FINDDATA (&finddata)
263 #else // Win16
264 #define PTR_TO_FINDDATA (m_finddata)
265 #endif
266
267 if ( !IsFindDataOk(m_finddata) )
268 {
269 // open first
270 wxString filespec;
271 filespec << m_dirname << _T('\\')
272 << (!m_filespec ? _T("*.*") : m_filespec.c_str());
273
274 m_finddata = FindFirst(filespec, PTR_TO_FINDDATA);
275
276 first = TRUE;
277 }
278
279 if ( !IsFindDataOk(m_finddata) )
280 {
281 #ifdef __WIN32__
282 DWORD err = ::GetLastError();
283
284 if ( err != ERROR_FILE_NOT_FOUND )
285 {
286 wxLogSysError(err, _("Can not enumerate files in directory '%s'"),
287 m_dirname.c_str());
288 }
289 #endif // __WIN32__
290 //else: not an error, just no (such) files
291
292 return FALSE;
293 }
294
295 const wxChar *name;
296 FIND_ATTR attr;
297
298 for ( ;; )
299 {
300 if ( first )
301 {
302 first = FALSE;
303 }
304 else
305 {
306 if ( !FindNext(m_finddata, PTR_TO_FINDDATA) )
307 {
308 #ifdef __WIN32__
309 DWORD err = ::GetLastError();
310
311 if ( err != ERROR_NO_MORE_FILES )
312 {
313 wxLogLastError(_T("FindNext"));
314 }
315 #endif // __WIN32__
316 //else: not an error, just no more (such) files
317
318 return FALSE;
319 }
320 }
321
322 name = GetNameFromFindData(PTR_TO_FINDDATA);
323 attr = GetAttrFromFindData(PTR_TO_FINDDATA);
324
325 // don't return "." and ".." unless asked for
326 if ( name[0] == _T('.') &&
327 ((name[1] == _T('.') && name[2] == _T('\0')) ||
328 (name[1] == _T('\0'))) )
329 {
330 if ( !(m_flags & wxDIR_DOTDOT) )
331 continue;
332 }
333
334 // check the type now
335 if ( !(m_flags & wxDIR_FILES) && !IsDir(attr) )
336 {
337 // it's a file, but we don't want them
338 continue;
339 }
340 else if ( !(m_flags & wxDIR_DIRS) && IsDir(attr) )
341 {
342 // it's a dir, and we don't want it
343 continue;
344 }
345
346 // finally, check whether it's a hidden file
347 if ( !(m_flags & wxDIR_HIDDEN) )
348 {
349 if ( IsHidden(attr) )
350 {
351 // it's a hidden file, skip it
352 continue;
353 }
354 }
355
356 *filename = name;
357
358 break;
359 }
360
361 return TRUE;
362 }
363
364 // ----------------------------------------------------------------------------
365 // wxDir helpers
366 // ----------------------------------------------------------------------------
367
368 /* static */
369 bool wxDir::Exists(const wxString& dir)
370 {
371 return wxPathExists(dir);
372 }
373
374 // ----------------------------------------------------------------------------
375 // wxDir construction/destruction
376 // ----------------------------------------------------------------------------
377
378 wxDir::wxDir(const wxString& dirname)
379 {
380 m_data = NULL;
381
382 (void)Open(dirname);
383 }
384
385 bool wxDir::Open(const wxString& dirname)
386 {
387 delete M_DIR;
388 m_data = new wxDirData(dirname);
389
390 return TRUE;
391 }
392
393 bool wxDir::IsOpened() const
394 {
395 return m_data != NULL;
396 }
397
398 wxDir::~wxDir()
399 {
400 delete M_DIR;
401 }
402
403 // ----------------------------------------------------------------------------
404 // wxDir enumerating
405 // ----------------------------------------------------------------------------
406
407 bool wxDir::GetFirst(wxString *filename,
408 const wxString& filespec,
409 int flags) const
410 {
411 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
412
413 M_DIR->Rewind();
414
415 M_DIR->SetFileSpec(filespec);
416 M_DIR->SetFlags(flags);
417
418 return GetNext(filename);
419 }
420
421 bool wxDir::GetNext(wxString *filename) const
422 {
423 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
424
425 wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
426
427 return M_DIR->Read(filename);
428 }