]> git.saurik.com Git - wxWidgets.git/blame - src/mac/corefoundation/utilsexc_base.cpp
use safer RemoveEventHandler() instead of PopEventHandler() (patch 1678016)
[wxWidgets.git] / src / mac / corefoundation / utilsexc_base.cpp
CommitLineData
1ccb7433
DE
1/////////////////////////////////////////////////////////////////////////////
2// Name: mac/corefoundation/utilsexc_base.cpp
3// Purpose: wxMacExecute
4// Author: Ryan Norton
5// Modified by:
6// Created: 2005-06-21
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10// Notes: Source was originally in utilsexc_cf.cpp,1.6 then moved
11// to totally unrelated hid.cpp,1.8.
12/////////////////////////////////////////////////////////////////////////////
13
7db33dd7
SC
14//===========================================================================
15// DECLARATIONS
16//===========================================================================
17
18//---------------------------------------------------------------------------
19// Pre-compiled header stuff
20//---------------------------------------------------------------------------
21
1ccb7433
DE
22// For compilers that support precompilation, includes "wx.h".
23#include "wx/wxprec.h"
7db33dd7
SC
24
25// WX includes
1ccb7433
DE
26#ifndef WX_PRECOMP
27 #include "wx/string.h"
28 #include "wx/log.h"
29 #include "wx/intl.h"
30 #include "wx/utils.h"
31#endif // WX_PRECOMP
32
7db33dd7 33// Mac Includes
1ccb7433
DE
34#include <CoreFoundation/CoreFoundation.h>
35#include <ApplicationServices/ApplicationServices.h>
36
7db33dd7
SC
37// More WX Includes
38#include "wx/filename.h"
1ccb7433
DE
39#include "wx/mac/corefoundation/cfstring.h"
40
7db33dd7
SC
41// Default path style
42#ifdef __WXMAC_OSX__
43#define kDefaultPathStyle kCFURLPOSIXPathStyle
44#else
45#define kDefaultPathStyle kCFURLHFSPathStyle
46#endif
47
48//===========================================================================
49// IMPLEMENTATION
50//===========================================================================
51
52//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
53//
a8d69700 54// wxMacExecute
7db33dd7
SC
55//
56// argv is the command line split up, with the application path first
a8d69700 57// flags are the flags from wxExecute
7db33dd7
SC
58// process is the process passed from wxExecute for pipe streams etc.
59// returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC
60//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1ccb7433
DE
61long wxMacExecute(wxChar **argv,
62 int flags,
63 wxProcess *process)
64{
7db33dd7 65 // Semi-macros used for return value of wxMacExecute
a8d69700
VZ
66 const long errorCode = ((flags & wxEXEC_SYNC) ? -1 : 0);
67 const long successCode = ((flags & wxEXEC_SYNC) ? 0 : -1); // fake PID
1ccb7433 68
7db33dd7
SC
69 // Obtains the number of arguments for determining the size of
70 // the CFArray used to hold them
1ccb7433 71 CFIndex cfiCount = 0;
1ccb7433
DE
72 for(wxChar** argvcopy = argv; *argvcopy != NULL ; ++argvcopy)
73 {
74 ++cfiCount;
75 }
76
7db33dd7
SC
77 // If there is not a single argument then there is no application
78 // to launch
79 if(cfiCount == 0)
1ccb7433
DE
80 {
81 wxLogDebug(wxT("wxMacExecute No file to launch!"));
82 return errorCode ;
83 }
a8d69700 84
7db33dd7
SC
85 // Path to bundle
86 wxString path = *argv++;
87
88 // Create a CFURL for the application path
89 // Created this way because we are opening a bundle which is a directory
a8d69700 90 CFURLRef cfurlApp =
7db33dd7 91 CFURLCreateWithFileSystemPath(
1ccb7433 92 kCFAllocatorDefault,
a8d69700
VZ
93 wxMacCFStringHolder(path),
94 kDefaultPathStyle,
7db33dd7 95 true); //false == not a directory
1ccb7433 96
7db33dd7
SC
97 // Check for error from the CFURL
98 if(!cfurlApp)
99 {
100 wxLogDebug(wxT("wxMacExecute Can't open path: %s"), path.c_str());
101 return errorCode ;
102 }
103
104 // Create a CFBundle from the CFURL created earlier
1ccb7433 105 CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp);
7db33dd7
SC
106
107 // Check to see if CFBundleCreate returned an error,
108 // and if it did this was an invalid bundle or not a bundle
109 // at all (maybe a simple directory etc.)
1ccb7433
DE
110 if(!cfbApp)
111 {
7db33dd7 112 wxLogDebug(wxT("wxMacExecute Bad bundle: %s"), path.c_str());
1ccb7433
DE
113 CFRelease(cfurlApp);
114 return errorCode ;
115 }
a8d69700 116
7db33dd7
SC
117 // Get the bundle type and make sure its an 'APPL' bundle
118 // Otherwise we're dealing with something else here...
1ccb7433
DE
119 UInt32 dwBundleType, dwBundleCreator;
120 CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator);
1ccb7433
DE
121 if(dwBundleType != 'APPL')
122 {
7db33dd7
SC
123 wxLogDebug(wxT("wxMacExecute Not an APPL bundle: %s"), path.c_str());
124 CFRelease(cfbApp);
1ccb7433
DE
125 CFRelease(cfurlApp);
126 return errorCode ;
127 }
a8d69700 128
7db33dd7
SC
129 // Create a CFArray for dealing with the command line
130 // arguments to the bundle
a8d69700 131 CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault,
7db33dd7
SC
132 cfiCount-1, &kCFTypeArrayCallBacks);
133 if(!cfaFiles) //This should never happen
1ccb7433 134 {
a8d69700 135 wxLogDebug(wxT("wxMacExecute Could not create CFMutableArray"));
7db33dd7
SC
136 CFRelease(cfbApp);
137 CFRelease(cfurlApp);
138 return errorCode ;
139 }
a8d69700 140
7db33dd7
SC
141 // Loop through command line arguments to the bundle,
142 // turn them into CFURLs and then put them in cfaFiles
143 // For use to launch services call
1ccb7433
DE
144 for( ; *argv != NULL ; ++argv)
145 {
a8d69700 146 // Check for '<' as this will ring true for
7db33dd7
SC
147 // CFURLCreateWithString but is generally not considered
148 // typical on mac but is usually passed here from wxExecute
149 if (wxStrcmp(*argv, wxT("<")) == 0)
150 continue;
a8d69700
VZ
151
152
153 CFURLRef cfurlCurrentFile; // CFURL to hold file path
154 wxFileName argfn(*argv); // Filename for path
155
7db33dd7
SC
156 if(argfn.DirExists())
157 {
158 // First, try creating as a directory
159 cfurlCurrentFile = CFURLCreateWithFileSystemPath(
160 kCFAllocatorDefault,
a8d69700
VZ
161 wxMacCFStringHolder(*argv),
162 kDefaultPathStyle,
7db33dd7
SC
163 true); //true == directory
164 }
165 else if(argfn.FileExists())
166 {
167 // And if it isn't a directory try creating it
168 // as a regular file
169 cfurlCurrentFile = CFURLCreateWithFileSystemPath(
170 kCFAllocatorDefault,
a8d69700
VZ
171 wxMacCFStringHolder(*argv),
172 kDefaultPathStyle,
7db33dd7 173 false); //false == regular file
a8d69700 174 }
7db33dd7
SC
175 else
176 {
177 // Argument did not refer to
178 // an entry in the local filesystem,
179 // so try creating it through CFURLCreateWithString
180 cfurlCurrentFile = CFURLCreateWithString(
a8d69700
VZ
181 kCFAllocatorDefault,
182 wxMacCFStringHolder(*argv),
183 NULL);
7db33dd7 184 }
a8d69700 185
7db33dd7
SC
186 // Continue in the loop if the CFURL could not be created
187 if(!cfurlCurrentFile)
188 {
189 wxLogDebug(
a8d69700 190 wxT("wxMacExecute Could not create CFURL for argument:%s"),
7db33dd7
SC
191 *argv);
192 continue;
193 }
1ccb7433 194
7db33dd7
SC
195 // Add the valid CFURL to the argument array and then
196 // release it as the CFArray adds a ref count to it
1ccb7433
DE
197 CFArrayAppendValue(
198 cfaFiles,
199 cfurlCurrentFile
200 );
201 CFRelease(cfurlCurrentFile); // array has retained it
202 }
a8d69700 203
7db33dd7
SC
204 // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec
205 // Note that there are several flag options (launchFlags) such
206 // as kLSLaunchDontSwitch etc. and maybe we could be more
207 // picky about the flags we choose
1ccb7433
DE
208 LSLaunchURLSpec launchspec;
209 launchspec.appURL = cfurlApp;
210 launchspec.itemURLs = cfaFiles;
a8d69700
VZ
211 launchspec.passThruParams = NULL; //AEDesc*
212 launchspec.launchFlags = kLSLaunchDefaults;
1ccb7433 213 launchspec.asyncRefCon = NULL;
a8d69700 214
7db33dd7
SC
215 // Finally, call LSOpenFromURL spec with our arguments
216 // 2nd parameter is a pointer to a CFURL that gets
217 // the actual path launched by the function
218 OSStatus status = LSOpenFromURLSpec(&launchspec, NULL);
1ccb7433 219
7db33dd7
SC
220 // Cleanup corefoundation references
221 CFRelease(cfbApp);
1ccb7433
DE
222 CFRelease(cfurlApp);
223 CFRelease(cfaFiles);
a8d69700 224
7db33dd7 225 // Check for error from LSOpenFromURLSpec
1ccb7433
DE
226 if(status != noErr)
227 {
a8d69700 228 wxLogDebug(wxT("wxMacExecute LSOpenFromURLSpec Error: %d"),
7db33dd7 229 (int)status);
1ccb7433
DE
230 return errorCode ;
231 }
a8d69700 232
7db33dd7 233 // No error from LSOpenFromURLSpec, so app was launched
a8d69700 234 return successCode;
1ccb7433
DE
235}
236