]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/mimetmac.cpp
Remove my binary compatibility stuff from HEAD. Patch #1367014 used for reference.
[wxWidgets.git] / src / mac / carbon / mimetmac.cpp
index ff6ef1d39f9eaaff497b4c47cd06c158d86447ce..634c70065c8c01028caaa55f0a963b88bffcda79 100644 (file)
@@ -1,17 +1,30 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        mac/mimetype.cpp
-// Purpose:     classes and functions to manage MIME types
-// Author:      Vadim Zeitlin
+// Purpose:     Mac Carbon implementation for wx mime-related classes
+// Author:      Ryan Norton
 // Modified by:
-// Created:     23.09.98
+// Created:     04/16/2005
 // RCS-ID:      $Id$
-// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// Licence:     wxWidgets licence (part of wxExtra library)
+// Copyright:   (c) 2005 Ryan Norton (<wxprojects@comcast.net>)
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef    __GNUG__
-#pragma implementation "mimetype.h"
-#endif
+//
+//
+//  TODO:  Search Info[-macos](classic).plist dictionary in addition
+//  to Internet Config database.
+//
+//  Maybe try a brainstorm a way to change the wxMimeTypesManager API
+//  to get info from a file instead/addition to current get all stuff
+//  API so that we can use Launch Services to get mime type info.
+//
+//  Implement geticon from one of the finder info functions - or
+//  use launch services and search that app's plist for the icon.
+//
+//  Put some special juice in for the print command.
+//
+//
+//
 
 // for compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
   #pragma hdrstop
 #endif
 
-#ifndef WX_PRECOMP
-  #include "wx/defs.h"
-#endif
-
 #ifndef WX_PRECOMP
   #include "wx/string.h"
   #if wxUSE_GUI
@@ -32,6 +41,8 @@
 #endif //WX_PRECOMP
 
 
+#if wxUSE_MIMETYPE
+
 #include "wx/log.h"
 #include "wx/file.h"
 #include "wx/intl.h"
 #include "wx/confbase.h"
 
 #include "wx/mac/mimetype.h"
+#include "wx/mac/private.h" //wxMacMakeStringFromPascal
 
 // other standard headers
 #include <ctype.h>
 
