]> git.saurik.com Git - wxWidgets.git/commitdiff
wxMimeTypesManager now supports creating associations as well as querying
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 18 Dec 2000 04:48:37 +0000 (04:48 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 18 Dec 2000 04:48:37 +0000 (04:48 +0000)
them (MSW only, thanks to Chris Elliott)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8936 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/mimetype.h
include/wx/msw/mimetype.h
samples/console/console.cpp
src/common/mimecmn.cpp
src/msw/mimetype.cpp

index dcd26cafa46f272ec526633b05e051a40620b9e1..28a529dddab028b1b25e8efb5eb2e7a4a7ed358b 100644 (file)
@@ -3,6 +3,7 @@
 // Purpose:     classes and functions to manage MIME types
 // Author:      Vadim Zeitlin
 // Modified by:
+//  Chris Elliott (biol75@york.ac.uk) 5 Dec 00: write support for Win32
 // Created:     23.09.98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
@@ -81,8 +82,12 @@ public:
         // fill passed in array with all extensions associated with this file
         // type
     bool GetExtensions(wxArrayString& extensions);
-        // get the icon corresponding to this file type
-    bool GetIcon(wxIcon *icon) const;
+        // get the icon corresponding to this file type, the name of the file
+        // where the icon resides is return in iconfile if !NULL and its index
+        // in this file (Win-only) is in iconIndex
+    bool GetIcon(wxIcon *icon,
+                 wxString *iconFile = NULL,
+                 int *iconIndex = NULL) const;
         // get a brief file type description ("*.txt" => "text document")
     bool GetDescription(wxString *desc) const;
 
@@ -94,6 +99,39 @@ public:
     bool GetPrintCommand(wxString *printCmd,
                          const MessageParameters& params) const;
 
+
+        // return the number of commands defined for this file type, 0 if none
+    size_t GetAllCommands(wxArrayString *verbs, wxArrayString *commands,
+                          const wxFileType::MessageParameters& params) const;
+
+    // the methods which modify the system database are only implemented under
+    // Win32 so far (on other platforms they will just return FALSE)
+    //
+    // also, they should only be used with the objects created using
+    // wxMimeTypesManager::Associate()
+
+        // set the command to be used for opening the file
+    bool SetOpenCommand(const wxString& cmd, bool overwriteprompt = TRUE);
+
+        // set an arbitrary command, ask confirmation if it already exists and
+        // overwriteprompt is TRUE
+    bool SetCommand(const wxString& cmd, const wxString& verb,
+                    bool overwriteprompt = TRUE);
+
+        // set the MIME type for this filetype
+    bool SetMimeType(const wxString& mimeType);
+        // set the default icon for this filetype
+    bool SetDefaultIcon(const wxString& cmd = wxEmptyString, int index = 0);
+
+        // remove the association from the system database
+    bool Unassociate();
+
+        // delete registration info
+    bool RemoveOpenCommand();
+    bool RemoveCommand(const wxString& verb);
+    bool RemoveMimeType();
+    bool RemoveDefaultIcon();
+
     // operations
         // expand a string in the format of GetOpenCommand (which may contain
         // '%s' and '%t' format specificators for the file name and mime type
@@ -186,6 +224,7 @@ public:
     // deleting it.
         // get file type from file extension
     wxFileType *GetFileTypeFromExtension(const wxString& ext);
+    wxFileType *GetOrAllocateFileTypeFromExtension(const wxString& ext);
         // get file type from MIME type (in format <category>/<format>)
     wxFileType *GetFileTypeFromMimeType(const wxString& mimeType);
 
@@ -218,6 +257,14 @@ public:
     // The filetypes array should be terminated by a NULL entry
     void AddFallbacks(const wxFileTypeInfo *filetypes);
 
+    // create a new association between the given extension and MIME type and
+    // return the wxFileType object corresponding (which should be deleted by
+    // caller) or NULL if something went wrong
+    wxFileType *Associate(const wxString& ext,
+                          const wxString& mimeType,
+                          const wxString& filetype = wxEmptyString,
+                          const wxString& desc = wxEmptyString);
+
     // dtor (not virtual, shouldn't be derived from)
     ~wxMimeTypesManager();
 
@@ -227,10 +274,10 @@ private:
     wxMimeTypesManager& operator=(const wxMimeTypesManager&);
 
     wxMimeTypesManagerImpl *m_impl;
-    
+
     // if m_impl is NULL, create one
     void EnsureImpl();
-    
+
     friend class wxMimeTypeCmnModule;
 };
 
