2.5.3 - cleanups, fixes, etc. etc. -
[wxWidgets.git] / src / cocoa / utilsexc.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        utilsexec.mm
3 // Purpose:     Execution-related utilities for wxCocoa
4 // Author:      Ryan Norton
5 // Modified by:
6 // Created:     2004-10-05
7 // RCS-ID:      $Id$
8 // Copyright:   (c) Ryan Norton
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include "wx/utils.h"
17
18 #include "wx/process.h"
19 #include "wx/stream.h"
20
21 #include "wx/cocoa/string.h"
22
23 #import <Foundation/Foundation.h>
24 #import <AppKit/NSWorkspace.h>
25
26 class wxPipeInputStream : public wxInputStream
27 {
28 public:
29     wxPipeInputStream(NSPipe* thePipe) : 
30             m_thePipe(thePipe),
31             m_theHandle([m_thePipe fileHandleForReading])
32     {
33     }
34
35     ~wxPipeInputStream()
36     {   
37         [m_thePipe release];
38     }
39
40 protected:
41     virtual size_t OnSysRead(void *buffer, size_t size)
42     {
43         NSData* theData = [m_theHandle readDataOfLength:size];
44         memcpy(buffer, [theData bytes], [theData length]);
45         return [theData length];
46     }
47     
48     
49     NSPipe*             m_thePipe;
50     NSFileHandle*       m_theHandle;
51 };
52
53 class wxPipeOutputStream : public wxOutputStream
54 {
55 public:
56     wxPipeOutputStream(NSPipe* thePipe) : 
57             m_thePipe(thePipe),
58             m_theHandle([m_thePipe fileHandleForWriting])
59     {
60     }
61
62     ~wxPipeOutputStream()
63     {   
64         [m_thePipe release];
65     }
66
67 protected:
68
69     virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
70     {
71         NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer 
72                                   length:bufsize];
73         [m_theHandle writeData:theData];
74         return bufsize;
75     }
76         
77     NSPipe*             m_thePipe;
78     NSFileHandle*       m_theHandle;
79 };
80
81 @interface wxTaskHandler : NSObject
82 {
83     long m_pid;
84     void* m_handle;
85 }
86 -(id)init:(void*)handle processIdentifier:(long)pid;
87 - (void)termHandler:(NSNotification *)aNotification;
88 @end
89
90 @implementation wxTaskHandler : NSObject
91
92 -(id)init:(void*)handle processIdentifier:(long)pid 
93 {
94     self = [super init];
95     
96     m_handle = handle;
97     m_pid = pid;
98
99     [[NSNotificationCenter defaultCenter] addObserver:self 
100             selector:@selector(termHandler:) 
101             name:NSTaskDidTerminateNotification 
102             object:nil];
103     return self;
104 }
105
106 - (void)termHandler:(NSNotification *)aNotification 
107 {
108     NSTask* theTask = [aNotification object];
109     
110     if ([theTask processIdentifier] == m_pid)
111     {
112         ((wxProcess*)m_handle)->OnTerminate([theTask processIdentifier], 
113                           [theTask terminationStatus]);
114         
115         [self release];
116     }
117 }
118
119 @end
120
121 long wxExecute(const wxString& command, 
122                 int sync = wxEXEC_ASYNC, 
123                 wxProcess *handle = NULL)
124 {
125     NSTask* theTask = [[NSTask alloc] init];
126     
127     if (handle && handle->IsRedirected())
128     {
129         NSPipe* theStdinPipe = [[NSPipe alloc] init];
130         NSPipe* theStderrPipe = [[NSPipe alloc] init];
131         NSPipe* theStdoutPipe = [[NSPipe alloc] init];
132     
133         [theTask setStandardInput:theStdinPipe];
134         [theTask setStandardError:theStderrPipe];
135         [theTask setStandardOutput:theStdoutPipe];
136         
137         handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
138                                new wxPipeOutputStream(theStdinPipe),
139                                new wxPipeInputStream(theStderrPipe) );
140     }
141     
142     NSArray* theQuoteArguments = 
143         [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
144         
145     NSMutableArray* theSeperatedArguments = 
146         [NSMutableArray arrayWithCapacity:10];
147         
148     for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
149     {
150         [theSeperatedArguments addObjectsFromArray:
151             [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
152         ];
153         
154         if(++i < [theQuoteArguments count])
155             [theSeperatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
156     }
157     
158     [theTask setLaunchPath:[theSeperatedArguments objectAtIndex:0]];
159     [theTask setArguments:theSeperatedArguments];
160     [theTask launch];
161     
162     if(sync & wxEXEC_ASYNC)
163     {
164         [[wxTaskHandler alloc]init:handle 
165                               processIdentifier:[theTask processIdentifier]];
166                                 
167         return 0;
168     }
169     else
170     {
171         [theTask waitUntilExit];
172         
173         return [theTask terminationStatus];
174     }                      
175 }