]> git.saurik.com Git - wxWidgets.git/blob - src/common/mimecmn.cpp
fixed stupid loop in wxFileSystem::OpenFile
[wxWidgets.git] / src / common / mimecmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/mimecmn.cpp
3 // Purpose: classes and functions to manage MIME types
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 23.09.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license (part of wxExtra library)
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "mimetypebase.h"
14 #endif
15
16 // for compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18 #include "wx/module.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/defs.h"
26 #endif
27
28 #if (wxUSE_FILE && wxUSE_TEXTFILE) || defined(__WXMSW__)
29
30 #ifndef WX_PRECOMP
31 #include "wx/string.h"
32 #if wxUSE_GUI
33 #include "wx/icon.h"
34 #endif
35 #endif //WX_PRECOMP
36
37 // Doesn't compile in WIN16 mode
38 #ifndef __WIN16__
39
40 #include "wx/log.h"
41 #include "wx/file.h"
42 #include "wx/intl.h"
43 #include "wx/dynarray.h"
44 #include "wx/confbase.h"
45
46 #ifdef __WXMSW__
47 #include "wx/msw/registry.h"
48 #include "windows.h"
49 #elif defined(__UNIX__) || defined(__WXPM__)
50 #include "wx/ffile.h"
51 #include "wx/textfile.h"
52 #include "wx/dir.h"
53 #include "wx/utils.h"
54 #include "wx/tokenzr.h"
55 #endif // OS
56
57 #include "wx/mimetype.h"
58
59 // other standard headers
60 #include <ctype.h>
61
62 // in case we're compiling in non-GUI mode
63 class WXDLLEXPORT wxIcon;
64
65
66 // implementation classes:
67
68 #if defined(__WXMSW__)
69 #include "wx/msw/mimetype.h"
70 #elif defined (__WXMAC__)
71 #include "wx/mac/mimetype.h"
72 #elif defined (__WXPM__)
73 #include "wx/os2/mimetype.h"
74 #else
75 #include "wx/unix/mimetype.h"
76 #endif
77
78 // ============================================================================
79 // common classes
80 // ============================================================================
81
82 // ----------------------------------------------------------------------------
83 // wxFileTypeInfo
84 // ----------------------------------------------------------------------------
85
86 wxFileTypeInfo::wxFileTypeInfo(const char *mimeType,
87 const char *openCmd,
88 const char *printCmd,
89 const char *desc,
90 ...)
91 : m_mimeType(mimeType),
92 m_openCmd(openCmd),
93 m_printCmd(printCmd),
94 m_desc(desc)
95 {
96 va_list argptr;
97 va_start(argptr, desc);
98
99 for ( ;; )
100 {
101 const char *ext = va_arg(argptr, const char *);
102 if ( !ext )
103 {
104 // NULL terminates the list
105 break;
106 }
107
108 m_exts.Add(ext);
109 }
110
111 va_end(argptr);
112 }
113
114 #include "wx/arrimpl.cpp"
115 WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo);
116
117
118 // ============================================================================
119 // implementation of the wrapper classes
120 // ============================================================================
121
122 // ----------------------------------------------------------------------------
123 // wxFileType
124 // ----------------------------------------------------------------------------
125
126 wxString wxFileType::ExpandCommand(const wxString& command,
127 const wxFileType::MessageParameters& params)
128 {
129 bool hasFilename = FALSE;
130
131 wxString str;
132 for ( const wxChar *pc = command.c_str(); *pc != wxT('\0'); pc++ ) {
133 if ( *pc == wxT('%') ) {
134 switch ( *++pc ) {
135 case wxT('s'):
136 // '%s' expands into file name (quoted because it might
137 // contain spaces) - except if there are already quotes
138 // there because otherwise some programs may get confused
139 // by double double quotes
140 #if 0
141 if ( *(pc - 2) == wxT('"') )
142 str << params.GetFileName();
143 else
144 str << wxT('"') << params.GetFileName() << wxT('"');
145 #endif
146 str << params.GetFileName();
147 hasFilename = TRUE;
148 break;
149
150 case wxT('t'):
151 // '%t' expands into MIME type (quote it too just to be
152 // consistent)
153 str << wxT('\'') << params.GetMimeType() << wxT('\'');
154 break;
155
156 case wxT('{'):
157 {
158 const wxChar *pEnd = wxStrchr(pc, wxT('}'));
159 if ( pEnd == NULL ) {
160 wxString mimetype;
161 wxLogWarning(_("Unmatched '{' in an entry for mime type %s."),
162 params.GetMimeType().c_str());
163 str << wxT("%{");
164 }
165 else {
166 wxString param(pc + 1, pEnd - pc - 1);
167 str << wxT('\'') << params.GetParamValue(param) << wxT('\'');
168 pc = pEnd;
169 }
170 }
171 break;
172
173 case wxT('n'):
174 case wxT('F'):
175 // TODO %n is the number of parts, %F is an array containing
176 // the names of temp files these parts were written to
177 // and their mime types.
178 break;
179
180 default:
181 wxLogDebug(wxT("Unknown field %%%c in command '%s'."),
182 *pc, command.c_str());
183 str << *pc;
184 }
185 }
186 else {
187 str << *pc;
188 }
189 }
190
191 // metamail(1) man page states that if the mailcap entry doesn't have '%s'
192 // the program will accept the data on stdin so normally we should append
193 // "< %s" to the end of the command in such case, but not all commands
194 // behave like this, in particular a common test is 'test -n "$DISPLAY"'
195 // and appending "< %s" to this command makes the test fail... I don't
196 // know of the correct solution, try to guess what we have to do.
197 if ( !hasFilename && !str.IsEmpty()
198 #ifdef __UNIX__
199 && !str.StartsWith(_T("test "))
200 #endif // Unix
201 ) {
202 str << wxT(" < '") << params.GetFileName() << wxT('\'');
203 }
204
205 return str;
206 }
207
208 wxFileType::wxFileType()
209 {
210 m_impl = new wxFileTypeImpl;
211 }
212
213 wxFileType::~wxFileType()
214 {
215 delete m_impl;
216 }
217
218 bool wxFileType::GetExtensions(wxArrayString& extensions)
219 {
220 return m_impl->GetExtensions(extensions);
221 }
222
223 bool wxFileType::GetMimeType(wxString *mimeType) const
224 {
225 return m_impl->GetMimeType(mimeType);
226 }
227
228 bool wxFileType::GetMimeTypes(wxArrayString& mimeTypes) const
229 {
230 return m_impl->GetMimeTypes(mimeTypes);
231 }
232
233 bool wxFileType::GetIcon(wxIcon *icon) const
234 {
235 return m_impl->GetIcon(icon);
236 }
237
238 bool wxFileType::GetDescription(wxString *desc) const
239 {
240 return m_impl->GetDescription(desc);
241 }
242
243 bool
244 wxFileType::GetOpenCommand(wxString *openCmd,
245 const wxFileType::MessageParameters& params) const
246 {
247 return m_impl->GetOpenCommand(openCmd, params);
248 }
249
250 bool
251 wxFileType::GetPrintCommand(wxString *printCmd,
252 const wxFileType::MessageParameters& params) const
253 {
254 return m_impl->GetPrintCommand(printCmd, params);
255 }
256
257 // ----------------------------------------------------------------------------
258 // wxMimeTypesManager
259 // ----------------------------------------------------------------------------
260
261 void wxMimeTypesManager::EnsureImpl()
262 {
263 if (m_impl == NULL)
264 m_impl = new wxMimeTypesManagerImpl;
265 }
266
267 bool wxMimeTypesManager::IsOfType(const wxString& mimeType,
268 const wxString& wildcard)
269 {
270 wxASSERT_MSG( mimeType.Find(wxT('*')) == wxNOT_FOUND,
271 wxT("first MIME type can't contain wildcards") );
272
273 // all comparaisons are case insensitive (2nd arg of IsSameAs() is FALSE)
274 if ( wildcard.BeforeFirst(wxT('/')).IsSameAs(mimeType.BeforeFirst(wxT('/')), FALSE) )
275 {
276 wxString strSubtype = wildcard.AfterFirst(wxT('/'));
277
278 if ( strSubtype == wxT("*") ||
279 strSubtype.IsSameAs(mimeType.AfterFirst(wxT('/')), FALSE) )
280 {
281 // matches (either exactly or it's a wildcard)
282 return TRUE;
283 }
284 }
285
286 return FALSE;
287 }
288
289 wxMimeTypesManager::wxMimeTypesManager()
290 {
291 m_impl = NULL;
292 }
293
294 wxMimeTypesManager::~wxMimeTypesManager()
295 {
296 if (m_impl != NULL)
297 delete m_impl;
298 }
299
300 wxFileType *
301 wxMimeTypesManager::GetFileTypeFromExtension(const wxString& ext)
302 {
303 EnsureImpl();
304 return m_impl->GetFileTypeFromExtension(ext);
305 }
306
307 wxFileType *
308 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString& mimeType)
309 {
310 EnsureImpl();
311 return m_impl->GetFileTypeFromMimeType(mimeType);
312 }
313
314 bool wxMimeTypesManager::ReadMailcap(const wxString& filename, bool fallback)
315 {
316 EnsureImpl();
317 return m_impl->ReadMailcap(filename, fallback);
318 }
319
320 bool wxMimeTypesManager::ReadMimeTypes(const wxString& filename)
321 {
322 EnsureImpl();
323 return m_impl->ReadMimeTypes(filename);
324 }
325
326 void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo *filetypes)
327 {
328 EnsureImpl();
329 for ( const wxFileTypeInfo *ft = filetypes; ft->IsValid(); ft++ ) {
330 m_impl->AddFallback(*ft);
331 }
332 }
333
334 size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString& mimetypes)
335 {
336 EnsureImpl();
337 return m_impl->EnumAllFileTypes(mimetypes);
338 }
339
340
341 // ----------------------------------------------------------------------------
342 // global data
343 // ----------------------------------------------------------------------------
344
345 // private object
346 static wxMimeTypesManager gs_mimeTypesManager;
347
348 // and public pointer
349 wxMimeTypesManager * wxTheMimeTypesManager = &gs_mimeTypesManager;
350
351
352
353
354
355 class wxMimeTypeCmnModule: public wxModule
356 {
357 DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule)
358 public:
359 wxMimeTypeCmnModule() : wxModule() {}
360 bool OnInit() { return TRUE; }
361 void OnExit()
362 { // this avoids false memory leak allerts:
363 if (gs_mimeTypesManager.m_impl != NULL)
364 {
365 delete gs_mimeTypesManager.m_impl;
366 gs_mimeTypesManager.m_impl = NULL;
367 }
368 }
369 };
370
371 IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule, wxModule)
372
373
374
375 #endif
376 // wxUSE_FILE && wxUSE_TEXTFILE
377
378 #endif
379 // __WIN16__