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