]> git.saurik.com Git - wxWidgets.git/commitdiff
MIME type manager fixes described earlier on the list:
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 24 Jan 2001 14:51:06 +0000 (14:51 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 24 Jan 2001 14:51:06 +0000 (14:51 +0000)
1. extended wxFileTypeInfo
2. moved handling of fallbacks into wxMimeTypesManager (instead of Impl)
3. added wxMimeTypesManager::Associate() and Unassociate()
4. Unix version only reads the files on demand => much faster startup

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

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

index 28a529dddab028b1b25e8efb5eb2e7a4a7ed358b..dfa9d6caa23c9bea30e044fbf8e3df70dad61b7f 100644 (file)
 // Licence:     wxWindows license (part of wxExtra library)
 /////////////////////////////////////////////////////////////////////////////
 
-#ifndef _MIMETYPE_H
-#define _MIMETYPE_H
+#ifndef _WX_MIMETYPE_H_
+#define _WX_MIMETYPE_H_
 
 #ifdef __GNUG__
-#pragma interface "mimetypebase.h"
-#endif
-
+    #pragma interface "mimetypebase.h"
+#endif // __GNUG__
 
-// fwd decls
-class wxIcon;
-class wxFileTypeImpl;
-class wxMimeTypesManagerImpl;
+// ----------------------------------------------------------------------------
+// headers and such
+// ----------------------------------------------------------------------------
 
 #include "wx/defs.h"
 
-#if wxUSE_FILE
-
 // the things we really need
 #include "wx/string.h"
 #include "wx/dynarray.h"
 
-class wxMimeTypeCmnModule;
+// fwd decls
+class WXDLLEXPORT wxIcon;
+class WXDLLEXPORT wxFileTypeImpl;
+class WXDLLEXPORT wxMimeTypesManagerImpl;
+
+/*
+    TODO: would it be more convenient to have this class?
+
+class WXDLLEXPORT wxMimeType : public wxString
+{
+public:
+    // all string ctors here
+
+    wxString GetType() const { return BeforeFirst(_T('/')); }
+    wxString GetSubType() const { return AfterFirst(_T('/')); }
+
+    void SetSubType(const wxString& subtype)
+    {
+        *this = GetType() + _T('/') + subtype;
+    }
+
+    bool Matches(const wxMimeType& wildcard)
+    {
+        // implement using wxMimeTypesManager::IsOfType()
+    }
+};
+
+*/
+
+// ----------------------------------------------------------------------------
+// wxFileTypeInfo: static container of information accessed via wxFileType.
+//
+// This class is used with wxMimeTypesManager::AddFallbacks() and Associate()
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxFileTypeInfo
+{
+public:
+    // ctors
+        // a normal item
+    wxFileTypeInfo(const char *mimeType,
+                   const char *openCmd,
+                   const char *printCmd,
+                   const char *desc,
+                   // the other parameters form a NULL terminated list of
+                   // extensions
+                   ...);
+
+        // invalid item - use this to terminate the array passed to
+        // wxMimeTypesManager::AddFallbacks
+    wxFileTypeInfo() { }
+
+    // test if this object can be used
+    bool IsValid() const { return !m_mimeType.IsEmpty(); }
+
+    // setters
+        // set the icon info
+    void SetIcon(const wxString& iconFile, int iconIndex = 0)
+    {
+        m_iconFile = iconFile;
+        m_iconIndex = iconIndex;
+    }
+        // set the short desc
+    void SetShortDesc(const wxString& shortDesc) { m_shortDesc = shortDesc; }
+
+    // accessors
+        // get the MIME type
+    const wxString& GetMimeType() const { return m_mimeType; }
+        // get the open command
+    const wxString& GetOpenCommand() const { return m_openCmd; }
+        // get the print command
+    const wxString& GetPrintCommand() const { return m_printCmd; }
+        // get the short description (only used under Win32 so far)
+    const wxString& GetShortDesc() const { return m_shortDesc; }
+        // get the long, user visible description
+    const wxString& GetDescription() const { return m_desc; }
+        // get the array of all extensions
+    const wxArrayString& GetExtensions() const { return m_exts; }
+        // get the icon info
+    const wxString& GetIconFile() const { return m_iconFile; }
+    int GetIconIndex() const { return m_iconIndex; }
+
+private:
+    wxString m_mimeType,    // the MIME type in "type/subtype" form
+             m_openCmd,     // command to use for opening the file (%s allowed)
+             m_printCmd,    // command to use for printing the file (%s allowed)
+             m_shortDesc,   // a short string used in the registry
+             m_desc;        // a free form description of this file type
+
+    // icon stuff
+    wxString m_iconFile;    // the file containing the icon
+    int      m_iconIndex;   // icon index in this file
+
+    wxArrayString m_exts;   // the extensions which are mapped on this filetype
+
+#if 0 // TODO
+    // the additional (except "open" and "print") command names and values
+    wxArrayString m_commandNames,
+                  m_commandValues;
+#endif // 0
+};
+
+WX_DECLARE_EXPORTED_OBJARRAY(wxFileTypeInfo, wxArrayFileTypeInfo);
 
+// ----------------------------------------------------------------------------
+// wxFileType: gives access to all information about the files of given type.
+//
 // This class holds information about a given "file type". File type is the
 // same as MIME type under Unix, but under Windows it corresponds more to an
 // extension than to MIME type (in fact, several extensions may correspond to a
 // file type). This object may be created in many different ways and depending
 // on how it was created some fields may be unknown so the return value of all
 // the accessors *must* be checked!
+// ----------------------------------------------------------------------------
+
 class WXDLLEXPORT wxFileType
 {
 friend class WXDLLEXPORT wxMimeTypesManagerImpl;  // it has access to m_impl
@@ -63,8 +166,8 @@ public:
         const wxString& GetMimeType() const { return m_mimetype; }
 
         // override this function in derived class
-        virtual wxString GetParamValue(const wxString& WXUNUSED(paramName)) const
-            { return ""; }
+        virtual wxString GetParamValue(const wxString& WXUNUSED(name)) const
+            { return wxEmptyString; }
 
         // virtual dtor as in any base class
         virtual ~MessageParameters() { }
@@ -73,6 +176,9 @@ public:
         wxString m_filename, m_mimetype;
     };
 
+    // ctor from static data
+    wxFileType(const wxFileTypeInfo& ftInfo);
+
     // accessors: all of them return true if the corresponding information
     // could be retrieved/found, false otherwise (and in this case all [out]
     // parameters are unchanged)
@@ -104,34 +210,11 @@ public:
     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
+    // remove the association for this filetype from the system MIME database:
+    // notice that it will only work if the association is defined in the user
+    // file/registry part, we will never modify the system-wide settings
     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
@@ -150,68 +233,32 @@ private:
     wxFileType(const wxFileType&);
     wxFileType& operator=(const wxFileType&);
 
-    wxFileTypeImpl *m_impl;
-};
-
-// This class is only used wuth wxMimeTypesManager::AddFallbacks() and is meant
-// just as the container for the wxFileType data.
-class WXDLLEXPORT wxFileTypeInfo
-{
-public:
-    // ctors
-        // a normal item
-    wxFileTypeInfo(const char *mimeType,
-                   const char *openCmd,
-                   const char *printCmd,
-                   const char *desc,
-                   // the other parameters form a NULL terminated list of
-                   // extensions
-                   ...);
-
-        // invalid item - use this to terminate the array passed to
-        // wxMimeTypesManager::AddFallbacks
-    wxFileTypeInfo() { }
-
-    bool IsValid() const { return !m_mimeType.IsEmpty(); }
-
-    // accessors
-        // get the MIME type
-    const wxString& GetMimeType() const { return m_mimeType; }
-        // get the open command
-    const wxString& GetOpenCommand() const { return m_openCmd; }
-        // get the print command
-    const wxString& GetPrintCommand() const { return m_printCmd; }
-        // get the description
-    const wxString& GetDescription() const { return m_desc; }
-        // get the array of all extensions
-    const wxArrayString& GetExtensions() const { return m_exts; }
-
-private:
-    wxString m_mimeType,    // the MIME type in "type/subtype" form
-             m_openCmd,     // command to use for opening the file (%s allowed)
-             m_printCmd,    // command to use for printing the file (%s allowed)
-             m_desc;        // a free form description of this file type
+    // the static container of wxFileType data: if it's not NULL, it means that
+    // this object is used as fallback only
+    const wxFileTypeInfo *m_info;
 
-    wxArrayString m_exts;   // the extensions which are mapped on this filetype
+    // the object which implements the real stuff like reading and writing
+    // to/from system MIME database
+    wxFileTypeImpl *m_impl;
 };
 
