X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1ccb7433ee436af9f5d908a5de561a48c83f2014..0bbe61b8c18a1795189f0cf73cc61c14a0fb846d:/src/mac/corefoundation/utilsexc_base.cpp diff --git a/src/mac/corefoundation/utilsexc_base.cpp b/src/mac/corefoundation/utilsexc_base.cpp index 855a605c6c..41172aed2d 100644 --- a/src/mac/corefoundation/utilsexc_base.cpp +++ b/src/mac/corefoundation/utilsexc_base.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: mac/corefoundation/utilsexc_base.cpp -// Purpose: wxMacExecute +// Purpose: wxMacLaunch // Author: Ryan Norton // Modified by: // Created: 2005-06-21 @@ -11,122 +11,217 @@ // to totally unrelated hid.cpp,1.8. ///////////////////////////////////////////////////////////////////////////// +//=========================================================================== +// DECLARATIONS +//=========================================================================== + +//--------------------------------------------------------------------------- +// Pre-compiled header stuff +//--------------------------------------------------------------------------- + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" + +// WX includes #ifndef WX_PRECOMP #include "wx/string.h" #include "wx/log.h" #include "wx/intl.h" #include "wx/utils.h" + #include "wx/wxcrt.h" #endif // WX_PRECOMP - +// Mac Includes #include #include -#include "wx/uri.h" +// More WX Includes +#include "wx/filename.h" #include "wx/mac/corefoundation/cfstring.h" -long wxMacExecute(wxChar **argv, - int flags, - wxProcess *process) -{ - const long errorCode = ((flags & wxEXEC_SYNC) ? -1 : 0); - const long successCode = ((flags & wxEXEC_SYNC) ? 0 : -1); // fake PID +// Default path style +#define kDefaultPathStyle kCFURLPOSIXPathStyle +//=========================================================================== +// IMPLEMENTATION +//=========================================================================== + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// wxMacLaunch +// +// argv is the command line split up, with the application path first +// flags are the flags from wxExecute +// process is the process passed from wxExecute for pipe streams etc. +// returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +bool wxMacLaunch(char **argv) +{ + // Obtains the number of arguments for determining the size of + // the CFArray used to hold them CFIndex cfiCount = 0; - //get count - for(wxChar** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) + for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) { ++cfiCount; } - if(cfiCount == 0) //no file to launch? + // If there is not a single argument then there is no application + // to launch + if(cfiCount == 0) { - wxLogDebug(wxT("wxMacExecute No file to launch!")); - return errorCode ; + wxLogDebug(wxT("wxMacLaunch No file to launch!")); + return false ; } - - CFURLRef cfurlApp = CFURLCreateWithString( + + // Path to bundle + wxString path = *argv++; + + // Create a CFURL for the application path + // Created this way because we are opening a bundle which is a directory + CFURLRef cfurlApp = + CFURLCreateWithFileSystemPath( kCFAllocatorDefault, - wxMacCFStringHolder(*argv++, wxLocale::GetSystemEncoding()), - NULL); - wxASSERT(cfurlApp); + wxCFStringRef(path), + kDefaultPathStyle, + true); //false == not a directory + // Check for error from the CFURL + if(!cfurlApp) + { + wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str()); + return false ; + } + + // Create a CFBundle from the CFURL created earlier CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp); + + // Check to see if CFBundleCreate returned an error, + // and if it did this was an invalid bundle or not a bundle + // at all (maybe a simple directory etc.) if(!cfbApp) { - wxLogDebug(wxT("wxMacExecute Bad bundle")); + wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str()); CFRelease(cfurlApp); - return errorCode ; + return false ; } - - + + // Get the bundle type and make sure its an 'APPL' bundle + // Otherwise we're dealing with something else here... UInt32 dwBundleType, dwBundleCreator; CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator); - - //Only call wxMacExecute for .app bundles - others could be actual unix programs if(dwBundleType != 'APPL') { + wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str()); + CFRelease(cfbApp); CFRelease(cfurlApp); - return errorCode ; + return false ; } - - // - // We have a good bundle - so let's launch it! - // - - CFMutableArrayRef cfaFiles = - CFArrayCreateMutable(kCFAllocatorDefault, cfiCount - 1, &kCFTypeArrayCallBacks); - - wxASSERT(cfaFiles); - - if(--cfiCount) + + // Create a CFArray for dealing with the command line + // arguments to the bundle + CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault, + cfiCount-1, &kCFTypeArrayCallBacks); + if(!cfaFiles) //This should never happen { + wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray")); + CFRelease(cfbApp); + CFRelease(cfurlApp); + return false ; + } + + // Loop through command line arguments to the bundle, + // turn them into CFURLs and then put them in cfaFiles + // For use to launch services call for( ; *argv != NULL ; ++argv) { -// wxLogDebug(*argv); - wxString sCurrentFile; - - if(wxURI(*argv).IsReference()) - sCurrentFile = wxString(wxT("file://")) + *argv; - else - sCurrentFile = *argv; - - CFURLRef cfurlCurrentFile = CFURLCreateWithString( - kCFAllocatorDefault, - wxMacCFStringHolder(sCurrentFile, wxLocale::GetSystemEncoding()), - NULL); - wxASSERT(cfurlCurrentFile); + // Check for '<' as this will ring true for + // CFURLCreateWithString but is generally not considered + // typical on mac but is usually passed here from wxExecute + if (wxStrcmp(*argv, wxT("<")) == 0) + continue; + + + CFURLRef cfurlCurrentFile; // CFURL to hold file path + wxFileName argfn(*argv); // Filename for path + + if(argfn.DirExists()) + { + // First, try creating as a directory + cfurlCurrentFile = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault, + wxCFStringRef(*argv), + kDefaultPathStyle, + true); //true == directory + } + else if(argfn.FileExists()) + { + // And if it isn't a directory try creating it + // as a regular file + cfurlCurrentFile = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault, + wxCFStringRef(*argv), + kDefaultPathStyle, + false); //false == regular file + } + else + { + // Argument did not refer to + // an entry in the local filesystem, + // so try creating it through CFURLCreateWithString + cfurlCurrentFile = CFURLCreateWithString( + kCFAllocatorDefault, + wxCFStringRef(*argv), + NULL); + } + // Continue in the loop if the CFURL could not be created + if(!cfurlCurrentFile) + { + wxLogDebug( + wxT("wxMacLaunch Could not create CFURL for argument:%s"), + *argv); + continue; + } + + // Add the valid CFURL to the argument array and then + // release it as the CFArray adds a ref count to it CFArrayAppendValue( cfaFiles, cfurlCurrentFile ); CFRelease(cfurlCurrentFile); // array has retained it } - } - + + // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec + // Note that there are several flag options (launchFlags) such + // as kLSLaunchDontSwitch etc. and maybe we could be more + // picky about the flags we choose LSLaunchURLSpec launchspec; launchspec.appURL = cfurlApp; launchspec.itemURLs = cfaFiles; - launchspec.passThruParams = NULL; //AEDesc* - launchspec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch; //TODO: Possibly be smarter with flags + launchspec.passThruParams = NULL; //AEDesc* + launchspec.launchFlags = kLSLaunchDefaults; launchspec.asyncRefCon = NULL; - - OSStatus status = LSOpenFromURLSpec(&launchspec, - NULL); //2nd is CFURLRef* really launched - //cleanup + // Finally, call LSOpenFromURL spec with our arguments + // 2nd parameter is a pointer to a CFURL that gets + // the actual path launched by the function + OSStatus status = LSOpenFromURLSpec(&launchspec, NULL); + + // Cleanup corefoundation references + CFRelease(cfbApp); CFRelease(cfurlApp); CFRelease(cfaFiles); - - //check for error + + // Check for error from LSOpenFromURLSpec if(status != noErr) { - wxLogDebug(wxT("wxMacExecute ERROR: %d"), (int)status); - return errorCode ; + wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"), + (int)status); + return false ; } - return successCode; //success + + // No error from LSOpenFromURLSpec, so app was launched + return true ; }