1. wxDir works for MSW and documented
[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
96 wxDirData::~wxDirData()
97 {
98 Close();
99 }
100
101 void wxDirData::Close()
102 {
103 if ( m_handle != INVALID_HANDLE_VALUE )
104 {
105 if ( !::FindClose(m_handle) )
106 {
107 wxLogLastError(_T("FindClose"));
108 }
109
110 m_handle = INVALID_HANDLE_VALUE;
111 }
112 }
113
114 void wxDirData::Rewind()
115 {
116 Close();
117 }
118
119 bool wxDirData::Read(wxString *filename)
120 {
121 bool first = FALSE;
122
123 WIN32_FIND_DATA finddata;
124 if ( m_handle == INVALID_HANDLE_VALUE )
125 {
126 // open first
127 wxString filespec;
128 filespec << m_dirname << _T('\\')
129 << (!m_filespec ? _T("*.*") : m_filespec.c_str());
130
131 m_handle = ::FindFirstFile(filespec, &finddata);
132
133 first = TRUE;
134 }
135
136 if ( m_handle == INVALID_HANDLE_VALUE )
137 {
138 DWORD err = ::GetLastError();
139
140 if ( err != ERROR_FILE_NOT_FOUND )
141 {
142 wxLogSysError(err, _("Can not enumerate files in directory '%s'"),
143 m_dirname.c_str());
144 }
145 //else: not an error, just no (such) files
146
147 return FALSE;
148 }
149
150 const wxChar *name;
151 DWORD attr;
152
153 for ( ;; )
154 {
155 if ( first )
156 {
157 first = FALSE;
158 }
159 else
160 {
161 if ( !::FindNextFile(m_handle, &finddata) )
162 {
163 DWORD err = ::GetLastError();
164
165 if ( err != ERROR_NO_MORE_FILES )
166 {
167 wxLogLastError(_T("FindNext"));
168 }
169 //else: not an error, just no more (such) files
170
171 return FALSE;
172 }
173 }
174
175 name = finddata.cFileName;
176 attr = finddata.dwFileAttributes;
177
178 // don't return "." and ".." unless asked for
179 if ( name[0] == _T('.') &&
180 ((name[1] == _T('.') && name[2] == _T('\0')) ||
181 (name[1] == _T('\0'))) )
182 {
183 if ( !(m_flags & wxDIR_DOTDOT) )
184 continue;
185 }
186
187 // check the type now
188 if ( !(m_flags & wxDIR_FILES) && !(attr & FILE_ATTRIBUTE_DIRECTORY) )
189 {
190 // it's a file, but we don't want them
191 continue;
192 }
193 else if ( !(m_flags & wxDIR_DIRS) && (attr & FILE_ATTRIBUTE_DIRECTORY) )
194 {
195 // it's a dir, and we don't want it
196 continue;
197 }
198
199 // finally, check whether it's a hidden file
200 if ( !(m_flags & wxDIR_HIDDEN) )
201 {
202 if ( attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM) )
203 {
204 // it's a hidden file, skip it
205 continue;
206 }
207 }
208
209 *filename = name;
210
211 break;
212 }
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 }