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