+#ifndef __DARWIN__
+#include <InternetConfig.h> //For mime types
+#endif
+
+/*   START CODE SAMPLE FROM TECHNOTE 1002 (http://developer.apple.com/technotes/tn/tn1002.html) */
+
+ /* IsRemoteVolume can be used to find out if the
+    volume referred to by vRefNum is a remote volume
+    located somewhere on a network. the volume's attribute
+    flags (copied from the GetVolParmsInfoBuffer structure)
+    are returned in the longword pointed to by vMAttrib. */
+OSErr IsRemoteVolume(short vRefNum, Boolean *isRemote, long *vMAttrib) {
+    HParamBlockRec volPB;
+    GetVolParmsInfoBuffer volinfo;
+    OSErr err;
+    volPB.ioParam.ioVRefNum = vRefNum;
+    volPB.ioParam.ioNamePtr = NULL;
+    volPB.ioParam.ioBuffer = (Ptr) &volinfo;
+    volPB.ioParam.ioReqCount = sizeof(volinfo);
+    err = PBHGetVolParmsSync(&volPB);
+    if (err == noErr) {
+        *isRemote = (volinfo.vMServerAdr != 0);
+        *vMAttrib = volinfo.vMAttrib;
+    }
+    return err;
+}
+
+
+    /* BuildVolumeList fills the array pointed to by vols with
+    a list of the currently mounted volumes.  If includeRemote
+    is true, then remote server volumes will be included in
+    the list.  When remote server volumes are included in the
+    list, they will be added to the end of the list.  On entry,
+    *count should contain the size of the array pointed to by
+    vols.  On exit, *count will be set to the number of id numbers
+    placed in the array. If vMAttribMask is non-zero, then
+    only volumes with matching attributes are added to the
+    list of volumes. bits in the vMAttribMask should use the
+    same encoding as bits in the vMAttrib field of
+    the GetVolParmsInfoBuffer structure. */
+OSErr BuildVolumeList(Boolean includeRemote, short *vols,
+        long *count, long vMAttribMask) {
+    HParamBlockRec volPB;
+    Boolean isRemote;
+    OSErr err = noErr;
+    long nlocal, nremote;
+    long vMAttrib;
+
+        /* set up and check parameters */
+    volPB.volumeParam.ioNamePtr = NULL;
+    nlocal = nremote = 0;
+    if (*count == 0) return noErr;
+
+        /* iterate through volumes */
+    for (volPB.volumeParam.ioVolIndex = 1;
+        PBHGetVInfoSync(&volPB) == noErr;
+        volPB.volumeParam.ioVolIndex++) {
+
+                /* skip remote volumes, if necessary */
+        err = IsRemoteVolume(volPB.volumeParam.ioVRefNum, &isRemote, &vMAttrib);
+        if (err != noErr) goto bail;
+        if ( ( includeRemote || ! isRemote )
+        && (vMAttrib & vMAttribMask) == vMAttribMask ) {
+
+                /* add local volumes at the front, remote
+                volumes at the end */
+            if (isRemote)
+                vols[nlocal + nremote++] = volPB.volumeParam.ioVRefNum;
+            else {
+                if (nremote > 0)
+                    BlockMoveData(vols+nlocal, vols+nlocal+1,
+                        nremote*sizeof(short));
+                vols[nlocal++] = volPB.volumeParam.ioVRefNum;
+            }
+
+                /* list full? */
+            if ((nlocal + nremote) >= *count) break;
+        }
+    }
+bail:
+    *count = (nlocal + nremote);
+    return err;
+}
+
+
+    /* FindApplication iterates through mounted volumes
+    searching for an application with the given creator
+    type.  If includeRemote is true, then remote volumes
+    will be searched (after local ones) for an application
+    with the creator type. */
+
+#define kMaxVols 20
+
+/* Hacked to output to appName */
+
+OSErr FindApplication(OSType appCreator, Boolean includeRemote, Str255 appName, FSSpec* appSpec) {
+    short rRefNums[kMaxVols];
+    long i, volCount;
+    DTPBRec desktopPB;
+    OSErr err;
+
+        /* get a list of volumes - with desktop files */
+    volCount = kMaxVols;
+    err = BuildVolumeList(includeRemote, rRefNums, &volCount,
+        (1<<bHasDesktopMgr) );
+    if (err != noErr) return err;
+
+        /* iterate through the list */
+    for (i=0; i<volCount; i++) {
+
+            /* has a desktop file? */
+        desktopPB.ioCompletion = NULL;
+        desktopPB.ioVRefNum = rRefNums[i];
+        desktopPB.ioNamePtr = NULL;
+        desktopPB.ioIndex = 0;
+        err = PBDTGetPath(&desktopPB);
+        if (err != noErr) continue;
+
+            /* has the correct app?? */
+        desktopPB.ioFileCreator = appCreator;
+        desktopPB.ioNamePtr = appName;
+        err = PBDTGetAPPLSync(&desktopPB);
+        if (err != noErr) continue;
+
+            /* make a file spec referring to it */
+        err = FSMakeFSSpec(rRefNums[i],
+              desktopPB.ioAPPLParID, appName,
+              appSpec);
+        if (err != noErr) continue;
+
+           /* found it! */
+        return noErr;
+
+    }
+    return fnfErr;
+}
+
+/*   END CODE SAMPLE FROM TECHNOTE 1002 (http://developer.apple.com/technotes/tn/tn1002.html) */
+
+//yeah, duplicated code
+pascal  OSErr  FSpGetFullPath(const FSSpec *spec,
+                 short *fullPathLength,
+                 Handle *fullPath)
+{
+  OSErr    result;
+  OSErr    realResult;
+  FSSpec    tempSpec;
+  CInfoPBRec  pb;
+
+  *fullPathLength = 0;
+  *fullPath = NULL;
+
+
+  /* Default to noErr */
+  realResult = result = noErr;
+
+  /* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
+/*
+  if ( spec->name[0] == 0 )
+  {
+    result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
+  }
+  else
+  {
+*/
+    /* Make a copy of the input FSSpec that can be modified */
+    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+/*  }*/
+
+  if ( result == noErr )
+  {
+    if ( tempSpec.parID == fsRtParID )
+    {
+      /* The object is a volume */
+
+      /* Add a colon to make it a full pathname */
+      ++tempSpec.name[0];
+      tempSpec.name[tempSpec.name[0]] = ':';
+
+      /* We're done */
+      result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+    }
+    else
+    {
+      /* The object isn't a volume */
+
+      /* Is the object a file or a directory? */
+      pb.dirInfo.ioNamePtr = tempSpec.name;
+      pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+      pb.dirInfo.ioDrDirID = tempSpec.parID;
+      pb.dirInfo.ioFDirIndex = 0;
+      result = PBGetCatInfoSync(&pb);
+      /* Allow file/directory name at end of path to not exist. */
+      realResult = result;
+      if ( (result == noErr) || (result == fnfErr) )
+      {
+        /* if the object is a directory, append a colon so full pathname ends with colon */
+        if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
+        {
+          ++tempSpec.name[0];
+          tempSpec.name[tempSpec.name[0]] = ':';
+        }
+
+        /* Put the object name in first */
+        result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+        if ( result == noErr )
+        {
+          /* Get the ancestor directory names */
+          pb.dirInfo.ioNamePtr = tempSpec.name;
+          pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+          pb.dirInfo.ioDrParID = tempSpec.parID;
+          do  /* loop until we have an error or find the root directory */
+          {
+            pb.dirInfo.ioFDirIndex = -1;
+            pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
+            result = PBGetCatInfoSync(&pb);
+            if ( result == noErr )
+            {
+              /* Append colon to directory name */
+              ++tempSpec.name[0];
+              tempSpec.name[tempSpec.name[0]] = ':';
+
+              /* Add directory name to beginning of fullPath */
+              (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
+              result = MemError();
+            }
+          } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
+        }
+      }
+    }
+  }
+
+  if ( result == noErr )
+  {
+    /* Return the length */
+    *fullPathLength = GetHandleSize(*fullPath);
+    result = realResult;  /* return realResult in case it was fnfErr */
+  }
+  else
+  {
+    /* Dispose of the handle and return NULL and zero length */
+    if ( *fullPath != NULL )
+    {
+      DisposeHandle(*fullPath);
+    }
+    *fullPath = NULL;
+    *fullPathLength = 0;
+  }
+
+  return ( result );
+}
+
+//
+// On the mac there are two ways to open a file - one is through apple events and the
+// finder, another is through mime types.
+//
+// So, really there are two ways to implement wxFileType...
+//
+// Mime types are only available on OS 8.1+ through the InternetConfig API
+//
+// Much like the old-style file manager, it has 3 levels of flexibility for its methods -
+// Low - which means you have to iterate yourself through the mime database
+// Medium - which lets you sort of cache the database if you want to use lowlevel functions
+// High - which requires access to the database every time
+//
+// We want to be efficient (i.e. professional :) ) about it, so we use a combo of low
+// and mid-level functions
+//
+// TODO: Should we call ICBegin/ICEnd?  Then where?
+//
+
+// debug helper
+inline void wxLogMimeDebug(const wxChar* szMsg, OSStatus status)
+{
+    wxLogDebug(wxString::Format(wxT("%s  LINE:%i  OSERROR:%i"), szMsg, __LINE__, (int)status));
+}
+
 // in case we're compiling in non-GUI mode
 class WXDLLEXPORT wxIcon;
 
 bool wxFileTypeImpl::SetCommand(const wxString& cmd, const wxString& verb, bool overwriteprompt)
 {
-    return FALSE;
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    return false;
 }
 
 bool wxFileTypeImpl::SetDefaultIcon(const wxString& strIcon, int index)
 {
-    return FALSE;
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    return false;
 }
 
-bool wxFileTypeImpl::GetCommand(wxString *command, const char *verb) const
+bool wxFileTypeImpl::GetOpenCommand(wxString *openCmd,
+                               const wxFileType::MessageParameters& params) const
 {
-    return FALSE;
+    wxString cmd = GetCommand(wxT("open"));
+
+    *openCmd = wxFileType::ExpandCommand(cmd, params);
+
+    return !openCmd->empty();
 }
 
-// @@ this function is half implemented
-bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
+bool
+wxFileTypeImpl::GetPrintCommand(wxString *printCmd,
+                                const wxFileType::MessageParameters& params)
+                                const
 {
-    return FALSE;
+    wxString cmd = GetCommand(wxT("print"));
+
+    *printCmd = wxFileType::ExpandCommand(cmd, params);
+
+    return !printCmd->empty();
 }
 
-bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
+//
+// Internet Config vs. Launch Services
+//
+// From OS 8 on there was internet config...
+// However, OSX and its finder does not use info
+// from Internet Config at all - the Internet Config
+// database ONLY CONTAINS APPS THAT ARE CLASSIC APPS
+// OR REGISTERED THROUGH INTERNET CONFIG
+//
+// Therefore on OSX in order for the open command to be useful
+// we need to go straight to launch services
+//
+
+#if defined(__DARWIN__)
+
+//on darwin, use launch services
+#include <ApplicationServices/ApplicationServices.h>
+
+wxString wxFileTypeImpl::GetCommand(const wxString& verb) const
 {
-    if ( m_strFileType.Length() > 0 )
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    if(verb == wxT("open"))
     {
-        *mimeType = m_strFileType ;
-        return TRUE ;
+        ICMapEntry entry;
+        ICGetMapEntry( (ICInstance) m_manager->m_hIC,
+                       (Handle) m_manager->m_hDatabase,
+                       m_lIndex, &entry);
+
+        wxString sCurrentExtension = wxMacMakeStringFromPascal(entry.extension);
+        sCurrentExtension = sCurrentExtension.Right(sCurrentExtension.Length()-1 );
+
+        //type, creator, ext, roles, outapp (FSRef), outappurl
+        CFURLRef cfurlAppPath;
+        OSStatus status = LSGetApplicationForInfo (kLSUnknownType,
+            kLSUnknownCreator,
+            wxMacCFStringHolder(sCurrentExtension, wxLocale::GetSystemEncoding()),
+            kLSRolesAll,
+            NULL,
+            &cfurlAppPath);
+
+        if(status == noErr)
+        {
+            CFStringRef cfsUnixPath = CFURLCopyFileSystemPath(cfurlAppPath, kCFURLPOSIXPathStyle);
+            CFRelease(cfurlAppPath);
+
+            //PHEW!  Success!
+            //Since a filename might have spaces in it, so surround it with quotes
+            if(cfsUnixPath)
+                return wxString(wxT("'")) + wxMacCFStringHolder(cfsUnixPath).AsString(wxLocale::GetSystemEncoding()) + wxString(wxT("'"));
+        }
+        else
+        {
+            wxLogDebug(wxString::Format(wxT("%i - %s - %i"),
+            __LINE__,
+            wxT("LSGetApplicationForInfo failed."),
+            (int)status));
+        }
     }
-    else
-    return FALSE;
+
+    return wxEmptyString;
+}
+
+#else //carbon/classic implementation
+
+wxString wxFileTypeImpl::GetCommand(const wxString& verb) const
+{
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    if(verb == wxT("open"))
+    {
+        ICMapEntry entry;
+        ICGetMapEntry( (ICInstance) m_manager->m_hIC,
+                       (Handle) m_manager->m_hDatabase,
+                       m_lIndex, &entry);
+
+        //The entry in the mimetype database only contains the app
+        //that's registered - it may not exist... we need to remap the creator
+        //type and find the right application
+
+        // THIS IS REALLY COMPLICATED :\.  There are a lot of conversions going
+        // on here.
+        Str255 outName;
+        FSSpec outSpec;
+        if(FindApplication(entry.fileCreator, false, outName, &outSpec) != noErr)
+            return wxEmptyString;
+
+        Handle outPathHandle;
+        short outPathSize;
+        OSErr err = FSpGetFullPath(&outSpec, &outPathSize, &outPathHandle);
+
+        if(err == noErr)
+        {
+            char* szPath = *outPathHandle;
+            wxString sClassicPath(szPath, wxConvLocal, outPathSize);
+#if defined(__DARWIN__)
+            //Classic Path --> Unix (OSX) Path
+            CFURLRef finalURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+                        wxMacCFStringHolder(sClassicPath, wxLocale::GetSystemEncoding()),
+                        kCFURLHFSPathStyle,
+                        false); //false == not a directory
+
+            //clean up memory from the classic path handle
+            DisposeHandle(outPathHandle);
+
+            if(finalURL)
+            {
+                CFStringRef cfsUnixPath = CFURLCopyFileSystemPath(finalURL, kCFURLPOSIXPathStyle);
+                CFRelease(finalURL);
+
+                //PHEW!  Success!
+                if(cfsUnixPath)
+                    return wxMacCFStringHolder(cfsUnixPath).AsString(wxLocale::GetSystemEncoding());
+            }
+#else //classic HFS path acceptable
+            return sClassicPath;
+#endif
+        }
+        else
+        {
+            wxLogMimeDebug(wxT("FSpGetFullPath failed."), (OSStatus)err);
+        }
+    }
+    return wxEmptyString;
+}
+#endif //!DARWIN
+
+bool wxFileTypeImpl::GetDescription(wxString *desc) const
+{
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    ICMapEntry entry;
+    ICGetMapEntry( (ICInstance) m_manager->m_hIC,
+                   (Handle) m_manager->m_hDatabase,
+                   m_lIndex, &entry);
+
+    *desc = wxMacMakeStringFromPascal(entry.entryName);
+    return true;
+}
+
+bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
+{
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    ICMapEntry entry;
+    ICGetMapEntry( (ICInstance) m_manager->m_hIC,
+                   (Handle) m_manager->m_hDatabase,
+                   m_lIndex, &entry);
+
+    //entry has period in it
+    wxString sCurrentExtension = wxMacMakeStringFromPascal(entry.extension);
+    extensions.Add( sCurrentExtension.Right(sCurrentExtension.Length()-1) );
+    return true;
+}
+
+bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
+{
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    ICMapEntry entry;
+    ICGetMapEntry( (ICInstance) m_manager->m_hIC,
+                   (Handle) m_manager->m_hDatabase,
+                   m_lIndex, &entry);
+
+    *mimeType = wxMacMakeStringFromPascal(entry.MIMEType);
+    return true;
 }
 
 bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const
 {
     wxString s;
-    
+
     if (GetMimeType(&s))
     {
         mimeTypes.Clear();
         mimeTypes.Add(s);
-        return TRUE;
+        return true;
     }
-    else 
-        return FALSE;
+    else
+        return false;
 }
 
 bool wxFileTypeImpl::GetIcon(wxIconLocation *WXUNUSED(icon)) const
 {
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
     // no such file type or no value or incorrect icon entry
-    return FALSE;
+    return false;
 }
 
