]> git.saurik.com Git - wxWidgets.git/blob - src/common/filesys.cpp
Small fixes for Tex2RTF but alas, we still get memory problems.
[wxWidgets.git] / src / common / filesys.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: filesys.cpp
3 // Purpose: wxFileSystem class - interface for opening files
4 // Author: Vaclav Slavik
5 // Copyright: (c) 1999 Vaclav Slavik
6 // CVS-ID: $Id$
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include "wx/wxprec.h"
15
16 #ifdef __BORDLANDC__
17 #pragma hdrstop
18 #endif
19
20
21 #if wxUSE_FILESYSTEM
22
23 #include "wx/wfstream.h"
24 #include "wx/module.h"
25 #include "wx/filesys.h"
26 #include "wx/mimetype.h"
27
28
29
30
31 //--------------------------------------------------------------------------------
32 // wxFileSystemHandler
33 //--------------------------------------------------------------------------------
34
35 IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler, wxObject)
36
37
38 wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
39 {
40 wxString ext = wxEmptyString, mime = wxEmptyString;
41 wxString loc = GetRightLocation(location);
42 char c;
43 int l = loc.Length(), l2;
44 wxFileType *ft;
45
46 l2 = l;
47 for (int i = l-1; i >= 0; i--) {
48 c = loc[(unsigned int) i];
49 if (c == wxT('#')) l2 = i + 1;
50 if (c == wxT('.')) {ext = loc.Right(l2-i-1); break;}
51 if ((c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':'))) {return wxEmptyString;}
52 }
53
54 static bool s_MinimalMimeEnsured = FALSE;
55 if (!s_MinimalMimeEnsured) {
56 static const wxFileTypeInfo fallbacks[] =
57 {
58 wxFileTypeInfo("image/jpeg",
59 "",
60 "",
61 "JPEG image (from fallback)",
62 "jpg", "jpeg", NULL),
63 wxFileTypeInfo("image/gif",
64 "",
65 "",
66 "GIF image (from fallback)",
67 "gif", NULL),
68 wxFileTypeInfo("image/png",
69 "",
70 "",
71 "PNG image (from fallback)",
72 "png", NULL),
73 wxFileTypeInfo("image/bmp",
74 "",
75 "",
76 "windows bitmap image (from fallback)",
77 "bmp", NULL),
78 wxFileTypeInfo("text/html",
79 "",
80 "",
81 "HTML document (from fallback)",
82 "htm", "html", NULL),
83
84 // must terminate the table with this!
85 wxFileTypeInfo()
86 };
87
88 wxTheMimeTypesManager -> AddFallbacks(fallbacks);
89 }
90
91 ft = wxTheMimeTypesManager -> GetFileTypeFromExtension(ext);
92 if (ft && (ft -> GetMimeType(&mime))) {
93 delete ft;
94 return mime;
95 }
96 else {
97 delete ft;
98 return wxEmptyString;
99 }
100 }
101
102
103
104 wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
105 {
106 wxString s = wxEmptyString;
107 int i, l = location.Length();
108 bool fnd;
109
110 fnd = FALSE;
111 for (i = l-1; (i >= 0) && ((location[i] != wxT('#')) || (!fnd)); i--) {
112 if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
113 }
114 if (!fnd) return wxT("file");
115 for (++i; (i < l) && (location[i] != wxT(':')); i++) s << location[i];
116 return s;
117 }
118
119
120 wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
121 {
122 int i;
123 bool fnd;
124
125 fnd = FALSE;
126 for (i = location.Length()-1; i >= 0; i--) {
127 if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
128 else if (fnd && (location[i] == wxT('#'))) return location.Left(i);
129 }
130 return wxEmptyString;
131 }
132
133 wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
134 {
135 int i, l = location.Length();
136 int l2 = l + 1;
137 for (i = l-1; (i >= 0) && ((location[i] != wxT(':')) || (i == 1) || (location[i-2] == wxT(':'))); i--) {if (location[i] == wxT('#')) l2 = i + 1;}
138 if (i == 0) return wxEmptyString;
139 else return location.Mid(i + 1, l2 - i - 2);
140 }
141
142 wxString wxFileSystemHandler::GetAnchor(const wxString& location) const
143 {
144 char c;
145 int l = location.Length();
146
147 for (int i = l-1; i >= 0; i--) {
148 c = location[i];
149 if (c == wxT('#')) return location.Right(l-i-1);
150 else if ((c == wxT('.')) || (c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':'))) return wxEmptyString;
151 }
152 return wxEmptyString;
153 }
154
155
156 wxString wxFileSystemHandler::FindFirst(const wxString& WXUNUSED(spec),
157 int WXUNUSED(flags))
158 {
159 return wxEmptyString;
160 }
161
162 wxString wxFileSystemHandler::FindNext()
163 {
164 return wxEmptyString;
165 }
166
167 //--------------------------------------------------------------------------------
168 // wxLocalFSHandler
169 //--------------------------------------------------------------------------------
170
171 class wxLocalFSHandler : public wxFileSystemHandler
172 {
173 public:
174 virtual bool CanOpen(const wxString& location);
175 virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location);
176 virtual wxString FindFirst(const wxString& spec, int flags = 0);
177 virtual wxString FindNext();
178 };
179
180
181 bool wxLocalFSHandler::CanOpen(const wxString& location)
182 {
183 return GetProtocol(location) == wxT("file");
184 }
185
186 wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
187 {
188 wxString right = GetRightLocation(location);
189 if (wxFileExists(right))
190 return new wxFSFile(new wxFileInputStream(right),
191 right,
192 GetMimeTypeFromExt(location),
193 GetAnchor(location),
194 wxDateTime(wxFileModificationTime(right)));
195 else return (wxFSFile*) NULL;
196 }
197
198 wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags)
199 {
200 wxString right = GetRightLocation(spec);
201 return wxFindFirstFile(right, flags);
202 }
203
204 wxString wxLocalFSHandler::FindNext()
205 {
206 return wxFindNextFile();
207 }
208
209
210
211 //-----------------------------------------------------------------------------
212 // wxFileSystem
213 //-----------------------------------------------------------------------------
214
215 IMPLEMENT_DYNAMIC_CLASS(wxFileSystem, wxObject)
216
217
218 wxList wxFileSystem::m_Handlers;
219
220
221 static wxString MakeCorrectPath(const wxString& path)
222 {
223 wxString p(path);
224 wxString r;
225 int i, j, cnt;
226
227 cnt = p.Length();
228 for (i = 0; i < cnt; i++)
229 if (p.GetChar(i) == wxT('\\')) p.GetWritableChar(i) = wxT('/'); // Want to be windows-safe
230
231 if (p.Left(2) == wxT("./")) { p = p.Mid(2); cnt -= 2; }
232
233 if (cnt < 3) return p;
234
235 r << p.GetChar(0) << p.GetChar(1);
236
237 // skip trailing ../.., if any
238 for (i = 2; i < cnt && (p.GetChar(i) == wxT('/') || p.GetChar(i) == wxT('.')); i++) r << p.GetChar(i);
239
240 // remove back references: translate dir1/../dir2 to dir2
241 for (; i < cnt; i++)
242 {
243 r << p.GetChar(i);
244 if (p.GetChar(i) == wxT('/') && p.GetChar(i-1) == wxT('.') && p.GetChar(i-2) == wxT('.'))
245 {
246 for (j = r.Length() - 2; j >= 0 && r.GetChar(j) != wxT('/') && r.GetChar(j) != wxT(':'); j--) {}
247 if (j >= 0 && r.GetChar(j) != wxT(':'))
248 {
249 for (j = j - 1; j >= 0 && r.GetChar(j) != wxT('/') && r.GetChar(j) != wxT(':'); j--) {}
250 r.Remove(j + 1);
251 }
252 }
253 }
254
255 for (; i < cnt; i++) r << p.GetChar(i);
256
257 return r;
258 }
259
260
261 void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir)
262 {
263 int i, pathpos = -1;
264
265 m_Path = MakeCorrectPath(location);
266
267 if (is_dir)
268 {
269 if (m_Path.Length() > 0 && m_Path.Last() != wxT('/') && m_Path.Last() != wxT(':'))
270 m_Path << wxT('/');
271 }
272
273 else
274 {
275 for (i = m_Path.Length()-1; i >= 0; i--)
276 {
277 if (m_Path[(unsigned int) i] == wxT('/'))
278 {
279 if ((i > 1) && (m_Path[(unsigned int) (i-1)] == wxT('/')) && (m_Path[(unsigned int) (i-2)] == wxT(':')))
280 {
281 i -= 2;
282 continue;
283 }
284 else
285 {
286 pathpos = i;
287 break;
288 }
289 }
290 else if (m_Path[(unsigned int) i] == wxT(':')) {
291 pathpos = i;
292 break;
293 }
294 }
295 if (pathpos == -1)
296 {
297 for (i = 0; i < (int) m_Path.Length(); i++)
298 {
299 if (m_Path[(unsigned int) i] == wxT(':'))
300 {
301 m_Path.Remove(i+1);
302 break;
303 }
304 }
305 if (i == (int) m_Path.Length())
306 m_Path = wxEmptyString;
307 }
308 else
309 {
310 m_Path.Remove(pathpos+1);
311 }
312 }
313 }
314
315
316
317 wxFSFile* wxFileSystem::OpenFile(const wxString& location)
318 {
319 wxString loc = MakeCorrectPath(location);
320 unsigned i, ln;
321 char meta;
322 wxFSFile *s = NULL;
323 wxNode *node;
324
325 ln = loc.Length();
326 meta = 0;
327 for (i = 0; i < ln; i++)
328 {
329 if (!meta)
330 switch (loc[i])
331 {
332 case wxT('/') : case wxT(':') : case wxT('#') : meta = loc[i];
333 }
334 }
335 m_LastName = wxEmptyString;
336
337 // try relative paths first :
338 if (meta != wxT(':'))
339 {
340 node = m_Handlers.GetFirst();
341 while (node)
342 {
343 wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
344 if (h->CanOpen(m_Path + loc))
345 {
346 s = h->OpenFile(*this, m_Path + loc);
347 if (s) { m_LastName = m_Path + loc; break; }
348 }
349 node = node->GetNext();
350 }
351 }
352
353 // if failed, try absolute paths :
354 if (s == NULL)
355 {
356 node = m_Handlers.GetFirst();
357 while (node)
358 {
359 wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
360 if (h->CanOpen(loc))
361 {
362 s = h->OpenFile(*this, loc);
363 if (s) { m_LastName = loc; break; }
364 }
365 node = node->GetNext();
366 }
367 }
368 return (s);
369 }
370
371
372
373 wxString wxFileSystem::FindFirst(const wxString& spec, int flags)
374 {
375 wxNode *node;
376 wxString spec2(spec);
377
378 m_FindFileHandler = NULL;
379
380 for (int i = spec2.Length()-1; i >= 0; i--)
381 if (spec2[(unsigned int) i] == wxT('\\')) spec2.GetWritableChar(i) = wxT('/'); // Want to be windows-safe
382
383 node = m_Handlers.GetFirst();
384 while (node)
385 {
386 m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
387 if (m_FindFileHandler -> CanOpen(m_Path + spec2))
388 return m_FindFileHandler -> FindFirst(m_Path + spec2, flags);
389 node = node->GetNext();
390 }
391
392 node = m_Handlers.GetFirst();
393 while (node)
394 {
395 m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
396 if (m_FindFileHandler -> CanOpen(spec2))
397 return m_FindFileHandler -> FindFirst(spec2, flags);
398 node = node->GetNext();
399 }
400
401 return wxEmptyString;
402 }
403
404
405
406 wxString wxFileSystem::FindNext()
407 {
408 if (m_FindFileHandler == NULL) return wxEmptyString;
409 else return m_FindFileHandler -> FindNext();
410 }
411
412
413
414 void wxFileSystem::AddHandler(wxFileSystemHandler *handler)
415 {
416 m_Handlers.Append(handler);
417 }
418
419
420 void wxFileSystem::CleanUpHandlers()
421 {
422 m_Handlers.DeleteContents(TRUE);
423 m_Handlers.Clear();
424 }
425
426
427
428
429 ///// Module:
430
431 class wxFileSystemModule : public wxModule
432 {
433 DECLARE_DYNAMIC_CLASS(wxFileSystemModule)
434
435 public:
436 virtual bool OnInit()
437 {
438 wxFileSystem::AddHandler(new wxLocalFSHandler);
439 return TRUE;
440 }
441 virtual void OnExit()
442 {
443 wxFileSystem::CleanUpHandlers();
444 }
445 };
446
447 IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule)
448
449 #endif
450 // wxUSE_FILESYSTEM
451
452
453