index 605c00fe01cd91f217461c86dc378336348aa8ea..4a15a2b72f0c9905a844e190561baa9d8a60416a 100644 (file)
@@ -32,8 +32,7 @@ public:
 
         // initialize us with our file type name and extension - in this case
         // we will read all other data from the registry
-    void Init(const wxString& strFileType, const wxString& ext)
-        { m_strFileType = strFileType; m_ext = ext; }
+    void Init(const wxString& strFileType, const wxString& ext);
 
         // initialize us with a wxFileTypeInfo object - it contains all the
         // data
@@ -44,26 +43,43 @@ public:
     bool GetExtensions(wxArrayString& extensions);
     bool GetMimeType(wxString *mimeType) const;
     bool GetMimeTypes(wxArrayString& mimeTypes) const;
-    bool GetIcon(wxIcon *icon) const;
+    bool GetIcon(wxIcon *icon, wxString *sCommand = NULL, int *iIndex = NULL) const;
     bool GetDescription(wxString *desc) const;
     bool GetOpenCommand(wxString *openCmd,
                         const wxFileType::MessageParameters& params) const;
     bool GetPrintCommand(wxString *printCmd,
                          const wxFileType::MessageParameters& params) const;
 
+    size_t GetAllCommands(wxArrayString * verbs, wxArrayString * commands,
+                          const wxFileType::MessageParameters& params) const;
+
+    bool SetCommand(const wxString& cmd, const wxString& verb,
+                    bool overwriteprompt = true);
+    bool SetMimeType(const wxString& mimeType);
+    bool SetDefaultIcon(const wxString& cmd = wxEmptyString, int index = 0);
+
+    bool RemoveCommand(const wxString& verb);
+    bool RemoveMimeType();
+    bool RemoveDefaultIcon();
+
 private:
     // helper function: reads the command corresponding to the specified verb
     // from the registry (returns an empty string if not found)
     wxString GetCommand(const wxChar *verb) const;
 
+    // get the registry path for the given verb
+    wxString GetVerbPath(const wxString& verb) const;
+
+    // check that the registry key for our extension exists, create it if it
+    // doesn't, return FALSE if this failed
+    bool EnsureExtKeyExists();
+
     // we use either m_info or read the data from the registry if m_info == NULL
     const wxFileTypeInfo *m_info;
     wxString m_strFileType,         // may be empty
              m_ext;
 };
 
-
-
 class WXDLLEXPORT wxMimeTypesManagerImpl
 {
 public:
@@ -73,6 +89,7 @@ public:
 
     // implement containing class functions
     wxFileType *GetFileTypeFromExtension(const wxString& ext);
+    wxFileType *GetOrAllocateFileTypeFromExtension(const wxString& ext) ;
     wxFileType *GetFileTypeFromMimeType(const wxString& mimeType);
 
     size_t EnumAllFileTypes(wxArrayString& mimetypes);
@@ -85,6 +102,9 @@ public:
 
     void AddFallback(const wxFileTypeInfo& ft) { m_fallbacks.Add(ft); }
 
+    // create a new filetype with the given name and extension
+    wxFileType *CreateFileType(const wxString& filetype, const wxString& ext);
+
 private:
     wxArrayFileTypeInfo m_fallbacks;
 };
index bf78c7d95736fd0234b173e4a0d75da312f3b6f9..984046b47ac5f849fabe15d5504ecd809e5e7084 100644 (file)
@@ -40,7 +40,7 @@
 //#define TEST_DATETIME
 //#define TEST_DIR
 //#define TEST_DLLLOADER
-#define TEST_ENVIRON
+//#define TEST_ENVIRON
 //#define TEST_EXECUTE
 //#define TEST_FILE
 //#define TEST_FILECONF
