]> git.saurik.com Git - wxWidgets.git/blame - src/msw/mimetype.cpp
Added filename.cpp to .dsp files
[wxWidgets.git] / src / msw / mimetype.cpp
CommitLineData
7dc3cc31 1/////////////////////////////////////////////////////////////////////////////
4d2976ad 2// Name: msw/mimetype.cpp
7dc3cc31
VS
3// Purpose: classes and functions to manage MIME types
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 23.09.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license (part of wxExtra library)
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "mimetype.h"
14#endif
15
16// for compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
f1df0927
VZ
23// Doesn't compile in WIN16 mode
24#ifndef __WIN16__
7dc3cc31
VS
25
26#ifndef WX_PRECOMP
f5f4c6ce
VZ
27 #include "wx/string.h"
28 #if wxUSE_GUI
29 #include "wx/icon.h"
30 #include "wx/msgdlg.h"
31 #endif
7dc3cc31
VS
32#endif //WX_PRECOMP
33
7dc3cc31
VS
34#include "wx/log.h"
35#include "wx/file.h"
36#include "wx/intl.h"
37#include "wx/dynarray.h"
38#include "wx/confbase.h"
39
40#ifdef __WXMSW__
41 #include "wx/msw/registry.h"
42 #include "windows.h"
7dc3cc31
VS
43#endif // OS
44
45#include "wx/msw/mimetype.h"
46
47// other standard headers
48#include <ctype.h>
49
50// in case we're compiling in non-GUI mode
51class WXDLLEXPORT wxIcon;
52
7dc3cc31
VS
53// These classes use Windows registry to retrieve the required information.
54//
55// Keys used (not all of them are documented, so it might actually stop working
c7ce8392 56// in future versions of Windows...):
7dc3cc31
VS
57// 1. "HKCR\MIME\Database\Content Type" contains subkeys for all known MIME
58// types, each key has a string value "Extension" which gives (dot preceded)
59// extension for the files of this MIME type.
60//
61// 2. "HKCR\.ext" contains
62// a) unnamed value containing the "filetype"
63// b) value "Content Type" containing the MIME type
64//
65// 3. "HKCR\filetype" contains
66// a) unnamed value containing the description
67// b) subkey "DefaultIcon" with single unnamed value giving the icon index in
68// an icon file
69// c) shell\open\command and shell\open\print subkeys containing the commands
70// to open/print the file (the positional parameters are introduced by %1,
71// %2, ... in these strings, we change them to %s ourselves)
72
73// although I don't know of any official documentation which mentions this
74// location, uses it, so it isn't likely to change
75static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\");
76
c7ce8392
VZ
77void wxFileTypeImpl::Init(const wxString& strFileType, const wxString& ext)
78{
79 // VZ: does it? (FIXME)
80 wxCHECK_RET( !ext.IsEmpty(), _T("needs an extension") );
81
82 if ( ext[0u] != wxT('.') ) {
83 m_ext = wxT('.');
84 }
85 m_ext << ext;
86
87 m_strFileType = strFileType;
88 if ( !strFileType ) {
89 m_strFileType = m_ext.AfterFirst('.') + "_auto_file";
90 }
91}
92
93wxString wxFileTypeImpl::GetVerbPath(const wxString& verb) const
94{
95 wxString path;
96 path << m_strFileType << _T("\\shell\\") << verb << _T("\\command");
97 return path;
98}
99
100size_t wxFileTypeImpl::GetAllCommands(wxArrayString *verbs,
101 wxArrayString *commands,
102 const wxFileType::MessageParameters& params) const
103{
104 wxCHECK_MSG( !m_ext.IsEmpty(), 0, _T("GetAllCommands() needs an extension") );
105
106 if ( m_strFileType.IsEmpty() )
107 {
108 // get it from the registry
109 wxFileTypeImpl *self = wxConstCast(this, wxFileTypeImpl);
110 wxRegKey rkey(wxRegKey::HKCR, m_ext);
111 if ( !rkey.Exists() || !rkey.QueryValue(_T(""), self->m_strFileType) )
112 {
113 wxLogDebug(_T("Can't get the filetype for extension '%s'."),
114 m_ext.c_str());
115
116 return 0;
117 }
118 }
119
120 // enum all subkeys of HKCR\filetype\shell
121 size_t count = 0;
122 wxRegKey rkey(wxRegKey::HKCR, m_strFileType + _T("\\shell"));
123 long dummy;
124 wxString verb;
125 bool ok = rkey.GetFirstKey(verb, dummy);
126 while ( ok )
127 {
128 wxString command = wxFileType::ExpandCommand(GetCommand(verb), params);
129
130 // we want the open bverb to eb always the first
131
132 if ( verb.CmpNoCase(_T("open")) == 0 )
133 {
134 if ( verbs )
135 verbs->Insert(verb, 0);
136 if ( commands )
137 commands->Insert(command, 0);
138 }
139 else // anything else than "open"
140 {
141 if ( verbs )
142 verbs->Add(verb);
143 if ( commands )
144 commands->Add(command);
145 }
146
0354a70c
VZ
147 count++;
148
c7ce8392
VZ
149 ok = rkey.GetNextKey(verb, dummy);
150 }
151
152 return count;
153}
154
155// ----------------------------------------------------------------------------
156// modify the registry database
157// ----------------------------------------------------------------------------
158
159bool wxFileTypeImpl::EnsureExtKeyExists()
160{
161 wxRegKey rkey(wxRegKey::HKCR, m_ext);
162 if ( !rkey.Exists() )
163 {
164 if ( !rkey.Create() || !rkey.SetValue(_T(""), m_strFileType) )
165 {
166 wxLogError(_("Failed to create registry entry for '%s' files."),
167 m_ext.c_str());
168 return FALSE;
169 }
170 }
171
172 return TRUE;
173}
174
175bool wxFileTypeImpl::SetCommand(const wxString& cmd,
176 const wxString& verb,
177 bool overwriteprompt)
178{
179 wxCHECK_MSG( !m_ext.IsEmpty() && !verb.IsEmpty(), FALSE,
180 _T("SetCommand() needs an extension and a verb") );
181
182 if ( !EnsureExtKeyExists() )
183 return FALSE;
184
185 wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb));
186
187 if ( rkey.Exists() && overwriteprompt )
188 {
189#if wxUSE_GUI
190 wxString old;
191 rkey.QueryValue(wxT(""), old);
192 if ( wxMessageBox
193 (
194 wxString::Format(
195 _("Do you want to overwrite the command used to %s "
196 "files with extension \"%s\" (current value is '%s', "
197 "new value is '%s')?"),
198 verb.c_str(),
199 m_ext.c_str(),
200 old.c_str(),
201 cmd.c_str()),
202 _("Confirm registry update"),
203 wxYES_NO | wxICON_QUESTION
204 ) != wxYES )
205#endif // wxUSE_GUI
206 {
207 // cancelled by user
208 return FALSE;
209 }
210 }
211
212 // TODO:
213 // 1. translate '%s' to '%1' instead of always adding it
214 // 2. create DDEExec value if needed (undo GetCommand)
215 return rkey.Create() && rkey.SetValue(_T(""), cmd + _T(" \"%1\"") );
216}
217
218bool wxFileTypeImpl::SetMimeType(const wxString& mimeTypeOrig)
219{
220 wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("SetMimeType() needs extension") );
221
222 if ( !EnsureExtKeyExists() )
223 return FALSE;
224
225 // VZ: is this really useful? (FIXME)
226 wxString mimeType;
227 if ( !mimeTypeOrig )
228 {
229 // make up a default value for it
230 wxString cmd;
231 wxSplitPath(GetCommand(_T("open")), NULL, &cmd, NULL);
232 mimeType << _T("application/x-") << cmd;
233 }
234 else
235 {
236 mimeType = mimeTypeOrig;
237 }
238
239 wxRegKey rkey(wxRegKey::HKCR, m_ext);
240 return rkey.Create() && rkey.SetValue(_T("Content Type"), mimeType);
241}
242
243bool wxFileTypeImpl::SetDefaultIcon(const wxString& cmd, int index)
244{
245 wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("SetMimeType() needs extension") );
246 wxCHECK_MSG( wxFileExists(cmd), FALSE, _T("Icon file not found.") );
247
248 if ( !EnsureExtKeyExists() )
249 return FALSE;
250
251 wxRegKey rkey(wxRegKey::HKCR, m_strFileType + _T("\\DefaultIcon"));
252
253 return rkey.Create() &&
254 rkey.SetValue(_T(""),
255 wxString::Format(_T("%s,%d"), cmd.c_str(), index));
256}
257
258// ----------------------------------------------------------------------------
259// remove file association
260// ----------------------------------------------------------------------------
261
262bool wxFileTypeImpl::RemoveCommand(const wxString& verb)
263{
264 wxCHECK_MSG( !m_ext.IsEmpty() && !verb.IsEmpty(), FALSE,
265 _T("RemoveCommand() needs an extension and a verb") );
266
267 wxString sKey = m_strFileType;
268 wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb));
269
270 // if the key already doesn't exist, it's a success
271 return !rkey.Exists() || rkey.DeleteSelf();
272}
273
274bool wxFileTypeImpl::RemoveMimeType()
275{
276 wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("RemoveMimeType() needs extension") );
277
278 wxRegKey rkey(wxRegKey::HKCR, m_ext);
279 return !rkey.Exists() || rkey.DeleteSelf();
280}
281
282bool wxFileTypeImpl::RemoveDefaultIcon()
283{
284 wxCHECK_MSG( !m_ext.IsEmpty(), FALSE,
285 _T("RemoveDefaultIcon() needs extension") );
286
287 wxRegKey rkey (wxRegKey::HKCR, m_strFileType + _T("\\DefaultIcon"));
288 return !rkey.Exists() || rkey.DeleteSelf();
289}
290
7dc3cc31
VS
291wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
292{
293 // suppress possible error messages
294 wxLogNull nolog;
295 wxString strKey;
296
297 if ( wxRegKey(wxRegKey::HKCR, m_ext + _T("\\shell")).Exists() )
298 strKey = m_ext;
299 if ( wxRegKey(wxRegKey::HKCR, m_strFileType + _T("\\shell")).Exists() )
300 strKey = m_strFileType;
301
302 if ( !strKey )
303 {
304 // no info
305 return wxEmptyString;
306 }
307
308 strKey << wxT("\\shell\\") << verb;
309 wxRegKey key(wxRegKey::HKCR, strKey + _T("\\command"));
310 wxString command;
311 if ( key.Open() ) {
312 // it's the default value of the key
313 if ( key.QueryValue(wxT(""), command) ) {
314 // transform it from '%1' to '%s' style format string (now also
315 // test for %L - apparently MS started using it as well for the
316 // same purpose)
317
318 // NB: we don't make any attempt to verify that the string is valid,
319 // i.e. doesn't contain %2, or second %1 or .... But we do make
320 // sure that we return a string with _exactly_ one '%s'!
321 bool foundFilename = FALSE;
322 size_t len = command.Len();
323 for ( size_t n = 0; (n < len) && !foundFilename; n++ ) {
324 if ( command[n] == wxT('%') &&
325 (n + 1 < len) &&
326 (command[n + 1] == wxT('1') ||
327 command[n + 1] == wxT('L')) ) {
328 // replace it with '%s'
329 command[n + 1] = wxT('s');
330
331 foundFilename = TRUE;
332 }
333 }
334
f6bcfd97 335#if wxUSE_IPC
7dc3cc31
VS
336 // look whether we must issue some DDE requests to the application
337 // (and not just launch it)
338 strKey += _T("\\DDEExec");
339 wxRegKey keyDDE(wxRegKey::HKCR, strKey);
340 if ( keyDDE.Open() ) {
341 wxString ddeCommand, ddeServer, ddeTopic;
342 keyDDE.QueryValue(_T(""), ddeCommand);
343 ddeCommand.Replace(_T("%1"), _T("%s"));
344
345 wxRegKey(wxRegKey::HKCR, strKey + _T("\\Application")).
346 QueryValue(_T(""), ddeServer);
347 wxRegKey(wxRegKey::HKCR, strKey + _T("\\Topic")).
348 QueryValue(_T(""), ddeTopic);
349
350 // HACK: we use a special feature of wxExecute which exists
351 // just because we need it here: it will establish DDE
352 // conversation with the program it just launched
353 command.Prepend(_T("WX_DDE#"));
354 command << _T('#') << ddeServer
355 << _T('#') << ddeTopic
356 << _T('#') << ddeCommand;
357 }
6e7ce624 358 else
f6bcfd97 359#endif // wxUSE_IPC
6e7ce624 360 if ( !foundFilename ) {
7dc3cc31
VS
361 // we didn't find any '%1' - the application doesn't know which
362 // file to open (note that we only do it if there is no DDEExec
363 // subkey)
364 //
365 // HACK: append the filename at the end, hope that it will do
366 command << wxT(" %s");
367 }
368 }
369 }
370 //else: no such file type or no value, will return empty string
371
372 return command;
373}
374
375bool
376wxFileTypeImpl::GetOpenCommand(wxString *openCmd,
377 const wxFileType::MessageParameters& params)
378 const
379{
380 wxString cmd;
381 if ( m_info ) {
382 cmd = m_info->GetOpenCommand();
383 }
384 else {
385 cmd = GetCommand(wxT("open"));
386 }
387
388 *openCmd = wxFileType::ExpandCommand(cmd, params);
389
390 return !openCmd->IsEmpty();
391}
392
393bool
394wxFileTypeImpl::GetPrintCommand(wxString *printCmd,
395 const wxFileType::MessageParameters& params)
396 const
397{
398 wxString cmd;
399 if ( m_info ) {
400 cmd = m_info->GetPrintCommand();
401 }
402 else {
403 cmd = GetCommand(wxT("print"));
404 }
405
406 *printCmd = wxFileType::ExpandCommand(cmd, params);
407
408 return !printCmd->IsEmpty();
409}
410
411// TODO this function is half implemented
412bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
413{
414 if ( m_info ) {
415 extensions = m_info->GetExtensions();
416
417 return TRUE;
418 }
419 else if ( m_ext.IsEmpty() ) {
420 // the only way to get the list of extensions from the file type is to
421 // scan through all extensions in the registry - too slow...
422 return FALSE;
423 }
424 else {
425 extensions.Empty();
426 extensions.Add(m_ext);
427
428 // it's a lie too, we don't return _all_ extensions...
429 return TRUE;
430 }
431}
432
433bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
434{
435 if ( m_info ) {
436 // we already have it
437 *mimeType = m_info->GetMimeType();
438
439 return TRUE;
440 }
441
442 // suppress possible error messages
443 wxLogNull nolog;
c7ce8392 444 wxRegKey key(wxRegKey::HKCR, m_ext);
f6bcfd97
BP
445
446 return key.Open() && key.QueryValue(wxT("Content Type"), *mimeType);
7dc3cc31
VS
447}
448
4d2976ad
VS
449bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const
450{
451 wxString s;
f6bcfd97
BP
452
453 if ( !GetMimeType(&s) )
4d2976ad 454 {
4d2976ad 455 return FALSE;
f6bcfd97
BP
456 }
457
458 mimeTypes.Clear();
459 mimeTypes.Add(s);
460 return TRUE;
4d2976ad
VS
461}
462
463
c7ce8392
VZ
464bool wxFileTypeImpl::GetIcon(wxIcon *icon,
465 wxString *iconFile,
466 int *iconIndex) const
7dc3cc31
VS
467{
468#if wxUSE_GUI
469 if ( m_info ) {
470 // we don't have icons in the fallback resources
471 return FALSE;
472 }
473
474 wxString strIconKey;
475 strIconKey << m_strFileType << wxT("\\DefaultIcon");
476
477 // suppress possible error messages
478 wxLogNull nolog;
479 wxRegKey key(wxRegKey::HKCR, strIconKey);
480
481 if ( key.Open() ) {
482 wxString strIcon;
483 // it's the default value of the key
484 if ( key.QueryValue(wxT(""), strIcon) ) {
485 // the format is the following: <full path to file>, <icon index>
486 // NB: icon index may be negative as well as positive and the full
487 // path may contain the environment variables inside '%'
488 wxString strFullPath = strIcon.BeforeLast(wxT(',')),
489 strIndex = strIcon.AfterLast(wxT(','));
490
491 // index may be omitted, in which case BeforeLast(',') is empty and
492 // AfterLast(',') is the whole string
493 if ( strFullPath.IsEmpty() ) {
494 strFullPath = strIndex;
495 strIndex = wxT("0");
496 }
497
498 wxString strExpPath = wxExpandEnvVars(strFullPath);
c7ce8392 499 int nIndex = wxAtoi(strIndex) - 1 ; //bug here we need C based counting!!
7dc3cc31
VS
500
501 HICON hIcon = ExtractIcon(GetModuleHandle(NULL), strExpPath, nIndex);
502 switch ( (int)hIcon ) {
503 case 0: // means no icons were found
504 case 1: // means no such file or it wasn't a DLL/EXE/OCX/ICO/...
505 wxLogDebug(wxT("incorrect registry entry '%s': no such icon."),
506 key.GetName().c_str());
507 break;
508
509 default:
510 icon->SetHICON((WXHICON)hIcon);
c7ce8392
VZ
511 if ( iconIndex )
512 *iconIndex = nIndex;
513 if ( iconFile )
514 *iconFile = strFullPath;
7dc3cc31
VS
515 return TRUE;
516 }
517 }
518 }
519
520 // no such file type or no value or incorrect icon entry
521#endif // wxUSE_GUI
522
523 return FALSE;
524}
525
526bool wxFileTypeImpl::GetDescription(wxString *desc) const
527{
528 if ( m_info ) {
529 // we already have it
530 *desc = m_info->GetDescription();
531
532 return TRUE;
533 }
534
535 // suppress possible error messages
536 wxLogNull nolog;
537 wxRegKey key(wxRegKey::HKCR, m_strFileType);
538
539 if ( key.Open() ) {
540 // it's the default value of the key
541 if ( key.QueryValue(wxT(""), *desc) ) {
542 return TRUE;
543 }
544 }
545
546 return FALSE;
547}
548
c7ce8392
VZ
549// helper function
550wxFileType *
551wxMimeTypesManagerImpl::CreateFileType(const wxString& filetype, const wxString& ext)
552{
553 wxFileType *fileType = new wxFileType;
554 fileType->m_impl->Init(filetype, ext);
555 return fileType;
556}
557
7dc3cc31
VS
558// extension -> file type
559wxFileType *
560wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
561{
562 // add the leading point if necessary
563 wxString str;
564 if ( ext[0u] != wxT('.') ) {
565 str = wxT('.');
566 }
567 str << ext;
568
569 // suppress possible error messages
570 wxLogNull nolog;
571
572 bool knownExtension = FALSE;
573
574 wxString strFileType;
575 wxRegKey key(wxRegKey::HKCR, str);
576 if ( key.Open() ) {
577 // it's the default value of the key
578 if ( key.QueryValue(wxT(""), strFileType) ) {
579 // create the new wxFileType object
c7ce8392 580 return CreateFileType(strFileType, ext);
7dc3cc31
VS
581 }
582 else {
583 // this extension doesn't have a filetype, but it's known to the
584 // system and may be has some other useful keys (open command or
585 // content-type), so still return a file type object for it
586 knownExtension = TRUE;
587 }
588 }
589
590 // check the fallbacks
591 // TODO linear search is potentially slow, perhaps we should use a sorted
592 // array?
593 size_t count = m_fallbacks.GetCount();
594 for ( size_t n = 0; n < count; n++ ) {
595 if ( m_fallbacks[n].GetExtensions().Index(ext) != wxNOT_FOUND ) {
596 wxFileType *fileType = new wxFileType;
597 fileType->m_impl->Init(m_fallbacks[n]);
598
599 return fileType;
600 }
601 }
602
f6bcfd97 603 if ( !knownExtension )
7dc3cc31
VS
604 {
605 // unknown extension
606 return NULL;
607 }
f6bcfd97 608
c7ce8392
VZ
609 return CreateFileType(wxEmptyString, ext);
610}
611
612wxFileType *
613wxMimeTypesManagerImpl::GetOrAllocateFileTypeFromExtension(const wxString& ext)
614{
615 wxFileType *fileType = GetFileTypeFromExtension(ext);
616 if ( !fileType )
617 {
618 fileType = CreateFileType(wxEmptyString, ext);
619 }
f6bcfd97
BP
620
621 return fileType;
7dc3cc31
VS
622}
623
c7ce8392 624
7dc3cc31
VS
625// MIME type -> extension -> file type
626wxFileType *
627wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
628{
629 wxString strKey = MIME_DATABASE_KEY;
630 strKey << mimeType;
631
632 // suppress possible error messages
633 wxLogNull nolog;
634
635 wxString ext;
636 wxRegKey key(wxRegKey::HKCR, strKey);
637 if ( key.Open() ) {
638 if ( key.QueryValue(wxT("Extension"), ext) ) {
639 return GetFileTypeFromExtension(ext);
640 }
641 }
642
643 // check the fallbacks
644 // TODO linear search is potentially slow, perhaps we should use a sorted
645 // array?
646 size_t count = m_fallbacks.GetCount();
647 for ( size_t n = 0; n < count; n++ ) {
648 if ( wxMimeTypesManager::IsOfType(mimeType,
649 m_fallbacks[n].GetMimeType()) ) {
650 wxFileType *fileType = new wxFileType;
651 fileType->m_impl->Init(m_fallbacks[n]);
652
653 return fileType;
654 }
655 }
656
657 // unknown MIME type
658 return NULL;
659}
660
661size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
662{
663 // enumerate all keys under MIME_DATABASE_KEY
664 wxRegKey key(wxRegKey::HKCR, MIME_DATABASE_KEY);
665
666 wxString type;
667 long cookie;
668 bool cont = key.GetFirstKey(type, cookie);
669 while ( cont )
670 {
671 mimetypes.Add(type);
672
673 cont = key.GetNextKey(type, cookie);
674 }
675
676 return mimetypes.GetCount();
677}
678
c7ce8392
VZ
679// ----------------------------------------------------------------------------
680// create a new association
681// ----------------------------------------------------------------------------
682
683wxFileType *wxMimeTypesManager::Associate(const wxString& ext,
684 const wxString& mimetype,
685 const wxString& filetypeOrig,
686 const wxString& WXUNUSED(desc))
687{
688 wxCHECK_MSG( !ext.empty(), NULL, _T("Associate() needs extension") );
689
690 wxString extWithDot;
691 if ( ext[0u] != _T('.') )
692 extWithDot = _T('.');
693 extWithDot += ext;
694
695 wxRegKey key(wxRegKey::HKCR, extWithDot);
696 wxFileType *ft = NULL;
697 if ( !key.Exists() )
698 {
699 wxString filetype;
700
701 // create the mapping from the extension to the filetype
702 bool ok = key.Create();
703 if ( ok )
704 {
705 if ( filetypeOrig.empty() )
706 {
707 // make it up from the extension
708 filetype << extWithDot.c_str() + 1 << _T("_auto_file");
709 }
710 else
711 {
712 // just use the provided one
713 filetype = filetypeOrig;
714 }
715
716 ok = key.SetValue(_T(""), filetype);
717 }
718
719 if ( ok && !mimetype.empty() )
720 {
721 // set the MIME type
722 ok = key.SetValue(_T("Content Type"), mimetype);
723
724 if ( ok )
725 {
726 // create the MIME key
727 wxString strKey = MIME_DATABASE_KEY;
728 strKey << mimetype;
729 wxRegKey keyMIME(wxRegKey::HKCR, strKey);
730 ok = keyMIME.Create();
731
732 if ( ok )
733 {
734 // and provide a back link to the extension
735 ok = keyMIME.SetValue(_T("Extension"), extWithDot);
736 }
737 }
738 }
739
740 if ( ok )
741 {
742 // create the filetype key itself (it will be empty for now, but
743 // SetCommand(), SetDefaultIcon() &c will use it later)
744 wxRegKey keyFT(wxRegKey::HKCR, filetype);
745 ok = keyFT.Create();
746 }
747
748 if ( ok )
749 {
750 // ok, we've created everything correctly
751 ft = m_impl->CreateFileType(filetype, extWithDot);
752 }
753 else
754 {
755 // one of the registry operations failed
756 wxLogError(_("Failed to register extension '%s'."), ext.c_str());
757 }
758 }
759 else // key already exists
760 {
761 // FIXME we probably should return an existing file type then?
762 }
763
764 return ft;
765}
7dc3cc31 766
7dc3cc31
VS
767#endif
768 // __WIN16__