From: Ryan Norton Date: Mon, 18 Apr 2005 21:23:11 +0000 (+0000) Subject: Some corefoundation wrappers, Implement Associate and Unassociate for mac mime types X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/dd9b4b7f114427e2fc089c4f1b2d4d43d7b003d4?ds=inline Some corefoundation wrappers, Implement Associate and Unassociate for mac mime types git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33732 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/mac/corefoundation/cfstring.h b/include/wx/mac/corefoundation/cfstring.h index 428e5c8c14..526f5791a5 100644 --- a/include/wx/mac/corefoundation/cfstring.h +++ b/include/wx/mac/corefoundation/cfstring.h @@ -9,6 +9,9 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +#ifndef __WX_CFSTRINGHOLDER_H__ +#define __WX_CFSTRINGHOLDER_H__ + #ifdef __DARWIN__ #include #else @@ -70,7 +73,7 @@ public: void Assign( const wxString &str , wxFontEncoding encoding ) ; - operator CFStringRef () { return m_cfs; } + operator CFStringRef () const { return m_cfs; } wxString AsString( wxFontEncoding encoding = wxFONTENCODING_DEFAULT ) ; private: @@ -81,3 +84,4 @@ private: DECLARE_NO_COPY_CLASS( wxMacCFStringHolder ) } ; +#endif //__WXCFSTRINGHOLDER_H__ diff --git a/include/wx/mac/corefoundation/cfwrappers.h b/include/wx/mac/corefoundation/cfwrappers.h new file mode 100644 index 0000000000..ac6d3aa227 --- /dev/null +++ b/include/wx/mac/corefoundation/cfwrappers.h @@ -0,0 +1,536 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/mac/corefoundation/cfwrappers.h +// Purpose: Wrappers around some complex core foundation types +// Author: Ryan Norton +// Modified by: +// Created: 17/04/2005 +// RCS-ID: $Id$ +// Copyright: (c) 2005 Ryan Norton +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __WX_CFWRAPPERS_H__ +#define __WX_CFWRAPPERS_H__ + +#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) + { + m_cfmdRef = (CFMutableDictionaryRef) ref; + if(bRetain == wxCF_RETAIN && ref) + CFRetain(ref); + } + + wxCFDictionary(CFIndex cfiSize = 0) + { + CFDictionaryKeyCallBacks kcbs; + CFDictionaryValueCallBacks vcbs; + BuildKeyCallbacks(&kcbs); + BuildValueCallbacks(&vcbs); + + m_cfmdRef = CFDictionaryCreateMutable( + kCFAllocatorDefault, cfiSize, &kcbs, &vcbs); + + } + + ~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) + { + CFDictionaryRef oldref = (CFDictionaryRef) m_cfmdRef; + + m_cfmdRef = CFDictionaryCreateMutableCopy( + kCFAllocatorDefault, + cfiSize, + oldref); + + CFRelease(oldref); + } + + void BuildKeyCallbacks(CFDictionaryKeyCallBacks* pCbs) + { + pCbs->version = 0; + pCbs->retain = RetainProc; + pCbs->release = ReleaseProc; + pCbs->copyDescription = NULL; + pCbs->equal = NULL; + pCbs->hash = NULL; + } + + void BuildValueCallbacks(CFDictionaryValueCallBacks* pCbs) + { + pCbs->version = 0; + pCbs->retain = RetainProc; + pCbs->release = ReleaseProc; + pCbs->copyDescription = NULL; + pCbs->equal = NULL; + } + + 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 + { + wxASSERT(IsValid()); + return (CFTypeRef) CFDictionaryGetValue((CFDictionaryRef)m_cfmdRef, cftEntry); + } + + CFIndex GetCount() const + { + wxASSERT(IsValid()); + return CFDictionaryGetCount((CFDictionaryRef)m_cfmdRef); + } + + void Add(CFTypeRef cftKey, CFTypeRef cftValue) + { + wxASSERT(IsValid()); + wxASSERT(Exists(cftKey) == false); + CFDictionaryAddValue(m_cfmdRef, cftKey, cftValue); + } + + void Remove(CFTypeRef cftKey) + { + wxASSERT(IsValid()); + wxASSERT(Exists(cftKey)); + CFDictionaryRemoveValue(m_cfmdRef, cftKey); + } + + void Set(CFTypeRef cftKey, CFTypeRef cftValue) + { + wxASSERT(IsValid()); + wxASSERT(Exists(cftKey)); + CFDictionarySetValue(m_cfmdRef, cftKey, cftValue); + } + + bool Exists(CFTypeRef cftKey) const + { + wxASSERT(IsValid()); + return CFDictionaryContainsKey((CFDictionaryRef)m_cfmdRef, cftKey) == true; + } + + 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, 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 +{ +public: + wxCFArray(CFTypeRef ref, bool bRetain = wxCF_RELEASE) + { + m_cfmaRef = (CFMutableArrayRef)ref; + if(bRetain == wxCF_RETAIN && ref) + CFRetain(ref); + } + + 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 +{ +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); } + + + 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, bool bRetain = wxCF_RELEASE) : m_cfurlRef((CFURLRef)ref) + { + if(bRetain == wxCF_RETAIN && ref) + CFRetain(ref); + } + wxCFURL(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; +}; + +#endif //__WX_CFWRAPPERS_H__ \ No newline at end of file diff --git a/include/wx/mac/corefoundation/hid.h b/include/wx/mac/corefoundation/hid.h index 3789e81ff3..6ea4535f3a 100644 --- a/include/wx/mac/corefoundation/hid.h +++ b/include/wx/mac/corefoundation/hid.h @@ -41,16 +41,7 @@ #include -//Utility wrapper around CFArray -class wxCFArray -{ -public: - wxCFArray(CFTypeRef pData) : pArray((CFArrayRef) pData) {} - CFTypeRef operator [] (const int& nIndex) {return CFArrayGetValueAtIndex(pArray, nIndex); } - int Count() {return CFArrayGetCount(pArray);} -private: - CFArrayRef pArray; -}; +#include "wx/mac/corefoundation/cfwrappers.h" // // A wrapper around OS X HID Manager procedures. diff --git a/src/mac/carbon/mimetmac.cpp b/src/mac/carbon/mimetmac.cpp index 5663744e77..87a187113c 100644 --- a/src/mac/carbon/mimetmac.cpp +++ b/src/mac/carbon/mimetmac.cpp @@ -754,13 +754,333 @@ pascal OSStatus MoreProcGetProcessTypeSignature( return anErr; }//end MoreProcGetProcessTypeSignature -wxFileType * -wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) +#include "wx/mac/corefoundation/cfwrappers.h" + +void wxCFDictionary::MakeValidXML() { -#if 1 - wxFAIL_MSG(wxT("Associate not ready for production use")); - return NULL; -#else + { + 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() ) == false ) + { + 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; + } +} + +void wxCFArray::MakeValidXML() +{ +{ + 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() ) == false ) + { + Remove(i); + --i; + } + } + } +} + +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( (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 ); + + 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... @@ -781,7 +1101,7 @@ wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) //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 = GetFileTypeFromMimeType(ftInfo.GetMimeType()); + wxFileType* pFileType = GetFileTypeFromExtension(asExtensions[dwFoundIndex]); if(pFileType) { ICMapEntry entry; @@ -796,7 +1116,18 @@ wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) //success if(status == noErr) - return pFileType; + { + //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."))); @@ -821,7 +1152,6 @@ wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) //add the entry to the database - //TODO: Does this work? ICMapEntry entry; entry.totalLength = sizeof(ICMapEntry); entry.fixedLength = kICMapFixedLength; @@ -842,16 +1172,16 @@ wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) { //kICAttrNoChange means we don't care about attributes such as //locking in the database - status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping, - kICAttrNoChange, (Handle) m_hDatabase); + // status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping, + // kICAttrNoChange, (Handle) m_hDatabase); //return the entry in the database if successful - if(status == noErr) - return GetFileTypeFromMimeType(ftInfo.GetMimeType()); - else - { - wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetPrefHandle failed."))); - } + // if(status == noErr) + return GetFileTypeFromExtension(ftInfo.GetMimeType()); + // else + // { + // wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("ICSetPrefHandle failed."))); + // } } else { @@ -869,16 +1199,185 @@ wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo) wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__, wxT("GetProcessSignature failed."))); } return NULL; -#endif } bool wxMimeTypesManagerImpl::Unassociate(wxFileType *pFileType) { -#if 1 - wxFAIL_MSG(wxT("Unassociate not ready for production use")); - return FALSE; -#else + 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 NULL; +#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, @@ -888,15 +1387,15 @@ wxMimeTypesManagerImpl::Unassociate(wxFileType *pFileType) { //kICAttrNoChange means we don't care about attributes such as //locking in the database - status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping, - kICAttrNoChange, (Handle) m_hDatabase); +// status = ICSetPrefHandle((ICInstance) m_hIC, kICMapping, +// kICAttrNoChange, (Handle) m_hDatabase); - if(status == noErr) +// 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("ICSetPrefHandle failed."))); +// } } else @@ -905,7 +1404,44 @@ wxMimeTypesManagerImpl::Unassociate(wxFileType *pFileType) } return FALSE; -#endif } +/* + 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 \ No newline at end of file diff --git a/src/mac/corefoundation/hid.cpp b/src/mac/corefoundation/hid.cpp index f3e2f937f9..dc115dccf1 100644 --- a/src/mac/corefoundation/hid.cpp +++ b/src/mac/corefoundation/hid.cpp @@ -347,7 +347,7 @@ void wxHIDKeyboard::BuildCookies(wxCFArray& Array) InitCookies(500); int i, nUsage; - for (i = 0; i < Array.Count(); ++i) + for (i = 0; i < Array.GetCount(); ++i) { CFNumberGetValue( (CFNumberRef) CFDictionaryGetValue((CFDictionaryRef) Array[i], CFSTR(kIOHIDElementUsageKey)), diff --git a/src/mac/corefoundation/hidjoystick.cpp b/src/mac/corefoundation/hidjoystick.cpp index 780c1b5ca6..0d6ed6b2dc 100644 --- a/src/mac/corefoundation/hidjoystick.cpp +++ b/src/mac/corefoundation/hidjoystick.cpp @@ -91,7 +91,7 @@ void wxHIDJoystick::MakeCookies(wxCFArray& Array) int i, nUsage, nPage; - for (i = 0; i < Array.Count(); ++i) + for (i = 0; i < Array.GetCount(); ++i) { const void* ref = CFDictionaryGetValue((CFDictionaryRef)Array[i], CFSTR(kIOHIDElementKey));