@@ -48,7 +48,7 @@
 //#define TEST_LIST
 //#define TEST_LOG
 //#define TEST_LONGLONG
-//#define TEST_MIME
+#define TEST_MIME
 //#define TEST_INFO_FUNCTIONS
 //#define TEST_REGISTRY
 //#define TEST_SOCKETS
@@ -763,6 +763,32 @@ static void TestMimeFilename()
     }
 }
 
+static void TestMimeAssociate()
+{
+    wxPuts(_T("*** Testing creation of filetype association ***\n"));
+
+    wxFileType *ft = g_mimeManager.Associate
+                     (
+                        _T(".xyz"),
+                        _T("application/x-xyz"),
+                        _T("XYZFile"), // filetype (MSW only)
+                        _T("XYZ File") // description (Unix only)
+                     );
+    if ( !ft )
+    {
+        wxPuts(_T("ERROR: failed to create association!"));
+    }
+    else
+    {
+        if ( !ft->SetOpenCommand(_T("myprogram")) )
+        {
+            wxPuts(_T("ERROR: failed to set open command!"));
+        }
+
+        delete ft;
+    }
+}
+
 #endif // TEST_MIME
 
 // ----------------------------------------------------------------------------
@@ -3809,9 +3835,12 @@ int main(int argc, char **argv)
 #ifdef TEST_MIME
     wxLog::AddTraceMask(_T("mime"));
     if ( 0 )
+    {
         TestMimeEnum();
-    TestMimeOverride();
-    TestMimeFilename();
+        TestMimeOverride();
+        TestMimeFilename();
+    }
+    TestMimeAssociate();
 #endif // TEST_MIME
 
 #ifdef TEST_INFO_FUNCTIONS
index 7a773543f0c9248fb28647d8c5e71f97899ba574..8bf7953030fe62c69b2ef88bda3681d7f7735ff4 100644 (file)
@@ -3,6 +3,7 @@
 // Purpose:     classes and functions to manage MIME types
 // Author:      Vadim Zeitlin
 // Modified by:
+//  Chris Elliott (biol75@york.ac.uk) 5 Dec 00: write support for Win32
 // Created:     23.09.98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
@@ -66,13 +67,13 @@ class WXDLLEXPORT wxIcon;
 // implementation classes:
 
 #if defined(__WXMSW__)
-#include "wx/msw/mimetype.h"
+    #include "wx/msw/mimetype.h"
 #elif defined (__WXMAC__)
-#include "wx/mac/mimetype.h"
+    #include "wx/mac/mimetype.h"
 #elif defined (__WXPM__)
-#include "wx/os2/mimetype.h"
-#else
-#include "wx/unix/mimetype.h"
+    #include "wx/os2/mimetype.h"
+#else // Unix
+    #include "wx/unix/mimetype.h"
 #endif
 
 // ============================================================================
@@ -230,9 +231,15 @@ bool wxFileType::GetMimeTypes(wxArrayString& mimeTypes) const
     return m_impl->GetMimeTypes(mimeTypes);
 }
 
-bool wxFileType::GetIcon(wxIcon *icon) const
+bool wxFileType::GetIcon(wxIcon *icon,
+                         wxString *iconFile,
+                         int *iconIndex) const
 {
+#ifdef __WXMSW__
+    return m_impl->GetIcon(icon, iconFile, iconIndex);
+#else
     return m_impl->GetIcon(icon);
+#endif
 }
 
 bool wxFileType::GetDescription(wxString *desc) const
@@ -254,13 +261,156 @@ wxFileType::GetPrintCommand(wxString *printCmd,
     return m_impl->GetPrintCommand(printCmd, params);
 }
 
