]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/mimetype.cpp
7d09acec8b6ad5ad35d108b15bdbe1572cfe2ed1
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/mimetype.cpp
3 // Purpose: classes and functions to manage MIME types
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license (part of wxExtra library)
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "mimetype.h"
16 // for compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #if (wxUSE_FILE && wxUSE_TEXTFILE) || defined(__WXMSW__)
30 #include "wx/string.h"
36 // Doesn't compile in WIN16 mode
42 #include "wx/dynarray.h"
43 #include "wx/confbase.h"
46 #include "wx/msw/registry.h"
48 #elif defined(__UNIX__) || defined(__WXPM__)
50 #include "wx/textfile.h"
53 #include "wx/tokenzr.h"
56 #include "wx/msw/mimetype.h"
58 // other standard headers
61 // in case we're compiling in non-GUI mode
62 class WXDLLEXPORT wxIcon
;
65 // These classes use Windows registry to retrieve the required information.
67 // Keys used (not all of them are documented, so it might actually stop working
68 // in futur versions of Windows...):
69 // 1. "HKCR\MIME\Database\Content Type" contains subkeys for all known MIME
70 // types, each key has a string value "Extension" which gives (dot preceded)
71 // extension for the files of this MIME type.
73 // 2. "HKCR\.ext" contains
74 // a) unnamed value containing the "filetype"
75 // b) value "Content Type" containing the MIME type
77 // 3. "HKCR\filetype" contains
78 // a) unnamed value containing the description
79 // b) subkey "DefaultIcon" with single unnamed value giving the icon index in
81 // c) shell\open\command and shell\open\print subkeys containing the commands
82 // to open/print the file (the positional parameters are introduced by %1,
83 // %2, ... in these strings, we change them to %s ourselves)
85 // although I don't know of any official documentation which mentions this
86 // location, uses it, so it isn't likely to change
87 static const wxChar
*MIME_DATABASE_KEY
= wxT("MIME\\Database\\Content Type\\");
92 wxString
wxFileTypeImpl::GetCommand(const wxChar
*verb
) const
94 // suppress possible error messages
98 if ( wxRegKey(wxRegKey::HKCR
, m_ext
+ _T("\\shell")).Exists() )
100 if ( wxRegKey(wxRegKey::HKCR
, m_strFileType
+ _T("\\shell")).Exists() )
101 strKey
= m_strFileType
;
106 return wxEmptyString
;
109 strKey
<< wxT("\\shell\\") << verb
;
110 wxRegKey
key(wxRegKey::HKCR
, strKey
+ _T("\\command"));
113 // it's the default value of the key
114 if ( key
.QueryValue(wxT(""), command
) ) {
115 // transform it from '%1' to '%s' style format string (now also
116 // test for %L - apparently MS started using it as well for the
119 // NB: we don't make any attempt to verify that the string is valid,
120 // i.e. doesn't contain %2, or second %1 or .... But we do make
121 // sure that we return a string with _exactly_ one '%s'!
122 bool foundFilename
= FALSE
;
123 size_t len
= command
.Len();
124 for ( size_t n
= 0; (n
< len
) && !foundFilename
; n
++ ) {
125 if ( command
[n
] == wxT('%') &&
127 (command
[n
+ 1] == wxT('1') ||
128 command
[n
+ 1] == wxT('L')) ) {
129 // replace it with '%s'
130 command
[n
+ 1] = wxT('s');
132 foundFilename
= TRUE
;
136 // look whether we must issue some DDE requests to the application
137 // (and not just launch it)
138 strKey
+= _T("\\DDEExec");
139 wxRegKey
keyDDE(wxRegKey::HKCR
, strKey
);
140 if ( keyDDE
.Open() ) {
141 wxString ddeCommand
, ddeServer
, ddeTopic
;
142 keyDDE
.QueryValue(_T(""), ddeCommand
);
143 ddeCommand
.Replace(_T("%1"), _T("%s"));
145 wxRegKey(wxRegKey::HKCR
, strKey
+ _T("\\Application")).
146 QueryValue(_T(""), ddeServer
);
147 wxRegKey(wxRegKey::HKCR
, strKey
+ _T("\\Topic")).
148 QueryValue(_T(""), ddeTopic
);
150 // HACK: we use a special feature of wxExecute which exists
151 // just because we need it here: it will establish DDE
152 // conversation with the program it just launched
153 command
.Prepend(_T("WX_DDE#"));
154 command
<< _T('#') << ddeServer
155 << _T('#') << ddeTopic
156 << _T('#') << ddeCommand
;
158 else if ( !foundFilename
) {
159 // we didn't find any '%1' - the application doesn't know which
160 // file to open (note that we only do it if there is no DDEExec
163 // HACK: append the filename at the end, hope that it will do
164 command
<< wxT(" %s");
168 //else: no such file type or no value, will return empty string
174 wxFileTypeImpl::GetOpenCommand(wxString
*openCmd
,
175 const wxFileType::MessageParameters
& params
)
180 cmd
= m_info
->GetOpenCommand();
183 cmd
= GetCommand(wxT("open"));
186 *openCmd
= wxFileType::ExpandCommand(cmd
, params
);
188 return !openCmd
->IsEmpty();
192 wxFileTypeImpl::GetPrintCommand(wxString
*printCmd
,
193 const wxFileType::MessageParameters
& params
)
198 cmd
= m_info
->GetPrintCommand();
201 cmd
= GetCommand(wxT("print"));
204 *printCmd
= wxFileType::ExpandCommand(cmd
, params
);
206 return !printCmd
->IsEmpty();
209 // TODO this function is half implemented
210 bool wxFileTypeImpl::GetExtensions(wxArrayString
& extensions
)
213 extensions
= m_info
->GetExtensions();
217 else if ( m_ext
.IsEmpty() ) {
218 // the only way to get the list of extensions from the file type is to
219 // scan through all extensions in the registry - too slow...
224 extensions
.Add(m_ext
);
226 // it's a lie too, we don't return _all_ extensions...
231 bool wxFileTypeImpl::GetMimeType(wxString
*mimeType
) const
234 // we already have it
235 *mimeType
= m_info
->GetMimeType();
240 // suppress possible error messages
242 wxRegKey
key(wxRegKey::HKCR
, wxT(".") + m_ext
);
243 if ( key
.Open() && key
.QueryValue(wxT("Content Type"), *mimeType
) ) {
251 bool wxFileTypeImpl::GetIcon(wxIcon
*icon
) const
255 // we don't have icons in the fallback resources
260 strIconKey
<< m_strFileType
<< wxT("\\DefaultIcon");
262 // suppress possible error messages
264 wxRegKey
key(wxRegKey::HKCR
, strIconKey
);
268 // it's the default value of the key
269 if ( key
.QueryValue(wxT(""), strIcon
) ) {
270 // the format is the following: <full path to file>, <icon index>
271 // NB: icon index may be negative as well as positive and the full
272 // path may contain the environment variables inside '%'
273 wxString strFullPath
= strIcon
.BeforeLast(wxT(',')),
274 strIndex
= strIcon
.AfterLast(wxT(','));
276 // index may be omitted, in which case BeforeLast(',') is empty and
277 // AfterLast(',') is the whole string
278 if ( strFullPath
.IsEmpty() ) {
279 strFullPath
= strIndex
;
283 wxString strExpPath
= wxExpandEnvVars(strFullPath
);
284 int nIndex
= wxAtoi(strIndex
);
286 HICON hIcon
= ExtractIcon(GetModuleHandle(NULL
), strExpPath
, nIndex
);
287 switch ( (int)hIcon
) {
288 case 0: // means no icons were found
289 case 1: // means no such file or it wasn't a DLL/EXE/OCX/ICO/...
290 wxLogDebug(wxT("incorrect registry entry '%s': no such icon."),
291 key
.GetName().c_str());
295 icon
->SetHICON((WXHICON
)hIcon
);
301 // no such file type or no value or incorrect icon entry
307 bool wxFileTypeImpl::GetDescription(wxString
*desc
) const
310 // we already have it
311 *desc
= m_info
->GetDescription();
316 // suppress possible error messages
318 wxRegKey
key(wxRegKey::HKCR
, m_strFileType
);
321 // it's the default value of the key
322 if ( key
.QueryValue(wxT(""), *desc
) ) {
330 // extension -> file type
332 wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString
& ext
)
334 // add the leading point if necessary
336 if ( ext
[0u] != wxT('.') ) {
341 // suppress possible error messages
344 bool knownExtension
= FALSE
;
346 wxString strFileType
;
347 wxRegKey
key(wxRegKey::HKCR
, str
);
349 // it's the default value of the key
350 if ( key
.QueryValue(wxT(""), strFileType
) ) {
351 // create the new wxFileType object
352 wxFileType
*fileType
= new wxFileType
;
353 fileType
->m_impl
->Init(strFileType
, ext
);
358 // this extension doesn't have a filetype, but it's known to the
359 // system and may be has some other useful keys (open command or
360 // content-type), so still return a file type object for it
361 knownExtension
= TRUE
;
365 // check the fallbacks
366 // TODO linear search is potentially slow, perhaps we should use a sorted
368 size_t count
= m_fallbacks
.GetCount();
369 for ( size_t n
= 0; n
< count
; n
++ ) {
370 if ( m_fallbacks
[n
].GetExtensions().Index(ext
) != wxNOT_FOUND
) {
371 wxFileType
*fileType
= new wxFileType
;
372 fileType
->m_impl
->Init(m_fallbacks
[n
]);
378 if ( knownExtension
)
380 wxFileType
*fileType
= new wxFileType
;
381 fileType
->m_impl
->Init(wxEmptyString
, ext
);
392 // MIME type -> extension -> file type
394 wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString
& mimeType
)
396 wxString strKey
= MIME_DATABASE_KEY
;
399 // suppress possible error messages
403 wxRegKey
key(wxRegKey::HKCR
, strKey
);
405 if ( key
.QueryValue(wxT("Extension"), ext
) ) {
406 return GetFileTypeFromExtension(ext
);
410 // check the fallbacks
411 // TODO linear search is potentially slow, perhaps we should use a sorted
413 size_t count
= m_fallbacks
.GetCount();
414 for ( size_t n
= 0; n
< count
; n
++ ) {
415 if ( wxMimeTypesManager::IsOfType(mimeType
,
416 m_fallbacks
[n
].GetMimeType()) ) {
417 wxFileType
*fileType
= new wxFileType
;
418 fileType
->m_impl
->Init(m_fallbacks
[n
]);
428 size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString
& mimetypes
)
430 // enumerate all keys under MIME_DATABASE_KEY
431 wxRegKey
key(wxRegKey::HKCR
, MIME_DATABASE_KEY
);
435 bool cont
= key
.GetFirstKey(type
, cookie
);
440 cont
= key
.GetNextKey(type
, cookie
);
443 return mimetypes
.GetCount();
448 // wxUSE_FILE && wxUSE_TEXTFILE