///////////////////////////////////////////////////////////////////////////// // Name: mac/corefoundation/utilsexc_base.cpp // Purpose: wxMacLaunch // Author: Ryan Norton // Modified by: // Created: 2005-06-21 // RCS-ID: $Id$ // Copyright: (c) Ryan Norton // Licence: wxWindows licence // Notes: Source was originally in utilsexc_cf.cpp,1.6 then moved // 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 #ifndef __WXOSX_IPHONE__ #include #endif // More WX Includes #include "wx/filename.h" #include "wx/osx/core/cfstring.h" #include "wx/osx/core/private.h" // Default path style #define kDefaultPathStyle kCFURLPOSIXPathStyle extern bool WXDLLEXPORT wxIsDebuggerRunning() { // TODO : try to find out ... return false; } #if wxOSX_USE_COCOA_OR_CARBON // have a fast version for mac code that returns the version as a return value long UMAGetSystemVersion() { static SInt32 sUMASystemVersion = 0 ; if ( sUMASystemVersion == 0 ) { verify_noerr(Gestalt(gestaltSystemVersion, &sUMASystemVersion)); } return sUMASystemVersion ; } // our OS version is the same in non GUI and GUI cases wxOperatingSystemId wxGetOsVersion(int *majorVsn, int *minorVsn) { SInt32 theSystem; Gestalt(gestaltSystemVersion, &theSystem); if ( majorVsn != NULL ) *majorVsn = (theSystem >> 8); if ( minorVsn != NULL ) *minorVsn = (theSystem & 0xFF); return wxOS_MAC_OSX_DARWIN; } #include wxString wxGetOsDescription() { struct utsname name; uname(&name); return wxString::Format(_T("Mac OS X (%s %s %s)"), wxString::FromAscii(name.sysname).c_str(), wxString::FromAscii(name.release).c_str(), wxString::FromAscii(name.machine).c_str()); } #endif // wxOSX_USE_COCOA_OR_CARBON //=========================================================================== // 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; for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) { ++cfiCount; } // If there is not a single argument then there is no application // to launch if(cfiCount == 0) { wxLogDebug(wxT("wxMacLaunch No file to launch!")); return false ; } // 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, 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("wxMacLaunch Bad bundle: %s"), path.c_str()); CFRelease(cfurlApp); 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); if(dwBundleType != 'APPL') { wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str()); CFRelease(cfbApp); CFRelease(cfurlApp); return false ; } // 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) { // 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; launchspec.asyncRefCon = NULL; // 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 from LSOpenFromURLSpec if(status != noErr) { wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"), (int)status); return false ; } // No error from LSOpenFromURLSpec, so app was launched return true ; }