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