]> git.saurik.com Git - wxWidgets.git/blame - src/common/mimecmn.cpp
removed shift/reduce conflict
[wxWidgets.git] / src / common / mimecmn.cpp
CommitLineData
7dc3cc31
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: common/mimecmn.cpp
3// Purpose: classes and functions to manage MIME types
4// Author: Vadim Zeitlin
5// Modified by:
c7ce8392 6// Chris Elliott (biol75@york.ac.uk) 5 Dec 00: write support for Win32
7dc3cc31
VS
7// Created: 23.09.98
8// RCS-ID: $Id$
9// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10// Licence: wxWindows license (part of wxExtra library)
11/////////////////////////////////////////////////////////////////////////////
12
13#ifdef __GNUG__
14#pragma implementation "mimetypebase.h"
15#endif
16
17// for compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
66806a0b 19#include "wx/module.h"
7dc3cc31
VS
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#ifndef WX_PRECOMP
26 #include "wx/defs.h"
27#endif
28
29#if (wxUSE_FILE && wxUSE_TEXTFILE) || defined(__WXMSW__)
30
31#ifndef WX_PRECOMP
32 #include "wx/string.h"
33 #if wxUSE_GUI
34 #include "wx/icon.h"
35 #endif
36#endif //WX_PRECOMP
37
38// Doesn't compile in WIN16 mode
39#ifndef __WIN16__
40
41#include "wx/log.h"
42#include "wx/file.h"
43#include "wx/intl.h"
44#include "wx/dynarray.h"
45#include "wx/confbase.h"
46
47#ifdef __WXMSW__
48 #include "wx/msw/registry.h"
49 #include "windows.h"
50#elif defined(__UNIX__) || defined(__WXPM__)
51 #include "wx/ffile.h"
52 #include "wx/textfile.h"
53 #include "wx/dir.h"
54 #include "wx/utils.h"
55 #include "wx/tokenzr.h"
56#endif // OS
57
58#include "wx/mimetype.h"
59
60// other standard headers
61#include <ctype.h>
62
63// in case we're compiling in non-GUI mode
64class WXDLLEXPORT wxIcon;
65
66
67// implementation classes:
68
69#if defined(__WXMSW__)
c7ce8392 70 #include "wx/msw/mimetype.h"
7dc3cc31 71#elif defined (__WXMAC__)
c7ce8392 72 #include "wx/mac/mimetype.h"
e1c8c2f8 73#elif defined (__WXPM__)
c7ce8392
VZ
74 #include "wx/os2/mimetype.h"
75#else // Unix
76 #include "wx/unix/mimetype.h"
7dc3cc31
VS
77#endif
78
79// ============================================================================
80// common classes
81// ============================================================================
82
83// ----------------------------------------------------------------------------
84// wxFileTypeInfo
85// ----------------------------------------------------------------------------
86
87wxFileTypeInfo::wxFileTypeInfo(const char *mimeType,
88 const char *openCmd,
89 const char *printCmd,
90 const char *desc,
91 ...)
92 : m_mimeType(mimeType),
93 m_openCmd(openCmd),
94 m_printCmd(printCmd),
95 m_desc(desc)
96{
97 va_list argptr;
98 va_start(argptr, desc);
99
100 for ( ;; )
101 {
102 const char *ext = va_arg(argptr, const char *);
103 if ( !ext )
104 {
105 // NULL terminates the list
106 break;
107 }
108
109 m_exts.Add(ext);
110 }
111
112 va_end(argptr);
113}
114
115#include "wx/arrimpl.cpp"
116WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo);
117
118
119// ============================================================================
120// implementation of the wrapper classes
121// ============================================================================
122
123// ----------------------------------------------------------------------------
124// wxFileType
125// ----------------------------------------------------------------------------
126
127wxString wxFileType::ExpandCommand(const wxString& command,
128 const wxFileType::MessageParameters& params)
129{
130 bool hasFilename = FALSE;
131
132 wxString str;
133 for ( const wxChar *pc = command.c_str(); *pc != wxT('\0'); pc++ ) {
134 if ( *pc == wxT('%') ) {
135 switch ( *++pc ) {
136 case wxT('s'):
137 // '%s' expands into file name (quoted because it might
138 // contain spaces) - except if there are already quotes
139 // there because otherwise some programs may get confused
140 // by double double quotes
141#if 0
142 if ( *(pc - 2) == wxT('"') )
143 str << params.GetFileName();
144 else
145 str << wxT('"') << params.GetFileName() << wxT('"');
146#endif
147 str << params.GetFileName();
148 hasFilename = TRUE;
149 break;
150
151 case wxT('t'):
152 // '%t' expands into MIME type (quote it too just to be
153 // consistent)
154 str << wxT('\'') << params.GetMimeType() << wxT('\'');
155 break;
156
157 case wxT('{'):
158 {
159 const wxChar *pEnd = wxStrchr(pc, wxT('}'));
160 if ( pEnd == NULL ) {
161 wxString mimetype;
f6bcfd97 162 wxLogWarning(_("Unmatched '{' in an entry for mime type %s."),
7dc3cc31
VS
163 params.GetMimeType().c_str());
164 str << wxT("%{");
165 }
166 else {
167 wxString param(pc + 1, pEnd - pc - 1);
168 str << wxT('\'') << params.GetParamValue(param) << wxT('\'');
169 pc = pEnd;
170 }
171 }
172 break;
173
174 case wxT('n'):
175 case wxT('F'):
176 // TODO %n is the number of parts, %F is an array containing
177 // the names of temp files these parts were written to
178 // and their mime types.
179 break;
180
181 default:
182 wxLogDebug(wxT("Unknown field %%%c in command '%s'."),
183 *pc, command.c_str());
184 str << *pc;
185 }
186 }
187 else {
188 str << *pc;
189 }
190 }
191
192 // metamail(1) man page states that if the mailcap entry doesn't have '%s'
f6bcfd97
BP
193 // the program will accept the data on stdin so normally we should append
194 // "< %s" to the end of the command in such case, but not all commands
195 // behave like this, in particular a common test is 'test -n "$DISPLAY"'
196 // and appending "< %s" to this command makes the test fail... I don't
197 // know of the correct solution, try to guess what we have to do.
198 if ( !hasFilename && !str.IsEmpty()
199#ifdef __UNIX__
200 && !str.StartsWith(_T("test "))
201#endif // Unix
202 ) {
7dc3cc31
VS
203 str << wxT(" < '") << params.GetFileName() << wxT('\'');
204 }
205
206 return str;
207}
208
209wxFileType::wxFileType()
210{
211 m_impl = new wxFileTypeImpl;
212}
213
214wxFileType::~wxFileType()
215{
216 delete m_impl;
217}
218
219bool wxFileType::GetExtensions(wxArrayString& extensions)
220{
221 return m_impl->GetExtensions(extensions);
222}
223
224bool wxFileType::GetMimeType(wxString *mimeType) const
225{
226 return m_impl->GetMimeType(mimeType);
227}
228
4d2976ad
VS
229bool wxFileType::GetMimeTypes(wxArrayString& mimeTypes) const
230{
231 return m_impl->GetMimeTypes(mimeTypes);
232}
233
c7ce8392
VZ
234bool wxFileType::GetIcon(wxIcon *icon,
235 wxString *iconFile,
236 int *iconIndex) const
7dc3cc31 237{
c7ce8392
VZ
238#ifdef __WXMSW__
239 return m_impl->GetIcon(icon, iconFile, iconIndex);
240#else
7dc3cc31 241 return m_impl->GetIcon(icon);
c7ce8392 242#endif
7dc3cc31
VS
243}
244
245bool wxFileType::GetDescription(wxString *desc) const
246{
247 return m_impl->GetDescription(desc);
248}
249
250bool
251wxFileType::GetOpenCommand(wxString *openCmd,
252 const wxFileType::MessageParameters& params) const
253{
254 return m_impl->GetOpenCommand(openCmd, params);
255}
256
257bool
258wxFileType::GetPrintCommand(wxString *printCmd,
259 const wxFileType::MessageParameters& params) const
260{
261 return m_impl->GetPrintCommand(printCmd, params);
262}
263
c7ce8392
VZ
264
265size_t wxFileType::GetAllCommands(wxArrayString *verbs,
266 wxArrayString *commands,
267 const wxFileType::MessageParameters& params) const
268{
269 if ( verbs )
270 verbs->Clear();
271 if ( commands )
272 commands->Clear();
273
274#ifdef __WXMSW__
275 return m_impl->GetAllCommands(verbs, commands, params);
276#else // !__WXMSW__
277 // we don't know how to retrieve all commands, so just try the 2 we know
278 // about
279 size_t count = 0;
280 wxString cmd;
281 if ( m_impl->GetOpenCommand(&cmd, params) )
282 {
283 if ( verbs )
284 verbs->Add(_T("Open"));
285 if ( commands )
286 commands->Add(cmd);
287 count++;
288 }
289
290 if ( GetPrintCommand(&cmd, params) )
291 {
292 if ( verbs )
293 verbs->Add(_T("Print"));
294 if ( commands )
295 commands->Add(cmd);
296
297 count++;
298 }
299
300 return count;
301#endif // __WXMSW__/!__WXMSW__
302}
303
304bool wxFileType::SetOpenCommand(const wxString& cmd, bool overwriteprompt)
305{
306 return SetCommand(cmd, _T("open"), overwriteprompt);
307}
308
309bool wxFileType::SetCommand(const wxString& cmd, const wxString& verb,
310 bool overwriteprompt)
311{
312#ifdef __WXMSW__
313 return m_impl->SetCommand(cmd, verb, overwriteprompt);
314#else
315 wxFAIL_MSG(_T("not implemented"));
316
317 return FALSE;
318#endif
319}
320
321bool wxFileType::SetMimeType(const wxString& mimeType)
322{
323 // empty MIME type is meaningless here
324 wxCHECK_MSG( !mimeType.empty(), FALSE, _T("use RemoveMimeType()") );
325
326#ifdef __WXMSW__
327 return m_impl->SetMimeType(mimeType);
328#else
329 wxFAIL_MSG(_T("not implemented"));
330
331 return FALSE;
332#endif
333}
334
335bool wxFileType::SetDefaultIcon(const wxString& cmd, int index)
336{
337 wxString sTmp = cmd;
338 // VZ: should we do this?
339 if ( sTmp.empty() )
340 GetOpenCommand(&sTmp, wxFileType::MessageParameters("", ""));
341
e7ffb21b 342 wxCHECK_MSG( !sTmp.empty(), FALSE, _T("need the icon file") );
c7ce8392
VZ
343
344
345#ifdef __WXMSW__
346 return m_impl->SetDefaultIcon (cmd, index);
347#else
348 wxFAIL_MSG(_T("not implemented"));
349
350 return FALSE;
351#endif
352}
353
354// now do remove functions
355bool wxFileType::RemoveOpenCommand()
356{
357 return RemoveCommand(_T("open"));
358}
359
360bool wxFileType::RemoveCommand(const wxString& verb)
361{
362#ifdef __WXMSW__
363 return m_impl->RemoveCommand(verb);
364#else
365 wxFAIL_MSG(_T("not implemented"));
366
367 return FALSE;
368#endif
369}
370
371bool wxFileType::RemoveMimeType()
372{
373#ifdef __WXMSW__
374 return m_impl->RemoveMimeType ();
375#else
376 wxFAIL_MSG(_T("not implemented"));
377
378 return FALSE;
379#endif
380}
381
382bool wxFileType::RemoveDefaultIcon()
383{
384#ifdef __WXMSW__
385 return m_impl->RemoveDefaultIcon();
386#else
387 wxFAIL_MSG(_T("not implemented"));
388
389 return FALSE;
390#endif
391}
392
393bool wxFileType::Unassociate()
394{
395 bool result = TRUE;
396 if ( !RemoveOpenCommand() )
397 result = FALSE;
398 if ( !RemoveDefaultIcon() )
399 result = FALSE;
400 if ( !RemoveMimeType() )
401 result = FALSE;
402
403 // in MSW this leaves a HKCR.xzy key
404 return result;
405}
406
7dc3cc31
VS
407// ----------------------------------------------------------------------------
408// wxMimeTypesManager
409// ----------------------------------------------------------------------------
410
411void wxMimeTypesManager::EnsureImpl()
412{
c7ce8392 413 if ( !m_impl )
7dc3cc31
VS
414 m_impl = new wxMimeTypesManagerImpl;
415}
416
417bool wxMimeTypesManager::IsOfType(const wxString& mimeType,
418 const wxString& wildcard)
419{
420 wxASSERT_MSG( mimeType.Find(wxT('*')) == wxNOT_FOUND,
421 wxT("first MIME type can't contain wildcards") );
422
423 // all comparaisons are case insensitive (2nd arg of IsSameAs() is FALSE)
424 if ( wildcard.BeforeFirst(wxT('/')).IsSameAs(mimeType.BeforeFirst(wxT('/')), FALSE) )
425 {
426 wxString strSubtype = wildcard.AfterFirst(wxT('/'));
427
428 if ( strSubtype == wxT("*") ||
429 strSubtype.IsSameAs(mimeType.AfterFirst(wxT('/')), FALSE) )
430 {
431 // matches (either exactly or it's a wildcard)
432 return TRUE;
433 }
434 }
435
436 return FALSE;
437}
438
439wxMimeTypesManager::wxMimeTypesManager()
440{
441 m_impl = NULL;
442}
443
444wxMimeTypesManager::~wxMimeTypesManager()
445{
c7ce8392 446 delete m_impl;
7dc3cc31
VS
447}
448
449wxFileType *
450wxMimeTypesManager::GetFileTypeFromExtension(const wxString& ext)
451{
452 EnsureImpl();
453 return m_impl->GetFileTypeFromExtension(ext);
454}
455
c7ce8392
VZ
456wxFileType *
457wxMimeTypesManager::GetOrAllocateFileTypeFromExtension(const wxString& ext)
458{
459 EnsureImpl();
460
461#ifdef __WXMSW__
462 // this writes a root entry to the registry in HKCR.ext
463 return m_impl->GetOrAllocateFileTypeFromExtension(ext);
464#else // !__WXMSW__
465 // VZ: "static const"??? (FIXME)
466 // just make a dummy entry with no writing to file
467 static const wxFileTypeInfo fallback[] =
468 {
469 wxFileTypeInfo("application/x-" + ext,
470 "",
471 "",
472 ext + " format file",
473 ext, NULL),
474 // must terminate the table with this!
475 wxFileTypeInfo()
476 };
477
478 AddFallbacks (fallback);
479 return m_impl->GetFileTypeFromExtension(ext);
480#endif // __WXMSW__/!__WXMSW__
481}
482
483
7dc3cc31
VS
484wxFileType *
485wxMimeTypesManager::GetFileTypeFromMimeType(const wxString& mimeType)
486{
487 EnsureImpl();
488 return m_impl->GetFileTypeFromMimeType(mimeType);
489}
490
491bool wxMimeTypesManager::ReadMailcap(const wxString& filename, bool fallback)
492{
493 EnsureImpl();
494 return m_impl->ReadMailcap(filename, fallback);
495}
496
497bool wxMimeTypesManager::ReadMimeTypes(const wxString& filename)
498{
499 EnsureImpl();
500 return m_impl->ReadMimeTypes(filename);
501}
502
503void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo *filetypes)
504{
505 EnsureImpl();
506 for ( const wxFileTypeInfo *ft = filetypes; ft->IsValid(); ft++ ) {
507 m_impl->AddFallback(*ft);
508 }
509}
510
511size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString& mimetypes)
512{
513 EnsureImpl();
514 return m_impl->EnumAllFileTypes(mimetypes);
515}
516
517
518// ----------------------------------------------------------------------------
519// global data
520// ----------------------------------------------------------------------------
521
522// private object
523static wxMimeTypesManager gs_mimeTypesManager;
524
525// and public pointer
526wxMimeTypesManager * wxTheMimeTypesManager = &gs_mimeTypesManager;
527
66806a0b
VS
528class wxMimeTypeCmnModule: public wxModule
529{
66806a0b 530public:
c7ce8392
VZ
531 wxMimeTypeCmnModule() : wxModule() { }
532 virtual bool OnInit() { return TRUE; }
533 virtual void OnExit()
534 {
535 // this avoids false memory leak allerts:
536 if ( gs_mimeTypesManager.m_impl != NULL )
537 {
538 delete gs_mimeTypesManager.m_impl;
539 gs_mimeTypesManager.m_impl = NULL;
540 }
66806a0b 541 }
c7ce8392
VZ
542
543 DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule)
66806a0b
VS
544};
545
546IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule, wxModule)
547
7dc3cc31
VS
548#endif
549 // wxUSE_FILE && wxUSE_TEXTFILE
550
551#endif
552 // __WIN16__