-WX_DECLARE_EXPORTED_OBJARRAY(wxFileTypeInfo, wxArrayFileTypeInfo);
-
-
+// ----------------------------------------------------------------------------
+// wxMimeTypesManager: interface to system MIME database.
+//
 // This class accesses the information about all known MIME types and allows
 // the application to retrieve information (including how to handle data of
 // given type) about them.
-//
-// NB: currently it doesn't support modifying MIME database (read-only access).
+// ----------------------------------------------------------------------------
+
 class WXDLLEXPORT wxMimeTypesManager
 {
 public:
     // static helper functions
     // -----------------------
 
-        // check if the given MIME type is the same as the other one: the second
-        // argument may contain wildcards ('*'), but not the first. If the
-        // types are equal or if the mimeType matches wildcard the function
+        // check if the given MIME type is the same as the other one: the
+        // second argument may contain wildcards ('*'), but not the first. If
+        // the types are equal or if the mimeType matches wildcard the function
         // returns TRUE, otherwise it returns FALSE
     static bool IsOfType(const wxString& mimeType, const wxString& wildcard);
 
@@ -224,7 +271,6 @@ 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);
 
@@ -251,19 +297,19 @@ public:
     // ReadMailcap(filenameWithDefaultTypes, TRUE /* use as fallback */) to
     // achieve the same goal, but this requires having this info in a file).
     //
-    // It isn't possible (currently) to provide fallback icons using this
-    // function.
-    //
-    // The filetypes array should be terminated by a NULL entry
+    // The filetypes array should be terminated by either NULL entry or an
+    // invalid wxFileTypeInfo (i.e. the one created with default ctor)
     void AddFallbacks(const wxFileTypeInfo *filetypes);
+    void AddFallback(const wxFileTypeInfo& ft) { m_fallbacks.Add(ft); }
+
+    // create or remove associations
 
-    // 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);
+        // create a new association using the fields of wxFileTypeInfo (at least
+        // the MIME type and the extension should be set)
+    wxFileType *Associate(const wxFileTypeInfo& ftInfo);
+
+        // undo Associate()
+    bool Unassociate(wxFileType *ft) { return ft->Unassociate(); }
 
     // dtor (not virtual, shouldn't be derived from)
     ~wxMimeTypesManager();
@@ -273,6 +319,11 @@ private:
     wxMimeTypesManager(const wxMimeTypesManager&);
     wxMimeTypesManager& operator=(const wxMimeTypesManager&);
 
+    // the fallback info which is used if the information is not found in the
+    // real system database
+    wxArrayFileTypeInfo m_fallbacks;
+
+    // the object working with the system MIME database
     wxMimeTypesManagerImpl *m_impl;
 
     // if m_impl is NULL, create one
@@ -290,9 +341,6 @@ private:
 WXDLLEXPORT_DATA(extern wxMimeTypesManager *) wxTheMimeTypesManager;
 
 #endif
-  // wxUSE_FILE
-
-#endif
-  //_MIMETYPE_H
+  //_WX_MIMETYPE_H_
 
 /* vi: set cin tw=80 ts=4 sw=4: */
