]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dir.cpp
WXUNUSED_UNLESS_ODRAWN does not reflect wxUSE_MENUS_NATIVE.
[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
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
1944c6bd
VZ
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 wxPathExists()
38
4676948b
JS
39#ifdef __WXMSW__
40 #include "wx/msw/private.h"
41#endif
42
8f177c8e
VZ
43// ----------------------------------------------------------------------------
44// define the types and functions used for file searching
45// ----------------------------------------------------------------------------
46
3a5bcc4d
VZ
47typedef WIN32_FIND_DATA FIND_STRUCT;
48typedef HANDLE FIND_DATA;
49typedef DWORD FIND_ATTR;
8f177c8e 50
3a5bcc4d 51static inline FIND_DATA InitFindData() { return INVALID_HANDLE_VALUE; }
8f177c8e 52
3a5bcc4d
VZ
53static inline bool IsFindDataOk(FIND_DATA fd)
54{
8f177c8e 55 return fd != INVALID_HANDLE_VALUE;
3a5bcc4d 56}
8f177c8e 57
3a5bcc4d
VZ
58static inline void FreeFindData(FIND_DATA fd)
59{
8f177c8e
VZ
60 if ( !::FindClose(fd) )
61 {
62 wxLogLastError(_T("FindClose"));
63 }
3a5bcc4d 64}
8f177c8e 65
3a5bcc4d 66static inline FIND_DATA FindFirst(const wxString& spec,
8f177c8e 67 FIND_STRUCT *finddata)
3a5bcc4d 68{
c5a1681b 69 return ::FindFirstFile(spec, finddata);
3a5bcc4d 70}
8f177c8e 71
3a5bcc4d
VZ
72static inline bool FindNext(FIND_DATA fd, FIND_STRUCT *finddata)
73{
8f177c8e 74 return ::FindNextFile(fd, finddata) != 0;
3a5bcc4d 75}
8f177c8e 76
3a5bcc4d
VZ
77static const wxChar *GetNameFromFindData(FIND_STRUCT *finddata)
78{
8f177c8e 79 return finddata->cFileName;
3a5bcc4d 80}
8f177c8e 81
3a5bcc4d
VZ
82static const FIND_ATTR GetAttrFromFindData(FIND_STRUCT *finddata)
83{
8f177c8e 84 return finddata->dwFileAttributes;
3a5bcc4d 85}
8f177c8e 86
3a5bcc4d
VZ
87static inline bool IsDir(FIND_ATTR attr)
88{
8f177c8e 89 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
3a5bcc4d 90}
8f177c8e 91
3a5bcc4d
VZ
92static inline bool IsHidden(FIND_ATTR attr)
93{
8f177c8e 94 return (attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
3a5bcc4d 95}
1944c6bd
VZ
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
35332784
VZ
129 const wxString& GetName() const { return m_dirname; }
130
1944c6bd 131private:
8f177c8e 132 FIND_DATA m_finddata;
1944c6bd
VZ
133
134 wxString m_dirname;
135 wxString m_filespec;
136
137 int m_flags;
22f3361e
VZ
138
139 DECLARE_NO_COPY_CLASS(wxDirData)
1944c6bd
VZ
140};
141
142// ============================================================================
143// implementation
144// ============================================================================
145
146// ----------------------------------------------------------------------------
147// wxDirData
148// ----------------------------------------------------------------------------
149
150wxDirData::wxDirData(const wxString& dirname)
151 : m_dirname(dirname)
152{
8f177c8e 153 m_finddata = InitFindData();
1944c6bd
VZ
154}
155
156wxDirData::~wxDirData()
157{
158 Close();
159}
160
161void wxDirData::Close()
162{
8f177c8e 163 if ( IsFindDataOk(m_finddata) )
1944c6bd 164 {
8f177c8e 165 FreeFindData(m_finddata);
4afd7529 166
8f177c8e 167 m_finddata = InitFindData();
1944c6bd
VZ
168 }
169}
170
171void wxDirData::Rewind()
172{
173 Close();
174}
175
176bool wxDirData::Read(wxString *filename)
177{
d71cc120 178 bool first = false;
1944c6bd
VZ
179
180 WIN32_FIND_DATA finddata;
8f177c8e 181 #define PTR_TO_FINDDATA (&finddata)
8f177c8e
VZ
182
183 if ( !IsFindDataOk(m_finddata) )
1944c6bd
VZ
184 {
185 // open first
ad0dc53b
VZ
186 wxString filespec = m_dirname;
187 if ( !wxEndsWithPathSeparator(filespec) )
188 {
189 filespec += _T('\\');
190 }
191 filespec += (!m_filespec ? _T("*.*") : m_filespec.c_str());
4afd7529 192
8f177c8e 193 m_finddata = FindFirst(filespec, PTR_TO_FINDDATA);
1944c6bd 194
d71cc120 195 first = true;
1944c6bd
VZ
196 }
197
8f177c8e 198 if ( !IsFindDataOk(m_finddata) )
1944c6bd 199 {
8f177c8e 200#ifdef __WIN32__
1944c6bd
VZ
201 DWORD err = ::GetLastError();
202
4afd7529 203 if ( err != ERROR_FILE_NOT_FOUND )
1944c6bd
VZ
204 {
205 wxLogSysError(err, _("Can not enumerate files in directory '%s'"),
206 m_dirname.c_str());
207 }
8f177c8e 208#endif // __WIN32__
1944c6bd
VZ
209 //else: not an error, just no (such) files
210
d71cc120 211 return false;
1944c6bd
VZ
212 }
213
1944c6bd 214 const wxChar *name;
8f177c8e 215 FIND_ATTR attr;
1944c6bd 216
4afd7529 217 for ( ;; )
1944c6bd
VZ
218 {
219 if ( first )
220 {
d71cc120 221 first = false;
1944c6bd
VZ
222 }
223 else
224 {
8f177c8e 225 if ( !FindNext(m_finddata, PTR_TO_FINDDATA) )
1944c6bd 226 {
8f177c8e 227#ifdef __WIN32__
1944c6bd
VZ
228 DWORD err = ::GetLastError();
229
230 if ( err != ERROR_NO_MORE_FILES )
231 {
232 wxLogLastError(_T("FindNext"));
233 }
8f177c8e 234#endif // __WIN32__
1944c6bd
VZ
235 //else: not an error, just no more (such) files
236
d71cc120 237 return false;
1944c6bd
VZ
238 }
239 }
240
8f177c8e
VZ
241 name = GetNameFromFindData(PTR_TO_FINDDATA);
242 attr = GetAttrFromFindData(PTR_TO_FINDDATA);
1944c6bd
VZ
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
8f177c8e 254 if ( !(m_flags & wxDIR_FILES) && !IsDir(attr) )
1944c6bd
VZ
255 {
256 // it's a file, but we don't want them
257 continue;
258 }
8f177c8e 259 else if ( !(m_flags & wxDIR_DIRS) && IsDir(attr) )
1944c6bd
VZ
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 {
8f177c8e 268 if ( IsHidden(attr) )
4afd7529
VZ
269 {
270 // it's a hidden file, skip it
271 continue;
272 }
1944c6bd 273 }
1944c6bd 274
4afd7529
VZ
275 *filename = name;
276
277 break;
278 }
1944c6bd 279
d71cc120 280 return true;
1944c6bd
VZ
281}
282
283// ----------------------------------------------------------------------------
284// wxDir helpers
285// ----------------------------------------------------------------------------
286
287/* static */
288bool wxDir::Exists(const wxString& dir)
289{
290 return wxPathExists(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
d71cc120 309 return true;
1944c6bd
VZ
310}
311
312bool wxDir::IsOpened() const
313{
314 return m_data != NULL;
315}
316
35332784
VZ
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
1944c6bd
VZ
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{
d71cc120 352 wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
1944c6bd
VZ
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{
d71cc120 364 wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
1944c6bd 365
d71cc120 366 wxCHECK_MSG( filename, false, _T("bad pointer in wxDir::GetNext()") );
1944c6bd
VZ
367
368 return M_DIR->Read(filename);
369}
2b5f62a0
VZ
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 {
d71cc120 389 return false;
2b5f62a0
VZ
390 }
391
392 *ftAccess = fs.ftLastAccessTime;
393 *ftCreate = fs.ftCreationTime;
394 *ftMod = fs.ftLastWriteTime;
395
396 FindClose(fd);
397
d71cc120 398 return true;
2b5f62a0
VZ
399}
400
401#endif // __WIN32__
402