1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxDir implementation for Win32
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
33 #include "wx/filefn.h" // for wxDirExists()
36 #include "wx/msw/private.h"
39 // ----------------------------------------------------------------------------
40 // define the types and functions used for file searching
41 // ----------------------------------------------------------------------------
46 typedef WIN32_FIND_DATA FIND_STRUCT
;
47 typedef HANDLE FIND_DATA
;
48 typedef DWORD FIND_ATTR
;
50 inline FIND_DATA
InitFindData()
52 return INVALID_HANDLE_VALUE
;
55 inline bool IsFindDataOk(FIND_DATA fd
)
57 return fd
!= INVALID_HANDLE_VALUE
;
60 inline void FreeFindData(FIND_DATA fd
)
62 if ( !::FindClose(fd
) )
64 wxLogLastError(_T("FindClose"));
68 inline FIND_DATA
FindFirst(const wxString
& spec
,
69 FIND_STRUCT
*finddata
)
71 return ::FindFirstFile(spec
.fn_str(), finddata
);
74 inline bool FindNext(FIND_DATA fd
, FIND_STRUCT
*finddata
)
76 return ::FindNextFile(fd
, finddata
) != 0;
79 const wxChar
*GetNameFromFindData(FIND_STRUCT
*finddata
)
81 return finddata
->cFileName
;
84 inline FIND_ATTR
GetAttrFromFindData(FIND_STRUCT
*finddata
)
86 return finddata
->dwFileAttributes
;
89 inline bool IsDir(FIND_ATTR attr
)
91 return (attr
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
94 inline bool IsHidden(FIND_ATTR attr
)
96 return (attr
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) != 0;
99 } // anonymous namespace
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
106 #define MAX_PATH 260 // from VC++ headers
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
113 #define M_DIR ((wxDirData *)m_data)
115 // ----------------------------------------------------------------------------
117 // ----------------------------------------------------------------------------
119 // this class stores everything we need to enumerate the files
123 wxDirData(const wxString
& dirname
);
126 void SetFileSpec(const wxString
& filespec
) { m_filespec
= filespec
; }
127 void SetFlags(int flags
) { m_flags
= flags
; }
131 bool Read(wxString
*filename
);
133 const wxString
& GetName() const { return m_dirname
; }
136 FIND_DATA m_finddata
;
143 wxDECLARE_NO_COPY_CLASS(wxDirData
);
146 // ============================================================================
148 // ============================================================================
150 // ----------------------------------------------------------------------------
152 // ----------------------------------------------------------------------------
154 wxDirData::wxDirData(const wxString
& dirname
)
157 m_finddata
= InitFindData();
160 wxDirData::~wxDirData()
165 void wxDirData::Close()
167 if ( IsFindDataOk(m_finddata
) )
169 FreeFindData(m_finddata
);
171 m_finddata
= InitFindData();
175 void wxDirData::Rewind()
180 bool wxDirData::Read(wxString
*filename
)
184 WIN32_FIND_DATA finddata
;
185 #define PTR_TO_FINDDATA (&finddata)
187 if ( !IsFindDataOk(m_finddata
) )
190 wxString filespec
= m_dirname
;
191 if ( !wxEndsWithPathSeparator(filespec
) )
193 filespec
+= _T('\\');
196 filespec
+= _T("*.*");
198 filespec
+= m_filespec
;
200 m_finddata
= FindFirst(filespec
, PTR_TO_FINDDATA
);
205 if ( !IsFindDataOk(m_finddata
) )
208 DWORD err
= ::GetLastError();
210 if ( err
!= ERROR_FILE_NOT_FOUND
&& err
!= ERROR_NO_MORE_FILES
)
212 wxLogSysError(err
, _("Can not enumerate files in directory '%s'"),
216 //else: not an error, just no (such) files
232 if ( !FindNext(m_finddata
, PTR_TO_FINDDATA
) )
235 DWORD err
= ::GetLastError();
237 if ( err
!= ERROR_NO_MORE_FILES
)
239 wxLogLastError(_T("FindNext"));
242 //else: not an error, just no more (such) files
248 name
= GetNameFromFindData(PTR_TO_FINDDATA
);
249 attr
= GetAttrFromFindData(PTR_TO_FINDDATA
);
251 // don't return "." and ".." unless asked for
252 if ( name
[0] == _T('.') &&
253 ((name
[1] == _T('.') && name
[2] == _T('\0')) ||
254 (name
[1] == _T('\0'))) )
256 if ( !(m_flags
& wxDIR_DOTDOT
) )
260 // check the type now
261 if ( !(m_flags
& wxDIR_FILES
) && !IsDir(attr
) )
263 // it's a file, but we don't want them
266 else if ( !(m_flags
& wxDIR_DIRS
) && IsDir(attr
) )
268 // it's a dir, and we don't want it
272 // finally, check whether it's a hidden file
273 if ( !(m_flags
& wxDIR_HIDDEN
) )
275 if ( IsHidden(attr
) )
277 // it's a hidden file, skip it
290 // ----------------------------------------------------------------------------
292 // ----------------------------------------------------------------------------
295 bool wxDir::Exists(const wxString
& dir
)
297 return wxDirExists(dir
);
300 // ----------------------------------------------------------------------------
301 // wxDir construction/destruction
302 // ----------------------------------------------------------------------------
304 wxDir::wxDir(const wxString
& dirname
)
311 bool wxDir::Open(const wxString
& dirname
)
315 // The Unix code does a similar test
316 if (wxDirExists(dirname
))
318 m_data
= new wxDirData(dirname
);
330 bool wxDir::IsOpened() const
332 return m_data
!= NULL
;
335 wxString
wxDir::GetName() const
340 name
= M_DIR
->GetName();
343 // bring to canonical Windows form
344 name
.Replace(_T("/"), _T("\\"));
346 if ( name
.Last() == _T('\\') )
348 // chop off the last (back)slash
349 name
.Truncate(name
.length() - 1);
362 // ----------------------------------------------------------------------------
364 // ----------------------------------------------------------------------------
366 bool wxDir::GetFirst(wxString
*filename
,
367 const wxString
& filespec
,
370 wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
374 M_DIR
->SetFileSpec(filespec
);
375 M_DIR
->SetFlags(flags
);
377 return GetNext(filename
);
380 bool wxDir::GetNext(wxString
*filename
) const
382 wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
384 wxCHECK_MSG( filename
, false, _T("bad pointer in wxDir::GetNext()") );
386 return M_DIR
->Read(filename
);
389 // ----------------------------------------------------------------------------
390 // wxGetDirectoryTimes: used by wxFileName::GetTimes()
391 // ----------------------------------------------------------------------------
396 wxGetDirectoryTimes(const wxString
& dirname
,
397 FILETIME
*ftAccess
, FILETIME
*ftCreate
, FILETIME
*ftMod
)
400 // FindFirst() is going to fail
401 wxASSERT_MSG( !dirname
.empty(),
402 _T("incorrect directory name format in wxGetDirectoryTimes") );
404 // FindFirst() is going to fail
405 wxASSERT_MSG( !dirname
.empty() && dirname
.Last() != _T('\\'),
406 _T("incorrect directory name format in wxGetDirectoryTimes") );
410 FIND_DATA fd
= FindFirst(dirname
, &fs
);
411 if ( !IsFindDataOk(fd
) )
416 *ftAccess
= fs
.ftLastAccessTime
;
417 *ftCreate
= fs
.ftCreationTime
;
418 *ftMod
= fs
.ftLastWriteTime
;