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