+
+size_t wxFileType::GetAllCommands(wxArrayString *verbs,
+                                  wxArrayString *commands,
+                                  const wxFileType::MessageParameters& params) const
+{
+    if ( verbs )
+        verbs->Clear();
+    if ( commands )
+        commands->Clear();
+
+#ifdef __WXMSW__
+    return m_impl->GetAllCommands(verbs, commands, params);
+#else // !__WXMSW__
+    // we don't know how to retrieve all commands, so just try the 2 we know
+    // about
+    size_t count = 0;
+    wxString cmd;
+    if ( m_impl->GetOpenCommand(&cmd, params) )
+    {
+        if ( verbs )
+            verbs->Add(_T("Open"));
+        if ( commands )
+            commands->Add(cmd);
+        count++;
+    }
+
+    if ( GetPrintCommand(&cmd, params) )
+    {
+        if ( verbs )
+            verbs->Add(_T("Print"));
+        if ( commands )
+            commands->Add(cmd);
+
+        count++;
+    }
+
+    return count;
+#endif // __WXMSW__/!__WXMSW__
+}
+
+bool wxFileType::SetOpenCommand(const wxString& cmd, bool overwriteprompt)
+{
+    return SetCommand(cmd, _T("open"), overwriteprompt);
+}
+
+bool wxFileType::SetCommand(const wxString& cmd, const wxString& verb,
+                            bool overwriteprompt)
+{
+#ifdef __WXMSW__
+    return m_impl->SetCommand(cmd, verb, overwriteprompt);
+#else
+    wxFAIL_MSG(_T("not implemented"));
+
+    return FALSE;
+#endif
+}
+
+bool wxFileType::SetMimeType(const wxString& mimeType)
+{
+    // empty MIME type is meaningless here
+    wxCHECK_MSG( !mimeType.empty(), FALSE, _T("use RemoveMimeType()") );
+
+#ifdef __WXMSW__
+    return m_impl->SetMimeType(mimeType);
+#else
+    wxFAIL_MSG(_T("not implemented"));
+
+    return FALSE;
+#endif
+}
+
+bool wxFileType::SetDefaultIcon(const wxString& cmd, int index)
+{
+    wxString sTmp = cmd;
+    // VZ: should we do this?
+    if ( sTmp.empty() )
+        GetOpenCommand(&sTmp, wxFileType::MessageParameters("", ""));
+
+    wxCHECK_MSG( !sTmp.empty(), false, _T("need the icon file") );
+
+
+#ifdef __WXMSW__
+    return m_impl->SetDefaultIcon (cmd, index);
+#else
+    wxFAIL_MSG(_T("not implemented"));
+
+    return FALSE;
+#endif
+}
+
+// now do remove functions
+bool wxFileType::RemoveOpenCommand()
+{
+   return RemoveCommand(_T("open"));
+}
+
+bool wxFileType::RemoveCommand(const wxString& verb)
+{
+#ifdef __WXMSW__
+    return m_impl->RemoveCommand(verb);
+#else
+    wxFAIL_MSG(_T("not implemented"));
+
+    return FALSE;
+#endif
+}
+
+bool wxFileType::RemoveMimeType()
+{
+#ifdef __WXMSW__
+    return m_impl->RemoveMimeType ();
+#else
+    wxFAIL_MSG(_T("not implemented"));
+
+    return FALSE;
+#endif
+}
+
+bool wxFileType::RemoveDefaultIcon()
+{
+#ifdef __WXMSW__
+    return m_impl->RemoveDefaultIcon();
+#else
+    wxFAIL_MSG(_T("not implemented"));
+
+    return FALSE;
+#endif
+}
+
+bool wxFileType::Unassociate()
+{
+    bool result = TRUE;
+    if ( !RemoveOpenCommand() )
+        result = FALSE;
+    if ( !RemoveDefaultIcon() )
+        result = FALSE;
+    if ( !RemoveMimeType() )
+        result = FALSE;
+
+    // in MSW this leaves a HKCR.xzy key
+    return result;
+}
+
 // ----------------------------------------------------------------------------
 // wxMimeTypesManager
 // ----------------------------------------------------------------------------
 
 void wxMimeTypesManager::EnsureImpl()
 {
-    if (m_impl == NULL)
+    if ( !m_impl )
         m_impl = new wxMimeTypesManagerImpl;
 }
 
@@ -293,8 +443,7 @@ wxMimeTypesManager::wxMimeTypesManager()
 
 wxMimeTypesManager::~wxMimeTypesManager()
 {
-    if (m_impl != NULL)
-        delete m_impl;
+    delete m_impl;
 }
 
 wxFileType *
