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"
27 #include "wx/module.h"
38 #include "wx/string.h"
47 #include "wx/dynarray.h"
48 #include "wx/confbase.h"
50 #include "wx/mimetype.h"
52 // other standard headers
55 // implementation classes:
56 #if defined(__WXMSW__)
57 #include "wx/msw/mimetype.h"
58 #elif defined (__WXMAC__)
59 #include "wx/mac/mimetype.h"
60 #elif defined (__WXPM__)
61 #include "wx/os2/mimetype.h"
63 #include "wx/unix/mimetype.h"
66 // ============================================================================
68 // ============================================================================
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 wxFileTypeInfo::wxFileTypeInfo(const char *mimeType
,
79 : m_mimeType(mimeType
),
85 va_start(argptr
, desc
);
89 const char *ext
= va_arg(argptr
, const char *);
92 // NULL terminates the list
102 #include "wx/arrimpl.cpp"
103 WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo
);
105 // ============================================================================
106 // implementation of the wrapper classes
107 // ============================================================================
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
114 wxString
wxFileType::ExpandCommand(const wxString
& command
,
115 const wxFileType::MessageParameters
& params
)
117 bool hasFilename
= FALSE
;
120 for ( const wxChar
*pc
= command
.c_str(); *pc
!= wxT('\0'); pc
++ ) {
121 if ( *pc
== wxT('%') ) {
124 // '%s' expands into file name (quoted because it might
125 // contain spaces) - except if there are already quotes
126 // there because otherwise some programs may get confused
127 // by double double quotes
129 if ( *(pc
- 2) == wxT('"') )
130 str
<< params
.GetFileName();
132 str
<< wxT('"') << params
.GetFileName() << wxT('"');
134 str
<< params
.GetFileName();
139 // '%t' expands into MIME type (quote it too just to be
141 str
<< wxT('\'') << params
.GetMimeType() << wxT('\'');
146 const wxChar
*pEnd
= wxStrchr(pc
, wxT('}'));
147 if ( pEnd
== NULL
) {
149 wxLogWarning(_("Unmatched '{' in an entry for mime type %s."),
150 params
.GetMimeType().c_str());
154 wxString
param(pc
+ 1, pEnd
- pc
- 1);
155 str
<< wxT('\'') << params
.GetParamValue(param
) << wxT('\'');
163 // TODO %n is the number of parts, %F is an array containing
164 // the names of temp files these parts were written to
165 // and their mime types.
169 wxLogDebug(wxT("Unknown field %%%c in command '%s'."),
170 *pc
, command
.c_str());
179 // metamail(1) man page states that if the mailcap entry doesn't have '%s'
180 // the program will accept the data on stdin so normally we should append
181 // "< %s" to the end of the command in such case, but not all commands
182 // behave like this, in particular a common test is 'test -n "$DISPLAY"'
183 // and appending "< %s" to this command makes the test fail... I don't
184 // know of the correct solution, try to guess what we have to do.
185 if ( !hasFilename
&& !str
.IsEmpty()
187 && !str
.StartsWith(_T("test "))
190 str
<< wxT(" < '") << params
.GetFileName() << wxT('\'');
196 wxFileType::wxFileType(const wxFileTypeInfo
& info
)
202 wxFileType::wxFileType()
205 m_impl
= new wxFileTypeImpl
;
208 wxFileType::~wxFileType()
213 bool wxFileType::GetExtensions(wxArrayString
& extensions
)
217 extensions
= m_info
->GetExtensions();
221 return m_impl
->GetExtensions(extensions
);
224 bool wxFileType::GetMimeType(wxString
*mimeType
) const
226 wxCHECK_MSG( mimeType
, FALSE
, _T("invalid parameter in GetMimeType") );
230 *mimeType
= m_info
->GetMimeType();
235 return m_impl
->GetMimeType(mimeType
);
238 bool wxFileType::GetMimeTypes(wxArrayString
& mimeTypes
) const
243 mimeTypes
.Add(m_info
->GetMimeType());
248 return m_impl
->GetMimeTypes(mimeTypes
);
251 bool wxFileType::GetIcon(wxIcon
*icon
,
253 int *iconIndex
) const
258 *iconFile
= m_info
->GetIconFile();
260 *iconIndex
= m_info
->GetIconIndex();
263 if ( icon
&& !m_info
->GetIconFile().empty() )
265 // FIXME: what about the index?
266 icon
->LoadFile(m_info
->GetIconFile());
274 return m_impl
->GetIcon(icon
, iconFile
, iconIndex
);
276 return m_impl
->GetIcon(icon
);
280 bool wxFileType::GetDescription(wxString
*desc
) const
282 wxCHECK_MSG( desc
, FALSE
, _T("invalid parameter in GetDescription") );
286 *desc
= m_info
->GetDescription();
291 return m_impl
->GetDescription(desc
);
295 wxFileType::GetOpenCommand(wxString
*openCmd
,
296 const wxFileType::MessageParameters
& params
) const
298 wxCHECK_MSG( openCmd
, FALSE
, _T("invalid parameter in GetOpenCommand") );
302 *openCmd
= ExpandCommand(m_info
->GetOpenCommand(), params
);
307 return m_impl
->GetOpenCommand(openCmd
, params
);
311 wxFileType::GetPrintCommand(wxString
*printCmd
,
312 const wxFileType::MessageParameters
& params
) const
314 wxCHECK_MSG( printCmd
, FALSE
, _T("invalid parameter in GetPrintCommand") );
318 *printCmd
= ExpandCommand(m_info
->GetPrintCommand(), params
);
323 return m_impl
->GetPrintCommand(printCmd
, params
);
327 size_t wxFileType::GetAllCommands(wxArrayString
*verbs
,
328 wxArrayString
*commands
,
329 const wxFileType::MessageParameters
& params
) const
337 return m_impl
->GetAllCommands(verbs
, commands
, params
);
339 // we don't know how to retrieve all commands, so just try the 2 we know
343 if ( GetOpenCommand(&cmd
, params
) )
346 verbs
->Add(_T("Open"));
352 if ( GetPrintCommand(&cmd
, params
) )
355 verbs
->Add(_T("Print"));
363 #endif // __WXMSW__/!__WXMSW__
366 bool wxFileType::Unassociate()
368 #if defined(__WXMSW__) || defined(__UNIX__)
369 return m_impl
->Unassociate();
371 wxFAIL_MSG( _T("not implemented") ); // TODO
376 // ----------------------------------------------------------------------------
377 // wxMimeTypesManager
378 // ----------------------------------------------------------------------------
380 void wxMimeTypesManager::EnsureImpl()
383 m_impl
= new wxMimeTypesManagerImpl
;
386 bool wxMimeTypesManager::IsOfType(const wxString
& mimeType
,
387 const wxString
& wildcard
)
389 wxASSERT_MSG( mimeType
.Find(wxT('*')) == wxNOT_FOUND
,
390 wxT("first MIME type can't contain wildcards") );
392 // all comparaisons are case insensitive (2nd arg of IsSameAs() is FALSE)
393 if ( wildcard
.BeforeFirst(wxT('/')).
394 IsSameAs(mimeType
.BeforeFirst(wxT('/')), FALSE
) )
396 wxString strSubtype
= wildcard
.AfterFirst(wxT('/'));
398 if ( strSubtype
== wxT("*") ||
399 strSubtype
.IsSameAs(mimeType
.AfterFirst(wxT('/')), FALSE
) )
401 // matches (either exactly or it's a wildcard)
409 wxMimeTypesManager::wxMimeTypesManager()
414 wxMimeTypesManager::~wxMimeTypesManager()
420 wxMimeTypesManager::Associate(const wxFileTypeInfo
& ftInfo
)
424 #if defined(__WXMSW__) || defined(__UNIX__)
425 return m_impl
->Associate(ftInfo
);
426 #else // other platforms
427 wxFAIL_MSG( _T("not implemented") ); // TODO
433 wxMimeTypesManager::GetFileTypeFromExtension(const wxString
& ext
)
436 wxFileType
*ft
= m_impl
->GetFileTypeFromExtension(ext
);
439 // check the fallbacks
441 // TODO linear search is potentially slow, perhaps we should use a
443 size_t count
= m_fallbacks
.GetCount();
444 for ( size_t n
= 0; n
< count
; n
++ ) {
445 if ( m_fallbacks
[n
].GetExtensions().Index(ext
) != wxNOT_FOUND
) {
446 ft
= new wxFileType(m_fallbacks
[n
]);
457 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString
& mimeType
)
460 wxFileType
*ft
= m_impl
->GetFileTypeFromMimeType(mimeType
);
463 // check the fallbacks
465 // TODO linear search is potentially slow, perhaps we should use a sorted
467 size_t count
= m_fallbacks
.GetCount();
468 for ( size_t n
= 0; n
< count
; n
++ ) {
469 if ( wxMimeTypesManager::IsOfType(mimeType
,
470 m_fallbacks
[n
].GetMimeType()) ) {
471 ft
= new wxFileType(m_fallbacks
[n
]);
481 bool wxMimeTypesManager::ReadMailcap(const wxString
& filename
, bool fallback
)
484 return m_impl
->ReadMailcap(filename
, fallback
);
487 bool wxMimeTypesManager::ReadMimeTypes(const wxString
& filename
)
490 return m_impl
->ReadMimeTypes(filename
);
493 void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo
*filetypes
)
496 for ( const wxFileTypeInfo
*ft
= filetypes
; ft
&& ft
->IsValid(); ft
++ ) {
501 size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString
& mimetypes
)
504 size_t countAll
= m_impl
->EnumAllFileTypes(mimetypes
);
506 // add the fallback filetypes
507 size_t count
= m_fallbacks
.GetCount();
508 for ( size_t n
= 0; n
< count
; n
++ ) {
509 if ( mimetypes
.Index(m_fallbacks
[n
].GetMimeType()) == wxNOT_FOUND
) {
510 mimetypes
.Add(m_fallbacks
[n
].GetMimeType());
518 // ----------------------------------------------------------------------------
519 // global data and wxMimeTypeCmnModule
520 // ----------------------------------------------------------------------------
523 static wxMimeTypesManager gs_mimeTypesManager
;
525 // and public pointer
526 wxMimeTypesManager
*wxTheMimeTypesManager
= &gs_mimeTypesManager
;
528 class wxMimeTypeCmnModule
: public wxModule
531 wxMimeTypeCmnModule() : wxModule() { }
532 virtual bool OnInit() { return TRUE
; }
533 virtual void OnExit()
535 // this avoids false memory leak allerts:
536 if ( gs_mimeTypesManager
.m_impl
!= NULL
)
538 delete gs_mimeTypesManager
.m_impl
;
539 gs_mimeTypesManager
.m_impl
= NULL
;
543 DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule
)
546 IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule
, wxModule
)