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 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "mimetypebase.h"
17 // for compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19 #include "wx/module.h"
29 #if (wxUSE_FILE && wxUSE_TEXTFILE) || defined(__WXMSW__)
32 #include "wx/string.h"
38 // Doesn't compile in WIN16 mode
44 #include "wx/dynarray.h"
45 #include "wx/confbase.h"
48 #include "wx/msw/registry.h"
50 #elif defined(__UNIX__) || defined(__WXPM__)
52 #include "wx/textfile.h"
55 #include "wx/tokenzr.h"
58 #include "wx/mimetype.h"
60 // other standard headers
63 // in case we're compiling in non-GUI mode
64 class WXDLLEXPORT wxIcon
;
67 // implementation classes:
69 #if defined(__WXMSW__)
70 #include "wx/msw/mimetype.h"
71 #elif defined (__WXMAC__)
72 #include "wx/mac/mimetype.h"
73 #elif defined (__WXPM__)
74 #include "wx/os2/mimetype.h"
76 #include "wx/unix/mimetype.h"
79 // ============================================================================
81 // ============================================================================
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 wxFileTypeInfo::wxFileTypeInfo(const char *mimeType
,
92 : m_mimeType(mimeType
),
98 va_start(argptr
, desc
);
102 const char *ext
= va_arg(argptr
, const char *);
105 // NULL terminates the list
115 #include "wx/arrimpl.cpp"
116 WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo
);
119 // ============================================================================
120 // implementation of the wrapper classes
121 // ============================================================================
123 // ----------------------------------------------------------------------------
125 // ----------------------------------------------------------------------------
127 wxString
wxFileType::ExpandCommand(const wxString
& command
,
128 const wxFileType::MessageParameters
& params
)
130 bool hasFilename
= FALSE
;
133 for ( const wxChar
*pc
= command
.c_str(); *pc
!= wxT('\0'); pc
++ ) {
134 if ( *pc
== wxT('%') ) {
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
142 if ( *(pc
- 2) == wxT('"') )
143 str
<< params
.GetFileName();
145 str
<< wxT('"') << params
.GetFileName() << wxT('"');
147 str
<< params
.GetFileName();
152 // '%t' expands into MIME type (quote it too just to be
154 str
<< wxT('\'') << params
.GetMimeType() << wxT('\'');
159 const wxChar
*pEnd
= wxStrchr(pc
, wxT('}'));
160 if ( pEnd
== NULL
) {
162 wxLogWarning(_("Unmatched '{' in an entry for mime type %s."),
163 params
.GetMimeType().c_str());
167 wxString
param(pc
+ 1, pEnd
- pc
- 1);
168 str
<< wxT('\'') << params
.GetParamValue(param
) << wxT('\'');
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.
182 wxLogDebug(wxT("Unknown field %%%c in command '%s'."),
183 *pc
, command
.c_str());
192 // metamail(1) man page states that if the mailcap entry doesn't have '%s'
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()
200 && !str
.StartsWith(_T("test "))
203 str
<< wxT(" < '") << params
.GetFileName() << wxT('\'');
209 wxFileType::wxFileType()
211 m_impl
= new wxFileTypeImpl
;
214 wxFileType::~wxFileType()
219 bool wxFileType::GetExtensions(wxArrayString
& extensions
)
221 return m_impl
->GetExtensions(extensions
);
224 bool wxFileType::GetMimeType(wxString
*mimeType
) const
226 return m_impl
->GetMimeType(mimeType
);
229 bool wxFileType::GetMimeTypes(wxArrayString
& mimeTypes
) const
231 return m_impl
->GetMimeTypes(mimeTypes
);
234 bool wxFileType::GetIcon(wxIcon
*icon
,
236 int *iconIndex
) const
239 return m_impl
->GetIcon(icon
, iconFile
, iconIndex
);
241 return m_impl
->GetIcon(icon
);
245 bool wxFileType::GetDescription(wxString
*desc
) const
247 return m_impl
->GetDescription(desc
);
251 wxFileType::GetOpenCommand(wxString
*openCmd
,
252 const wxFileType::MessageParameters
& params
) const
254 return m_impl
->GetOpenCommand(openCmd
, params
);
258 wxFileType::GetPrintCommand(wxString
*printCmd
,
259 const wxFileType::MessageParameters
& params
) const
261 return m_impl
->GetPrintCommand(printCmd
, params
);
265 size_t wxFileType::GetAllCommands(wxArrayString
*verbs
,
266 wxArrayString
*commands
,
267 const wxFileType::MessageParameters
& params
) const
275 return m_impl
->GetAllCommands(verbs
, commands
, params
);
277 // we don't know how to retrieve all commands, so just try the 2 we know
281 if ( m_impl
->GetOpenCommand(&cmd
, params
) )
284 verbs
->Add(_T("Open"));
290 if ( GetPrintCommand(&cmd
, params
) )
293 verbs
->Add(_T("Print"));
301 #endif // __WXMSW__/!__WXMSW__
304 bool wxFileType::SetOpenCommand(const wxString
& cmd
, bool overwriteprompt
)
306 return SetCommand(cmd
, _T("open"), overwriteprompt
);
309 bool wxFileType::SetCommand(const wxString
& cmd
, const wxString
& verb
,
310 bool overwriteprompt
)
313 return m_impl
->SetCommand(cmd
, verb
, overwriteprompt
);
315 wxFAIL_MSG(_T("not implemented"));
321 bool wxFileType::SetMimeType(const wxString
& mimeType
)
323 // empty MIME type is meaningless here
324 wxCHECK_MSG( !mimeType
.empty(), FALSE
, _T("use RemoveMimeType()") );
327 return m_impl
->SetMimeType(mimeType
);
329 wxFAIL_MSG(_T("not implemented"));
335 bool wxFileType::SetDefaultIcon(const wxString
& cmd
, int index
)
338 // VZ: should we do this?
340 GetOpenCommand(&sTmp
, wxFileType::MessageParameters("", ""));
342 wxCHECK_MSG( !sTmp
.empty(), FALSE
, _T("need the icon file") );
346 return m_impl
->SetDefaultIcon (cmd
, index
);
348 wxFAIL_MSG(_T("not implemented"));
354 // now do remove functions
355 bool wxFileType::RemoveOpenCommand()
357 return RemoveCommand(_T("open"));
360 bool wxFileType::RemoveCommand(const wxString
& verb
)
363 return m_impl
->RemoveCommand(verb
);
365 wxFAIL_MSG(_T("not implemented"));
371 bool wxFileType::RemoveMimeType()
374 return m_impl
->RemoveMimeType ();
376 wxFAIL_MSG(_T("not implemented"));
382 bool wxFileType::RemoveDefaultIcon()
385 return m_impl
->RemoveDefaultIcon();
387 wxFAIL_MSG(_T("not implemented"));
393 bool wxFileType::Unassociate()
396 if ( !RemoveOpenCommand() )
398 if ( !RemoveDefaultIcon() )
400 if ( !RemoveMimeType() )
403 // in MSW this leaves a HKCR.xzy key
407 // ----------------------------------------------------------------------------
408 // wxMimeTypesManager
409 // ----------------------------------------------------------------------------
411 void wxMimeTypesManager::EnsureImpl()
414 m_impl
= new wxMimeTypesManagerImpl
;
417 bool wxMimeTypesManager::IsOfType(const wxString
& mimeType
,
418 const wxString
& wildcard
)
420 wxASSERT_MSG( mimeType
.Find(wxT('*')) == wxNOT_FOUND
,
421 wxT("first MIME type can't contain wildcards") );
423 // all comparaisons are case insensitive (2nd arg of IsSameAs() is FALSE)
424 if ( wildcard
.BeforeFirst(wxT('/')).IsSameAs(mimeType
.BeforeFirst(wxT('/')), FALSE
) )
426 wxString strSubtype
= wildcard
.AfterFirst(wxT('/'));
428 if ( strSubtype
== wxT("*") ||
429 strSubtype
.IsSameAs(mimeType
.AfterFirst(wxT('/')), FALSE
) )
431 // matches (either exactly or it's a wildcard)
439 wxMimeTypesManager::wxMimeTypesManager()
444 wxMimeTypesManager::~wxMimeTypesManager()
450 wxMimeTypesManager::GetFileTypeFromExtension(const wxString
& ext
)
453 return m_impl
->GetFileTypeFromExtension(ext
);
457 wxMimeTypesManager::GetOrAllocateFileTypeFromExtension(const wxString
& ext
)
462 // this writes a root entry to the registry in HKCR.ext
463 return m_impl
->GetOrAllocateFileTypeFromExtension(ext
);
465 // VZ: "static const"??? (FIXME)
466 // just make a dummy entry with no writing to file
467 static const wxFileTypeInfo fallback
[] =
469 wxFileTypeInfo("application/x-" + ext
,
472 ext
+ " format file",
474 // must terminate the table with this!
478 AddFallbacks (fallback
);
479 return m_impl
->GetFileTypeFromExtension(ext
);
480 #endif // __WXMSW__/!__WXMSW__
485 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString
& mimeType
)
488 return m_impl
->GetFileTypeFromMimeType(mimeType
);
491 bool wxMimeTypesManager::ReadMailcap(const wxString
& filename
, bool fallback
)
494 return m_impl
->ReadMailcap(filename
, fallback
);
497 bool wxMimeTypesManager::ReadMimeTypes(const wxString
& filename
)
500 return m_impl
->ReadMimeTypes(filename
);
503 void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo
*filetypes
)
506 for ( const wxFileTypeInfo
*ft
= filetypes
; ft
->IsValid(); ft
++ ) {
507 m_impl
->AddFallback(*ft
);
511 size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString
& mimetypes
)
514 return m_impl
->EnumAllFileTypes(mimetypes
);
518 // ----------------------------------------------------------------------------
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
)
549 // wxUSE_FILE && wxUSE_TEXTFILE