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