-bool wxFileTypeImpl::GetDescription(wxString *desc) const
+size_t wxFileTypeImpl::GetAllCommands(wxArrayString * verbs, wxArrayString * commands,
+                   const wxFileType::MessageParameters& params) const
 {
-    return FALSE;
+    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );
+
+    wxString sCommand;
+    size_t ulCount = 0;
+
+    if(GetOpenCommand(&sCommand, params))
+    {
+        verbs->Add(wxString(wxT("open")));
+        commands->Add(sCommand);
+        ++ulCount;
+    }
+
+    return ulCount;
 }
 
-size_t
-wxFileTypeImpl::GetAllCommands(wxArrayString * verbs, wxArrayString * commands,
-                   const wxFileType::MessageParameters& params) const
+void wxMimeTypesManagerImpl::Initialize(int mailcapStyles, const wxString& extraDir)
 {
-    wxFAIL_MSG( _T("wxFileTypeImpl::GetAllCommands() not yet implemented") );
-    return 0;
+    wxASSERT_MSG(m_hIC == NULL, wxT("Already initialized wxMimeTypesManager!"));
+
+    //some apps (non-wx) use the 'plst' resource instead
+/*
+    CFBundleRef cfbMain = CFBundleGetMainBundle();
+    wxCFDictionary cfdInfo( CFBundleGetInfoDictionary(cfbMain), wxCF_RETAIN );
+    wxString sLog;
+    cfdInfo.PrintOut(sLog);
+    wxLogDebug(sLog);
+*/
+
+    //start internet config - log if there's an error
+    //the second param is the signature of the application, also known
+    //as resource ID 0.  However, as per some recent discussions, we may not
+    //have a signature for this app, so a generic 'APPL' which is the executable
+    //type will work for now
+    OSStatus status = ICStart( (ICInstance*) &m_hIC, 'APPL');
+
+    if(status != noErr)
+    {
+        wxLogDebug(wxT("Could not initialize wxMimeTypesManager!"));
+        wxASSERT( false );
+        m_hIC = NULL;
+        return;
+    }
+
+    ICAttr attr;
+    m_hDatabase = (void**) NewHandle(0);
+    status = ICFindPrefHandle( (ICInstance) m_hIC, kICMapping, &attr, (Handle) m_hDatabase );
+
+    //the database file can be corrupt (on OSX its
+    //~/Library/Preferences/com.apple.internetconfig.plist)
+    //- bail if it is
+    if(status != noErr)
+    {
+        ClearData();
+        wxLogDebug(wxT("Corrupt Mime Database!"));
+        return;
+    }
+
+    //obtain the number of entries in the map
+    status = ICCountMapEntries( (ICInstance) m_hIC, (Handle) m_hDatabase, &m_lCount );
+    wxASSERT( status == noErr );
+    /*
+    //debug stuff
+    ICMapEntry entry;
+    long pos;
+
+    for(long i = 1; i <= m_lCount; ++i)
+    {
+        OSStatus status = ICGetIndMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, i, &pos, &entry);
+
+        if(status == noErr)
+        {
+            wxString sCreator = wxMacMakeStringFromPascal(entry.creatorAppName);
+            wxString sCurrentExtension = wxMacMakeStringFromPascal(entry.extension);
+            wxString sMIMEType = wxMacMakeStringFromPascal(entry.MIMEType);
+
+            wxFileTypeImpl impl;
+            impl.Init(this, pos);
+
+            if(sMIMEType == wxT("text/html") && sCurrentExtension == wxT(".html"))
+            {
+                wxString cmd;
+                    impl.GetOpenCommand (&cmd,
+        wxFileType::MessageParameters (wxT("http://www.google.com")));
+
+                wxPrintf(wxT("APP: [%s]\n"), cmd.c_str());
+            }
+        }
+    }
+        */
 }
 
-void
-wxMimeTypesManagerImpl::Initialize(int mailcapStyles, const wxString& extraDir)
+void wxMimeTypesManagerImpl::ClearData()
 {
-    wxFAIL_MSG( _T("wxMimeTypesManagerImpl::Initialize() not yet implemented") );
+    if(m_hIC != NULL)
+    {
+        DisposeHandle((Handle)m_hDatabase);
+        //this can return an error, but we don't really care that much about it
+        ICStop( (ICInstance) m_hIC );
+        m_hIC = NULL;
+    }
 }
 
-void
-wxMimeTypesManagerImpl::ClearData()
+//
+//  Q) Iterating through the map - why does it use if (err == noErr) instead of just asserting?
+//  A) Some intermediate indexes are bad while subsequent ones may be good.  Its wierd, I know.
+//
+
+// extension -> file type
+wxFileType* wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& e)
 {
-    wxFAIL_MSG( _T("wxMimeTypesManagerImpl::ClearData() not yet implemented") );
+    wxASSERT_MSG( m_hIC != NULL, wxT("wxMimeTypesManager not Initialized!") );
+
+    //low level functions - iterate through the database
+    ICMapEntry entry;
+    long pos;
+
+    for(long i = 1; i <= m_lCount; ++i)
+    {
+        OSStatus status = ICGetIndMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, i, &pos, &entry);
+
+        if(status == noErr)
+        {
+            wxString sCurrentExtension = wxMacMakeStringFromPascal(entry.extension);
+            if( sCurrentExtension.Right(sCurrentExtension.Length()-1) == e ) //entry has period in it
+            {
+                wxFileType* pFileType = new wxFileType();
+                pFileType->m_impl->Init((wxMimeTypesManagerImpl*)this, pos);
+                return pFileType;
+            }
+        }
+    }
+
+    return NULL;
 }
 
