patches for BC++ 5.3 from Ricky Gonzales <gonzales@pyramid3.net>
[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(spec, 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 = m_dirname;
271 if ( !wxEndsWithPathSeparator(filespec) )
272 {
273 filespec += _T('\\');
274 }
275 filespec += (!m_filespec ? _T("*.*") : m_filespec.c_str());
276
277 m_finddata = FindFirst(filespec, PTR_TO_FINDDATA);
278
279 first = TRUE;
280 }
281
282 if ( !IsFindDataOk(m_finddata) )
283 {
284 #ifdef __WIN32__
285 DWORD err = ::GetLastError();
286
287 if ( err != ERROR_FILE_NOT_FOUND )
288 {
289 wxLogSysError(err, _("Can not enumerate files in directory '%s'"),
290 m_dirname.c_str());
291 }
292 #endif // __WIN32__
293 //else: not an error, just no (such) files
294
295 return FALSE;
296 }
297
298 const wxChar *name;
299 FIND_ATTR attr;
300
301 for ( ;; )
302 {
303 if ( first )
304 {
305 first = FALSE;
306 }
307 else
308 {
309 if ( !FindNext(m_finddata, PTR_TO_FINDDATA) )
310 {
311 #ifdef __WIN32__
312 DWORD err = ::GetLastError();
313
314 if ( err != ERROR_NO_MORE_FILES )
315 {
316 wxLogLastError(_T("FindNext"));
317 }
318 #endif // __WIN32__
319 //else: not an error, just no more (such) files
320
321 return FALSE;
322 }
323 }
324
325 name = GetNameFromFindData(PTR_TO_FINDDATA);
326 attr = GetAttrFromFindData(PTR_TO_FINDDATA);
327
328 // don't return "." and ".." unless asked for
329 if ( name[0] == _T('.') &&
330 ((name[1] == _T('.') && name[2] == _T('\0')) ||
331 (name[1] == _T('\0'))) )
332 {
333 if ( !(m_flags & wxDIR_DOTDOT) )
334 continue;
335 }
336
337 // check the type now
338 if ( !(m_flags & wxDIR_FILES) && !IsDir(attr) )
339 {
340 // it's a file, but we don't want them
341 continue;
342 }
343 else if ( !(m_flags & wxDIR_DIRS) && IsDir(attr) )
344 {
345 // it's a dir, and we don't want it
346 continue;
347 }
348
349 // finally, check whether it's a hidden file
350 if ( !(m_flags & wxDIR_HIDDEN) )
351 {
352 if ( IsHidden(attr) )
353 {
354 // it's a hidden file, skip it
355 continue;
356 }
357 }
358
359 *filename = name;
360
361 break;
362 }
363
364 return TRUE;
365 }
366
367 // ----------------------------------------------------------------------------
368 // wxDir helpers
369 // ----------------------------------------------------------------------------
370
371 /* static */
372 bool wxDir::Exists(const wxString& dir)
373 {
374 return wxPathExists(dir);
375 }
376
377 // ----------------------------------------------------------------------------
378 // wxDir construction/destruction
379 // ----------------------------------------------------------------------------
380
381 wxDir::wxDir(const wxString& dirname)
382 {
383 m_data = NULL;
384
385 (void)Open(dirname);
386 }
387
388 bool wxDir::Open(const wxString& dirname)
389 {
390 delete M_DIR;
391 m_data = new wxDirData(dirname);
392
393 return TRUE;
394 }
395
396 bool wxDir::IsOpened() const
397 {
398 return m_data != NULL;
399 }
400
401 wxDir::~wxDir()
402 {
403 delete M_DIR;
404 }
405
406 // ----------------------------------------------------------------------------
407 // wxDir enumerating
408 // ----------------------------------------------------------------------------
409
410 bool wxDir::GetFirst(wxString *filename,
411 const wxString& filespec,
412 int flags) const
413 {
414 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
415
416 M_DIR->Rewind();
417
418 M_DIR->SetFileSpec(filespec);
419 M_DIR->SetFlags(flags);
420
421 return GetNext(filename);
422 }
423
424 bool wxDir::GetNext(wxString *filename) const
425 {
426 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
427
428 wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
429
430 return M_DIR->Read(filename);
431 }