index 4a15a2b72f0c9905a844e190561baa9d8a60416a..d931a52d4f374c6857df4d3ce3b8c58a06583c00 100644 (file)
 #define _MIMETYPE_IMPL_H
 
 #ifdef    __GNUG__
-#pragma interface "mimetype.h"
+    #pragma interface "mimetype.h"
 #endif
 
 #include "wx/defs.h"
 
 #include "wx/mimetype.h"
 
+// ----------------------------------------------------------------------------
+// wxFileTypeImpl is the MSW version of wxFileType, this is a private class
+// and is never used directly by the application
+// ----------------------------------------------------------------------------
 
 class WXDLLEXPORT wxFileTypeImpl
 {
 public:
     // ctor
-    wxFileTypeImpl() { m_info = NULL; }
+    wxFileTypeImpl() { }
 
     // one of these Init() function must be called (ctor can't take any
     // arguments because it's common)
@@ -34,11 +38,6 @@ public:
         // we will read all other data from the registry
     void Init(const wxString& strFileType, const wxString& ext);
 
-        // initialize us with a wxFileTypeInfo object - it contains all the
-        // data
-    void Init(const wxFileTypeInfo& info)
-        { m_info = &info; }
-
     // implement accessor functions
     bool GetExtensions(wxArrayString& extensions);
     bool GetMimeType(wxString *mimeType) const;
@@ -53,11 +52,17 @@ public:
     size_t GetAllCommands(wxArrayString * verbs, wxArrayString * commands,
                           const wxFileType::MessageParameters& params) const;
 
+    bool Unassociate();
+
+    // these methods are not publicly accessible (as wxMimeTypesManager
+    // doesn't know about them), and generally not very useful - they could be
+    // removed in the (near) future
     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 RemoveOpenCommand();
     bool RemoveCommand(const wxString& verb);
     bool RemoveMimeType();
     bool RemoveDefaultIcon();
@@ -74,8 +79,6 @@ private:
     // 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;
 };
@@ -100,13 +103,11 @@ public:
     bool ReadMimeTypes(const wxString& filename)
         { return TRUE; }
 
-    void AddFallback(const wxFileTypeInfo& ft) { m_fallbacks.Add(ft); }
+    // create a new filetype association
+    wxFileType *Associate(const wxFileTypeInfo& ftInfo);
 
     // create a new filetype with the given name and extension
     wxFileType *CreateFileType(const wxString& filetype, const wxString& ext);
-
-private:
-    wxArrayFileTypeInfo m_fallbacks;
 };
 
 
index 3b7f478fd4fd525c4c891b2bd3f46bbff8c302bd..28407b23b697181e8569de19076530487de7a719 100644 (file)
@@ -30,14 +30,13 @@ WX_DEFINE_ARRAY(MailCapEntry *, ArrayTypeEntries);
 // this is the real wxMimeTypesManager for Unix
 class WXDLLEXPORT wxMimeTypesManagerImpl
 {
-friend class WXDLLEXPORT wxFileTypeImpl; // give it access to m_aXXX variables
-
 public:
-    // ctor loads all info into memory for quicker access later on
-    // TODO it would be nice to load them all, but parse on demand only...
+    // ctor and dtor
     wxMimeTypesManagerImpl();
     ~wxMimeTypesManagerImpl();
-    
+
+    // load all data into memory - done when it is needed for the first time
+    void Initialize();
 
     // implement containing class functions
     wxFileType *GetFileTypeFromExtension(const wxString& ext);
@@ -60,6 +59,9 @@ public:
                         const wxString& strTest,
                         const wxString& strDesc);
 
+    // add a new record to the user .mailcap/.mime.types files
+    wxFileType *Associate(const wxFileTypeInfo& ftInfo);
+
     // accessors
         // get the string containing space separated extensions for the given
         // file type
@@ -69,13 +71,28 @@ public:
     static ArrayIconHandlers& GetIconHandlers();
 
 private:
+    void InitIfNeeded()
+    {
+        if ( !m_initialized ) {
+            // set the flag first to prevent recursion
+            m_initialized = TRUE;
+            Initialize();
+        }
+    }
+
     wxArrayString m_aTypes,         // MIME types
                   m_aDescriptions,  // descriptions (just some text)
                   m_aExtensions;    // space separated list of extensions
     ArrayTypeEntries m_aEntries;    // commands and tests for this file type
 
+    // are we initialized?
+    bool m_initialized;
+
     // head of the linked list of the icon handlers
     static ArrayIconHandlers ms_iconHandlers;
+
+    // give it access to m_aXXX variables
+    friend class WXDLLEXPORT wxFileTypeImpl;
 };
 
 
@@ -108,6 +125,9 @@ public:
         return GetExpandedCommand(printCmd, params, FALSE);
     }
 
+    // remove the record for this file type
+    bool Unassociate();
+
 private:
     // get the entry which passes the test (may return NULL)
     MailCapEntry *GetEntry(const wxFileType::MessageParameters& params) const;
@@ -121,8 +141,6 @@ private:
     wxArrayInt              m_index; // in the wxMimeTypesManagerImpl arrays
 };
 
-
-
 #endif
   // wxUSE_FILE
 
index 395b6d6f2fa42799e082b40a23db8134a62c6d50..74e84c5c78d500b3f8ae7b4be0025cbdffc3a851 100644 (file)
 //#define TEST_EXECUTE
 //#define TEST_FILE
 //#define TEST_FILECONF
-#define TEST_FILENAME
+//#define TEST_FILENAME
 //#define TEST_FTP
 //#define TEST_HASH
 //#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
