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