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