-// extension -> file type
-wxFileType *
-wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& e)
+// MIME type -> extension -> file type
+wxFileType* wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
+{
+    wxASSERT_MSG( m_hIC != NULL, wxT("wxMimeTypesManager not Initialized!") );
+
+    //low level functions - iterate through the database
+    ICMapEntry entry;
+    long pos;
+
+    for(long i = 1; i <= m_lCount; ++i)
+    {
+        OSStatus status = ICGetIndMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, i, &pos, &entry);
+        wxASSERT_MSG( status == noErr, wxString::Format(wxT("Error: %d"), (int)status) );
+
+        if(status == noErr)
+        {
+            if( wxMacMakeStringFromPascal(entry.MIMEType) == mimeType)
+            {
+                wxFileType* pFileType = new wxFileType();
+                pFileType->m_impl->Init((wxMimeTypesManagerImpl*)this, pos);
+                return pFileType;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
+{
+    wxASSERT_MSG( m_hIC != NULL, wxT("wxMimeTypesManager not Initialized!") );
+
+    //low level functions - iterate through the database
+    ICMapEntry entry;
+    long pos;
+
+    long lStartCount = (long) mimetypes.GetCount();
+
+    for(long i = 1; i <= m_lCount; ++i)
+    {
+        OSStatus status = ICGetIndMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, i, &pos, &entry);
+        if( status == noErr )
+            mimetypes.Add( wxMacMakeStringFromPascal(entry.MIMEType) );
+    }
+
+    return mimetypes.GetCount() - lStartCount;
+}
+
+
+pascal  OSStatus  MoreProcGetProcessTypeSignature(
+            const ProcessSerialNumberPtr pPSN,
+            OSType *pProcessType,
+            OSType *pCreator)
 {
-    wxString ext = e ;
-    ext = ext.Lower() ;
-    if ( ext == wxT("txt") )
+  OSStatus      anErr = noErr;
+  ProcessInfoRec    infoRec;
+  ProcessSerialNumber localPSN;
+
+  infoRec.processInfoLength = sizeof(ProcessInfoRec);
+  infoRec.processName = nil;
+  infoRec.processAppSpec = nil;
+
+  if ( pPSN == nil ) {
+    localPSN.highLongOfPSN = 0;
+    localPSN.lowLongOfPSN  = kCurrentProcess;
+  } else {
+    localPSN = *pPSN;
+  }
+
+  anErr = GetProcessInformation(&localPSN, &infoRec);
+  if (anErr == noErr)
+  {
+    *pProcessType = infoRec.processType;
+    *pCreator = infoRec.processSignature;
+  }
+
+  return anErr;
+}//end MoreProcGetProcessTypeSignature
+
+//
+//
+//  TODO: clean this up, its messy
+//
+//
+//
+
+#include "wx/mac/corefoundation/cfstring.h"
+#include "wx/intl.h" //wxLocale for wxCFString
+
+#define wxCF_RELEASE true
+#define wxCF_RETAIN  false
+
+// ----------------------------------------------------------------------------
+// wxCFDictionary
+// ----------------------------------------------------------------------------
+
+class wxCFDictionary
+{
+public:
+    wxCFDictionary(CFTypeRef ref, bool bRetain = wxCF_RELEASE)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("text/text"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        m_cfmdRef = (CFMutableDictionaryRef) ref;
+        if(bRetain == wxCF_RETAIN && ref)
+            CFRetain(ref);
     }
-    else if ( ext == wxT("htm") || ext == wxT("html") )
+
+    wxCFDictionary(CFIndex cfiSize = 0)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("text/html"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        CFDictionaryKeyCallBacks kcbs;
+        CFDictionaryValueCallBacks vcbs;
+        BuildKeyCallbacks(&kcbs);
+        BuildValueCallbacks(&vcbs);
+
+        m_cfmdRef = CFDictionaryCreateMutable(
+            kCFAllocatorDefault, cfiSize, &kcbs, &vcbs);
+
     }
-    else if ( ext == wxT("gif") )
+
+    ~wxCFDictionary()
+    { Clear(); }
+
+    void Clear()
+    {if(m_cfmdRef) CFRelease(m_cfmdRef);}
+
+    static const void* RetainProc(CFAllocatorRef, const void* v)
+    { return (const void*) CFRetain(v); }
+
+    static void ReleaseProc(CFAllocatorRef, const void* v)
+    { CFRelease(v); }
+
+    void MakeMutable(CFIndex cfiSize = 0)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/gif"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        CFDictionaryRef oldref = (CFDictionaryRef) m_cfmdRef;
+
+        m_cfmdRef = CFDictionaryCreateMutableCopy(
+            kCFAllocatorDefault,
+            cfiSize,
+            oldref);
+
+        CFRelease(oldref);
     }
-    else if ( ext == wxT("png" ))
+
+    void BuildKeyCallbacks(CFDictionaryKeyCallBacks* pCbs)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/png"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        pCbs->version = 0;
+        pCbs->retain = RetainProc;
+        pCbs->release = ReleaseProc;
+        pCbs->copyDescription = NULL;
+        pCbs->equal = NULL;
+        pCbs->hash = NULL;
     }
-    else if ( ext == wxT("jpg" )|| ext == wxT("jpeg") )
+
+    void BuildValueCallbacks(CFDictionaryValueCallBacks* pCbs)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/jpeg"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        pCbs->version = 0;
+        pCbs->retain = RetainProc;
+        pCbs->release = ReleaseProc;
+        pCbs->copyDescription = NULL;
+        pCbs->equal = NULL;
     }
-    else if ( ext == wxT("bmp") )
+
+    operator CFTypeRef () const
+    { return (CFTypeRef)m_cfmdRef; }
+
+    CFDictionaryRef GetCFDictionary() const
+    { return (CFDictionaryRef)m_cfmdRef; }
+
+    CFMutableDictionaryRef GetCFMutableDictionary()
+    { return (CFMutableDictionaryRef) m_cfmdRef; }
+
+    CFTypeRef operator [] (CFTypeRef cftEntry) const
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/bmp"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        wxASSERT(IsValid());
+        return (CFTypeRef) CFDictionaryGetValue((CFDictionaryRef)m_cfmdRef, cftEntry);
     }
-    else if ( ext == wxT("tif") || ext == wxT("tiff") )
+
+    CFIndex GetCount() const
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/tiff"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        wxASSERT(IsValid());
+        return CFDictionaryGetCount((CFDictionaryRef)m_cfmdRef);
     }
-    else if ( ext == wxT("xpm") )
+
+    void Add(CFTypeRef cftKey, CFTypeRef cftValue)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/xpm"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        wxASSERT(IsValid());
+        wxASSERT(Exists(cftKey) == false);
+        CFDictionaryAddValue(m_cfmdRef, cftKey, cftValue);
     }
-    else if ( ext == wxT("xbm") )
+
+    void Remove(CFTypeRef cftKey)
     {
-        wxFileType *fileType = new wxFileType;
-        fileType->m_impl->SetFileType(wxT("image/xbm"));
-        fileType->m_impl->SetExt(ext);
-        return fileType;
+        wxASSERT(IsValid());
+        wxASSERT(Exists(cftKey));
+        CFDictionaryRemoveValue(m_cfmdRef, cftKey);
     }
 
-    // unknown extension
-    return NULL;
-}
+    void Set(CFTypeRef cftKey, CFTypeRef cftValue)
+    {
+        wxASSERT(IsValid());
+        wxASSERT(Exists(cftKey));
+        CFDictionarySetValue(m_cfmdRef, cftKey, cftValue);
+    }
 
-// MIME type -> extension -> file type
-wxFileType *
-wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
+    bool Exists(CFTypeRef cftKey) const
+    {
+        wxASSERT(IsValid());
+        return CFDictionaryContainsKey((CFDictionaryRef)m_cfmdRef, cftKey);
+    }
+
+    bool IsOk() const {return m_cfmdRef != NULL; }
+
+    bool IsValid() const
+    {
+        return IsOk() && CFGetTypeID((CFTypeRef)m_cfmdRef) == CFDictionaryGetTypeID();
+    }
+
+    void PrintOut(wxString& sMessage)
+    {
+        PrintOutDictionary(sMessage, m_cfmdRef);
+    }
+
+    static void PrintOutDictionary(wxString& sMessage, CFDictionaryRef cfdRef)
+    {
+        CFIndex cfiCount = CFDictionaryGetCount(cfdRef);
+        CFTypeRef* pKeys = new CFTypeRef[cfiCount];
+        CFTypeRef* pValues = new CFTypeRef[cfiCount];
+
+        CFDictionaryGetKeysAndValues(cfdRef, pKeys, pValues);
+
+        for(CFIndex i = 0; i < cfiCount; ++i)
+        {
+            wxString sKey = wxMacCFStringHolder(CFCopyTypeIDDescription(CFGetTypeID(pKeys[i]))).AsString();
+            wxString sValue = wxMacCFStringHolder(CFCopyTypeIDDescription(CFGetTypeID(pValues[i]))).AsString();
+
+            sMessage <<
+                wxString::Format(wxT("[{#%d} Key : %s]"), (int) i,
+                        sKey.c_str());
+
+            PrintOutType(sMessage, sKey, pKeys[i]);
+
+            sMessage <<
+                wxString::Format(wxT("\n\t[Value : %s]"),
+                        sValue.c_str());
+
+            PrintOutType(sMessage, sValue, pValues[i]);
+
+            sMessage << wxT("\n");
+        }
+
+        delete[] pKeys;
+        delete[] pValues;
+    }
+
+    static void PrintOutArray(wxString& sMessage, CFArrayRef cfaRef)
+    {
+
+        for(CFIndex i = 0; i < CFArrayGetCount(cfaRef); ++i)
+        {
+            wxString sValue = wxMacCFStringHolder(CFCopyTypeIDDescription(CFGetTypeID(
+                CFArrayGetValueAtIndex(cfaRef, i)
+                ))).AsString();
+
+            sMessage <<
+                wxString::Format(wxT("\t\t[{#%d} ArrayValue : %s]\n"), (int) i,
+                        sValue.c_str());
+
+            PrintOutType(sMessage, sValue, CFArrayGetValueAtIndex(cfaRef, i));
+        }
+    }
+
+    static void PrintOutType(wxString& sMessage, const wxString& sValue, CFTypeRef cfRef)
+    {
+            sMessage << wxT(" {");
+
+            if(sValue == wxT("CFString"))
+            {
+                 sMessage << wxMacCFStringHolder((CFStringRef)cfRef, false).AsString();
+            }
+            else if(sValue == wxT("CFNumber"))
+            {
+                int nOut;
+                CFNumberGetValue((CFNumberRef)cfRef, kCFNumberIntType, &nOut);
+                sMessage << nOut;
+            }
+            else if(sValue == wxT("CFDictionary"))
+            {
+                PrintOutDictionary(sMessage, (CFDictionaryRef)cfRef);
+            }
+            else if(sValue == wxT("CFArray"))
+            {
+                PrintOutArray(sMessage, (CFArrayRef)cfRef);
+            }
+            else if(sValue == wxT("CFBoolean"))
+            {
+                sMessage << (cfRef == kCFBooleanTrue ? wxT("true") : wxT("false"));
+            }
+            else if(sValue == wxT("CFURL"))
+            {
+                sMessage << wxMacCFStringHolder(CFURLCopyPath((CFURLRef) cfRef)).AsString();
+            }
+            else
+            {
+                sMessage << wxT("*****UNKNOWN TYPE******");
+            }
+
+            sMessage << wxT("} ");
+    }
+
+#if wxUSE_MIMETYPE
+    void MakeValidXML();
+#endif
+
+    CFTypeRef WriteAsXML()
+    {
+        return CFPropertyListCreateXMLData(kCFAllocatorDefault, m_cfmdRef);
+    }
+
+    bool ReadAsXML(CFTypeRef cfData, wxString* pErrorMsg = NULL)
+    {
+        Clear();
+        CFStringRef cfsError=NULL;
+        m_cfmdRef = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData(
+                    kCFAllocatorDefault,
+                    (CFDataRef)cfData,
+                    kCFPropertyListMutableContainersAndLeaves,
+                    &cfsError );
+        if(cfsError)
+        {
+            if(pErrorMsg)
+                *pErrorMsg = wxMacCFStringHolder(cfsError).AsString();
+            else
+                CFRelease(cfsError);
+        }
+
+        return m_cfmdRef != NULL;
+    }
+ private:
+    CFMutableDictionaryRef m_cfmdRef;
+};
+
+// ----------------------------------------------------------------------------
+// wxCFArray
+// ----------------------------------------------------------------------------
+
+class wxCFArray
 {
-    return NULL;
-}
+public:
+    wxCFArray(CFTypeRef ref, bool bRetain = wxCF_RELEASE)
+    {
+        m_cfmaRef = (CFMutableArrayRef)ref;
+        if(bRetain == wxCF_RETAIN && ref)
+            CFRetain(ref);
+    }
 
