]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dir.cpp
Forward port 2.8 fix.
[wxWidgets.git] / src / msw / dir.cpp
CommitLineData
1944c6bd
VZ
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>
65571936 9// Licence: wxWindows licence
1944c6bd
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
1944c6bd
VZ
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"
da865fdd 33#include "wx/filefn.h" // for wxDirExists()
1944c6bd 34
532d575b 35#ifdef __WINDOWS__
4676948b
JS
36 #include "wx/msw/private.h"
37#endif
38
8f177c8e
VZ
39// ----------------------------------------------------------------------------
40// define the types and functions used for file searching
41// ----------------------------------------------------------------------------
42
145bbf1f
VZ
43namespace
44{
45
3a5bcc4d
VZ
46typedef WIN32_FIND_DATA FIND_STRUCT;
47typedef HANDLE FIND_DATA;
48typedef DWORD FIND_ATTR;
8f177c8e 49
145bbf1f
VZ
50inline FIND_DATA InitFindData()
51{
52 return INVALID_HANDLE_VALUE;
53}
8f177c8e 54
145bbf1f 55inline bool IsFindDataOk(FIND_DATA fd)
3a5bcc4d 56{
8f177c8e 57 return fd != INVALID_HANDLE_VALUE;
3a5bcc4d 58}
8f177c8e 59
145bbf1f 60inline void FreeFindData(FIND_DATA fd)
3a5bcc4d 61{
145bbf1f
VZ
62 if ( !::FindClose(fd) )
63 {
9a83f860 64 wxLogLastError(wxT("FindClose"));
145bbf1f 65 }
3a5bcc4d 66}
8f177c8e 67
145bbf1f
VZ
68inline FIND_DATA FindFirst(const wxString& spec,
69 FIND_STRUCT *finddata)
3a5bcc4d 70{
145bbf1f 71 return ::FindFirstFile(spec.fn_str(), finddata);
3a5bcc4d 72}
8f177c8e 73
145bbf1f 74inline bool FindNext(FIND_DATA fd, FIND_STRUCT *finddata)
3a5bcc4d 75{
145bbf1f 76 return ::FindNextFile(fd, finddata) != 0;
3a5bcc4d 77}
8f177c8e 78
145bbf1f 79const wxChar *GetNameFromFindData(FIND_STRUCT *finddata)
3a5bcc4d 80{
145bbf1f 81 return finddata->cFileName;
3a5bcc4d 82}
8f177c8e 83
145bbf1f 84inline FIND_ATTR GetAttrFromFindData(FIND_STRUCT *finddata)
3a5bcc4d 85{
145bbf1f 86 return finddata->dwFileAttributes;
3a5bcc4d 87}
8f177c8e 88
145bbf1f 89inline bool IsDir(FIND_ATTR attr)
3a5bcc4d 90{
145bbf1f 91 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
3a5bcc4d 92}
8f177c8e 93
145bbf1f 94inline bool IsHidden(FIND_ATTR attr)
3a5bcc4d 95{
145bbf1f 96 return (attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
3a5bcc4d 97}
1944c6bd 98
145bbf1f
VZ
99} // anonymous namespace
100
1944c6bd
VZ
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
35332784
VZ
133 const wxString& GetName() const { return m_dirname; }
134
1944c6bd 135private:
8f177c8e 136 FIND_DATA m_finddata;
1944c6bd
VZ
137
138 wxString m_dirname;
139 wxString m_filespec;
140
141 int m_flags;
22f3361e 142
c0c133e1 143 wxDECLARE_NO_COPY_CLASS(wxDirData);
1944c6bd
VZ
144};
145
146// ============================================================================
147// implementation
148// ============================================================================
149
150// ----------------------------------------------------------------------------
151// wxDirData
152// ----------------------------------------------------------------------------
153
154wxDirData::wxDirData(const wxString& dirname)
155 : m_dirname(dirname)
156{
8f177c8e 157 m_finddata = InitFindData();
1944c6bd
VZ
158}
159
160wxDirData::~wxDirData()
161{
162 Close();
163}
164
165void wxDirData::Close()
166{
8f177c8e 167 if ( IsFindDataOk(m_finddata) )
1944c6bd 168 {
8f177c8e 169 FreeFindData(m_finddata);
4afd7529 170
8f177c8e 171 m_finddata = InitFindData();
1944c6bd
VZ
172 }
173}
174
175void wxDirData::Rewind()
176{
177 Close();
178}
179
180bool wxDirData::Read(wxString *filename)
181{
d71cc120 182 bool first = false;
1944c6bd
VZ
183
184 WIN32_FIND_DATA finddata;
8f177c8e 185 #define PTR_TO_FINDDATA (&finddata)
8f177c8e
VZ
186
187 if ( !IsFindDataOk(m_finddata) )
1944c6bd
VZ
188 {
189 // open first
ad0dc53b
VZ
190 wxString filespec = m_dirname;
191 if ( !wxEndsWithPathSeparator(filespec) )
192 {
9a83f860 193 filespec += wxT('\\');
ad0dc53b 194 }
c9f78968 195 if ( !m_filespec )
9a83f860 196 filespec += wxT("*.*");
c9f78968
VS
197 else
198 filespec += m_filespec;
4afd7529 199
8f177c8e 200 m_finddata = FindFirst(filespec, PTR_TO_FINDDATA);
1944c6bd 201
d71cc120 202 first = true;
1944c6bd
VZ
203 }
204
8f177c8e 205 if ( !IsFindDataOk(m_finddata) )
1944c6bd 206 {
8f177c8e 207#ifdef __WIN32__
1944c6bd
VZ
208 DWORD err = ::GetLastError();
209
5613bc20 210 if ( err != ERROR_FILE_NOT_FOUND && err != ERROR_NO_MORE_FILES )
1944c6bd 211 {
a236aa20 212 wxLogSysError(err, _("Can not enumerate files in directory '%s'"),
1944c6bd
VZ
213 m_dirname.c_str());
214 }
8f177c8e 215#endif // __WIN32__
1944c6bd
VZ
216 //else: not an error, just no (such) files
217
d71cc120 218 return false;
1944c6bd
VZ
219 }
220
1944c6bd 221 const wxChar *name;
8f177c8e 222 FIND_ATTR attr;
1944c6bd 223
4afd7529 224 for ( ;; )
1944c6bd
VZ
225 {
226 if ( first )
227 {
d71cc120 228 first = false;
1944c6bd
VZ
229 }
230 else
231 {
8f177c8e 232 if ( !FindNext(m_finddata, PTR_TO_FINDDATA) )
1944c6bd 233 {
8f177c8e 234#ifdef __WIN32__
1944c6bd
VZ
235 DWORD err = ::GetLastError();
236
237 if ( err != ERROR_NO_MORE_FILES )
238 {
9a83f860 239 wxLogLastError(wxT("FindNext"));
1944c6bd 240 }
8f177c8e 241#endif // __WIN32__
1944c6bd
VZ
242 //else: not an error, just no more (such) files
243
d71cc120 244 return false;
1944c6bd
VZ
245 }
246 }
247
8f177c8e
VZ
248 name = GetNameFromFindData(PTR_TO_FINDDATA);
249 attr = GetAttrFromFindData(PTR_TO_FINDDATA);
1944c6bd
VZ
250
251 // don't return "." and ".." unless asked for
9a83f860
VZ
252 if ( name[0] == wxT('.') &&
253 ((name[1] == wxT('.') && name[2] == wxT('\0')) ||
254 (name[1] == wxT('\0'))) )
1944c6bd
VZ
255 {
256 if ( !(m_flags & wxDIR_DOTDOT) )
257 continue;
258 }
259
260 // check the type now
8f177c8e 261 if ( !(m_flags & wxDIR_FILES) && !IsDir(attr) )
1944c6bd
VZ
262 {
263 // it's a file, but we don't want them
264 continue;
265 }
8f177c8e 266 else if ( !(m_flags & wxDIR_DIRS) && IsDir(attr) )
1944c6bd
VZ
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 {
8f177c8e 275 if ( IsHidden(attr) )
4afd7529
VZ
276 {
277 // it's a hidden file, skip it
278 continue;
279 }
1944c6bd 280 }
1944c6bd 281
4afd7529
VZ
282 *filename = name;
283
284 break;
285 }
1944c6bd 286
d71cc120 287 return true;
1944c6bd
VZ
288}
289
290// ----------------------------------------------------------------------------
291// wxDir helpers
292// ----------------------------------------------------------------------------
293
294/* static */
295bool wxDir::Exists(const wxString& dir)
296{
da865fdd 297 return wxDirExists(dir);
1944c6bd
VZ
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;
03647350 314
89432923
RR
315 // The Unix code does a similar test
316 if (wxDirExists(dirname))
317 {
318 m_data = new wxDirData(dirname);
1944c6bd 319
89432923
RR
320 return true;
321 }
322 else
323 {
324 m_data = NULL;
03647350 325
89432923
RR
326 return false;
327 }
1944c6bd
VZ
328}
329
330bool wxDir::IsOpened() const
331{
332 return m_data != NULL;
333}
334
35332784
VZ
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
9a83f860 344 name.Replace(wxT("/"), wxT("\\"));
35332784 345
9a83f860 346 if ( name.Last() == wxT('\\') )
35332784
VZ
347 {
348 // chop off the last (back)slash
349 name.Truncate(name.length() - 1);
350 }
351 }
352 }
353
354 return name;
355}
356
1944c6bd
VZ
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{
9a83f860 370 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
1944c6bd
VZ
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{
9a83f860 382 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
1944c6bd 383
9a83f860 384 wxCHECK_MSG( filename, false, wxT("bad pointer in wxDir::GetNext()") );
1944c6bd
VZ
385
386 return M_DIR->Read(filename);
387}
2b5f62a0
VZ
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{
4de1b652
JS
399#ifdef __WXWINCE__
400 // FindFirst() is going to fail
401 wxASSERT_MSG( !dirname.empty(),
9a83f860 402 wxT("incorrect directory name format in wxGetDirectoryTimes") );
4de1b652 403#else
2b5f62a0 404 // FindFirst() is going to fail
9a83f860
VZ
405 wxASSERT_MSG( !dirname.empty() && dirname.Last() != wxT('\\'),
406 wxT("incorrect directory name format in wxGetDirectoryTimes") );
4de1b652 407#endif
2b5f62a0
VZ
408
409 FIND_STRUCT fs;
410 FIND_DATA fd = FindFirst(dirname, &fs);
411 if ( !IsFindDataOk(fd) )
412 {
d71cc120 413 return false;
2b5f62a0
VZ
414 }
415
416 *ftAccess = fs.ftLastAccessTime;
417 *ftCreate = fs.ftCreationTime;
418 *ftMod = fs.ftLastWriteTime;
419
420 FindClose(fd);
421
d71cc120 422 return true;
2b5f62a0
VZ
423}
424
425#endif // __WIN32__
426