@@ -813,6 +813,8 @@ static wxMimeTypesManager g_mimeManager;
 
 static void TestMimeEnum()
 {
+    wxPuts(_T("*** Testing wxMimeTypesManager::EnumAllFileTypes() ***\n"));
+
     wxArrayString mimetypes;
 
     size_t count = g_mimeManager.EnumAllFileTypes(mimetypes);
@@ -908,24 +910,24 @@ 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)
-                     );
+    wxFileTypeInfo ftInfo(
+                            _T("application/x-xyz"),
+                            _T("xyzview '%s'"), // open cmd
+                            _T(""),             // print cmd
+                            _T("XYZ File")  // description
+                            _T(".xyz"),     // extensions
+                            NULL            // end of extensions
+                         );
+    ftInfo.SetShortDesc(_T("XYZFile")); // used under Win32 only
+
+    wxFileType *ft = g_mimeManager.Associate(ftInfo);
     if ( !ft )
     {
         wxPuts(_T("ERROR: failed to create association!"));
     }
     else
     {
-        if ( !ft->SetOpenCommand(_T("myprogram")) )
-        {
-            wxPuts(_T("ERROR: failed to set open command!"));
-        }
-
+        // TODO: read it back
         delete ft;
     }
 }
@@ -4089,13 +4091,14 @@ int main(int argc, char **argv)
 
 #ifdef TEST_MIME
     wxLog::AddTraceMask(_T("mime"));
-    if ( 0 )
+    if ( 1 )
     {
         TestMimeEnum();
         TestMimeOverride();
         TestMimeFilename();
     }
-    TestMimeAssociate();
+    else
+        TestMimeAssociate();
 #endif // TEST_MIME
 
 #ifdef TEST_INFO_FUNCTIONS
index 353a604b7a8dc63ac1a51d803749814c330f271f..278d3bc4afce2f17b63a18c3285f6da854569a4c 100644 (file)
 // Licence:     wxWindows license (part of wxExtra library)
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 #ifdef    __GNUG__
-#pragma implementation "mimetypebase.h"
+    #pragma implementation "mimetypebase.h"
 #endif
 
 // for compilers that support precompilation, includes "wx.h".
@@ -26,8 +34,6 @@
   #include "wx/defs.h"
 #endif
 
-#if (wxUSE_FILE && wxUSE_TEXTFILE) || defined(__WXMSW__)
-
 #ifndef WX_PRECOMP
   #include "wx/string.h"
   #if wxUSE_GUI
   #endif
 #endif //WX_PRECOMP
 
-// Doesn't compile in WIN16 mode
-#ifndef __WIN16__
-
 #include "wx/log.h"
 #include "wx/file.h"
 #include "wx/intl.h"
 #include "wx/dynarray.h"
 #include "wx/confbase.h"
 
-#ifdef __WXMSW__
-    #include "wx/msw/registry.h"
-    #include "windows.h"
-#elif defined(__UNIX__)  || defined(__WXPM__)
-    #include "wx/ffile.h"
-    #include "wx/textfile.h"
-    #include "wx/dir.h"
-    #include "wx/utils.h"
-    #include "wx/tokenzr.h"
-#endif // OS
-
 #include "wx/mimetype.h"
 
 // other standard headers
 #include <ctype.h>
 
-// in case we're compiling in non-GUI mode
-class WXDLLEXPORT wxIcon;
-
-
 // implementation classes:
-
 #if defined(__WXMSW__)
     #include "wx/msw/mimetype.h"
 #elif defined (__WXMAC__)
@@ -115,7 +102,6 @@ wxFileTypeInfo::wxFileTypeInfo(const char *mimeType,
 #include "wx/arrimpl.cpp"
 WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo);
 
-
 // ============================================================================
 // implementation of the wrapper classes
 // ============================================================================
@@ -124,6 +110,7 @@ WX_DEFINE_OBJARRAY(wxArrayFileTypeInfo);
 // wxFileType
 // ----------------------------------------------------------------------------
 