-size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& mimetypes)
+    wxCFArray(CFIndex cfiSize = 0) : m_cfmaRef(NULL)
+    { Create(cfiSize); }
+
+    ~wxCFArray()
+    { Clear(); }
+
+    void MakeMutable(CFIndex cfiSize = 0)
+    {
+        wxASSERT(IsValid());
+
+        CFMutableArrayRef oldref = m_cfmaRef;
+        m_cfmaRef = CFArrayCreateMutableCopy(
+                kCFAllocatorDefault,
+                cfiSize,
+                (CFArrayRef)oldref);
+        CFRelease(oldref);
+    }
+
+    void BuildCallbacks(CFArrayCallBacks* pCbs)
+    {
+        pCbs->version = 0;
+        pCbs->retain = RetainProc;
+        pCbs->release = ReleaseProc;
+        pCbs->copyDescription = NULL;
+        pCbs->equal = NULL;
+    }
+
+    void Create(CFIndex cfiSize = 0)
+    {
+        Clear();
+        CFArrayCallBacks cb;
+        BuildCallbacks(&cb);
+
+        m_cfmaRef = CFArrayCreateMutable(kCFAllocatorDefault, cfiSize, &cb);
+    }
+
+    void Clear()
+    {if(m_cfmaRef) CFRelease(m_cfmaRef);}
+
+    static const void* RetainProc(CFAllocatorRef, const void* v)
+    { return (const void*) CFRetain(v); }
+
+    static void ReleaseProc(CFAllocatorRef, const void* v)
+    { CFRelease(v); }
+
+    operator CFTypeRef () const
+    { return (CFTypeRef)m_cfmaRef; }
+
+    CFArrayRef GetCFArray() const
+    { return (CFArrayRef)m_cfmaRef; }
+
+    CFMutableArrayRef GetCFMutableArray()
+    { return (CFMutableArrayRef) m_cfmaRef; }
+
+    CFTypeRef operator [] (CFIndex cfiIndex) const
+    {
+        wxASSERT(IsValid());
+        return (CFTypeRef) CFArrayGetValueAtIndex((CFArrayRef)m_cfmaRef, cfiIndex);
+    }
+
+    CFIndex GetCount()
+    {
+        wxASSERT(IsValid());
+        return CFArrayGetCount((CFArrayRef)m_cfmaRef);
+    }
+
+    void Add(CFTypeRef cftValue)
+    {
+        wxASSERT(IsValid());
+        CFArrayAppendValue(m_cfmaRef, cftValue);
+    }
+
+    void Remove(CFIndex cfiIndex)
+    {
+        wxASSERT(IsValid());
+        wxASSERT(cfiIndex < GetCount());
+        CFArrayRemoveValueAtIndex(m_cfmaRef, cfiIndex);
+    }
+
+    void Set(CFIndex cfiIndex, CFTypeRef cftValue)
+    {
+        wxASSERT(IsValid());
+        wxASSERT(cfiIndex < GetCount());
+        CFArraySetValueAtIndex(m_cfmaRef, cfiIndex, cftValue);
+    }
+
+    bool IsOk() const {return m_cfmaRef != NULL; }
+
+    bool IsValid() const
+    {
+        return IsOk() && CFGetTypeID((CFTypeRef)m_cfmaRef) == CFArrayGetTypeID();
+    }
+
+#if wxUSE_MIMETYPE
+    void MakeValidXML();
+#endif
+
+private:
+    CFMutableArrayRef m_cfmaRef;
+};
+
+// ----------------------------------------------------------------------------
+// wxCFString
+// ----------------------------------------------------------------------------
+
+class wxCFString
 {
-    // VZ: don't know anything about this for Mac
-    wxFAIL_MSG( _T("wxMimeTypesManagerImpl::EnumAllFileTypes() not yet implemented") );
+public:
+    wxCFString(CFTypeRef ref, bool bRetain = wxCF_RELEASE) : m_Holder((CFStringRef)ref, bRetain == wxCF_RELEASE)
+    { }
+
+    wxCFString(const wxChar* szString) : m_Holder(wxString(szString), wxLocale::GetSystemEncoding())
+    { }
+
+    wxCFString(const wxString& sString) : m_Holder(sString, wxLocale::GetSystemEncoding())
+    { }
+
+    operator CFTypeRef() const
+    { return (CFTypeRef) ((CFStringRef) m_Holder); }
+
+    bool IsOk() { return ((CFTypeRef)(*this)) != NULL; }
+
+    wxString BuildWXString() {return m_Holder.AsString(); }
+
+private:
+    wxMacCFStringHolder m_Holder;
+};
+
+// ----------------------------------------------------------------------------
+// wxCFNumber
+// ----------------------------------------------------------------------------
+
+class wxCFNumber
+{
+public:
+    wxCFNumber(int nValue)
+    {
+        m_cfnRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &nValue);
+    }
+
+    wxCFNumber(CFTypeRef ref, bool bRetain = wxCF_RELEASE) : m_cfnRef((CFNumberRef)ref)
+    {
+        if(bRetain == wxCF_RETAIN && ref)
+            CFRetain(ref);
+    }
+
+    ~wxCFNumber()
+    {
+        if(m_cfnRef)
+            CFRelease(m_cfnRef);
+    }
+
 