@@ -304,6 +453,34 @@ wxMimeTypesManager::GetFileTypeFromExtension(const wxString& ext)
     return m_impl->GetFileTypeFromExtension(ext);
 }
 
+wxFileType *
+wxMimeTypesManager::GetOrAllocateFileTypeFromExtension(const wxString& ext)
+{
+    EnsureImpl();
+
+#ifdef __WXMSW__
+    // this writes a root entry to the registry in HKCR.ext
+    return m_impl->GetOrAllocateFileTypeFromExtension(ext);
+#else // !__WXMSW__
+    // VZ: "static const"??? (FIXME)
+    // just make a dummy entry with no writing to file
+    static const wxFileTypeInfo fallback[] =
+    {
+        wxFileTypeInfo("application/x-" + ext,
+                       "",
+                       "",
+                       ext + " format file",
+                       ext, NULL),
+        // must terminate the table with this!
+        wxFileTypeInfo()
+    };
+
+    AddFallbacks (fallback);
+    return m_impl->GetFileTypeFromExtension(ext);
+#endif // __WXMSW__/!__WXMSW__
+}
+
+
 wxFileType *
 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString& mimeType)
 {
@@ -348,30 +525,26 @@ static wxMimeTypesManager gs_mimeTypesManager;
 // and public pointer
 wxMimeTypesManager * wxTheMimeTypesManager = &gs_mimeTypesManager;
 
-
-
-
-
 class wxMimeTypeCmnModule: public wxModule
 {
-DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule)
 public:
-    wxMimeTypeCmnModule() : wxModule() {}
-    bool OnInit() { return TRUE; }
-    void OnExit() 
-    {   // this avoids false memory leak allerts:
-        if (gs_mimeTypesManager.m_impl != NULL)
-       {
-           delete gs_mimeTypesManager.m_impl;
-           gs_mimeTypesManager.m_impl = NULL;
-       }
+    wxMimeTypeCmnModule() : wxModule() { }
+    virtual bool OnInit() { return TRUE; }
+    virtual void OnExit()
+    {
+        // this avoids false memory leak allerts:
+        if ( gs_mimeTypesManager.m_impl != NULL )
+        {
+            delete gs_mimeTypesManager.m_impl;
+            gs_mimeTypesManager.m_impl = NULL;
+        }
     }
+
+    DECLARE_DYNAMIC_CLASS(wxMimeTypeCmnModule)
 };
 
 IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule, wxModule)
 
-
-
 #endif
   // wxUSE_FILE && wxUSE_TEXTFILE
 
index 4ca0315ec22d6c6493d558cac2c22b552a48baf6..699c76c856a8eb1a70f888818f1fa6516ed21860 100644 (file)
@@ -52,7 +52,7 @@ class WXDLLEXPORT wxIcon;
 // These classes use Windows registry to retrieve the required information.
 //
 // Keys used (not all of them are documented, so it might actually stop working
-// in futur versions of Windows...):
+// in future versions of Windows...):
 //  1. "HKCR\MIME\Database\Content Type" contains subkeys for all known MIME
 //     types, each key has a string value "Extension" which gives (dot preceded)
 //     extension for the files of this MIME type.
@@ -73,6 +73,218 @@ class WXDLLEXPORT wxIcon;
 // location, uses it, so it isn't likely to change
 static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\");
 
