1. more wxMotif fixes
[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 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 #ifdef __GNUG__
10 #pragma implementation
11 #endif
12
13 #include "wx/wxprec.h"
14
15 #ifdef __BORDLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if !wxUSE_SOCKETS
20 #undef wxUSE_FS_ZIP
21 #undef wxUSE_FS_INET
22 #define wxUSE_FS_ZIP 0
23 #define wxUSE_FS_INET 0
24 #endif
25
26 #if (wxUSE_FS_INET || wxUSE_FS_ZIP) && wxUSE_STREAMS
27
28 #include "wx/wfstream.h"
29 #include "wx/module.h"
30 #include "wx/filesys.h"
31
32 //--------------------------------------------------------------------------------
33 // wxFileSystemHandler
34 //--------------------------------------------------------------------------------
35
36 IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler, wxObject)
37
38 wxMimeTypesManager wxFileSystemHandler::m_MimeMng;
39
40
41 wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
42 {
43 wxString ext = wxEmptyString, mime = wxEmptyString;
44 wxString loc = GetRightLocation(location);
45 char c;
46 int l = loc.Length(), l2;
47 wxFileType *ft;
48
49 l2 = l;
50 for (int i = l-1; i >= 0; i--) {
51 c = loc[i];
52 if (c == _T('#')) l2 = i + 1;
53 if (c == _T('.')) {ext = loc.Right(l2-i-1); break;}
54 if ((c == _T('/')) || (c == _T('\\')) || (c == _T(':'))) {return wxEmptyString;}
55 }
56 ft = m_MimeMng.GetFileTypeFromExtension(ext);
57 if (ft && (ft -> GetMimeType(&mime))) return mime;
58 else return wxEmptyString;
59 }
60
61
62
63 wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
64 {
65 wxString s = wxEmptyString;
66 int i, l = location.Length();
67 bool fnd;
68
69 fnd = FALSE;
70 for (i = l-1; (i >= 0) && ((location[i] != _T('#')) || (!fnd)); i--) {
71 if ((location[i] == _T(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
72 }
73 if (!fnd) return _T("file");
74 for (++i; (i < l) && (location[i] != _T(':')); i++) s << location[i];
75 return s;
76 }
77
78
79 wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
80 {
81 int i;
82 bool fnd;
83
84 fnd = FALSE;
85 for (i = location.Length()-1; i >= 0; i--) {
86 if ((location[i] == _T(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
87 else if (fnd && (location[i] == _T('#'))) return location.Left(i);
88 }
89 return wxEmptyString;
90 }
91
92 wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
93 {
94 int i, l = location.Length();
95 int l2 = l + 1;
96 for (i = l-1; (i >= 0) && ((location[i] != _T(':')) || (i == 1) || (location[i-2] == _T(':'))); i--) {if (location[i] == _T('#')) l2 = i + 1;}
97 if (i == 0) return wxEmptyString;
98 else return location.Mid(i + 1, l2 - i - 2);
99 }
100
101 wxString wxFileSystemHandler::GetAnchor(const wxString& location) const
102 {
103 char c;
104 int l = location.Length();
105
106 for (int i = l-1; i >= 0; i--) {
107 c = location[i];
108 if (c == _T('#')) return location.Right(l-i-1);
109 else if ((c == _T('.')) || (c == _T('/')) || (c == _T('\\')) || (c == _T(':'))) return wxEmptyString;
110 }
111 return wxEmptyString;
112 }
113
114 //--------------------------------------------------------------------------------
115 // wxLocalFSHandler
116 //--------------------------------------------------------------------------------
117
118 class wxLocalFSHandler : public wxFileSystemHandler
119 {
120 public:
121 virtual bool CanOpen(const wxString& location);
122 virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location);
123 };
124
125
126 bool wxLocalFSHandler::CanOpen(const wxString& location)
127 {
128 return GetProtocol(location) == _T("file");
129 }
130
131 wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
132 {
133 wxString right = GetRightLocation(location);
134 if (wxFileExists(right))
135 return new wxFSFile(new wxFileInputStream(right),
136 right,
137 GetMimeTypeFromExt(location),
138 GetAnchor(location));
139 else return (wxFSFile*) NULL;
140 }
141
142 //-----------------------------------------------------------------------------
143 // wxFileSystem
144 //-----------------------------------------------------------------------------
145
146 IMPLEMENT_DYNAMIC_CLASS(wxFileSystem, wxObject)
147
148
149 wxList wxFileSystem::m_Handlers;
150
151
152
153 void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir)
154 {
155 int i, pathpos = -1;
156 m_Path = location;
157
158 for (i = m_Path.Length()-1; i >= 0; i--)
159 if (m_Path[i] == _T('\\')) m_Path.GetWritableChar(i) = _T('/'); // wanna be windows-safe
160
161 if (is_dir == FALSE)
162 {
163 for (i = m_Path.Length()-1; i >= 0; i--)
164 {
165 if (m_Path[i] == _T('/'))
166 {
167 if ((i > 1) && (m_Path[i-1] == _T('/')) && (m_Path[i-2] == _T(':')))
168 {
169 i -= 2;
170 continue;
171 }
172 else
173 {
174 pathpos = i;
175 break;
176 }
177 }
178 else if (m_Path[i] == _T(':')) {
179 pathpos = i;
180 break;
181 }
182 }
183 if (pathpos == -1)
184 {
185 for (i = 0; i < (int) m_Path.Length(); i++)
186 {
187 if (m_Path[i] == _T(':'))
188 {
189 //m_Path << _T('/');
190 m_Path.Remove(i+1);
191 break;
192 }
193 }
194 if (i == (int) m_Path.Length())
195 m_Path = wxEmptyString;
196 }
197 else
198 {
199 if (m_Path[m_Path.Length()-1] != _T('/'))
200 m_Path << _T('/');
201 m_Path.Remove(pathpos+1);
202 }
203 }
204 }
205
206
207
208 wxFSFile* wxFileSystem::OpenFile(const wxString& location)
209 {
210 wxString loc = location;
211 int i, ln;
212 char meta;
213 wxFSFile *s = NULL;
214 wxNode *node;
215
216 ln = loc.Length();
217 meta = 0;
218 for (i = 0; i < ln; i++)
219 {
220 if (loc[i] == _T('\\')) loc.GetWritableChar(i) = _T('/'); // wanna be windows-safe
221 if (!meta) switch (loc[i])
222 {
223 case _T('/') : case _T(':') : case _T('#') : meta = loc[i];
224 }
225 }
226 m_LastName = wxEmptyString;
227
228 // try relative paths first :
229 if (meta != _T(':'))
230 {
231 node = m_Handlers.GetFirst();
232 while (node)
233 {
234 wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
235 if (h->CanOpen(m_Path + location))
236 {
237 s = h->OpenFile(*this, m_Path + location);
238 if (s) { m_LastName = m_Path + location; break; }
239 }
240 node = node->GetNext();
241 }
242 }
243
244 // if failed, try absolute paths :
245 if (s == NULL)
246 {
247 node = m_Handlers.GetFirst();
248 while (node)
249 {
250 wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
251 if (h->CanOpen(location))
252 {
253 s = h->OpenFile(*this, location);
254 if (s) { m_LastName = location; break; }
255 }
256 node = node->GetNext();
257 }
258 }
259 return (s);
260 }
261
262
263 void wxFileSystem::AddHandler(wxFileSystemHandler *handler)
264 {
265 m_Handlers.Append(handler);
266 }
267
268
269
270 ///// Module:
271
272 class wxFileSystemModule : public wxModule
273 {
274 DECLARE_DYNAMIC_CLASS(wxFileSystemModule)
275
276 public:
277 virtual bool OnInit()
278 {
279 wxFileSystem::AddHandler(new wxLocalFSHandler);
280 return TRUE;
281 }
282 virtual void OnExit() {}
283 };
284
285 IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule)
286
287 #endif
288 // (wxUSE_FS_INET || wxUSE_FS_ZIP) && wxUSE_STREAMS
289