-    return 0;
+    operator CFTypeRef() const
+    { return (CFTypeRef) m_cfnRef; }
+
+    int GetValue()
+    {
+        int nOut;
+        CFNumberGetValue( m_cfnRef,
+                          kCFNumberIntType,
+                          &nOut
+                        );
+
+        return nOut;
+    }
+
+    bool IsOk() { return m_cfnRef != NULL; }
+
+private:
+    CFNumberRef m_cfnRef;
+};
+
+// ----------------------------------------------------------------------------
+// wxCFURL
+// ----------------------------------------------------------------------------
+
+class wxCFURL
+{
+public:
+    wxCFURL(CFTypeRef ref = NULL, bool bRetain = wxCF_RELEASE) : m_cfurlRef((CFURLRef)ref)
+    {
+        if(bRetain == wxCF_RETAIN && ref)
+            CFRetain(ref);
+    }
+    wxCFURL(const wxCFString& URLString, CFTypeRef BaseURL = NULL)
+    {
+        Create(URLString, BaseURL);
+    }
+
+    void Create(const wxCFString& URLString, CFTypeRef BaseURL = NULL)
+    {
+        m_cfurlRef = CFURLCreateWithString(
+            kCFAllocatorDefault,
+            (CFStringRef)(CFTypeRef)URLString,
+            (CFURLRef) BaseURL);
+    }
+
+    ~wxCFURL() {if(m_cfurlRef) CFRelease(m_cfurlRef);}
+
+    wxString BuildWXString()
+    {
+        return wxCFString(CFURLCopyPath(m_cfurlRef)).BuildWXString();
+    }
+
+    operator CFTypeRef() const
+    { return (CFTypeRef)m_cfurlRef; }
+
+    bool IsOk() { return m_cfurlRef != NULL; }
+private:
+    CFURLRef m_cfurlRef;
+};
+
+// ----------------------------------------------------------------------------
+// wxCFData
+// ----------------------------------------------------------------------------
+
+#define wxCFDATA_RELEASEBUFFER  1
+#define wxCFDATA_RETAINBUFFER   0
+
+class wxCFData
+{
+public:
+    wxCFData(CFTypeRef ref, bool bRetain = wxCF_RELEASE) : m_cfdaRef((CFDataRef)ref)
+    {
+        if(bRetain == wxCF_RETAIN && ref)
+            CFRetain(ref);
+    }
+    wxCFData(const UInt8* pBytes, CFIndex len, bool bKeep = wxCFDATA_RELEASEBUFFER)
+    {
+        if(bKeep == wxCFDATA_RELEASEBUFFER)
+        {
+            m_cfdaRef = CFDataCreateWithBytesNoCopy
+                            (kCFAllocatorDefault, pBytes, len, kCFAllocatorDefault);
+        }
+        else
+        {
+            m_cfdaRef = CFDataCreate(kCFAllocatorDefault, pBytes, len);
+        }
+    }
+    ~wxCFData() {if(m_cfdaRef) CFRelease(m_cfdaRef);}
+
+    const UInt8* GetValue()
+    {
+        return CFDataGetBytePtr(m_cfdaRef);
+    }
+
+    CFIndex GetCount()
+    {
+        return CFDataGetLength(m_cfdaRef);
+    }
+
+    operator CFTypeRef() const
+    { return (CFTypeRef)m_cfdaRef; }
+
+    bool IsOk() { return m_cfdaRef != NULL; }
+private:
+    CFDataRef m_cfdaRef;
+};
+
+void wxCFDictionary::MakeValidXML()
+{
+        CFIndex cfiCount = GetCount();
+        CFTypeRef* pKeys = new CFTypeRef[cfiCount];
+        CFTypeRef* pValues = new CFTypeRef[cfiCount];
+
+        CFDictionaryGetKeysAndValues(m_cfmdRef, pKeys, pValues);
+
+        //for plist xml format all dictionary keys must be cfstrings and no values in
+        //the dictionary or subkeys/values can be NULL
+        //Also, CFURLs are not allowed
+        for(CFIndex i = 0; i < cfiCount; ++i)
+        {
+            //must be an array, dictionary, string, bool, or int and cannot be null
+            //and dictionaries can only contain cfstring keys
+            CFTypeRef cfRef = pValues[i];
+            if(!pKeys[i] ||
+                CFGetTypeID(pKeys[i]) != CFStringGetTypeID() ||
+                !cfRef)
+            {
+                Remove(pKeys[i]);
+                --i;
+                --cfiCount;
+                delete[] pKeys;
+                delete[] pValues;
+                pKeys = new CFTypeRef[cfiCount];
+                pValues = new CFTypeRef[cfiCount];
+                CFDictionaryGetKeysAndValues(m_cfmdRef, pKeys, pValues);
+            }
+            else if (CFGetTypeID(cfRef) == CFArrayGetTypeID())
+            {
+                CFRetain(cfRef);
+                wxCFArray cfaCurrent(cfRef);
+                cfaCurrent.MakeMutable();
+                cfaCurrent.MakeValidXML();
+                Set(pKeys[i], cfaCurrent);
+            }
+            else if (CFGetTypeID(cfRef) == CFDictionaryGetTypeID())
+            {
+                CFRetain(cfRef);
+                wxCFDictionary cfdCurrent(cfRef);
+                cfdCurrent.MakeMutable();
+                cfdCurrent.MakeValidXML();
+                Set(pKeys[i], cfdCurrent);
+            }
+            else if ( CFGetTypeID(cfRef) != CFStringGetTypeID() &&
+                      CFGetTypeID(cfRef) != CFNumberGetTypeID() &&
+                      CFGetTypeID(cfRef) != CFBooleanGetTypeID() )
+            {
+                Remove(pKeys[i]);
+                --i;
+                --cfiCount;
+                delete[] pKeys;
+                delete[] pValues;
+                pKeys = new CFTypeRef[cfiCount];
+                pValues = new CFTypeRef[cfiCount];
+                CFDictionaryGetKeysAndValues(m_cfmdRef, pKeys, pValues);
+            }
+        }
+
+        delete[] pValues;
+        delete[] pKeys;
 }
 