+void wxFileTypeImpl::Init(const wxString& strFileType, const wxString& ext)
+{
+    // VZ: does it? (FIXME)
+    wxCHECK_RET( !ext.IsEmpty(), _T("needs an extension") );
+
+    if ( ext[0u] != wxT('.') ) {
+        m_ext = wxT('.');
+    }
+    m_ext << ext;
+
+    m_strFileType = strFileType;
+    if ( !strFileType ) {
+        m_strFileType = m_ext.AfterFirst('.') + "_auto_file";
+    }
+}
+
+wxString wxFileTypeImpl::GetVerbPath(const wxString& verb) const
+{
+    wxString path;
+    path << m_strFileType << _T("\\shell\\") << verb << _T("\\command");
+    return path;
+}
+
+size_t wxFileTypeImpl::GetAllCommands(wxArrayString *verbs,
+                                      wxArrayString *commands,
+                                      const wxFileType::MessageParameters& params) const
+{
+    wxCHECK_MSG( !m_ext.IsEmpty(), 0, _T("GetAllCommands() needs an extension") );
+
+    if ( m_strFileType.IsEmpty() )
+    {
+        // get it from the registry
+        wxFileTypeImpl *self = wxConstCast(this, wxFileTypeImpl);
+        wxRegKey rkey(wxRegKey::HKCR, m_ext);
+        if ( !rkey.Exists() || !rkey.QueryValue(_T(""), self->m_strFileType) )
+        {
+            wxLogDebug(_T("Can't get the filetype for extension '%s'."),
+                       m_ext.c_str());
+
+            return 0;
+        }
+    }
+
+    // enum all subkeys of HKCR\filetype\shell
+    size_t count = 0;
+    wxRegKey rkey(wxRegKey::HKCR, m_strFileType  + _T("\\shell"));
+    long dummy;
+    wxString verb;
+    bool ok = rkey.GetFirstKey(verb, dummy);
+    while ( ok )
+    {
+        wxString command = wxFileType::ExpandCommand(GetCommand(verb), params);
+
+        // we want the open bverb to eb always the first
+
+        if ( verb.CmpNoCase(_T("open")) == 0 )
+        {
+            if ( verbs )
+                verbs->Insert(verb, 0);
+            if ( commands )
+                commands->Insert(command, 0);
+        }
+        else // anything else than "open"
+        {
+            if ( verbs )
+                verbs->Add(verb);
+            if ( commands )
+                commands->Add(command);
+        }
+
+        ok = rkey.GetNextKey(verb, dummy);
+    }
+
+    return count;
+}
+
+// ----------------------------------------------------------------------------
+// modify the registry database
+// ----------------------------------------------------------------------------
+
+bool wxFileTypeImpl::EnsureExtKeyExists()
+{
+    wxRegKey rkey(wxRegKey::HKCR, m_ext);
+    if ( !rkey.Exists() )
+    {
+        if ( !rkey.Create() || !rkey.SetValue(_T(""), m_strFileType) )
+        {
+            wxLogError(_("Failed to create registry entry for '%s' files."),
+                       m_ext.c_str());
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+bool wxFileTypeImpl::SetCommand(const wxString& cmd,
+                                const wxString& verb,
+                                bool overwriteprompt)
+{
+    wxCHECK_MSG( !m_ext.IsEmpty() && !verb.IsEmpty(), FALSE,
+                 _T("SetCommand() needs an extension and a verb") );
+
+    if ( !EnsureExtKeyExists() )
+        return FALSE;
+
+    wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb));
+
+    if ( rkey.Exists() && overwriteprompt )
+    {
+#if wxUSE_GUI
+        wxString old;
+        rkey.QueryValue(wxT(""), old);
+        if ( wxMessageBox
+             (
+                wxString::Format(
+                    _("Do you want to overwrite the command used to %s "
+                      "files with extension \"%s\" (current value is '%s', "
+                      "new value is '%s')?"),
+                    verb.c_str(),
+                    m_ext.c_str(),
+                    old.c_str(),
+                    cmd.c_str()),
+                _("Confirm registry update"),
+                wxYES_NO | wxICON_QUESTION
+             ) != wxYES )
+#endif // wxUSE_GUI
+        {
+            // cancelled by user
+            return FALSE;
+        }
+    }
+
+    // TODO:
+    // 1. translate '%s' to '%1' instead of always adding it
+    // 2. create DDEExec value if needed (undo GetCommand)
+    return rkey.Create() && rkey.SetValue(_T(""), cmd + _T(" \"%1\"") );
+}
+
+bool wxFileTypeImpl::SetMimeType(const wxString& mimeTypeOrig)
+{
+    wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("SetMimeType() needs extension") );
+
+    if ( !EnsureExtKeyExists() )
+        return FALSE;
+
+    // VZ: is this really useful? (FIXME)
+    wxString mimeType;
+    if ( !mimeTypeOrig )
+    {
+        // make up a default value for it
+        wxString cmd;
+        wxSplitPath(GetCommand(_T("open")), NULL, &cmd, NULL);
+        mimeType << _T("application/x-") << cmd;
+    }
+    else
+    {
+        mimeType = mimeTypeOrig;
+    }
+
+    wxRegKey rkey(wxRegKey::HKCR, m_ext);
+    return rkey.Create() && rkey.SetValue(_T("Content Type"), mimeType);
+}
+
+bool wxFileTypeImpl::SetDefaultIcon(const wxString& cmd, int index)
+{
+    wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("SetMimeType() needs extension") );
+    wxCHECK_MSG( wxFileExists(cmd), FALSE, _T("Icon file not found.") );
+
+    if ( !EnsureExtKeyExists() )
+        return FALSE;
+
+    wxRegKey rkey(wxRegKey::HKCR, m_strFileType + _T("\\DefaultIcon"));
+
+    return rkey.Create() &&
+           rkey.SetValue(_T(""),
+                         wxString::Format(_T("%s,%d"), cmd.c_str(), index));
+}
+
+// ----------------------------------------------------------------------------
+// remove file association
+// ----------------------------------------------------------------------------
+
+bool wxFileTypeImpl::RemoveCommand(const wxString& verb)
+{
+    wxCHECK_MSG( !m_ext.IsEmpty() && !verb.IsEmpty(), FALSE,
+                 _T("RemoveCommand() needs an extension and a verb") );
+
+    wxString  sKey = m_strFileType;
+    wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb));
+
+    // if the key already doesn't exist, it's a success
+    return !rkey.Exists() || rkey.DeleteSelf();
+}
+
+bool wxFileTypeImpl::RemoveMimeType()
+{
+    wxCHECK_MSG( !m_ext.IsEmpty(), FALSE, _T("RemoveMimeType() needs extension") );
+
+    wxRegKey rkey(wxRegKey::HKCR, m_ext);
+    return !rkey.Exists() || rkey.DeleteSelf();
+}
+
+bool wxFileTypeImpl::RemoveDefaultIcon()
+{
+    wxCHECK_MSG( !m_ext.IsEmpty(), FALSE,
+                 _T("RemoveDefaultIcon() needs extension") );
+
+    wxRegKey rkey (wxRegKey::HKCR, m_strFileType  + _T("\\DefaultIcon"));
+    return !rkey.Exists() || rkey.DeleteSelf();
+}
+
 wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
 {
     // suppress possible error messages
@@ -226,12 +438,11 @@ bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
 
     // suppress possible error messages
     wxLogNull nolog;
-    wxRegKey key(wxRegKey::HKCR, wxT(".") + m_ext);
+    wxRegKey key(wxRegKey::HKCR, m_ext);
 
     return key.Open() && key.QueryValue(wxT("Content Type"), *mimeType);
 }
 
