wxDir class added
[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 license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "dir.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34 #endif // PCH
35
36 #include "wx/dir.h"
37 #include "wx/filefn.h" // for wxPathExists()
38
39 #include <windows.h>
40
41 // ----------------------------------------------------------------------------
42 // constants
43 // ----------------------------------------------------------------------------
44
45 #ifndef MAX_PATH
46 #define MAX_PATH 260 // from VC++ headers
47 #endif
48
49 // ----------------------------------------------------------------------------
50 // macros
51 // ----------------------------------------------------------------------------
52
53 #define M_DIR ((wxDirData *)m_data)
54
55 // ----------------------------------------------------------------------------
56 // private classes
57 // ----------------------------------------------------------------------------
58
59 // this class stores everything we need to enumerate the files
60 class wxDirData
61 {
62 public:
63 wxDirData(const wxString& dirname);
64 ~wxDirData();
65
66 void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
67 void SetFlags(int flags) { m_flags = flags; }
68
69 void Close();
70 void Rewind();
71 bool Read(wxString *filename);
72
73 private:
74 HANDLE m_handle;
75
76 wxString m_dirname;
77 wxString m_filespec;
78
79 int m_flags;
80 };
81
82 // ============================================================================
83 // implementation
84 // ============================================================================
85
86 // ----------------------------------------------------------------------------
87 // wxDirData
88 // ----------------------------------------------------------------------------
89
90 wxDirData::wxDirData(const wxString& dirname)
91 : m_dirname(dirname)
92 {
93 m_handle = INVALID_HANDLE_VALUE;
94
95 // throw away the trailing slashes
96 size_t n = m_dirname.length();
97 wxCHECK_RET( n, _T("empty dir name in wxDir") );
98
99 while ( n > 0 && wxIsPathSeparator(m_dirname[--n]) )
100 ;
101
102 m_dirname.Truncate(n + 1);
103 }
104
105 wxDirData::~wxDirData()
106 {
107 Close();
108 }
109
110 void wxDirData::Close()
111 {
112 if ( m_handle != INVALID_HANDLE_VALUE )
113 {
114 if ( !::FindClose(m_handle) )
115 {
116 wxLogLastError(_T("FindClose"));
117 }
118 }
119 }
120
121 void wxDirData::Rewind()
122 {
123 Close();
124 }
125
126 bool wxDirData::Read(wxString *filename)
127 {
128 bool first = FALSE;
129
130 WIN32_FIND_DATA finddata;
131 if ( m_handle == INVALID_HANDLE_VALUE )
132 {
133 // open first
134 m_handle = ::FindFirstFile(!m_filespec ? _T("*.*") : m_filespec.c_str(),
135 &finddata);
136
137 first = TRUE;
138 }
139
140 if ( m_handle == INVALID_HANDLE_VALUE )
141 {
142 DWORD err = ::GetLastError();
143
144 if ( err != ERROR_NO_MORE_FILES )
145 {
146 wxLogSysError(err, _("Can not enumerate files in directory '%s'"),
147 m_dirname.c_str());
148 }
149 //else: not an error, just no (such) files
150
151 return FALSE;
152 }
153
154 bool matches = FALSE;
155
156 const wxChar *name;
157 DWORD attr;
158
159 while ( !matches )
160 {
161 if ( first )
162 {
163 first = FALSE;
164 }
165 else
166 {
167 if ( !::FindNextFile(m_handle, &finddata) )
168 {
169 DWORD err = ::GetLastError();
170
171 if ( err != ERROR_NO_MORE_FILES )
172 {
173 wxLogLastError(_T("FindNext"));
174 }
175 //else: not an error, just no more (such) files
176
177 return FALSE;
178 }
179 }
180
181 name = finddata.cFileName;
182 attr = finddata.dwFileAttributes;
183
184 // don't return "." and ".." unless asked for
185 if ( name[0] == _T('.') &&
186 ((name[1] == _T('.') && name[2] == _T('\0')) ||
187 (name[1] == _T('\0'))) )
188 {
189 if ( !(m_flags & wxDIR_DOTDOT) )
190 continue;
191 }
192
193 // check the type now
194 if ( !(m_flags & wxDIR_FILES) && !(attr & FILE_ATTRIBUTE_DIRECTORY) )
195 {
196 // it's a file, but we don't want them
197 continue;
198 }
199 else if ( !(m_flags & wxDIR_DIRS) && (attr & FILE_ATTRIBUTE_DIRECTORY) )
200 {
201 // it's a dir, and we don't want it
202 continue;
203 }
204
205 // finally, check whether it's a hidden file
206 if ( !(m_flags & wxDIR_HIDDEN) )
207 {
208 matches = !(attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM));
209 }
210 }
211
212 *filename = name;
213
214 return TRUE;
215 }
216
217 // ----------------------------------------------------------------------------
218 // wxDir helpers
219 // ----------------------------------------------------------------------------
220
221 /* static */
222 bool wxDir::Exists(const wxString& dir)
223 {
224 return wxPathExists(dir);
225 }
226
227 // ----------------------------------------------------------------------------
228 // wxDir construction/destruction
229 // ----------------------------------------------------------------------------
230
231 wxDir::wxDir(const wxString& dirname)
232 {
233 m_data = NULL;
234
235 (void)Open(dirname);
236 }
237
238 bool wxDir::Open(const wxString& dirname)
239 {
240 delete M_DIR;
241 m_data = new wxDirData(dirname);
242
243 return TRUE;
244 }
245
246 bool wxDir::IsOpened() const
247 {
248 return m_data != NULL;
249 }
250
251 wxDir::~wxDir()
252 {
253 delete M_DIR;
254 }
255
256 // ----------------------------------------------------------------------------
257 // wxDir enumerating
258 // ----------------------------------------------------------------------------
259
260 bool wxDir::GetFirst(wxString *filename,
261 const wxString& filespec,
262 int flags) const
263 {
264 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
265
266 M_DIR->Rewind();
267
268 M_DIR->SetFileSpec(filespec);
269 M_DIR->SetFlags(flags);
270
271 return GetNext(filename);
272 }
273
274 bool wxDir::GetNext(wxString *filename) const
275 {
276 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
277
278 wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
279
280 return M_DIR->Read(filename);
281 }