-wxFileType *
-wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
+void wxCFArray::MakeValidXML()
 {
-    wxFAIL_MSG( _T("wxMimeTypesManagerImpl::Associate() not yet implemented") );
+        for(CFIndex i = 0; i < GetCount(); ++i)
+        {
+            //must be an array, dictionary, string, bool, or int and cannot be null
+            //and dictionaries can only contain cfstring keys
+            CFTypeRef cfRef = (*this)[i];
+            if(!cfRef)
+            {
+                Remove(i);
+                --i;
+            }
+            else if (CFGetTypeID(cfRef) == CFArrayGetTypeID())
+            {
+                CFRetain(cfRef);
+                wxCFArray cfaCurrent(cfRef);
+                cfaCurrent.MakeMutable();
+                cfaCurrent.MakeValidXML();
+                Set(i, cfaCurrent);
+            }
+            else if (CFGetTypeID(cfRef) == CFDictionaryGetTypeID())
+            {
+                CFRetain(cfRef);
+                wxCFDictionary cfdCurrent(cfRef);
+                cfdCurrent.MakeMutable();
+                cfdCurrent.MakeValidXML();
+                Set(i, cfdCurrent);
+            }
+            else if ( CFGetTypeID(cfRef) != CFStringGetTypeID() &&
+                      CFGetTypeID(cfRef) != CFNumberGetTypeID() &&
+                      CFGetTypeID(cfRef) != CFBooleanGetTypeID() )
+            {
+                Remove(i);
+                --i;
+            }
+        }
+}
+
+//
+//
+//
+//  END TODO
+//
+//
+//
+
+wxFileType* wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
+{
+    bool bInfoSuccess = false;
+
+    const wxArrayString& asExtensions = ftInfo.GetExtensions();
+    size_t dwFoundIndex = 0;
+    if(!asExtensions.GetCount())
+    {
+        wxLogDebug(wxT("Must have extension to associate with"));
+    }
+
+    //Find and write to Info.plist in main bundle (note that some other
+    //apps have theirs named differently, i.e. IE's is named Info-macos.plist
+    //some apps (non-wx) use the 'plst' resource instead
+    CFBundleRef cfbMain = CFBundleGetMainBundle();
+    if(cfbMain)
+    {
+        UInt32 dwBundleType, dwBundleCreator;
+        CFBundleGetPackageInfo(cfbMain, &dwBundleType, &dwBundleCreator);
+
+        //if launching terminal non-app version will be 'BNDL' (generic bundle, maybe in other cases too),
+        //which will give us the incorrect info.plist path
+        //otherwise it will be 'APPL', or in the case of a framework,
+        //'FMWK'
+        if(dwBundleType == 'APPL')
+        {
+
+            wxCFURL cfurlBundleLoc((CFTypeRef)CFBundleCopyBundleURL(cfbMain));
+//             wxCFURL cfurlBundleLoc((CFTypeRef)CFBundleCopyExecutableURL(cfbMain));
+            wxString sInfoPath;
+//            sInfoPath << wxT("file://");
+            sInfoPath << cfurlBundleLoc.BuildWXString();
+            sInfoPath << wxT("Contents/Info.plist");
+
+//        wxCFDictionary cfdInfo( CFBundleGetInfoDictionary(cfbMain), wxCF_RETAIN );
+            wxCFDictionary cfdInfo;
+            bool bInfoOpenSuccess = false;
+            wxFile indictfile;
+            if(indictfile.Open(sInfoPath, wxFile::read))
+            {
+                CFIndex cfiBufLen = (CFIndex) indictfile.Length();
+                const UInt8* pBuffer = new UInt8[cfiBufLen];
+                indictfile.Read((void*)pBuffer, cfiBufLen);
+                wxCFData cfdaInDict(pBuffer, cfiBufLen);
+                wxString sError;
+                bInfoOpenSuccess = cfdInfo.ReadAsXML(cfdaInDict, &sError);
+                if(!bInfoOpenSuccess)
+                    wxLogDebug(sError);
+                indictfile.Close();
+            }
+            if(bInfoOpenSuccess)
+            {
+                cfdInfo.MakeMutable( cfdInfo.GetCount() + 1 );
+
+                wxCFArray cfaDocTypes( cfdInfo[ wxCFString(wxT("CFBundleDocumentTypes")) ], wxCF_RETAIN );
+
+                bool bAddDocTypesArrayToDictionary = cfaDocTypes.IsOk() == false;
+                if(bAddDocTypesArrayToDictionary)
+                    cfaDocTypes.Create();
+                else
+                    cfaDocTypes.MakeMutable( cfaDocTypes.GetCount() + 1 );
+
+                bool bEntryFound = false;
+
+                //search for duplicate
+                CFIndex i;
+                for(i = 0; i < cfaDocTypes.GetCount(); ++i)
+                {
+                    wxCFDictionary cfdDocTypeEntry( cfaDocTypes[i], wxCF_RETAIN );
+
+                    //A lot of apps dont do to mime types for some reason
+                    //so we go by extensions only
+                    wxCFArray cfaExtensions( cfdDocTypeEntry[ wxCFString(wxT("CFBundleTypeExtensions")) ],
+                                             wxCF_RETAIN );
+
+                    if(cfaExtensions.IsOk() == false)
+                        continue;
+
+                    for(CFIndex iExt = 0; iExt < cfaExtensions.GetCount(); ++iExt)
+                    {
+                        for (size_t iWXExt = 0; iWXExt < asExtensions.GetCount(); ++iWXExt)
+                        {
+                            if(asExtensions[iWXExt] ==
+                                    wxCFString(cfaExtensions[iExt], wxCF_RETAIN).BuildWXString())
+                            {
+                                bEntryFound = true;
+                                dwFoundIndex = iWXExt;
+                                break;
+                            }
+                        } //end of wxstring array
+
+                        if(bEntryFound)
+                            break;
+                    } //end for cf array
+
+                    if(bEntryFound)
+                        break;
+                }//end for doctypes
+
+                wxCFDictionary cfdNewEntry;
+
+                if(!ftInfo.GetDescription().empty())
+                {
+                    cfdNewEntry.Add( wxCFString(wxT("CFBundleTypeName")),
+                                wxCFString(ftInfo.GetDescription()) );
+                }
+
+                if(!ftInfo.GetIconFile().empty())
+                {
+                    cfdNewEntry.Add( wxCFString(wxT("CFBundleTypeIconFile")),
+                                    wxCFString(ftInfo.GetIconFile()) );
+                }
+
+
+                wxCFArray cfaOSTypes;
+                wxCFArray cfaExtensions;
+                wxCFArray cfaMimeTypes;
+
+
+                //OSTypes is a cfarray of four-char-codes - '****' for unrestricted
+                cfaOSTypes.Add( wxCFString(wxT("****")) );
+                cfdNewEntry.Add( wxCFString(wxT("CFBundleTypeOSTypes")), cfaOSTypes );
+
+                if(ftInfo.GetExtensionsCount() != 0) //'*' for unrestricted
+                {
+                    for(size_t iExtension = 0; iExtension < (size_t)ftInfo.GetExtensionsCount(); ++iExtension)
+                    {
+                        cfaExtensions.Add( wxCFString( asExtensions[iExtension] ) );
+                    }
+
+                    cfdNewEntry.Add( wxCFString(wxT("CFBundleTypeExtensions")), cfaExtensions );
+                }
+
+                if(!ftInfo.GetMimeType().empty())
+                {
+                    cfaMimeTypes.Add( wxCFString(ftInfo.GetMimeType()) );
+                    cfdNewEntry.Add( wxCFString(wxT("CFBundleTypeMIMETypes")), cfaMimeTypes );
+                }
+
+                // Editor - can perform all actions
+                // Viewer - all actions except manipulation/saving
+                // None - can perform no actions
+                cfdNewEntry.Add( wxCFString(wxT("CFBundleTypeRole")), wxCFString(wxT("Editor")) );
+
+                // Is application bundled?
+                cfdNewEntry.Add( wxCFString(wxT("LSTypeIsPackage")), kCFBooleanTrue );
+
+                if(bEntryFound)
+                    cfaDocTypes.Set(i, cfdNewEntry);
+                else
+                    cfaDocTypes.Add(cfdNewEntry);
+
+                //
+                // set the doc types array in the muted dictionary
+                //
+
+                if(bAddDocTypesArrayToDictionary)
+                    cfdInfo.Add(wxCFString(wxT("CFBundleDocumentTypes")), cfaDocTypes);
+                else
+                    cfdInfo.Set(wxCFString(wxT("CFBundleDocumentTypes")), cfaDocTypes);
+
+                cfdInfo.MakeValidXML();
+
+                wxFile outdictfile;
+                if(outdictfile.Open(sInfoPath, wxFile::write))
+                {
+                    wxCFData cfdaInfo(cfdInfo.WriteAsXML());
+                    if(cfdaInfo.IsOk())
+                    {
+                        if(outdictfile.Write(cfdaInfo.GetValue(), cfdaInfo.GetCount()) !=
+                            (wxFileOffset)cfdaInfo.GetCount())
+                        {
+                            wxLogDebug(wxT("error in writing to file"));
+                        }
+                        else
+                        {
+                            bInfoSuccess = true;
+//#if defined(__DARWIN__)
+//                //force launch services to update its database for the finder
+//                OSStatus status = LSRegisterURL((CFURLRef)(CFTypeRef)cfurlBundleLoc, true);
+//                if(status != noErr)
+//                {
+//                    wxLogDebug(wxT("LSRegisterURL Failed."));
+//                }
+//#endif
+                        }
+                        outdictfile.Close();
+                    }
+                    else
+                    {
+                        outdictfile.Close();
+                        wxLogDebug(wxT("Could not read in new dictionary"));
+                    }
+                }
+                else
+                {
+                    wxLogDebug(wxString(wxT("Could not open [")) +
+                    sInfoPath + wxT("] for writing."));
+                }
+            }
+            else
+            {
+                wxLogDebug(wxT("No info dictionary in main bundle"));
+            }
+        }
+        else
+        {
+            wxLogDebug(wxT("Can only call associate from bundled app within XXX.app"));
+        }
+    }
+    else
+    {
+        wxLogDebug(wxT("No main bundle"));
+    }
 
+#if defined(__DARWIN__)
+    if(!bInfoSuccess)
+        return NULL;
+#endif
+    //on mac you have to embed it into the mac's file reference resource ('FREF' I believe)
+    //or, alternately, you could just add an entry to m_hDatabase, but you'd need to get
+    //the app's signature somehow...
+
+    OSType processType,
+           creator;
+    OSStatus status = MoreProcGetProcessTypeSignature(NULL,&processType, &creator);
+
+    if(status == noErr)
+    {
+        Str255 psCreatorName;
+        FSSpec dummySpec;
+        status = FindApplication(creator, false, psCreatorName, &dummySpec);
+
+        if(status == noErr)
+        {
+
+            //get the file type if it exists -
+            //if it really does then modify the database then save it,
+            //otherwise we need to create a whole new entry
+            wxFileType* pFileType = GetFileTypeFromExtension(asExtensions[dwFoundIndex]);
+            if(pFileType)
+            {
+                ICMapEntry entry;
+                ICGetMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase,
+                                pFileType->m_impl->m_lIndex, &entry);
+
+                memcpy(entry.creatorAppName, psCreatorName, sizeof(Str255));
+                entry.fileCreator = creator;
+
+                status = ICSetMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase,
+                                pFileType->m_impl->m_lIndex, &entry);
+
+                //success
+                if(status == noErr)
+                {
+                    //kICAttrNoChange means we don't care about attributes such as
+                    //locking in the database
+//                    status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping,
+//                                             kICAttrNoChange, (Handle) m_hDatabase);
+//                    if(status == noErr)
+                        return pFileType;
+//                    else
+//                    {
+//                        wxLogDebug(wxString::Format(wxT("%i - %s"), (int)status, wxT("ICSetPrefHandle failed.")));
+       //             }
+                }
+                else
+                {
+                    wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetMapEntry failed.")));
+                }
+
+                //failure - cleanup
+                delete pFileType;
+            }
+            else
+            {
+                //TODO: Maybe force all 3 of these to be non-empty?
+                Str255 psExtension;
+                Str255 psMimeType;
+                Str255 psDescription;
+
+                wxMacStringToPascal(wxString(wxT(".")) + ftInfo.GetExtensions()[0], psExtension);
+                wxMacStringToPascal(ftInfo.GetMimeType(), psMimeType);
+                wxMacStringToPascal(ftInfo.GetDescription(), psDescription);
+
+                Str255 psPostCreatorName;
+                wxMacStringToPascal(wxT(""), psPostCreatorName);
+
+
+                //add the entry to the database
+                ICMapEntry entry;
+                entry.totalLength = sizeof(ICMapEntry);
+                entry.fixedLength = kICMapFixedLength;
+                entry.version = 0;
+                entry.fileType = 0; //TODO:  File type?
+                entry.fileCreator = creator;
+                entry.postCreator = 0;
+                entry.flags = kICMapDataForkBit; //TODO:  Maybe resource is valid by default too?
+                PLstrcpy( entry.extension , psExtension ) ;
+                memcpy(entry.creatorAppName, psCreatorName, sizeof(Str255));
+                memcpy(entry.postAppName, psPostCreatorName, sizeof(Str255));
+                memcpy(entry.MIMEType, psMimeType, sizeof(Str255));
+                memcpy(entry.entryName, psDescription, sizeof(Str255));
+
+                status = ICAddMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, &entry);
+
+                if(status == noErr)
+                {
+                    //kICAttrNoChange means we don't care about attributes such as
+                    //locking in the database
+         //           status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping,
+           //                                  kICAttrNoChange, (Handle) m_hDatabase);
+
+                    //return the entry in the database if successful
+             //       if(status == noErr)
+                        return GetFileTypeFromExtension(ftInfo.GetMimeType());
+             //       else
+              //      {
+               //         wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetPrefHandle failed.")));
+               //     }
+                }
+                else
+                {
+                    wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICAppMapEntry failed.")));
+                }
+            }
+        } //end if FindApplcation was successful
+        else
+        {
+            wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("FindApplication failed.")));
+        }
+    } //end if it could obtain app's signature
+    else
+    {
+        wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("GetProcessSignature failed.")));
+    }
     return NULL;
 }
 
 bool
