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