1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/mimecmn.cpp
3 // Purpose: classes and functions to manage MIME types
4 // Author: Vadim Zeitlin
6 // Chris Elliott (biol75@york.ac.uk) 5 Dec 00: write support for Win32
9 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10 // Licence: wxWindows license (part of wxExtra library)
11 /////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
22 #pragma implementation "mimetypebase.h"
25 // for compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
35 #include "wx/module.h"
37 // this one is needed for MSVC5
38 #include "wx/module.h"
41 #include "wx/string.h"
50 #include "wx/dynarray.h"
51 #include "wx/confbase.h"
53 #include "wx/mimetype.h"
55 // other standard headers
58 // implementation classes:
59 #if defined(__WXMSW__)
60 #include "wx/msw/mimetype.h"
61 #elif defined(__WXMAC__)
62 #include "wx/mac/mimetype.h"
63 #elif defined(__WXPM__)
64 #include "wx/os2/mimetype.h"
66 #include "wx/unix/mimetype.h"
69 // ============================================================================
71 // ============================================================================
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 wxFileTypeInfo::wxFileTypeInfo(const char *mimeType
,
82 : m_mimeType(mimeType
),
88 va_start(argptr
, desc
);
92 const char *ext
= va_arg(argptr
, const char *);
95 // NULL terminates the list
106 wxFileTypeInfo::wxFileTypeInfo(const wxArrayString
& sArray
)
108 m_mimeType
= sArray
[0u];
109 m_openCmd
= sArray
[1u];
110 m_printCmd
= sArray
[2u];
111 m_desc
= sArray
[3u];
113 size_t count
= sArray
.GetCount();
114 for ( size_t i
= 4; i
< count
; i
++ )
116 m_exts
.Add(sArray
[i
]);
120 #include "wx/arrimpl.cpp"
121 WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo
);
123 // ============================================================================
124 // implementation of the wrapper classes
125 // ============================================================================
127 // ----------------------------------------------------------------------------
129 // ----------------------------------------------------------------------------
132 wxString
wxFileType::ExpandCommand(const wxString
& command
,
133 const wxFileType::MessageParameters
& params
)
135 bool hasFilename
= FALSE
;
138 for ( const wxChar
*pc
= command
.c_str(); *pc
!= wxT('\0'); pc
++ ) {
139 if ( *pc
== wxT('%') ) {
142 // '%s' expands into file name (quoted because it might
143 // contain spaces) - except if there are already quotes
144 // there because otherwise some programs may get confused
145 // by double double quotes
147 if ( *(pc
- 2) == wxT('"') )
148 str
<< params
.GetFileName();
150 str
<< wxT('"') << params
.GetFileName() << wxT('"');
152 str
<< params
.GetFileName();
157 // '%t' expands into MIME type (quote it too just to be
159 str
<< wxT('\'') << params
.GetMimeType() << wxT('\'');
164 const wxChar
*pEnd
= wxStrchr(pc
, wxT('}'));
165 if ( pEnd
== NULL
) {
167 wxLogWarning(_("Unmatched '{' in an entry for mime type %s."),
168 params
.GetMimeType().c_str());
172 wxString
param(pc
+ 1, pEnd
- pc
- 1);
173 str
<< wxT('\'') << params
.GetParamValue(param
) << wxT('\'');
181 // TODO %n is the number of parts, %F is an array containing
182 // the names of temp files these parts were written to
183 // and their mime types.
187 wxLogDebug(wxT("Unknown field %%%c in command '%s'."),
188 *pc
, command
.c_str());
197 // metamail(1) man page states that if the mailcap entry doesn't have '%s'
198 // the program will accept the data on stdin so normally we should append
199 // "< %s" to the end of the command in such case, but not all commands
200 // behave like this, in particular a common test is 'test -n "$DISPLAY"'
201 // and appending "< %s" to this command makes the test fail... I don't
202 // know of the correct solution, try to guess what we have to do.
204 // test now carried out on reading file so test should never get here
205 if ( !hasFilename
&& !str
.IsEmpty()
207 && !str
.StartsWith(_T("test "))
210 str
<< wxT(" < '") << params
.GetFileName() << wxT('\'');
216 wxFileType::wxFileType(const wxFileTypeInfo
& info
)
222 wxFileType::wxFileType()
225 m_impl
= new wxFileTypeImpl
;
228 wxFileType::~wxFileType()
234 bool wxFileType::GetExtensions(wxArrayString
& extensions
)
238 extensions
= m_info
->GetExtensions();
242 return m_impl
->GetExtensions(extensions
);
245 bool wxFileType::GetMimeType(wxString
*mimeType
) const
247 wxCHECK_MSG( mimeType
, FALSE
, _T("invalid parameter in GetMimeType") );
251 *mimeType
= m_info
->GetMimeType();
256 return m_impl
->GetMimeType(mimeType
);
259 bool wxFileType::GetMimeTypes(wxArrayString
& mimeTypes
) const
264 mimeTypes
.Add(m_info
->GetMimeType());
269 return m_impl
->GetMimeTypes(mimeTypes
);
272 bool wxFileType::GetIcon(wxIcon
*icon
,
274 int *iconIndex
) const
279 *iconFile
= m_info
->GetIconFile();
281 *iconIndex
= m_info
->GetIconIndex();
284 if ( icon
&& !m_info
->GetIconFile().empty() )
286 // FIXME: what about the index?
287 icon
->LoadFile(m_info
->GetIconFile());
294 #if defined(__WXMSW__) || defined(__UNIX__)
295 return m_impl
->GetIcon(icon
, iconFile
, iconIndex
);
297 return m_impl
->GetIcon(icon
);
301 bool wxFileType::GetDescription(wxString
*desc
) const
303 wxCHECK_MSG( desc
, FALSE
, _T("invalid parameter in GetDescription") );
307 *desc
= m_info
->GetDescription();
312 return m_impl
->GetDescription(desc
);
316 wxFileType::GetOpenCommand(wxString
*openCmd
,
317 const wxFileType::MessageParameters
& params
) const
319 wxCHECK_MSG( openCmd
, FALSE
, _T("invalid parameter in GetOpenCommand") );
323 *openCmd
= ExpandCommand(m_info
->GetOpenCommand(), params
);
328 return m_impl
->GetOpenCommand(openCmd
, params
);
332 wxFileType::GetPrintCommand(wxString
*printCmd
,
333 const wxFileType::MessageParameters
& params
) const
335 wxCHECK_MSG( printCmd
, FALSE
, _T("invalid parameter in GetPrintCommand") );
339 *printCmd
= ExpandCommand(m_info
->GetPrintCommand(), params
);
344 return m_impl
->GetPrintCommand(printCmd
, params
);
348 size_t wxFileType::GetAllCommands(wxArrayString
*verbs
,
349 wxArrayString
*commands
,
350 const wxFileType::MessageParameters
& params
) const
357 #if defined (__WXMSW__) || defined(__UNIX__)
358 return m_impl
->GetAllCommands(verbs
, commands
, params
);
359 #else // !__WXMSW__ || Unix
360 // we don't know how to retrieve all commands, so just try the 2 we know
364 if ( GetOpenCommand(&cmd
, params
) )
367 verbs
->Add(_T("Open"));
373 if ( GetPrintCommand(&cmd
, params
) )
376 verbs
->Add(_T("Print"));
384 #endif // __WXMSW__/| __UNIX__
387 bool wxFileType::Unassociate()
389 #if defined(__WXMSW__)
390 return m_impl
->Unassociate();
391 #elif defined(__UNIX__) && !defined(__WXPM__)
392 return m_impl
->Unassociate(this);
394 wxFAIL_MSG( _T("not implemented") ); // TODO
399 bool wxFileType::SetCommand(const wxString
& cmd
, const wxString
& verb
,
400 bool overwriteprompt
)
402 #if defined (__WXMSW__) || defined(__UNIX__)
403 return m_impl
->SetCommand(cmd
, verb
, overwriteprompt
);
405 wxFAIL_MSG(_T("not implemented"));
410 bool wxFileType::SetDefaultIcon(const wxString
& cmd
, int index
)
414 // VZ: should we do this?
415 // chris elliott : only makes sense in MS windows
417 GetOpenCommand(&sTmp
, wxFileType::MessageParameters("", ""));
419 wxCHECK_MSG( !sTmp
.empty(), FALSE
, _T("need the icon file") );
421 #if defined (__WXMSW__) || defined(__UNIX__)
422 return m_impl
->SetDefaultIcon (cmd
, index
);
424 wxFAIL_MSG(_T("not implemented"));
431 // ----------------------------------------------------------------------------
432 // wxMimeTypesManager
433 // ----------------------------------------------------------------------------
435 void wxMimeTypesManager::EnsureImpl()
438 m_impl
= new wxMimeTypesManagerImpl
;
441 bool wxMimeTypesManager::IsOfType(const wxString
& mimeType
,
442 const wxString
& wildcard
)
444 wxASSERT_MSG( mimeType
.Find(wxT('*')) == wxNOT_FOUND
,
445 wxT("first MIME type can't contain wildcards") );
447 // all comparaisons are case insensitive (2nd arg of IsSameAs() is FALSE)
448 if ( wildcard
.BeforeFirst(wxT('/')).
449 IsSameAs(mimeType
.BeforeFirst(wxT('/')), FALSE
) )
451 wxString strSubtype
= wildcard
.AfterFirst(wxT('/'));
453 if ( strSubtype
== wxT("*") ||
454 strSubtype
.IsSameAs(mimeType
.AfterFirst(wxT('/')), FALSE
) )
456 // matches (either exactly or it's a wildcard)
464 wxMimeTypesManager::wxMimeTypesManager()
469 wxMimeTypesManager::~wxMimeTypesManager()
475 bool wxMimeTypesManager::Unassociate(wxFileType
*ft
)
477 #if defined(__UNIX__) && !defined(__WXPM__) && !defined(__CYGWIN__)
478 return m_impl
->Unassociate(ft
);
480 return ft
->Unassociate();
486 wxMimeTypesManager::Associate(const wxFileTypeInfo
& ftInfo
)
490 #if defined(__WXMSW__) || (defined(__UNIX__) && !defined(__WXPM__))
491 return m_impl
->Associate(ftInfo
);
492 #else // other platforms
493 wxFAIL_MSG( _T("not implemented") ); // TODO
499 wxMimeTypesManager::GetFileTypeFromExtension(const wxString
& ext
)
502 wxFileType
*ft
= m_impl
->GetFileTypeFromExtension(ext
);
505 // check the fallbacks
507 // TODO linear search is potentially slow, perhaps we should use a
509 size_t count
= m_fallbacks
.GetCount();
510 for ( size_t n
= 0; n
< count
; n
++ ) {
511 if ( m_fallbacks
[n
].GetExtensions().Index(ext
) != wxNOT_FOUND
) {
512 ft
= new wxFileType(m_fallbacks
[n
]);
523 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString
& mimeType
)
526 wxFileType
*ft
= m_impl
->GetFileTypeFromMimeType(mimeType
);
529 // check the fallbacks
531 // TODO linear search is potentially slow, perhaps we should use a sorted
533 size_t count
= m_fallbacks
.GetCount();
534 for ( size_t n
= 0; n
< count
; n
++ ) {
535 if ( wxMimeTypesManager::IsOfType(mimeType
,
536 m_fallbacks
[n
].GetMimeType()) ) {
537 ft
= new wxFileType(m_fallbacks
[n
]);
547 bool wxMimeTypesManager::ReadMailcap(const wxString
& filename
, bool fallback
)
550 return m_impl
->ReadMailcap(filename
, fallback
);
553 bool wxMimeTypesManager::ReadMimeTypes(const wxString
& filename
)
556 return m_impl
->ReadMimeTypes(filename
);
559 void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo
*filetypes
)
562 for ( const wxFileTypeInfo
*ft
= filetypes
; ft
&& ft
->IsValid(); ft
++ ) {
567 size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString
& mimetypes
)
570 size_t countAll
= m_impl
->EnumAllFileTypes(mimetypes
);
572 // add the fallback filetypes
573 size_t count
= m_fallbacks
.GetCount();
574 for ( size_t n
= 0; n
< count
; n
++ ) {
575 if ( mimetypes
.Index(m_fallbacks
[n
].GetMimeType()) == wxNOT_FOUND
) {
576 mimetypes
.Add(m_fallbacks
[n
].GetMimeType());
584 void wxMimeTypesManager::Initialize(int mcapStyle
,
585 const wxString
& sExtraDir
)
587 #if defined(__UNIX__) && !defined(__WXPM__) && !defined(__CYGWIN__)
590 m_impl
->Initialize(mcapStyle
, sExtraDir
);
597 // and this function clears all the data from the manager
598 void wxMimeTypesManager::ClearData()
600 #if defined(__UNIX__) && !defined(__WXPM__) && !defined(__CYGWIN__)
607 // ----------------------------------------------------------------------------
608 // global data and wxMimeTypeCmnModule
609 // ----------------------------------------------------------------------------
612 static wxMimeTypesManager gs_mimeTypesManager
;
614 // and public pointer
615 wxMimeTypesManager
*wxTheMimeTypesManager
= &gs_mimeTypesManager
;
617 class wxMimeTypeCmnModule
: public wxModule
620 wxMimeTypeCmnModule() : wxModule() { }
621 virtual bool OnInit() { return TRUE
; }
622 virtual void OnExit()
624 // this avoids false memory leak allerts:
625 if ( gs_mimeTypesManager
.m_impl
!= NULL
)
627 delete gs_mimeTypesManager
.m_impl
;
628 gs_mimeTypesManager
.m_impl
= NULL
;
629 gs_mimeTypesManager
.m_fallbacks
.Clear();
633 DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule
)
636 IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule
, wxModule
)
638 #endif // wxUSE_MIMETYPE