-wxMimeTypesManagerImpl::Unassociate(wxFileType *ft)
+wxMimeTypesManagerImpl::Unassociate(wxFileType *pFileType)
 {
-    return FALSE;
+    wxASSERT(pFileType);
+    bool bInfoSuccess = false;
+
+    wxArrayString asExtensions;
+    pFileType->GetExtensions(asExtensions);
+
+    if(!asExtensions.GetCount())
+    {
+        wxLogDebug(wxT("Must have extension to disassociate"));
+        return false;
+    }
+
+    //Find and write to Info.plist in main bundle (note that some other
+    //apps have theirs named differently, i.e. IE's is named Info-macos.plist
+    //some apps (non-wx) use the 'plst' resource instead
+    CFBundleRef cfbMain = CFBundleGetMainBundle();
+    if(cfbMain)
+    {
+        UInt32 dwBundleType, dwBundleCreator;
+        CFBundleGetPackageInfo(cfbMain, &dwBundleType, &dwBundleCreator);
+
+        //if launching terminal non-app version will be 'BNDL' (generic bundle, maybe in other cases too),
+        //which will give us the incorrect info.plist path
+        //otherwise it will be 'APPL', or in the case of a framework,
+        //'FMWK'
+        if(dwBundleType == 'APPL')
+        {
+
+            wxCFURL cfurlBundleLoc((CFTypeRef)CFBundleCopyBundleURL(cfbMain));
+//             wxCFURL cfurlBundleLoc((CFTypeRef)CFBundleCopyExecutableURL(cfbMain));
+            wxString sInfoPath;
+//            sInfoPath << wxT("file://");
+            sInfoPath << cfurlBundleLoc.BuildWXString();
+            sInfoPath << wxT("Contents/Info.plist");
+
+//        wxCFDictionary cfdInfo( (CFTypeRef) CFBundleGetInfoDictionary(cfbMain), wxCF_RETAIN );
+            wxCFDictionary cfdInfo;
+            bool bInfoOpenSuccess = false;
+            wxFile indictfile;
+            if(indictfile.Open(sInfoPath, wxFile::read))
+            {
+                CFIndex cfiBufLen = (CFIndex) indictfile.Length();
+                const UInt8* pBuffer = new UInt8[cfiBufLen];
+                indictfile.Read((void*)pBuffer, cfiBufLen);
+                wxCFData cfdaInDict(pBuffer, cfiBufLen);
+                wxString sError;
+                bInfoOpenSuccess = cfdInfo.ReadAsXML(cfdaInDict, &sError);
+                if(!bInfoOpenSuccess)
+                    wxLogDebug(sError);
+                indictfile.Close();
+            }
+            if(bInfoOpenSuccess)
+            {
+                cfdInfo.MakeMutable( cfdInfo.GetCount() + 1 );
+
+                wxCFArray cfaDocTypes( cfdInfo[ wxCFString(wxT("CFBundleDocumentTypes")) ], wxCF_RETAIN );
+
+                if(cfaDocTypes.IsOk())
+                {
+                    bool bEntryFound = false;
+
+                    //search for duplicate
+                    CFIndex i;
+                    for(i = 0; i < cfaDocTypes.GetCount(); ++i)
+                    {
+                        wxCFDictionary cfdDocTypeEntry( cfaDocTypes[i], wxCF_RETAIN );
+
+                        //A lot of apps dont do to mime types for some reason
+                        //so we go by extensions only
+                        wxCFArray cfaExtensions( cfdDocTypeEntry[ wxCFString(wxT("CFBundleTypeExtensions")) ],
+                                        wxCF_RETAIN );
+
+                        if(cfaExtensions.IsOk() == false)
+                            continue;
+
+                        for(CFIndex iExt = 0; iExt < cfaExtensions.GetCount(); ++iExt)
+                        {
+                            for (size_t iWXExt = 0; iWXExt < asExtensions.GetCount(); ++iWXExt)
+                            {
+                                if(asExtensions[iWXExt] ==
+                                    wxCFString(cfaExtensions[iExt], wxCF_RETAIN).BuildWXString())
+                                {
+                                    bEntryFound = true;
+                                    cfaDocTypes.Remove(i);
+                                    cfdInfo.Set( wxCFString(wxT("CFBundleDocumentTypes")) , cfaDocTypes );
+                                    break;
+                                }
+                            } //end of wxstring array
+
+                            if(bEntryFound)
+                                break;
+                        } //end for cf array
+
+                        if(bEntryFound)
+                            break;
+                    }//end for doctypes
+
+                    if(bEntryFound)
+                    {
+                        cfdInfo.MakeValidXML();
+
+                        wxFile outdictfile;
+                        if(outdictfile.Open(sInfoPath, wxFile::write))
+                        {
+                            wxCFData cfdaInfo(cfdInfo.WriteAsXML());
+                            if(cfdaInfo.IsOk())
+                            {
+                                if(outdictfile.Write(cfdaInfo.GetValue(), cfdaInfo.GetCount()) !=
+                                    (wxFileOffset)cfdaInfo.GetCount())
+                                {
+                                    wxLogDebug(wxT("error in writing to file"));
+                                }
+                                else
+                                {
+                                    bInfoSuccess = true;
+//#if defined(__DARWIN__)
+//                //force launch services to update its database for the finder
+//                OSStatus status = LSRegisterURL((CFURLRef)(CFTypeRef)cfurlBundleLoc, true);
+//                if(status != noErr)
+//                {
+//                    wxLogDebug(wxT("LSRegisterURL Failed."));
+//                }
+//#endif
+                                }
+                                outdictfile.Close();
+                            }
+                            else
+                            {
+                                outdictfile.Close();
+                                wxLogDebug(wxT("Could not read in new dictionary"));
+                            }
+                        }
+                        else
+                        {
+                            wxLogDebug(wxString(wxT("Could not open [")) +
+                            sInfoPath + wxT("] for writing."));
+                        }
+                    }
+                    else
+                    {
+                        wxLogDebug(wxT("Entry not found to remove"));
+                        wxString sPrintOut;
+                        wxCFDictionary::PrintOutArray(sPrintOut, (CFArrayRef)(CFTypeRef)cfaDocTypes);
+                        wxLogDebug(sPrintOut);
+                        for(size_t i = 0; i < asExtensions.GetCount(); ++i)
+                            wxLogDebug(asExtensions[i]);
+                    }
+                }
+                else
+                {
+                    wxLogDebug(wxT("No doc types array found"));
+                    wxString sPrintOut;  cfdInfo.PrintOut(sPrintOut);  wxLogDebug(sPrintOut);
+                }
+            }
+            else
+            {
+                wxLogDebug(wxT("No info dictionary in main bundle"));
+            }
+        }
+        else
+        {
+            wxLogDebug(wxT("Can only call associate from bundled app within XXX.app"));
+        }
+    }
+    else
+    {
+        wxLogDebug(wxT("No main bundle"));
+    }
+
+#if defined(__DARWIN__)
+    if(!bInfoSuccess)
+        return false;
+#endif
+
+    //this should be as easy as removing the entry from the database and then saving
+    //the database
+    OSStatus status = ICDeleteMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase,
+                            pFileType->m_impl->m_lIndex);
+
+    if(status == noErr)
+    {
+        //kICAttrNoChange means we don't care about attributes such as
+        //locking in the database
+//        status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping,
+//                    kICAttrNoChange, (Handle) m_hDatabase);
+
+//        if(status == noErr)
+            return true;
+//        else
+//        {
+//            wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetPrefHandle failed.")));
+//        }
+
+    }
+    else
+    {
+        wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICDeleteMapEntry failed.")));
+    }
+
+    return false;
 }
+/*
+                    CFWriteStreamRef cfwsInfo = CFWriteStreamCreateWithFile(
+                                        kCFAllocatorDefault,
+                                        (CFURLRef) (CFTypeRef)cfurlInfoLoc );
+
+//                CFShow(cfdInfo);
+                    if(cfwsInfo)
+                    {
+                        Boolean bOpened = CFWriteStreamOpen(cfwsInfo);
+                        if(bOpened)
+                        {
+                            CFStringRef cfsError;
+                            CFIndex cfiWritten = CFPropertyListWriteToStream((CFPropertyListRef)(CFTypeRef)cfdInfo,
+                                                cfwsInfo,
+                                                kCFPropertyListXMLFormat_v1_0, //100
+                                                &cfsError);
+                            if(cfsError && cfiWritten == 0)
+                            {
+                                wxLogDebug(wxCFString(cfsError).BuildWXString());
+                                wxString sMessage;
+                                cfdInfo.PrintOut(sMessage);
+                                wxLogDebug(sMessage);
+                            }
+                            else
+                            {
+                                bInfoSuccess = true;
+//#if defined(__DARWIN__)
+//                //force launch services to update its database for the finder
+//                OSStatus status = LSRegisterURL((CFURLRef)(CFTypeRef)cfurlBundleLoc, true);
+//                if(status != noErr)
+//                {
+//                    wxLogDebug(wxT("LSRegisterURL Failed."));
+//                }
+//#endif
+                            }
+
+                            CFWriteStreamClose(cfwsInfo);
 
+*/
+#endif //wxUSE_MIMETYPE