+/* static */
 wxString wxFileType::ExpandCommand(const wxString& command,
                                    const wxFileType::MessageParameters& params)
 {
@@ -206,8 +193,15 @@ wxString wxFileType::ExpandCommand(const wxString& command,
     return str;
 }
 
+wxFileType::wxFileType(const wxFileTypeInfo& info)
+{
+    m_info = &info;
+    m_impl = NULL;
+}
+
 wxFileType::wxFileType()
 {
+    m_info = NULL;
     m_impl = new wxFileTypeImpl;
 }
 
@@ -218,16 +212,39 @@ wxFileType::~wxFileType()
 
 bool wxFileType::GetExtensions(wxArrayString& extensions)
 {
+    if ( m_info )
+    {
+        extensions = m_info->GetExtensions();
+        return TRUE;
+    }
+
     return m_impl->GetExtensions(extensions);
 }
 
 bool wxFileType::GetMimeType(wxString *mimeType) const
 {
+    wxCHECK_MSG( mimeType, FALSE, _T("invalid parameter in GetMimeType") );
+
+    if ( m_info )
+    {
+        *mimeType = m_info->GetMimeType();
+
+        return TRUE;
+    }
+
     return m_impl->GetMimeType(mimeType);
 }
 
 bool wxFileType::GetMimeTypes(wxArrayString& mimeTypes) const
 {
+    if ( m_info )
+    {
+        mimeTypes.Clear();
+        mimeTypes.Add(m_info->GetMimeType());
+
+        return TRUE;
+    }
+
     return m_impl->GetMimeTypes(mimeTypes);
 }
 
@@ -235,6 +252,24 @@ bool wxFileType::GetIcon(wxIcon *icon,
                          wxString *iconFile,
                          int *iconIndex) const
 {
+    if ( m_info )
+    {
+        if ( iconFile )
+            *iconFile = m_info->GetIconFile();
+        if ( iconIndex )
+            *iconIndex = m_info->GetIconIndex();
+
+#if wxUSE_GUI
+        if ( icon && !m_info->GetIconFile().empty() )
+        {
+            // FIXME: what about the index?
+            icon->LoadFile(m_info->GetIconFile());
+        }
+#endif // wxUSE_GUI
+
+        return TRUE;
+    }
+
 #ifdef __WXMSW__
     return m_impl->GetIcon(icon, iconFile, iconIndex);
 #else
@@ -244,6 +279,15 @@ bool wxFileType::GetIcon(wxIcon *icon,
 
 bool wxFileType::GetDescription(wxString *desc) const
 {
+    wxCHECK_MSG( desc, FALSE, _T("invalid parameter in GetDescription") );
+
+    if ( m_info )
+    {
+        *desc = m_info->GetDescription();
+
+        return TRUE;
+    }
+
     return m_impl->GetDescription(desc);
 }
 
@@ -251,6 +295,15 @@ bool
 wxFileType::GetOpenCommand(wxString *openCmd,
                            const wxFileType::MessageParameters& params) const
 {
+    wxCHECK_MSG( openCmd, FALSE, _T("invalid parameter in GetOpenCommand") );
+
+    if ( m_info )
+    {
+        *openCmd = ExpandCommand(m_info->GetOpenCommand(), params);
+
+        return TRUE;
+    }
+
     return m_impl->GetOpenCommand(openCmd, params);
 }
 
@@ -258,6 +311,15 @@ bool
 wxFileType::GetPrintCommand(wxString *printCmd,
                             const wxFileType::MessageParameters& params) const
 {
+    wxCHECK_MSG( printCmd, FALSE, _T("invalid parameter in GetPrintCommand") );
+
+    if ( m_info )
+    {
+        *printCmd = ExpandCommand(m_info->GetPrintCommand(), params);
+
+        return TRUE;
+    }
+
     return m_impl->GetPrintCommand(printCmd, params);
 }
 
@@ -278,7 +340,7 @@ size_t wxFileType::GetAllCommands(wxArrayString *verbs,
     // about
     size_t count = 0;
     wxString cmd;
-    if ( m_impl->GetOpenCommand(&cmd, params) )
+    if ( GetOpenCommand(&cmd, params) )
     {
         if ( verbs )
             verbs->Add(_T("Open"));
@@ -301,109 +363,16 @@ size_t wxFileType::GetAllCommands(wxArrayString *verbs,
 #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()
+bool wxFileType::Unassociate()
 {
-#ifdef __WXMSW__
-    return m_impl->RemoveDefaultIcon();
+#if defined(__WXMSW__) || defined(__UNIX__)
+    return m_impl->Unassociate();
 #else
-    wxFAIL_MSG(_T("not implemented"));
-
+    wxFAIL_MSG( _T("not implemented") ); // TODO
     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
 // ----------------------------------------------------------------------------
@@ -421,7 +390,8 @@ bool wxMimeTypesManager::IsOfType(const wxString& mimeType,
                   wxT("first MIME type can't contain wildcards") );
 
     // all comparaisons are case insensitive (2nd arg of IsSameAs() is FALSE)
-    if ( wildcard.BeforeFirst(wxT('/')).IsSameAs(mimeType.BeforeFirst(wxT('/')), FALSE) )
+    if ( wildcard.BeforeFirst(wxT('/')).
+            IsSameAs(mimeType.BeforeFirst(wxT('/')), FALSE) )
     {
         wxString strSubtype = wildcard.AfterFirst(wxT('/'));
 
@@ -447,45 +417,65 @@ wxMimeTypesManager::~wxMimeTypesManager()
 }
 
 wxFileType *
-wxMimeTypesManager::GetFileTypeFromExtension(const wxString& ext)
+wxMimeTypesManager::Associate(const wxFileTypeInfo& ftInfo)
 {
     EnsureImpl();
-    return m_impl->GetFileTypeFromExtension(ext);
+
+#if defined(__WXMSW__) || defined(__UNIX__)
+    return m_impl->Associate(ftInfo);
+#else // other platforms
+    wxFAIL_MSG( _T("not implemented") ); // TODO
+    return NULL;
+#endif // platforms
 }
 
 wxFileType *
-wxMimeTypesManager::GetOrAllocateFileTypeFromExtension(const wxString& ext)
+wxMimeTypesManager::GetFileTypeFromExtension(const wxString& ext)
 {
     EnsureImpl();
+    wxFileType *ft = m_impl->GetFileTypeFromExtension(ext);
+
+    if ( !ft ) {
+        // check the fallbacks
+        //
+        // TODO linear search is potentially slow, perhaps we should use a
+        //       sorted array?
+        size_t count = m_fallbacks.GetCount();
+        for ( size_t n = 0; n < count; n++ ) {
+            if ( m_fallbacks[n].GetExtensions().Index(ext) != wxNOT_FOUND ) {
+                ft = new wxFileType(m_fallbacks[n]);
+
+                break;
+            }
+        }
+    }
 
-#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__
+    return ft;
 }
 
-
 wxFileType *
 wxMimeTypesManager::GetFileTypeFromMimeType(const wxString& mimeType)
 {
     EnsureImpl();
-    return m_impl->GetFileTypeFromMimeType(mimeType);
+    wxFileType *ft = m_impl->GetFileTypeFromMimeType(mimeType);
+
+    if ( ft ) {
+        // check the fallbacks
+        //
+        // TODO linear search is potentially slow, perhaps we should use a sorted
+        //      array?
+        size_t count = m_fallbacks.GetCount();
+        for ( size_t n = 0; n < count; n++ ) {
+            if ( wxMimeTypesManager::IsOfType(mimeType,
+                                              m_fallbacks[n].GetMimeType()) ) {
+                ft = new wxFileType(m_fallbacks[n]);
+
+                break;
+            }
+        }
+    }
+
+    return ft;
 }
 
 bool wxMimeTypesManager::ReadMailcap(const wxString& filename, bool fallback)
@@ -503,27 +493,37 @@ bool wxMimeTypesManager::ReadMimeTypes(const wxString& filename)
 void wxMimeTypesManager::AddFallbacks(const wxFileTypeInfo *filetypes)
 {
     EnsureImpl();
-    for ( const wxFileTypeInfo *ft = filetypes; ft->IsValid(); ft++ ) {
-        m_impl->AddFallback(*ft);
+    for ( const wxFileTypeInfo *ft = filetypes; ft && ft->IsValid(); ft++ ) {
+        AddFallback(*ft);
     }
 }
 
 size_t wxMimeTypesManager::EnumAllFileTypes(wxArrayString& mimetypes)
 {
     EnsureImpl();
-    return m_impl->EnumAllFileTypes(mimetypes);
-}
+    size_t countAll = m_impl->EnumAllFileTypes(mimetypes);
+
+    // add the fallback filetypes
+    size_t count = m_fallbacks.GetCount();
+    for ( size_t n = 0; n < count; n++ ) {
+        if ( mimetypes.Index(m_fallbacks[n].GetMimeType()) == wxNOT_FOUND ) {
+            mimetypes.Add(m_fallbacks[n].GetMimeType());
+            countAll++;
+        }
+    }
 
+    return countAll;
+}
 
 // ----------------------------------------------------------------------------
-// global data
+// global data and wxMimeTypeCmnModule
 // ----------------------------------------------------------------------------
 
 // private object
 static wxMimeTypesManager gs_mimeTypesManager;
 
 // and public pointer
-wxMimeTypesManager * wxTheMimeTypesManager = &gs_mimeTypesManager;
+wxMimeTypesManager *wxTheMimeTypesManager = &gs_mimeTypesManager;
 
 class wxMimeTypeCmnModule: public wxModule
 {
@@ -545,8 +545,3 @@ public:
 
 IMPLEMENT_DYNAMIC_CLASS(wxMimeTypeCmnModule, wxModule)
 
-#endif
-  // wxUSE_FILE && wxUSE_TEXTFILE
-
-#endif
-  // __WIN16__
index f4d69dab1ab93b8bd049b0c7d3aa9a42cce328c2..cdd77116e8c53f278992a1f0f2fe5f943f5671b2 100644 (file)
@@ -20,7 +20,7 @@
   #pragma hdrstop
 #endif
 
-// Doesn't compile in WIN16 mode
+// this is Win32 only code
 #ifndef __WIN16__
 
 #ifndef WX_PRECOMP
@@ -172,122 +172,10 @@ bool wxFileTypeImpl::EnsureExtKeyExists()
     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
+// get the command to use
 // ----------------------------------------------------------------------------
 
-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
@@ -377,13 +265,7 @@ wxFileTypeImpl::GetOpenCommand(wxString *openCmd,
                                const wxFileType::MessageParameters& params)
                                const
 {
-    wxString cmd;
-    if ( m_info ) {
-        cmd = m_info->GetOpenCommand();
-    }
-    else {
-        cmd = GetCommand(wxT("open"));
-    }
+    wxString cmd = GetCommand(wxT("open"));
 
     *openCmd = wxFileType::ExpandCommand(cmd, params);
 
@@ -395,28 +277,21 @@ wxFileTypeImpl::GetPrintCommand(wxString *printCmd,
                                 const wxFileType::MessageParameters& params)
                                 const
 {
-    wxString cmd;
-    if ( m_info ) {
-        cmd = m_info->GetPrintCommand();
-    }
-    else {
-        cmd = GetCommand(wxT("print"));
-    }
+    wxString cmd = GetCommand(wxT("print"));
 
     *printCmd = wxFileType::ExpandCommand(cmd, params);
 
     return !printCmd->IsEmpty();
 }
 
+// ----------------------------------------------------------------------------
+// getting other stuff
+// ----------------------------------------------------------------------------
+
 // TODO this function is half implemented
 bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
 {
-    if ( m_info ) {
-        extensions = m_info->GetExtensions();
-
-        return TRUE;
-    }
-    else if ( m_ext.IsEmpty() ) {
+    if ( m_ext.IsEmpty() ) {
         // the only way to get the list of extensions from the file type is to
         // scan through all extensions in the registry - too slow...
         return FALSE;
@@ -432,13 +307,6 @@ bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
 
 bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
 {
-    if ( m_info ) {
-        // we already have it
-        *mimeType = m_info->GetMimeType();
-
-        return TRUE;
-    }
-
     // suppress possible error messages
     wxLogNull nolog;
     wxRegKey key(wxRegKey::HKCR, m_ext);
@@ -466,11 +334,6 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon,
                              int *iconIndex) const
 {
 #if wxUSE_GUI
-    if ( m_info ) {
-        // we don't have icons in the fallback resources
-        return FALSE;
-    }
-
     wxString strIconKey;
     strIconKey << m_strFileType << wxT("\\DefaultIcon");
 
@@ -496,7 +359,8 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon,
             }
 
             wxString strExpPath = wxExpandEnvVars(strFullPath);
-            int nIndex = wxAtoi(strIndex) - 1 ; //bug here we need C based counting!!
+            // here we need C based counting!
+            int nIndex = wxAtoi(strIndex) - 1 ;
 
             HICON hIcon = ExtractIcon(GetModuleHandle(NULL), strExpPath, nIndex);
             switch ( (int)hIcon ) {
@@ -525,13 +389,6 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon,
 
 bool wxFileTypeImpl::GetDescription(wxString *desc) const
 {
-    if ( m_info ) {
-        // we already have it
-        *desc = m_info->GetDescription();
-
-        return TRUE;
-    }
-
     // suppress possible error messages
     wxLogNull nolog;
     wxRegKey key(wxRegKey::HKCR, m_strFileType);
@@ -587,19 +444,6 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
         }
     }
 
-    // check the fallbacks
-    // TODO linear search is potentially slow, perhaps we should use a sorted
-    //      array?
-    size_t count = m_fallbacks.GetCount();
-    for ( size_t n = 0; n < count; n++ ) {
-        if ( m_fallbacks[n].GetExtensions().Index(ext) != wxNOT_FOUND ) {
-            wxFileType *fileType = new wxFileType;
-            fileType->m_impl->Init(m_fallbacks[n]);
-
-            return fileType;
-        }
-    }
-
     if ( !knownExtension )
     {
         // unknown extension
@@ -640,20 +484,6 @@ wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
         }
     }
 
-    // check the fallbacks
-    // TODO linear search is potentially slow, perhaps we should use a sorted
-    //      array?
-    size_t count = m_fallbacks.GetCount();
-    for ( size_t n = 0; n < count; n++ ) {
-        if ( wxMimeTypesManager::IsOfType(mimeType,
-                                          m_fallbacks[n].GetMimeType()) ) {
-            wxFileType *fileType = new wxFileType;
-            fileType->m_impl->Init(m_fallbacks[n]);
-
-            return fileType;
-        }
-    }
-
     // unknown MIME type
     return NULL;
 }
@@ -680,12 +510,15 @@ size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
 // create a new association
 // ----------------------------------------------------------------------------
 
-wxFileType *wxMimeTypesManager::Associate(const wxString& ext,
-                                          const wxString& mimetype,
-                                          const wxString& filetypeOrig,
-                                          const wxString& WXUNUSED(desc))
+wxFileType *wxMimeTypesManager::Associate(const wxFileTypeInfo& ftInfo)
 {
-    wxCHECK_MSG( !ext.empty(), NULL, _T("Associate() needs extension") );
+    wxCHECK_MSG( !ftInfo.GetExtensions().IsEmpty(), NULL,
+                 _T("Associate() needs extension") );
+
+    const wxString& ext = ftInfo.GetExtensions()[0u];
+
+    wxCHECK_MSG( !ext.empty(), NULL,
+                 _T("Associate() needs non empty extension") );
 
     wxString extWithDot;
     if ( ext[0u] != _T('.') )
@@ -702,6 +535,7 @@ wxFileType *wxMimeTypesManager::Associate(const wxString& ext,
         bool ok = key.Create();
         if ( ok )
         {
+            const wxString& filetypeOrig = ftInfo.GetShortDesc();
             if ( filetypeOrig.empty() )
             {
                 // make it up from the extension
@@ -716,6 +550,7 @@ wxFileType *wxMimeTypesManager::Associate(const wxString& ext,
             ok = key.SetValue(_T(""), filetype);
         }
 
+        const wxString& mimetype = ftInfo.GetMimeType();
         if ( ok && !mimetype.empty() )
         {
             // set the MIME type
@@ -764,5 +599,147 @@ wxFileType *wxMimeTypesManager::Associate(const wxString& ext,
     return ft;
 }
 
+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::Unassociate()
+{
+    bool result = TRUE;
+    if ( !RemoveOpenCommand() )
+        result = FALSE;
+    if ( !RemoveDefaultIcon() )
+        result = FALSE;
+    if ( !RemoveMimeType() )
+        result = FALSE;
+
+    if ( result )
+    {
+        // delete the root key
+        wxRegKey key(wxRegKey::HKCR, m_ext);
+        if ( key.Exists() )
+            result = key.DeleteSelf();
+    }
+
+    return result;
+}
+
+bool wxFileTypeImpl::RemoveOpenCommand()
+{
+   return RemoveCommand(_T("open"));
+}
+
+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();
+}
+
 #endif
   // __WIN16__
index c6f51fb5423401678de133cf755e90a1e236be3d..ff2bb4218a962e812771f9281e2c2d65cf1b1b4e 100644 (file)
@@ -82,12 +82,12 @@ static bool IsKnownUnimportantField(const wxString& field);
 // private classes
 // ----------------------------------------------------------------------------
 
-
-// this class uses both mailcap and mime.types to gather information about file
+// This class uses both mailcap and mime.types to gather information about file
 // types.
 //
-// The information about mailcap file was extracted from metamail(1) sources and
-// documentation.
+// The information about mailcap file was extracted from metamail(1) sources
+// and documentation and subsequently revised when I found the RFC 1524
+// describing it.
 //
 // Format of mailcap file: spaces are ignored, each line is either a comment
 // (starts with '#') or a line of the form <field1>;<field2>;...;<fieldN>.
@@ -114,7 +114,8 @@ static bool IsKnownUnimportantField(const wxString& field);
 //  * print=xxx is the command to be used to print (and not view) the data of
 //    this type (parameter/filename expansion is done here too)
 //  * edit=xxx is the command to open/edit the data of this type
-//  * needsterminal means that a new console must be created for the viewer
+//  * needsterminal means that a new interactive console must be created for
+//    the viewer
 //  * copiousoutput means that the viewer doesn't interact with the user but
 //    produces (possibly) a lof of lines of output on stdout (i.e. "cat" is a
 //    good example), thus it might be a good idea to use some kind of paging
@@ -123,7 +124,7 @@ static bool IsKnownUnimportantField(const wxString& field);
 //  * compose and composetyped fields are used to determine the program to be
 //    called to create a new message pert in the specified format (unused).
 //
-// Parameter/filename xpansion:
+// Parameter/filename expansion:
 //  * %s is replaced with the (full) file name
 //  * %t is replaced with MIME type/subtype of the entry
 //  * for multipart type only %n is replaced with the nnumber of parts and %F is
@@ -132,18 +133,20 @@ static bool IsKnownUnimportantField(const wxString& field);
 //  * %{parameter} is replaced with the value of parameter taken from
 //    Content-type header line of the message.
 //
-// FIXME any docs with real descriptions of these files??
 //
 // There are 2 possible formats for mime.types file, one entry per line (used
-// for global mime.types) and "expanded" format where an entry takes multiple
-// lines (used for users mime.types).
+// for global mime.types and called Mosaic format) and "expanded" format where
+// an entry takes multiple lines (used for users mime.types and called
+// Netscape format).
 //
 // For both formats spaces are ignored and lines starting with a '#' are
 // comments. Each record has one of two following forms:
 //  a) for "brief" format:
 //      <mime type>  <space separated list of extensions>
 //  b) for "expanded" format:
-//      type=<mime type> \ desc="<description>" \ exts="ext"
+//      type=<mime type> \ 
+//      desc="<description>" \ 
+//      exts="<comma separated list of extensions>"
 //
 // We try to autodetect the format of mime.types: if a non-comment line starts
 // with "type=" we assume the second format, otherwise the first one.
@@ -636,7 +639,7 @@ bool wxGNOMEIconHandler::GetIcon(const wxString& mimetype,
         *icon = icn;
 #else
     // helpful for testing in console mode
-    wxLogDebug(_T("Found GNOME icon for '%s': '%s'\n"),
+    wxLogTrace(TRACE_MIME, _T("Found GNOME icon for '%s': '%s'\n"),
                mimetype.c_str(), iconname.c_str());
 #endif
 
@@ -882,7 +885,7 @@ bool wxKDEIconHandler::GetIcon(const wxString& mimetype,
         *icon = icn;
 #else
     // helpful for testing in console mode
-    wxLogDebug(_T("Found KDE icon for '%s': '%s'\n"),
+    wxLogTrace(TRACE_MIME, _T("Found KDE icon for '%s': '%s'\n"),
                mimetype.c_str(), iconname.c_str());
 #endif
 
@@ -1041,11 +1044,22 @@ ArrayIconHandlers& wxMimeTypesManagerImpl::GetIconHandlers()
     return ms_iconHandlers;
 }
 
-// read system and user mailcaps (TODO implement mime.types support)
 wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
+{
+    m_initialized = FALSE;
+}
+
+// read system and user mailcaps and other files
+void wxMimeTypesManagerImpl::Initialize()
 {
     // directories where we look for mailcap and mime.types by default
     // (taken from metamail(1) sources)
+    //
+    // although RFC 1524 specifies the search path of
+    // /etc/:/usr/etc:/usr/local/etc only, it doesn't hurt to search in more
+    // places - OTOH, the RFC also says that this path can be changed with
+    // MAILCAPS environment variable (containing the colon separated full
+    // filenames to try) which is not done yet (TODO?)
     static const wxChar *aStandardLocations[] =
     {
         wxT("/etc"),
@@ -1096,13 +1110,23 @@ wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
 wxMimeTypesManagerImpl::~wxMimeTypesManagerImpl()
 {
     size_t cnt = m_aEntries.GetCount();
-    for (size_t i = 0; i < cnt; i++) delete m_aEntries[i];
+    for (size_t i = 0; i < cnt; i++)
+        delete m_aEntries[i];
 }
 
+wxFileType *
+wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
+{
+    wxFAIL_MSG( _T("unimplemented") ); // TODO
+
+    return NULL;
+}
 
 wxFileType *
 wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
 {
+    InitIfNeeded();
+
     wxFileType *fileType = NULL;  
     size_t count = m_aExtensions.GetCount();
     for ( size_t n = 0; n < count; n++ ) {
@@ -1127,6 +1151,8 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
 wxFileType *
 wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
 {
+    InitIfNeeded();
+
     // mime types are not case-sensitive
     wxString mimetype(mimeType);
     mimetype.MakeLower();
@@ -1163,6 +1189,8 @@ wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
 
 void wxMimeTypesManagerImpl::AddFallback(const wxFileTypeInfo& filetype)
 {
+    InitIfNeeded();
+
     wxString extensions;
     const wxArrayString& exts = filetype.GetExtensions();
     size_t nExts = exts.GetCount();
@@ -1188,6 +1216,8 @@ void wxMimeTypesManagerImpl::AddMimeTypeInfo(const wxString& strMimeType,
                                              const wxString& strExtensions,
                                              const wxString& strDesc)
 {
+    InitIfNeeded();
+
     int index = m_aTypes.Index(strMimeType);
     if ( index == wxNOT_FOUND ) {
         // add a new entry
@@ -1211,6 +1241,8 @@ void wxMimeTypesManagerImpl::AddMailcapInfo(const wxString& strType,
                                             const wxString& strTest,
                                             const wxString& strDesc)
 {
+    InitIfNeeded();
+
     MailCapEntry *entry = new MailCapEntry(strOpenCmd, strPrintCmd, strTest);
 
     int nIndex = m_aTypes.Index(strType);
@@ -1364,9 +1396,8 @@ bool wxMimeTypesManagerImpl::ReadMimeTypes(const wxString& strFileName)
             }
         }
 
-        // although it doesn't seem to be covered by RFCs, some programs
-        // (notably Netscape) create their entries with several comma
-        // separated extensions (RFC mention the spaces only)
+        // depending on the format (Mosaic or Netscape) either space or comma
+        // is used to separate the extensions
         strExtensions.Replace(wxT(","), wxT(" "));
 
         // also deal with the leading dot
@@ -1592,6 +1623,11 @@ bool wxMimeTypesManagerImpl::ReadMailcap(const wxString& strFileName,
             // support for flags:
             //  1. create an xterm for 'needsterminal'
             //  2. append "| $PAGER" for 'copiousoutput'
+            //
+            // Note that the RFC says that having both needsterminal and
+            // copiousoutput is probably a mistake, so it seems that running
+            // programs with copiousoutput inside an xterm as it is done now
+            // is a bad idea (FIXME)
             if ( copiousoutput ) {
                 const wxChar *p = wxGetenv(_T("PAGER"));
                 strOpenCmd << _T(" | ") << (p ? p : _T("more"));
@@ -1680,6 +1716,8 @@ bool wxMimeTypesManagerImpl::ReadMailcap(const wxString& strFileName,
 
 size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
 {
+    InitIfNeeded();
+
     mimetypes.Empty();
 
     wxString type;
@@ -1697,6 +1735,17 @@ size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
     return mimetypes.GetCount();
 }
 
+// ----------------------------------------------------------------------------
+// writing to MIME type files
+// ----------------------------------------------------------------------------
+
+bool wxFileTypeImpl::Unassociate()
+{
+    wxFAIL_MSG( _T("unimplemented") ); // TODO
+
+    return FALSE;
+}
+
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------