]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/dir.cpp
better ownership handling
[wxWidgets.git] / src / msw / dir.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/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
34#ifdef __WINDOWS__
35 #include "wx/msw/private.h"
36#endif
37
38// ----------------------------------------------------------------------------
39// define the types and functions used for file searching
40// ----------------------------------------------------------------------------
41
42namespace
43{
44
45typedef WIN32_FIND_DATA FIND_STRUCT;
46typedef HANDLE FIND_DATA;
47typedef DWORD FIND_ATTR;
48
49inline FIND_DATA InitFindData()
50{
51 return INVALID_HANDLE_VALUE;
52}
53
54inline bool IsFindDataOk(FIND_DATA fd)
55{
56 return fd != INVALID_HANDLE_VALUE;
57}
58
59inline void FreeFindData(FIND_DATA fd)
60{
61 if ( !::FindClose(fd) )
62 {
63 wxLogLastError(wxT("FindClose"));
64 }
65}
66
67inline FIND_DATA FindFirst(const wxString& spec,
68 FIND_STRUCT *finddata)
69{
70 return ::FindFirstFile(spec.t_str(), finddata);
71}
72
73inline bool FindNext(FIND_DATA fd, FIND_STRUCT *finddata)
74{
75 return ::FindNextFile(fd, finddata) != 0;
76}
77
78const wxChar *GetNameFromFindData(FIND_STRUCT *finddata)
79{
80 return finddata->cFileName;
81}
82
83inline FIND_ATTR GetAttrFromFindData(FIND_STRUCT *finddata)
84{
85 return finddata->dwFileAttributes;
86}
87
88inline bool IsDir(FIND_ATTR attr)
89{
90 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
91}
92
93inline bool IsHidden(FIND_ATTR attr)
94{
95 return (attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
96}
97
98} // anonymous namespace
99
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
132 const wxString& GetName() const { return m_dirname; }
133
134private:
135 FIND_DATA m_finddata;
136
137 wxString m_dirname;
138 wxString m_filespec;
139
140 int m_flags;
141
142 wxDECLARE_NO_COPY_CLASS(wxDirData);
143};
144
145// ============================================================================
146// implementation
147// ============================================================================
148
149// ----------------------------------------------------------------------------
150// wxDirData
151// ----------------------------------------------------------------------------
152
153wxDirData::wxDirData(const wxString& dirname)
154 : m_dirname(dirname)
155{
156 m_finddata = InitFindData();
157}
158
159wxDirData::~wxDirData()
160{
161 Close();
162}
163
164void wxDirData::Close()
165{
166 if ( IsFindDataOk(m_finddata) )
167 {
168 FreeFindData(m_finddata);
169
170 m_finddata = InitFindData();
171 }
172}
173
174void wxDirData::Rewind()
175{
176 Close();
177}
178
179bool wxDirData::Read(wxString *filename)
180{
181 bool first = false;
182
183 WIN32_FIND_DATA finddata;
184 #define PTR_TO_FINDDATA (&finddata)
185
186 if ( !IsFindDataOk(m_finddata) )
187 {
188 // open first
189 wxString filespec = m_dirname;
190 if ( !wxEndsWithPathSeparator(filespec) )
191 {
192 filespec += wxT('\\');
193 }
194 if ( !m_filespec )
195 filespec += wxT("*.*");
196 else
197 filespec += m_filespec;
198
199 m_finddata = FindFirst(filespec, PTR_TO_FINDDATA);
200
201 first = true;
202 }
203
204 if ( !IsFindDataOk(m_finddata) )
205 {
206#ifdef __WIN32__
207 DWORD err = ::GetLastError();
208
209 if ( err != ERROR_FILE_NOT_FOUND && err != ERROR_NO_MORE_FILES )
210 {
211 wxLogSysError(err, _("Cannot enumerate files in directory '%s'"),
212 m_dirname.c_str());
213 }
214#endif // __WIN32__
215 //else: not an error, just no (such) files
216
217 return false;
218 }
219
220 const wxChar *name;
221 FIND_ATTR attr;
222
223 for ( ;; )
224 {
225 if ( first )
226 {
227 first = false;
228 }
229 else
230 {
231 if ( !FindNext(m_finddata, PTR_TO_FINDDATA) )
232 {
233#ifdef __WIN32__
234 DWORD err = ::GetLastError();
235
236 if ( err != ERROR_NO_MORE_FILES )
237 {
238 wxLogLastError(wxT("FindNext"));
239 }
240#endif // __WIN32__
241 //else: not an error, just no more (such) files
242
243 return false;
244 }
245 }
246
247 name = GetNameFromFindData(PTR_TO_FINDDATA);
248 attr = GetAttrFromFindData(PTR_TO_FINDDATA);
249
250 // don't return "." and ".." unless asked for
251 if ( name[0] == wxT('.') &&
252 ((name[1] == wxT('.') && name[2] == wxT('\0')) ||
253 (name[1] == wxT('\0'))) )
254 {
255 if ( !(m_flags & wxDIR_DOTDOT) )
256 continue;
257 }
258
259 // check the type now
260 if ( !(m_flags & wxDIR_FILES) && !IsDir(attr) )
261 {
262 // it's a file, but we don't want them
263 continue;
264 }
265 else if ( !(m_flags & wxDIR_DIRS) && IsDir(attr) )
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 {
274 if ( IsHidden(attr) )
275 {
276 // it's a hidden file, skip it
277 continue;
278 }
279 }
280
281 *filename = name;
282
283 break;
284 }
285
286 return true;
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
304 // The Unix code does a similar test
305 if (wxDirExists(dirname))
306 {
307 m_data = new wxDirData(dirname);
308
309 return true;
310 }
311 else
312 {
313 m_data = NULL;
314
315 return false;
316 }
317}
318
319bool wxDir::IsOpened() const
320{
321 return m_data != NULL;
322}
323
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
333 name.Replace(wxT("/"), wxT("\\"));
334
335 if ( name.Last() == wxT('\\') )
336 {
337 // chop off the last (back)slash
338 name.Truncate(name.length() - 1);
339 }
340 }
341 }
342
343 return name;
344}
345
346wxDir::~wxDir()
347{
348 delete M_DIR;
349}
350
351// ----------------------------------------------------------------------------
352// wxDir enumerating
353// ----------------------------------------------------------------------------
354
355bool wxDir::GetFirst(wxString *filename,
356 const wxString& filespec,
357 int flags) const
358{
359 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
360
361 M_DIR->Rewind();
362
363 M_DIR->SetFileSpec(filespec);
364 M_DIR->SetFlags(flags);
365
366 return GetNext(filename);
367}
368
369bool wxDir::GetNext(wxString *filename) const
370{
371 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
372
373 wxCHECK_MSG( filename, false, wxT("bad pointer in wxDir::GetNext()") );
374
375 return M_DIR->Read(filename);
376}
377
378// ----------------------------------------------------------------------------
379// wxGetDirectoryTimes: used by wxFileName::GetTimes()
380// ----------------------------------------------------------------------------
381
382#ifdef __WIN32__
383
384extern bool
385wxGetDirectoryTimes(const wxString& dirname,
386 FILETIME *ftAccess, FILETIME *ftCreate, FILETIME *ftMod)
387{
388#ifdef __WXWINCE__
389 // FindFirst() is going to fail
390 wxASSERT_MSG( !dirname.empty(),
391 wxT("incorrect directory name format in wxGetDirectoryTimes") );
392#else
393 // FindFirst() is going to fail
394 wxASSERT_MSG( !dirname.empty() && dirname.Last() != wxT('\\'),
395 wxT("incorrect directory name format in wxGetDirectoryTimes") );
396#endif
397
398 FIND_STRUCT fs;
399 FIND_DATA fd = FindFirst(dirname, &fs);
400 if ( !IsFindDataOk(fd) )
401 {
402 return false;
403 }
404
405 *ftAccess = fs.ftLastAccessTime;
406 *ftCreate = fs.ftCreationTime;
407 *ftMod = fs.ftLastWriteTime;
408
409 FindClose(fd);
410
411 return true;
412}
413
414#endif // __WIN32__
415