Added method for mimietype implementation.
[wxWidgets.git] / src / os2 / mimetype.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/mimetype.cpp
3 // Purpose: classes and functions to manage MIME types
4 // Author: David Webster
5 // Modified by:
6 // Created: 01.21.00
7 // RCS-ID: $Id$
8 // Copyright: Adopted from msw port --(c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license (part of wxExtra library)
10 /////////////////////////////////////////////////////////////////////////////
11
12 #define INCL_DOS
13 #define INCL_GPI
14 #define INCL_WIN
15 #include <os2.h>
16
17 #ifndef WX_PRECOMP
18 #include "wx/string.h"
19 #if wxUSE_GUI
20 #include "wx/icon.h"
21 #endif
22 #endif //WX_PRECOMP
23
24 #include "wx/log.h"
25 #include "wx/file.h"
26 #include "wx/intl.h"
27 #include "wx/dynarray.h"
28 #include "wx/confbase.h"
29
30 #include "wx/os2/mimetype.h"
31
32 // other standard headers
33 #include <ctype.h>
34
35 // in case we're compiling in non-GUI mode
36 class WXDLLEXPORT wxIcon;
37
38 // These classes use Windows registry to retrieve the required information.
39 //
40 // Keys used (not all of them are documented, so it might actually stop working
41 // in futur versions of Windows...):
42 // 1. "HKCR\MIME\Database\Content Type" contains subkeys for all known MIME
43 // types, each key has a string value "Extension" which gives (dot preceded)
44 // extension for the files of this MIME type.
45 //
46 // 2. "HKCR\.ext" contains
47 // a) unnamed value containing the "filetype"
48 // b) value "Content Type" containing the MIME type
49 //
50 // 3. "HKCR\filetype" contains
51 // a) unnamed value containing the description
52 // b) subkey "DefaultIcon" with single unnamed value giving the icon index in
53 // an icon file
54 // c) shell\open\command and shell\open\print subkeys containing the commands
55 // to open/print the file (the positional parameters are introduced by %1,
56 // %2, ... in these strings, we change them to %s ourselves)
57
58 // although I don't know of any official documentation which mentions this
59 // location, uses it, so it isn't likely to change
60 static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\");
61
62 wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
63 {
64 // TODO: OS/2 doesn't have a registry but uses Prf
65 /*
66 // suppress possible error messages
67 wxLogNull nolog;
68 wxString strKey;
69
70 if ( wxRegKey(wxRegKey::HKCR, m_ext + _T("\\shell")).Exists() )
71 strKey = m_ext;
72 if ( wxRegKey(wxRegKey::HKCR, m_strFileType + _T("\\shell")).Exists() )
73 strKey = m_strFileType;
74
75 if ( !strKey )
76 {
77 // no info
78 return wxEmptyString;
79 }
80
81 strKey << wxT("\\shell\\") << verb;
82 wxRegKey key(wxRegKey::HKCR, strKey + _T("\\command"));
83 wxString command;
84 if ( key.Open() ) {
85 // it's the default value of the key
86 if ( key.QueryValue(wxT(""), command) ) {
87 // transform it from '%1' to '%s' style format string (now also
88 // test for %L - apparently MS started using it as well for the
89 // same purpose)
90
91 // NB: we don't make any attempt to verify that the string is valid,
92 // i.e. doesn't contain %2, or second %1 or .... But we do make
93 // sure that we return a string with _exactly_ one '%s'!
94 bool foundFilename = FALSE;
95 size_t len = command.Len();
96 for ( size_t n = 0; (n < len) && !foundFilename; n++ ) {
97 if ( command[n] == wxT('%') &&
98 (n + 1 < len) &&
99 (command[n + 1] == wxT('1') ||
100 command[n + 1] == wxT('L')) ) {
101 // replace it with '%s'
102 command[n + 1] = wxT('s');
103
104 foundFilename = TRUE;
105 }
106 }
107
108 #if wxUSE_DDE
109 // look whether we must issue some DDE requests to the application
110 // (and not just launch it)
111 strKey += _T("\\DDEExec");
112 wxRegKey keyDDE(wxRegKey::HKCR, strKey);
113 if ( keyDDE.Open() ) {
114 wxString ddeCommand, ddeServer, ddeTopic;
115 keyDDE.QueryValue(_T(""), ddeCommand);
116 ddeCommand.Replace(_T("%1"), _T("%s"));
117
118 wxRegKey(wxRegKey::HKCR, strKey + _T("\\Application")).
119 QueryValue(_T(""), ddeServer);
120 wxRegKey(wxRegKey::HKCR, strKey + _T("\\Topic")).
121 QueryValue(_T(""), ddeTopic);
122
123 // HACK: we use a special feature of wxExecute which exists
124 // just because we need it here: it will establish DDE
125 // conversation with the program it just launched
126 command.Prepend(_T("WX_DDE#"));
127 command << _T('#') << ddeServer
128 << _T('#') << ddeTopic
129 << _T('#') << ddeCommand;
130 }
131 else
132 #endif // wxUSE_DDE
133 if ( !foundFilename ) {
134 // we didn't find any '%1' - the application doesn't know which
135 // file to open (note that we only do it if there is no DDEExec
136 // subkey)
137 //
138 // HACK: append the filename at the end, hope that it will do
139 command << wxT(" %s");
140 }
141 }
142 }
143 //else: no such file type or no value, will return empty string
144
145 return command;
146 */
147 return wxEmptyString;
148 }
149
150 bool
151 wxFileTypeImpl::GetOpenCommand(wxString *openCmd,
152 const wxFileType::MessageParameters& params)
153 const
154 {
155 wxString cmd;
156 if ( m_info ) {
157 cmd = m_info->GetOpenCommand();
158 }
159 else {
160 cmd = GetCommand(wxT("open"));
161 }
162
163 *openCmd = wxFileType::ExpandCommand(cmd, params);
164
165 return !openCmd->IsEmpty();
166 }
167
168 bool
169 wxFileTypeImpl::GetPrintCommand(wxString *printCmd,
170 const wxFileType::MessageParameters& params)
171 const
172 {
173 wxString cmd;
174 if ( m_info ) {
175 cmd = m_info->GetPrintCommand();
176 }
177 else {
178 cmd = GetCommand(wxT("print"));
179 }
180
181 *printCmd = wxFileType::ExpandCommand(cmd, params);
182
183 return !printCmd->IsEmpty();
184 }
185
186 // TODO this function is half implemented
187 bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
188 {
189 if ( m_info ) {
190 extensions = m_info->GetExtensions();
191
192 return TRUE;
193 }
194 else if ( m_ext.IsEmpty() ) {
195 // the only way to get the list of extensions from the file type is to
196 // scan through all extensions in the registry - too slow...
197 return FALSE;
198 }
199 else {
200 extensions.Empty();
201 extensions.Add(m_ext);
202
203 // it's a lie too, we don't return _all_ extensions...
204 return TRUE;
205 }
206 }
207
208 bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
209 {
210 if ( m_info ) {
211 // we already have it
212 *mimeType = m_info->GetMimeType();
213
214 return TRUE;
215 }
216
217 // suppress possible error messages
218 wxLogNull nolog;
219 // TODO: substitue reg key stuff (maybe make a Prf class for OS/2??)
220 /*
221 wxRegKey key(wxRegKey::HKCR, wxT(".") + m_ext);
222 if ( key.Open() && key.QueryValue(wxT("Content Type"), *mimeType) ) {
223 return TRUE;
224 }
225 else {
226 return FALSE;
227 }
228 */
229 return FALSE;
230 }
231
232 bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const
233 {
234 wxString s;
235
236 if (GetMimeType(&s))
237 {
238 mimeTypes.Clear();
239 mimeTypes.Add(s);
240 return TRUE;
241 }
242 else
243 return FALSE;
244 }
245
246 bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
247 {
248 #if wxUSE_GUI
249 if ( m_info ) {
250 // we don't have icons in the fallback resources
251 return FALSE;
252 }
253
254 wxString strIconKey;
255 strIconKey << m_strFileType << wxT("\\DefaultIcon");
256
257 // suppress possible error messages
258 wxLogNull nolog;
259 //TODO:
260 /*
261 wxRegKey key(wxRegKey::HKCR, strIconKey);
262
263 if ( key.Open() ) {
264 wxString strIcon;
265 // it's the default value of the key
266 if ( key.QueryValue(wxT(""), strIcon) ) {
267 // the format is the following: <full path to file>, <icon index>
268 // NB: icon index may be negative as well as positive and the full
269 // path may contain the environment variables inside '%'
270 wxString strFullPath = strIcon.BeforeLast(wxT(',')),
271 strIndex = strIcon.AfterLast(wxT(','));
272
273 // index may be omitted, in which case BeforeLast(',') is empty and
274 // AfterLast(',') is the whole string
275 if ( strFullPath.IsEmpty() ) {
276 strFullPath = strIndex;
277 strIndex = wxT("0");
278 }
279
280 wxString strExpPath = wxExpandEnvVars(strFullPath);
281 int nIndex = wxAtoi(strIndex);
282
283 HICON hIcon = ExtractIcon(GetModuleHandle(NULL), strExpPath, nIndex);
284 switch ( (int)hIcon ) {
285 case 0: // means no icons were found
286 case 1: // means no such file or it wasn't a DLL/EXE/OCX/ICO/...
287 wxLogDebug(wxT("incorrect registry entry '%s': no such icon."),
288 key.GetName().c_str());
289 break;
290
291 default:
292 icon->SetHICON((WXHICON)hIcon);
293 return TRUE;
294 }
295 }
296 }
297
298 // no such file type or no value or incorrect icon entry
299 */
300 #endif // wxUSE_GUI
301 return FALSE;
302 }
303
304 bool wxFileTypeImpl::GetDescription(wxString *desc) const
305 {
306 if ( m_info ) {
307 // we already have it
308 *desc = m_info->GetDescription();
309
310 return TRUE;
311 }
312
313 // suppress possible error messages
314 wxLogNull nolog;
315 // TODO:
316 /*
317 wxRegKey key(wxRegKey::HKCR, m_strFileType);
318
319 if ( key.Open() ) {
320 // it's the default value of the key
321 if ( key.QueryValue(wxT(""), *desc) ) {
322 return TRUE;
323 }
324 }
325 */
326 return FALSE;
327 }
328
329 // extension -> file type
330 wxFileType *
331 wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
332 {
333 // add the leading point if necessary
334 wxString str;
335 if ( ext[(size_t) 0] != wxT('.') ) {
336 str = wxT('.');
337 }
338 str << ext;
339
340 // suppress possible error messages
341 wxLogNull nolog;
342
343 bool knownExtension = FALSE;
344
345 wxString strFileType;
346 // TODO:
347 /*
348 wxRegKey key(wxRegKey::HKCR, str);
349 if ( key.Open() ) {
350 // it's the default value of the key
351 if ( key.QueryValue(wxT(""), strFileType) ) {
352 // create the new wxFileType object
353 wxFileType *fileType = new wxFileType;
354 fileType->m_impl->Init(strFileType, ext);
355
356 return fileType;
357 }
358 else {
359 // this extension doesn't have a filetype, but it's known to the
360 // system and may be has some other useful keys (open command or
361 // content-type), so still return a file type object for it
362 knownExtension = TRUE;
363 }
364 }
365 */
366 // check the fallbacks
367 // TODO linear search is potentially slow, perhaps we should use a sorted
368 // array?
369 size_t count = m_fallbacks.GetCount();
370 for ( size_t n = 0; n < count; n++ ) {
371 if ( m_fallbacks[n].GetExtensions().Index(ext) != wxNOT_FOUND ) {
372 wxFileType *fileType = new wxFileType;
373 fileType->m_impl->Init(m_fallbacks[n]);
374
375 return fileType;
376 }
377 }
378
379 if ( knownExtension )
380 {
381 wxFileType *fileType = new wxFileType;
382 fileType->m_impl->Init(wxEmptyString, ext);
383
384 return fileType;
385 }
386 else
387 {
388 // unknown extension
389 return NULL;
390 }
391 }
392
393 // MIME type -> extension -> file type
394 wxFileType *
395 wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
396 {
397 wxString strKey = MIME_DATABASE_KEY;
398 strKey << mimeType;
399
400 // suppress possible error messages
401 wxLogNull nolog;
402
403 wxString ext;
404 // TODO:
405 /*
406 wxRegKey key(wxRegKey::HKCR, strKey);
407 if ( key.Open() ) {
408 if ( key.QueryValue(wxT("Extension"), ext) ) {
409 return GetFileTypeFromExtension(ext);
410 }
411 }
412
413 // check the fallbacks
414 // TODO linear search is potentially slow, perhaps we should use a sorted
415 // array?
416 size_t count = m_fallbacks.GetCount();
417 for ( size_t n = 0; n < count; n++ ) {
418 if ( wxMimeTypesManager::IsOfType(mimeType,
419 m_fallbacks[n].GetMimeType()) ) {
420 wxFileType *fileType = new wxFileType;
421 fileType->m_impl->Init(m_fallbacks[n]);
422
423 return fileType;
424 }
425 }
426 */
427 // unknown MIME type
428 return NULL;
429 }
430
431 size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
432 {
433 // enumerate all keys under MIME_DATABASE_KEY
434 // TODO:
435 /*
436 wxRegKey key(wxRegKey::HKCR, MIME_DATABASE_KEY);
437
438 wxString type;
439 long cookie;
440 bool cont = key.GetFirstKey(type, cookie);
441 while ( cont )
442 {
443 mimetypes.Add(type);
444
445 cont = key.GetNextKey(type, cookie);
446 }
447
448 return mimetypes.GetCount();
449 */
450 return 0;
451 }
452