-
 bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const
 {
     wxString s;
@@ -247,7 +458,9 @@ bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const
 }
 
 
-bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
+bool wxFileTypeImpl::GetIcon(wxIcon *icon,
+                             wxString *iconFile,
+                             int *iconIndex) const
 {
 #if wxUSE_GUI
     if ( m_info ) {
@@ -280,7 +493,7 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
             }
 
             wxString strExpPath = wxExpandEnvVars(strFullPath);
-            int nIndex = wxAtoi(strIndex);
+            int nIndex = wxAtoi(strIndex) - 1 ; //bug here we need C based counting!!
 
             HICON hIcon = ExtractIcon(GetModuleHandle(NULL), strExpPath, nIndex);
             switch ( (int)hIcon ) {
@@ -292,6 +505,10 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
 
                 default:
                     icon->SetHICON((WXHICON)hIcon);
+                    if ( iconIndex )
+                        *iconIndex = nIndex;
+                    if ( iconFile )
+                        *iconFile = strFullPath;
                     return TRUE;
             }
         }
@@ -326,6 +543,15 @@ bool wxFileTypeImpl::GetDescription(wxString *desc) const
     return FALSE;
 }
 
+// helper function
+wxFileType *
+wxMimeTypesManagerImpl::CreateFileType(const wxString& filetype, const wxString& ext)
+{
+    wxFileType *fileType = new wxFileType;
+    fileType->m_impl->Init(filetype, ext);
+    return fileType;
+}
+
 // extension -> file type
 wxFileType *
 wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
