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 licence (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/string.h"
38 #include "wx/module.h"
41 #include "wx/iconloc.h"
43 #include "wx/dynarray.h"
44 #include "wx/confbase.h"
46 #include "wx/mimetype.h"
48 // other standard headers
51 // implementation classes:
52 #if defined(__WXMSW__)
53 #include "wx/msw/mimetype.h"
54 #elif defined(__WXMAC__)
55 #include "wx/mac/mimetype.h"
56 #elif defined(__WXPM__) || defined (__EMX__)
57 #include "wx/os2/mimetype.h"
59 #elif defined(__DOS__)
60 #include "wx/msdos/mimetype.h"
62 #include "wx/unix/mimetype.h"
65 // ============================================================================
67 // ============================================================================
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 wxFileTypeInfo::wxFileTypeInfo(const wxChar
*mimeType
,
74 const wxChar
*openCmd
,
75 const wxChar
*printCmd
,
78 : m_mimeType(mimeType
),
84 va_start(argptr
, desc
);
88 const wxChar
*ext
= va_arg(argptr
, const wxChar
*);
91 // NULL terminates the list
102 wxFileTypeInfo::wxFileTypeInfo(const wxArrayString
& sArray
)
104 m_mimeType
= sArray
[0u];
105 m_openCmd
= sArray
[1u];
106 m_printCmd
= sArray
[2u];
107 m_desc
= sArray
[3u];
109 size_t count
= sArray
.GetCount();
110 for ( size_t i
= 4; i
< count
; i
++ )
112 m_exts
.Add(sArray
[i
]);
116 #include "wx/arrimpl.cpp"
117 WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo
);
119 // ============================================================================
120 // implementation of the wrapper classes
121 // ============================================================================
123 // ----------------------------------------------------------------------------
125 // ----------------------------------------------------------------------------
128 wxString
wxFileType::ExpandCommand(const wxString
& command
,
129 const wxFileType::MessageParameters
& params
)
131 bool hasFilename
= false;
134 for ( const wxChar
*pc
= command
.c_str(); *pc
!= wxT('\0'); pc
++ ) {
135 if ( *pc
== wxT('%') ) {
138 // '%s' expands into file name (quoted because it might
139 // contain spaces) - except if there are already quotes
140 // there because otherwise some programs may get confused
141 // by double double quotes
143 if ( *(pc
- 2) == wxT('"') )
144 str
<< params
.GetFileName();
146 str
<< wxT('"') << params
.GetFileName() << wxT('"');
148 str
<< params
.GetFileName();
153 // '%t' expands into MIME type (quote it too just to be
155 str
<< wxT('\'') << params
.GetMimeType() << wxT('\'');
160 const wxChar
*pEnd
= wxStrchr(pc
, wxT('}'));
161 if ( pEnd
== NULL
) {
163 wxLogWarning(_("Unmatched '{' in an entry for mime type %s."),
164 params
.GetMimeType().c_str());
168 wxString
param(pc
+ 1, pEnd
- pc
- 1);
169 str
<< wxT('\'') << params
.GetParamValue(param
) << wxT('\'');
177 // TODO %n is the number of parts, %F is an array containing
178 // the names of temp files these parts were written to
179 // and their mime types.
183 wxLogDebug(wxT("Unknown field %%%c in command '%s'."),
184 *pc
, command
.c_str());
193 // metamail(1) man page states that if the mailcap entry doesn't have '%s'
194 // the program will accept the data on stdin so normally we should append
195 // "< %s" to the end of the command in such case, but not all commands
196 // behave like this, in particular a common test is 'test -n "$DISPLAY"'
197 // and appending "< %s" to this command makes the test fail... I don't
198 // know of the correct solution, try to guess what we have to do.
200 // test now carried out on reading file so test should never get here
201 if ( !hasFilename
&& !str
.empty()
203 && !str
.StartsWith(_T("test "))
206 str
<< wxT(" < '") << params
.GetFileName() << wxT('\'');
212 wxFileType::wxFileType(const wxFileTypeInfo
& info
)
218 wxFileType::wxFileType()
221 m_impl
= new wxFileTypeImpl
;
224 wxFileType::~wxFileType()
230 bool wxFileType::GetExtensions(wxArrayString
& extensions
)
234 extensions
= m_info
->GetExtensions();
238 return m_impl
->GetExtensions(extensions
);
241 bool wxFileType::GetMimeType(wxString
*mimeType
) const
243 wxCHECK_MSG( mimeType
, false, _T("invalid parameter in GetMimeType") );
247 *mimeType
= m_info
->GetMimeType();
252 return m_impl
->GetMimeType(mimeType
);
255 bool wxFileType::GetMimeTypes(wxArrayString
& mimeTypes
) const
260 mimeTypes
.Add(m_info
->GetMimeType());
265 return m_impl
->GetMimeTypes(mimeTypes
);
268 bool wxFileType::GetIcon(wxIconLocation
*iconLoc
) const
274 iconLoc
->SetFileName(m_info
->GetIconFile());
276 iconLoc
->SetIndex(m_info
->GetIconIndex());
283 return m_impl
->GetIcon(iconLoc
);
287 wxFileType::GetIcon(wxIconLocation
*iconloc
,
288 const MessageParameters
& params
) const
290 if ( !GetIcon(iconloc
) )
295 // we may have "%s" in the icon location string, at least under Windows, so
299 iconloc
->SetFileName(ExpandCommand(iconloc
->GetFileName(), params
));
305 bool wxFileType::GetDescription(wxString
*desc
) const
307 wxCHECK_MSG( desc
, false, _T("invalid parameter in GetDescription") );
311 *desc
= m_info
->GetDescription();
316 return m_impl
->GetDescription(desc
);
320 wxFileType::GetOpenCommand(wxString
*openCmd
,
321 const wxFileType::MessageParameters
& params
) const
323 wxCHECK_MSG( openCmd
, false, _T("invalid parameter in GetOpenCommand") );
327 *openCmd
= ExpandCommand(m_info
->GetOpenCommand(), params
);
332 return m_impl
->GetOpenCommand(openCmd
, params
);
335 wxString
wxFileType::GetOpenCommand(const wxString
& filename
) const
338 if ( !GetOpenCommand(&cmd
, filename
) )
340 // return empty string to indicate an error
348 wxFileType::GetPrintCommand(wxString
*printCmd
,
349 const wxFileType::MessageParameters
& params
) const
351 wxCHECK_MSG( printCmd
, false, _T("invalid parameter in GetPrintCommand") );
355 *printCmd
= ExpandCommand(m_info
->GetPrintCommand(), params
);
360 return m_impl
->GetPrintCommand(printCmd
, params
);
364 size_t wxFileType::GetAllCommands(wxArrayString
*verbs
,
365 wxArrayString
*commands
,
366 const wxFileType::MessageParameters
& params
) const
373 #if defined (__WXMSW__) || defined(__UNIX__)
374 return m_impl
->GetAllCommands(verbs
, commands
, params
);
375 #else // !__WXMSW__ || Unix
376 // we don't know how to retrieve all commands, so just try the 2 we know
380 if ( GetOpenCommand(&cmd
, params
) )
383 verbs
->Add(_T("Open"));
389 if ( GetPrintCommand(&cmd
, params
) )
392 verbs
->Add(_T("Print"));
400 #endif // __WXMSW__/| __UNIX__
403 bool wxFileType::Unassociate()
405 #if defined(__WXMSW__)
406 return m_impl
->Unassociate();
407 #elif defined(__UNIX__)
408 return m_impl
->Unassociate(this);
410 wxFAIL_MSG( _T("not implemented") ); // TODO
415 bool wxFileType::SetCommand(const wxString
& cmd
,
416 const wxString
& verb
,
417 bool overwriteprompt
)
419 #if defined (__WXMSW__) || defined(__UNIX__)
420 return m_impl
->SetCommand(cmd
, verb
, overwriteprompt
);
424 wxUnusedVar(overwriteprompt
);
425 wxFAIL_MSG(_T("not implemented"));
430 bool wxFileType::SetDefaultIcon(const wxString
& cmd
, int index
)
434 // VZ: should we do this?
435 // chris elliott : only makes sense in MS windows
437 GetOpenCommand(&sTmp
, wxFileType::MessageParameters(wxEmptyString
, wxEmptyString
));
439 wxCHECK_MSG( !sTmp
.empty(), false, _T("need the icon file") );
441 #if defined (__WXMSW__) || defined(__UNIX__)
442 return m_impl
->SetDefaultIcon (cmd
, index
);
445 wxFAIL_MSG(_T("not implemented"));
451 // ----------------------------------------------------------------------------
452 // wxMimeTypesManager
453 // ----------------------------------------------------------------------------
455 void wxMimeTypesManager::EnsureImpl()
458 m_impl
= new wxMimeTypesManagerImpl
;
461 bool wxMimeTypesManager::IsOfType(const wxString
& mimeType
,
462 const wxString
& wildcard
)
464 wxASSERT_MSG( mimeType
.Find(wxT('*')) == wxNOT_FOUND
,
465 wxT("first MIME type can't contain wildcards") );
467 // all comparaisons are case insensitive (2nd arg of IsSameAs() is false)
468 if ( wildcard
.BeforeFirst(wxT('/')).
469 IsSameAs(mimeType
.BeforeFirst(wxT('/')), false) )
471 wxString strSubtype
= wildcard
.AfterFirst(wxT('/'));
473 if ( strSubtype
== wxT("*") ||
474 strSubtype
.IsSameAs(mimeType
.AfterFirst(wxT('/')), false) )
476 // matches (either exactly or it's a wildcard)
484 wxMimeTypesManager::wxMimeTypesManager()
489 wxMimeTypesManager::~wxMimeTypesManager()
495 bool wxMimeTypesManager::Unassociate(wxFileType
*ft
)
497 #if defined(__UNIX__) && !defined(__CYGWIN__) && !defined(__WINE__)
498 return m_impl
->Unassociate(ft
);
500 return ft
->Unassociate();
506 wxMimeTypesManager::Associate(const wxFileTypeInfo
& ftInfo
)
510 #if defined(__WXMSW__) || defined(__UNIX__)
511 return m_impl
->Associate(ftInfo
);
512 #else // other platforms
514 wxFAIL_MSG( _T("not implemented") ); // TODO
520 wxMimeTypesManager::GetFileTypeFromExtension(const wxString
& ext
)
523 wxFileType
*ft
= m_impl
->GetFileTypeFromExtension(ext
);
526 // check the fallbacks
528 // TODO linear search is potentially slow, perhaps we should use a
530 size_t count
= m_fallbacks
.GetCount();
531 for ( size_t n
= 0; n
< count
; n
++ ) {
532 if ( m_fallbacks
[n
].GetExtensions().Index(ext
) != wxNOT_FOUND
) {
533 ft
= new wxFileType(m_fallbacks
[n
]);
544 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString
& mimeType
)
547 wxFileType
*ft
= m_impl
->GetFileTypeFromMimeType(mimeType
);
550 // check the fallbacks
552 // TODO linear search is potentially slow, perhaps we should use a
554 size_t count
= m_fallbacks
.GetCount();
555 for ( size_t n
= 0; n
< count
; n
++ ) {
556 if ( wxMimeTypesManager::IsOfType(mimeType
,
557 m_fallbacks
[n
].GetMimeType()) ) {
558 ft
= new wxFileType(m_fallbacks
[n
]);
568 bool wxMimeTypesManager::ReadMailcap(const wxString
& filename
, bool fallback
)
571 return m_impl
->ReadMailcap(filename
, fallback
);
574 bool wxMimeTypesManager::ReadMimeTypes(const wxString
& filename
)
577 return m_impl
->ReadMimeTypes(filename
);
580 void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo
*filetypes
)
583 for ( const wxFileTypeInfo
*ft
= filetypes
; ft
&& ft
->IsValid(); ft
++ ) {
588 size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString
& mimetypes
)
591 size_t countAll
= m_impl
->EnumAllFileTypes(mimetypes
);
593 // add the fallback filetypes
594 size_t count
= m_fallbacks
.GetCount();
595 for ( size_t n
= 0; n
< count
; n
++ ) {
596 if ( mimetypes
.Index(m_fallbacks
[n
].GetMimeType()) == wxNOT_FOUND
) {
597 mimetypes
.Add(m_fallbacks
[n
].GetMimeType());
605 void wxMimeTypesManager::Initialize(int mcapStyle
,
606 const wxString
& sExtraDir
)
608 #if defined(__UNIX__) && !defined(__CYGWIN__) && !defined(__WINE__)
611 m_impl
->Initialize(mcapStyle
, sExtraDir
);
618 // and this function clears all the data from the manager
619 void wxMimeTypesManager::ClearData()
621 #if defined(__UNIX__) && !defined(__CYGWIN__) && !defined(__WINE__)
628 // ----------------------------------------------------------------------------
629 // global data and wxMimeTypeCmnModule
630 // ----------------------------------------------------------------------------
633 static wxMimeTypesManager gs_mimeTypesManager
;
635 // and public pointer
636 wxMimeTypesManager
*wxTheMimeTypesManager
= &gs_mimeTypesManager
;
638 class wxMimeTypeCmnModule
: public wxModule
641 wxMimeTypeCmnModule() : wxModule() { }
642 virtual bool OnInit() { return true; }
643 virtual void OnExit()
645 // this avoids false memory leak allerts:
646 if ( gs_mimeTypesManager
.m_impl
!= NULL
)
648 delete gs_mimeTypesManager
.m_impl
;
649 gs_mimeTypesManager
.m_impl
= NULL
;
650 gs_mimeTypesManager
.m_fallbacks
.Clear();
654 DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule
)
657 IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule
, wxModule
)
659 #endif // wxUSE_MIMETYPE