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