@@ -348,10 +574,7 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
         // it's the default value of the key
         if ( key.QueryValue(wxT(""), strFileType) ) {
             // create the new wxFileType object
-            wxFileType *fileType = new wxFileType;
-            fileType->m_impl->Init(strFileType, ext);
-
-            return fileType;
+            return CreateFileType(strFileType, ext);
         }
         else {
             // this extension doesn't have a filetype, but it's known to the
@@ -380,12 +603,22 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
         return NULL;
     }
 
-    wxFileType *fileType = new wxFileType;
-    fileType->m_impl->Init(wxEmptyString, ext);
+    return CreateFileType(wxEmptyString, ext);
+}
+
+wxFileType *
+wxMimeTypesManagerImpl::GetOrAllocateFileTypeFromExtension(const wxString& ext)
+{
+    wxFileType *fileType = GetFileTypeFromExtension(ext);
+    if ( !fileType )
+    {
+        fileType = CreateFileType(wxEmptyString, ext);
+    }
 
     return fileType;
 }
 
+
 // MIME type -> extension -> file type
 wxFileType *
 wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
@@ -440,6 +673,93 @@ size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
     return mimetypes.GetCount();
 }
 
+// ----------------------------------------------------------------------------
+// create a new association
+// ----------------------------------------------------------------------------
+
+wxFileType *wxMimeTypesManager::Associate(const wxString& ext,
+                                          const wxString& mimetype,
+                                          const wxString& filetypeOrig,
+                                          const wxString& WXUNUSED(desc))
+{
+    wxCHECK_MSG( !ext.empty(), NULL, _T("Associate() needs extension") );
+
+    wxString extWithDot;
+    if ( ext[0u] != _T('.') )
+        extWithDot = _T('.');
+    extWithDot += ext;
+
+    wxRegKey key(wxRegKey::HKCR, extWithDot);
+    wxFileType *ft = NULL;
+    if ( !key.Exists() )
+    {
+        wxString filetype;
+
+        // create the mapping from the extension to the filetype
+        bool ok = key.Create();
+        if ( ok )
+        {
+            if ( filetypeOrig.empty() )
+            {
+                // make it up from the extension
+                filetype << extWithDot.c_str() + 1 << _T("_auto_file");
+            }
+            else
+            {
+                // just use the provided one
+                filetype = filetypeOrig;
+            }
+
+            ok = key.SetValue(_T(""), filetype);
+        }
+
+        if ( ok && !mimetype.empty() )
+        {
+            // set the MIME type
+            ok = key.SetValue(_T("Content Type"), mimetype);
+
+            if ( ok )
+            {
+                // create the MIME key
+                wxString strKey = MIME_DATABASE_KEY;
+                strKey << mimetype;
+                wxRegKey keyMIME(wxRegKey::HKCR, strKey);
+                ok = keyMIME.Create();
+
+                if ( ok )
+                {
+                    // and provide a back link to the extension
+                    ok = keyMIME.SetValue(_T("Extension"), extWithDot);
+                }
+            }
+        }
+
+        if ( ok )
+        {
+            // create the filetype key itself (it will be empty for now, but
+            // SetCommand(), SetDefaultIcon() &c will use it later)
+            wxRegKey keyFT(wxRegKey::HKCR, filetype);
+            ok = keyFT.Create();
+        }
+
+        if ( ok )
+        {
+            // ok, we've created everything correctly
+            ft = m_impl->CreateFileType(filetype, extWithDot);
+        }
+        else
+        {
+           // one of the registry operations failed
+            wxLogError(_("Failed to register extension '%s'."), ext.c_str());
+        }
+    }
+    else // key already exists
+    {
+        // FIXME we probably should return an existing file type then?
+    }
+
+    return ft;
+}
 
 #endif
   // __WIN16__