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