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"
35 #include "wx/msw/private.h"
38 // ----------------------------------------------------------------------------
39 // define the types and functions used for file searching
40 // ----------------------------------------------------------------------------
45 typedef WIN32_FIND_DATA FIND_STRUCT
;
46 typedef HANDLE FIND_DATA
;
47 typedef DWORD FIND_ATTR
;
49 inline FIND_DATA
InitFindData()
51 return INVALID_HANDLE_VALUE
;
54 inline bool IsFindDataOk(FIND_DATA fd
)
56 return fd
!= INVALID_HANDLE_VALUE
;
59 inline void FreeFindData(FIND_DATA fd
)
61 if ( !::FindClose(fd
) )
63 wxLogLastError(wxT("FindClose"));
67 inline FIND_DATA
FindFirst(const wxString
& spec
,
68 FIND_STRUCT
*finddata
)
70 return ::FindFirstFile(spec
.fn_str(), finddata
);
73 inline bool FindNext(FIND_DATA fd
, FIND_STRUCT
*finddata
)
75 return ::FindNextFile(fd
, finddata
) != 0;
78 const wxChar
*GetNameFromFindData(FIND_STRUCT
*finddata
)
80 return finddata
->cFileName
;
83 inline FIND_ATTR
GetAttrFromFindData(FIND_STRUCT
*finddata
)
85 return finddata
->dwFileAttributes
;
88 inline bool IsDir(FIND_ATTR attr
)
90 return (attr
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
93 inline bool IsHidden(FIND_ATTR attr
)
95 return (attr
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) != 0;
98 } // anonymous namespace
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
105 #define MAX_PATH 260 // from VC++ headers
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 #define M_DIR ((wxDirData *)m_data)
114 // ----------------------------------------------------------------------------
116 // ----------------------------------------------------------------------------
118 // this class stores everything we need to enumerate the files
122 wxDirData(const wxString
& dirname
);
125 void SetFileSpec(const wxString
& filespec
) { m_filespec
= filespec
; }
126 void SetFlags(int flags
) { m_flags
= flags
; }
130 bool Read(wxString
*filename
);
132 const wxString
& GetName() const { return m_dirname
; }
135 FIND_DATA m_finddata
;
142 wxDECLARE_NO_COPY_CLASS(wxDirData
);
145 // ============================================================================
147 // ============================================================================
149 // ----------------------------------------------------------------------------
151 // ----------------------------------------------------------------------------
153 wxDirData::wxDirData(const wxString
& dirname
)
156 m_finddata
= InitFindData();
159 wxDirData::~wxDirData()
164 void wxDirData::Close()
166 if ( IsFindDataOk(m_finddata
) )
168 FreeFindData(m_finddata
);
170 m_finddata
= InitFindData();
174 void wxDirData::Rewind()
179 bool wxDirData::Read(wxString
*filename
)
183 WIN32_FIND_DATA finddata
;
184 #define PTR_TO_FINDDATA (&finddata)
186 if ( !IsFindDataOk(m_finddata
) )
189 wxString filespec
= m_dirname
;
190 if ( !wxEndsWithPathSeparator(filespec
) )
192 filespec
+= wxT('\\');
195 filespec
+= wxT("*.*");
197 filespec
+= m_filespec
;
199 m_finddata
= FindFirst(filespec
, PTR_TO_FINDDATA
);
204 if ( !IsFindDataOk(m_finddata
) )
207 DWORD err
= ::GetLastError();
209 if ( err
!= ERROR_FILE_NOT_FOUND
&& err
!= ERROR_NO_MORE_FILES
)
211 wxLogSysError(err
, _("Can not enumerate files in directory '%s'"),
215 //else: not an error, just no (such) files
231 if ( !FindNext(m_finddata
, PTR_TO_FINDDATA
) )
234 DWORD err
= ::GetLastError();
236 if ( err
!= ERROR_NO_MORE_FILES
)
238 wxLogLastError(wxT("FindNext"));
241 //else: not an error, just no more (such) files
247 name
= GetNameFromFindData(PTR_TO_FINDDATA
);
248 attr
= GetAttrFromFindData(PTR_TO_FINDDATA
);
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'))) )
255 if ( !(m_flags
& wxDIR_DOTDOT
) )
259 // check the type now
260 if ( !(m_flags
& wxDIR_FILES
) && !IsDir(attr
) )
262 // it's a file, but we don't want them
265 else if ( !(m_flags
& wxDIR_DIRS
) && IsDir(attr
) )
267 // it's a dir, and we don't want it
271 // finally, check whether it's a hidden file
272 if ( !(m_flags
& wxDIR_HIDDEN
) )
274 if ( IsHidden(attr
) )
276 // it's a hidden file, skip it
289 // ----------------------------------------------------------------------------
290 // wxDir construction/destruction
291 // ----------------------------------------------------------------------------
293 wxDir::wxDir(const wxString
& dirname
)
300 bool wxDir::Open(const wxString
& dirname
)
304 // The Unix code does a similar test
305 if (wxDirExists(dirname
))
307 m_data
= new wxDirData(dirname
);
319 bool wxDir::IsOpened() const
321 return m_data
!= NULL
;
324 wxString
wxDir::GetName() const
329 name
= M_DIR
->GetName();
332 // bring to canonical Windows form
333 name
.Replace(wxT("/"), wxT("\\"));
335 if ( name
.Last() == wxT('\\') )
337 // chop off the last (back)slash
338 name
.Truncate(name
.length() - 1);
351 // ----------------------------------------------------------------------------
353 // ----------------------------------------------------------------------------
355 bool wxDir::GetFirst(wxString
*filename
,
356 const wxString
& filespec
,
359 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
363 M_DIR
->SetFileSpec(filespec
);
364 M_DIR
->SetFlags(flags
);
366 return GetNext(filename
);
369 bool wxDir::GetNext(wxString
*filename
) const
371 wxCHECK_MSG( IsOpened(), false, wxT("must wxDir::Open() first") );
373 wxCHECK_MSG( filename
, false, wxT("bad pointer in wxDir::GetNext()") );
375 return M_DIR
->Read(filename
);
378 // ----------------------------------------------------------------------------
379 // wxGetDirectoryTimes: used by wxFileName::GetTimes()
380 // ----------------------------------------------------------------------------
385 wxGetDirectoryTimes(const wxString
& dirname
,
386 FILETIME
*ftAccess
, FILETIME
*ftCreate
, FILETIME
*ftMod
)
389 // FindFirst() is going to fail
390 wxASSERT_MSG( !dirname
.empty(),
391 wxT("incorrect directory name format in wxGetDirectoryTimes") );
393 // FindFirst() is going to fail
394 wxASSERT_MSG( !dirname
.empty() && dirname
.Last() != wxT('\\'),
395 wxT("incorrect directory name format in wxGetDirectoryTimes") );
399 FIND_DATA fd
= FindFirst(dirname
, &fs
);
400 if ( !IsFindDataOk(fd
) )
405 *ftAccess
= fs
.ftLastAccessTime
;
406 *ftCreate
= fs
.ftCreationTime
;
407 *ftMod
= fs
.ftLastWriteTime
;