📄 mimetmac.cpp
字号:
// 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)
{
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.")));
}
// failure - cleanup
delete pFileType;
}
else
{
// TODO: Maybe force all 3 of these to be non-empty?
Str255 psExtension, psMimeType, psDescription;
wxMacStringToPascal(wxString(wxT(".")) + ftInfo.GetExtensions()[0], psExtension);
wxMacStringToPascal(ftInfo.GetMimeType(), psMimeType);
wxMacStringToPascal(ftInfo.GetDescription(), psDescription);
Str255 psPostCreatorName;
wxMacStringToPascal(wxEmptyString, 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)
{
return GetFileTypeFromExtension(ftInfo.GetMimeType());
// 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 *pFileType)
{
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())
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)
{
return true;
//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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -