1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/mimetype.cpp
3 // Purpose: Mac Carbon implementation for wx mime-related classes
8 // Copyright: (c) 2005 Ryan Norton (<wxprojects@comcast.net>)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "mimetype.h"
16 // for compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
24 #include "wx/string.h"
36 #include "wx/dynarray.h"
37 #include "wx/confbase.h"
39 #include "wx/mac/mimetype.h"
40 #include "wx/mac/private.h" //wxMacMakeStringFromPascal
42 // other standard headers
44 #include <InternetConfig.h> //For mime types
47 /* START CODE SAMPLE FROM TECHNOTE 1002 (http://developer.apple.com/technotes/tn/tn1002.html) */
49 /* IsRemoteVolume can be used to find out if the
50 volume referred to by vRefNum is a remote volume
51 located somewhere on a network. the volume's attribute
52 flags (copied from the GetVolParmsInfoBuffer structure)
53 are returned in the longword pointed to by vMAttrib. */
54 OSErr
IsRemoteVolume(short vRefNum
, Boolean
*isRemote
, long *vMAttrib
) {
56 GetVolParmsInfoBuffer volinfo
;
58 volPB
.ioParam
.ioVRefNum
= vRefNum
;
59 volPB
.ioParam
.ioNamePtr
= NULL
;
60 volPB
.ioParam
.ioBuffer
= (Ptr
) &volinfo
;
61 volPB
.ioParam
.ioReqCount
= sizeof(volinfo
);
62 err
= PBHGetVolParmsSync(&volPB
);
64 *isRemote
= (volinfo
.vMServerAdr
!= 0);
65 *vMAttrib
= volinfo
.vMAttrib
;
71 /* BuildVolumeList fills the array pointed to by vols with
72 a list of the currently mounted volumes. If includeRemote
73 is true, then remote server volumes will be included in
74 the list. When remote server volumes are included in the
75 list, they will be added to the end of the list. On entry,
76 *count should contain the size of the array pointed to by
77 vols. On exit, *count will be set to the number of id numbers
78 placed in the array. If vMAttribMask is non-zero, then
79 only volumes with matching attributes are added to the
80 list of volumes. bits in the vMAttribMask should use the
81 same encoding as bits in the vMAttrib field of
82 the GetVolParmsInfoBuffer structure. */
83 OSErr
BuildVolumeList(Boolean includeRemote
, short *vols
,
84 long *count
, long vMAttribMask
) {
91 /* set up and check parameters */
92 volPB
.volumeParam
.ioNamePtr
= NULL
;
94 if (*count
== 0) return noErr
;
96 /* iterate through volumes */
97 for (volPB
.volumeParam
.ioVolIndex
= 1;
98 PBHGetVInfoSync(&volPB
) == noErr
;
99 volPB
.volumeParam
.ioVolIndex
++) {
101 /* skip remote volumes, if necessary */
102 err
= IsRemoteVolume(volPB
.volumeParam
.ioVRefNum
, &isRemote
, &vMAttrib
);
103 if (err
!= noErr
) goto bail
;
104 if ( ( includeRemote
|| ! isRemote
)
105 && (vMAttrib
& vMAttribMask
) == vMAttribMask
) {
107 /* add local volumes at the front, remote
108 volumes at the end */
110 vols
[nlocal
+ nremote
++] = volPB
.volumeParam
.ioVRefNum
;
113 BlockMoveData(vols
+nlocal
, vols
+nlocal
+1,
114 nremote
*sizeof(short));
115 vols
[nlocal
++] = volPB
.volumeParam
.ioVRefNum
;
119 if ((nlocal
+ nremote
) >= *count
) break;
123 *count
= (nlocal
+ nremote
);
128 /* FindApplication iterates through mounted volumes
129 searching for an application with the given creator
130 type. If includeRemote is true, then remote volumes
131 will be searched (after local ones) for an application
132 with the creator type. */
136 /* Hacked to output to appName */
138 OSErr
FindApplication(OSType appCreator
, Boolean includeRemote
, Str255 appName
, FSSpec
* appSpec
) {
139 short rRefNums
[kMaxVols
];
144 /* get a list of volumes - with desktop files */
146 err
= BuildVolumeList(includeRemote
, rRefNums
, &volCount
,
147 (1<<bHasDesktopMgr
) );
148 if (err
!= noErr
) return err
;
150 /* iterate through the list */
151 for (i
=0; i
<volCount
; i
++) {
153 /* has a desktop file? */
154 desktopPB
.ioCompletion
= NULL
;
155 desktopPB
.ioVRefNum
= rRefNums
[i
];
156 desktopPB
.ioNamePtr
= NULL
;
157 desktopPB
.ioIndex
= 0;
158 err
= PBDTGetPath(&desktopPB
);
159 if (err
!= noErr
) continue;
161 /* has the correct app?? */
162 desktopPB
.ioFileCreator
= appCreator
;
163 desktopPB
.ioNamePtr
= appName
;
164 err
= PBDTGetAPPLSync(&desktopPB
);
165 if (err
!= noErr
) continue;
167 /* make a file spec referring to it */
168 err
= FSMakeFSSpec(rRefNums
[i
],
169 desktopPB
.ioAPPLParID
, appName
,
171 if (err
!= noErr
) continue;
180 /* END CODE SAMPLE FROM TECHNOTE 1002 (http://developer.apple.com/technotes/tn/tn1002.html) */
182 //yeah, duplicated code
183 pascal OSErr
FSpGetFullPath(const FSSpec
*spec
,
184 short *fullPathLength
,
196 /* Default to noErr */
197 realResult
= result
= noErr
;
199 /* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
201 if ( spec->name[0] == 0 )
203 result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
208 /* Make a copy of the input FSSpec that can be modified */
209 BlockMoveData(spec
, &tempSpec
, sizeof(FSSpec
));
212 if ( result
== noErr
)
214 if ( tempSpec
.parID
== fsRtParID
)
216 /* The object is a volume */
218 /* Add a colon to make it a full pathname */
220 tempSpec
.name
[tempSpec
.name
[0]] = ':';
223 result
= PtrToHand(&tempSpec
.name
[1], fullPath
, tempSpec
.name
[0]);
227 /* The object isn't a volume */
229 /* Is the object a file or a directory? */
230 pb
.dirInfo
.ioNamePtr
= tempSpec
.name
;
231 pb
.dirInfo
.ioVRefNum
= tempSpec
.vRefNum
;
232 pb
.dirInfo
.ioDrDirID
= tempSpec
.parID
;
233 pb
.dirInfo
.ioFDirIndex
= 0;
234 result
= PBGetCatInfoSync(&pb
);
235 /* Allow file/directory name at end of path to not exist. */
237 if ( (result
== noErr
) || (result
== fnfErr
) )
239 /* if the object is a directory, append a colon so full pathname ends with colon */
240 if ( (result
== noErr
) && (pb
.hFileInfo
.ioFlAttrib
& kioFlAttribDirMask
) != 0 )
243 tempSpec
.name
[tempSpec
.name
[0]] = ':';
246 /* Put the object name in first */
247 result
= PtrToHand(&tempSpec
.name
[1], fullPath
, tempSpec
.name
[0]);
248 if ( result
== noErr
)
250 /* Get the ancestor directory names */
251 pb
.dirInfo
.ioNamePtr
= tempSpec
.name
;
252 pb
.dirInfo
.ioVRefNum
= tempSpec
.vRefNum
;
253 pb
.dirInfo
.ioDrParID
= tempSpec
.parID
;
254 do /* loop until we have an error or find the root directory */
256 pb
.dirInfo
.ioFDirIndex
= -1;
257 pb
.dirInfo
.ioDrDirID
= pb
.dirInfo
.ioDrParID
;
258 result
= PBGetCatInfoSync(&pb
);
259 if ( result
== noErr
)
261 /* Append colon to directory name */
263 tempSpec
.name
[tempSpec
.name
[0]] = ':';
265 /* Add directory name to beginning of fullPath */
266 (void) Munger(*fullPath
, 0, NULL
, 0, &tempSpec
.name
[1], tempSpec
.name
[0]);
269 } while ( (result
== noErr
) && (pb
.dirInfo
.ioDrDirID
!= fsRtDirID
) );
275 if ( result
== noErr
)
277 /* Return the length */
278 *fullPathLength
= GetHandleSize(*fullPath
);
279 result
= realResult
; /* return realResult in case it was fnfErr */
283 /* Dispose of the handle and return NULL and zero length */
284 if ( *fullPath
!= NULL
)
286 DisposeHandle(*fullPath
);
296 // On the mac there are two ways to open a file - one is through apple events and the
297 // finder, another is through mime types.
299 // So, really there are two ways to implement wxFileType...
301 // Mime types are only available on OS 8.1+ through the InternetConfig API
303 // Much like the old-style file manager, it has 3 levels of flexibility for its methods -
304 // Low - which means you have to iterate yourself through the mime database
305 // Medium - which lets you sort of cache the database if you want to use lowlevel functions
306 // High - which requires access to the database every time
308 // We want to be efficient (i.e. professional :) ) about it, so we use a combo of low
309 // and mid-level functions
311 // TODO: Should we call ICBegin/ICEnd? Then where?
315 inline void wxLogMimeDebug(const wxChar
* szMsg
, OSStatus status
)
317 wxLogDebug(wxString::Format(wxT("%s LINE:%i OSERROR:%i"), szMsg
, __LINE__
, (int)status
));
320 // in case we're compiling in non-GUI mode
321 class WXDLLEXPORT wxIcon
;
323 bool wxFileTypeImpl::SetCommand(const wxString
& cmd
, const wxString
& verb
, bool overwriteprompt
)
325 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
330 bool wxFileTypeImpl::SetDefaultIcon(const wxString
& strIcon
, int index
)
332 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
337 bool wxFileTypeImpl::GetOpenCommand(wxString
*openCmd
,
338 const wxFileType::MessageParameters
& params
) const
340 wxString cmd
= GetCommand(wxT("open"));
342 *openCmd
= wxFileType::ExpandCommand(cmd
, params
);
344 return !openCmd
->empty();
348 wxFileTypeImpl::GetPrintCommand(wxString
*printCmd
,
349 const wxFileType::MessageParameters
& params
)
352 wxString cmd
= GetCommand(wxT("print"));
354 *printCmd
= wxFileType::ExpandCommand(cmd
, params
);
356 return !printCmd
->empty();
360 // Internet Config vs. Launch Services
362 // From OS 8 on there was internet config...
363 // However, OSX and its finder does not use info
364 // from Internet Config at all - the Internet Config
365 // database ONLY CONTAINS APPS THAT ARE CLASSIC APPS
366 // OR REGISTERED THROUGH INTERNET CONFIG
368 // Therefore on OSX in order for the open command to be useful
369 // we need to go straight to launch services
372 #if defined(__DARWIN__)
374 //on darwin, use launch services
375 #include "LaunchServices.h"
377 wxString
wxFileTypeImpl::GetCommand(const wxString
& verb
) const
379 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
381 if(verb
== wxT("open"))
384 ICGetMapEntry( (ICInstance
) m_manager
->m_hIC
,
385 (Handle
) m_manager
->m_hDatabase
,
388 wxString sCurrentExtension
= wxMacMakeStringFromPascal(entry
.extension
);
389 sCurrentExtension
= sCurrentExtension
.Right(sCurrentExtension
.Length()-1 );
391 //type, creator, ext, roles, outapp (FSRef), outappurl
392 CFURLRef cfurlAppPath
;
393 OSStatus status
= LSGetApplicationForInfo (kLSUnknownType
,
395 wxMacCFStringHolder(sCurrentExtension
, wxLocale::GetSystemEncoding()),
402 CFStringRef cfsUnixPath
= CFURLCopyFileSystemPath(cfurlAppPath
, kCFURLPOSIXPathStyle
);
403 CFRelease(cfurlAppPath
);
407 return wxMacCFStringHolder(cfsUnixPath
).AsString(wxLocale::GetSystemEncoding());
411 wxLogDebug(wxString::Format(wxT("%i - %s - %i"),
413 wxT("LSGetApplicationForInfo failed."),
418 return wxEmptyString
;
421 #else //carbon/classic implementation
423 wxString
wxFileTypeImpl::GetCommand(const wxString
& verb
) const
425 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
427 if(verb
== wxT("open"))
430 ICGetMapEntry( (ICInstance
) m_manager
->m_hIC
,
431 (Handle
) m_manager
->m_hDatabase
,
434 //The entry in the mimetype database only contains the app
435 //that's registered - it may not exist... we need to remap the creator
436 //type and find the right application
438 // THIS IS REALLY COMPLICATED :\. There are a lot of conversions going
442 if(FindApplication(entry
.fileCreator
, false, outName
, &outSpec
) != noErr
)
443 return wxEmptyString
;
445 Handle outPathHandle
;
447 OSErr err
= FSpGetFullPath(&outSpec
, &outPathSize
, &outPathHandle
);
451 char* szPath
= *outPathHandle
;
452 wxString
sClassicPath(szPath
, wxConvLocal
, outPathSize
);
453 #if defined(__DARWIN__)
454 //Classic Path --> Unix (OSX) Path
455 CFURLRef finalURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
,
456 wxMacCFStringHolder(sClassicPath
, wxLocale::GetSystemEncoding()),
458 false); //false == not a directory
460 //clean up memory from the classic path handle
461 DisposeHandle(outPathHandle
);
465 CFStringRef cfsUnixPath
= CFURLCopyFileSystemPath(finalURL
, kCFURLPOSIXPathStyle
);
470 return wxMacCFStringHolder(cfsUnixPath
).AsString(wxLocale::GetSystemEncoding());
472 #else //classic HFS path acceptable
478 wxLogMimeDebug(wxT("FSpGetFullPath failed."), (OSStatus
)err
);
481 return wxEmptyString
;
485 bool wxFileTypeImpl::GetDescription(wxString
*desc
) const
487 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
490 ICGetMapEntry( (ICInstance
) m_manager
->m_hIC
,
491 (Handle
) m_manager
->m_hDatabase
,
494 *desc
= wxMacMakeStringFromPascal(entry
.entryName
);
498 bool wxFileTypeImpl::GetExtensions(wxArrayString
& extensions
)
500 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
503 ICGetMapEntry( (ICInstance
) m_manager
->m_hIC
,
504 (Handle
) m_manager
->m_hDatabase
,
507 //entry has period in it
508 wxString sCurrentExtension
= wxMacMakeStringFromPascal(entry
.extension
);
509 extensions
.Add( sCurrentExtension
.Right(sCurrentExtension
.Length()-1) );
513 bool wxFileTypeImpl::GetMimeType(wxString
*mimeType
) const
515 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
518 ICGetMapEntry( (ICInstance
) m_manager
->m_hIC
,
519 (Handle
) m_manager
->m_hDatabase
,
522 *mimeType
= wxMacMakeStringFromPascal(entry
.MIMEType
);
526 bool wxFileTypeImpl::GetMimeTypes(wxArrayString
& mimeTypes
) const
540 bool wxFileTypeImpl::GetIcon(wxIconLocation
*WXUNUSED(icon
)) const
542 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
544 // no such file type or no value or incorrect icon entry
548 size_t wxFileTypeImpl::GetAllCommands(wxArrayString
* verbs
, wxArrayString
* commands
,
549 const wxFileType::MessageParameters
& params
) const
551 wxASSERT_MSG( m_manager
!= NULL
, wxT("Bad wxFileType") );
556 if(GetOpenCommand(&sCommand
, params
))
558 verbs
->Add(wxString(wxT("open")));
559 commands
->Add(sCommand
);
566 void wxMimeTypesManagerImpl::Initialize(int mailcapStyles
, const wxString
& extraDir
)
568 wxASSERT_MSG(m_hIC
== NULL
, wxT("Already initialized wxMimeTypesManager!"));
570 //start internet config - log if there's an error
571 //the second param is the signature of the application, also known
572 //as resource ID 0. However, as per some recent discussions, we may not
573 //have a signature for this app, so a generic 'APPL' which is the executable
574 //type will work for now
575 OSStatus status
= ICStart( (ICInstance
*) &m_hIC
, 'APPL');
579 wxLogDebug(wxT("Could not initialize wxMimeTypesManager!"));
586 m_hDatabase
= (void**) NewHandle(0);
587 status
= ICFindPrefHandle( (ICInstance
) m_hIC
, kICMapping
, &attr
, (Handle
) m_hDatabase
);
589 //the database file can be corrupt (on OSX its
590 //~/Library/Preferences/com.apple.internetconfig.plist)
595 wxLogDebug(wxT("Corrupt Mime Database!"));
599 //obtain the number of entries in the map
600 status
= ICCountMapEntries( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
, &m_lCount
);
601 wxASSERT( status
== noErr
);
607 for(long i = 1; i <= m_lCount; ++i)
609 OSStatus status = ICGetIndMapEntry( (ICInstance) m_hIC, (Handle) m_hDatabase, i, &pos, &entry);
613 wxString sCreator = wxMacMakeStringFromPascal(entry.creatorAppName);
614 wxString sCurrentExtension = wxMacMakeStringFromPascal(entry.extension);
615 wxString sMIMEType = wxMacMakeStringFromPascal(entry.MIMEType);
618 impl.Init(this, pos);
620 if(sMIMEType == wxT("text/html") && sCurrentExtension == wxT(".html"))
623 impl.GetOpenCommand (&cmd,
624 wxFileType::MessageParameters (wxT("http://www.google.com"),
627 wxPrintf(wxT("APP: [%s]\n"), cmd.c_str());
634 void wxMimeTypesManagerImpl::ClearData()
638 DisposeHandle((Handle
)m_hDatabase
);
639 //this can return an error, but we don't really care that much about it
640 ICStop( (ICInstance
) m_hIC
);
646 // Q) Iterating through the map - why does it use if (err == noErr) instead of just asserting?
647 // A) Some intermediate indexes are bad while subsequent ones may be good. Its wierd, I know.
650 // extension -> file type
651 wxFileType
* wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString
& e
)
653 wxASSERT_MSG( m_hIC
!= NULL
, wxT("wxMimeTypesManager not Initialized!") );
655 //low level functions - iterate through the database
659 for(long i
= 1; i
<= m_lCount
; ++i
)
661 OSStatus status
= ICGetIndMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
, i
, &pos
, &entry
);
665 wxString sCurrentExtension
= wxMacMakeStringFromPascal(entry
.extension
);
666 if( sCurrentExtension
.Right(sCurrentExtension
.Length()-1) == e
) //entry has period in it
668 wxFileType
* pFileType
= new wxFileType();
669 pFileType
->m_impl
->Init((wxMimeTypesManagerImpl
*)this, pos
);
678 // MIME type -> extension -> file type
679 wxFileType
* wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString
& mimeType
)
681 wxASSERT_MSG( m_hIC
!= NULL
, wxT("wxMimeTypesManager not Initialized!") );
683 //low level functions - iterate through the database
687 for(long i
= 1; i
<= m_lCount
; ++i
)
689 OSStatus status
= ICGetIndMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
, i
, &pos
, &entry
);
690 wxASSERT_MSG( status
== noErr
, wxString::Format(wxT("Error: %d"), (int)status
) );
694 if( wxMacMakeStringFromPascal(entry
.MIMEType
) == mimeType
)
696 wxFileType
* pFileType
= new wxFileType();
697 pFileType
->m_impl
->Init((wxMimeTypesManagerImpl
*)this, pos
);
706 size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString
& mimetypes
)
708 wxASSERT_MSG( m_hIC
!= NULL
, wxT("wxMimeTypesManager not Initialized!") );
710 //low level functions - iterate through the database
714 long lStartCount
= (long) mimetypes
.GetCount();
716 for(long i
= 1; i
<= m_lCount
; ++i
)
718 OSStatus status
= ICGetIndMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
, i
, &pos
, &entry
);
719 if( status
== noErr
)
720 mimetypes
.Add( wxMacMakeStringFromPascal(entry
.MIMEType
) );
723 return mimetypes
.GetCount() - lStartCount
;
727 pascal OSStatus
MoreProcGetProcessTypeSignature(
728 const ProcessSerialNumberPtr pPSN
,
729 OSType
*pProcessType
,
732 OSStatus anErr
= noErr
;
733 ProcessInfoRec infoRec
;
734 ProcessSerialNumber localPSN
;
736 infoRec
.processInfoLength
= sizeof(ProcessInfoRec
);
737 infoRec
.processName
= nil
;
738 infoRec
.processAppSpec
= nil
;
741 localPSN
.highLongOfPSN
= 0;
742 localPSN
.lowLongOfPSN
= kCurrentProcess
;
747 anErr
= GetProcessInformation(&localPSN
, &infoRec
);
750 *pProcessType
= infoRec
.processType
;
751 *pCreator
= infoRec
.processSignature
;
755 }//end MoreProcGetProcessTypeSignature
758 wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo
& ftInfo
)
761 wxFAIL_MSG(wxT("Associate not ready for production use"));
764 //on mac you have to embed it into the mac's file reference resource ('FREF' I believe)
765 //or, alternately, you could just add an entry to m_hDatabase, but you'd need to get
766 //the app's signature somehow...
770 OSStatus status
= MoreProcGetProcessTypeSignature(NULL
,&processType
, &creator
);
774 Str255 psCreatorName
;
776 status
= FindApplication(creator
, false, psCreatorName
, &dummySpec
);
781 //get the file type if it exists -
782 //if it really does then modify the database then save it,
783 //otherwise we need to create a whole new entry
784 wxFileType
* pFileType
= GetFileTypeFromMimeType(ftInfo
.GetMimeType());
788 ICGetMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
,
789 pFileType
->m_impl
->m_lIndex
, &entry
);
791 entry
.creatorAppName
= psCreatorName
;
792 entry
.fileCreator
= creator
;
794 status
= ICSetMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
,
795 pFileType
->m_impl
->m_lIndex
, &entry
);
802 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("ICSetMapEntry failed.")));
810 //TODO: Maybe force all 3 of these to be non-empty?
813 Str255 psDescription
;
815 wxMacStringToPascal(ftInfo
.GetExtensions()[0], psExtension
);
816 wxMacStringToPascal(ftInfo
.GetMimeType(), psMimeType
);
817 wxMacStringToPascal(ftInfo
.GetDescription(), psDescription
);
819 Str255 psPostCreatorName
;
820 wxMacStringToPascal(wxT(""), psPostCreatorName
);
823 //add the entry to the database
824 //TODO: Does this work?
826 entry
.totalLength
= sizeof(ICMapEntry
);
827 entry
.fixedLength
= kICMapFixedLength
;
829 entry
.fileType
= 0; //TODO: File type?
830 entry
.fileCreator
= creator
;
831 entry
.postCreator
= 0;
832 entry
.flags
= kICMapDataForkBit
; //TODO: Maybe resource is valid by default too?
833 entry
.extension
= psExtension
;
834 entry
.creatorAppName
= psCreatorName
;
835 entry
.postAppName
= psPostCreatorName
;
836 entry
.MIMEType
= psMimeType
;
837 entry
.entryName
= psDescription
;
839 status
= ICAddMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
, &entry
);
843 //kICAttrNoChange means we don't care about attributes such as
844 //locking in the database
845 status
= ICSetPrefHandle((ICInstance
) m_hIC
, kICMapping
,
846 kICAttrNoChange
, (Handle
) m_hDatabase
);
848 //return the entry in the database if successful
850 return GetFileTypeFromMimeType(ftInfo
.GetMimeType());
853 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("ICSetPrefHandle failed.")));
858 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("ICAppMapEntry failed.")));
861 } //end if FindApplcation was successful
864 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("FindApplication failed.")));
866 } //end if it could obtain app's signature
869 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("GetProcessSignature failed.")));
876 wxMimeTypesManagerImpl::Unassociate(wxFileType
*pFileType
)
879 wxFAIL_MSG(wxT("Unassociate not ready for production use"));
882 //this should be as easy as removing the entry from the database and then saving
884 OSStatus status
= ICDeleteMapEntry( (ICInstance
) m_hIC
, (Handle
) m_hDatabase
,
885 pFileType
->m_impl
->m_lIndex
);
889 //kICAttrNoChange means we don't care about attributes such as
890 //locking in the database
891 status
= ICSetPrefHandle((ICInstance
) m_hIC
, kICMapping
,
892 kICAttrNoChange
, (Handle
) m_hDatabase
);
898 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("ICSetPrefHandle failed.")));
904 wxLogDebug(wxString::Format(wxT("%i - %s"), __LINE__
, wxT("ICDeleteMapEntry failed.")));
911 #endif //wxUSE_MIMETYPE