source: trunk/Cocoa/F-Script Anywhere/Source/DeVercruesseProcess.m @ 405

Last change on this file since 405 was 405, checked in by Nicholas Riley, 12 years ago

Fix a compiler warning.

File size: 8.5 KB
Line 
1//
2//  DeVercruesseProcess.m
3//
4//  Created by Frank Vercruesse on Wed Apr 04 2001.
5//  Copyright (c) 2001 Frank Vercruesse.
6//
7//
8//  This program is free software; you can redistribute it and/or
9//  modify it under the terms of the GNU General Public License
10//  as published by the Free Software Foundation; either version 2
11//  of the License, or (at your option) any later version.
12//
13//  This program is distributed in the hope that it will be useful,
14//  but WITHOUT ANY WARRANTY; without even the implied warranty of
15//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16//  GNU General Public License for more details.
17//
18//  You should have received a copy of the GNU General Public License
19//  along with this program; if not, write to the Free Software
20//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21//  02111-1307, USA.
22
23#import "DeVercruesseProcess.h"
24#import "DeVercruesseProcessManager.h"
25
26
27@implementation DeVercruesseProcess
28
29+ (id)processWithPSN:(ProcessSerialNumber*)sn
30{
31    return [[[self alloc] initWithPSN:sn] autorelease];
32}
33
34- (id)init
35{
36    return [self initWithPSN:nil];
37}
38
39- (id)initWithPSN:(ProcessSerialNumber*)sn
40{
41    OSErr               err;
42    CPSProcessInfoRec   pInfo;
43    int                 dummy;
44   
45   
46    if( sn )
47    {
48        err = CPSGetProcessInfo( (CPSProcessSerNum*) sn, &pInfo, nil, 0, &dummy, nil, 0);
49       
50        if( !err )
51        {
52            self = [super init];
53           
54            if( self )
55            {
56                psn.highLongOfPSN = sn->highLongOfPSN;
57                psn.lowLongOfPSN = sn->lowLongOfPSN;
58               
59                pid = pInfo.UnixPID;
60                flavour = pInfo.Flavour;
61                attributes = pInfo.Attributes;
62                type = pInfo.ExecFileType;
63                creator = pInfo.ExecFileCreator;
64               
65                bundleIdentifier = nil;
66                identifier = nil;
67               
68                name = nil;
69                loc = nil;
70                img = nil;
71            }
72        }
73        else
74        {
75            [self dealloc];
76            return nil;
77        }
78    }
79    else
80    {
81        [self dealloc];
82        return nil;
83    }
84   
85    return self;
86}
87
88- (void)dealloc
89{
90    [bundleIdentifier release];
91    [identifier release];
92    [name release];
93    [img release];
94    [cachedImage release];
95    [loc release];
96   
97    [super dealloc];
98}
99
100- (NSString *)executableLoc;
101{
102    CFStringRef bundleLoc = (CFStringRef) [self loc];
103    CFURLRef bundleURL;
104    CFBundleRef bundleRef;
105
106    if (bundleLoc == NULL) {
107        // GetProcessBundleLocation returns NULL on 10.1.5 for certain CFM Carbon applications (BBEdit 6.5.3) - njr
108        return nil; // XXX should really handle this better, but for the purposes of F-Script Anywhere, we donÕt care if itÕs not a Carbon app, and this works fine going forward.
109    }
110   
111    bundleURL = CFURLCreateWithFileSystemPath(NULL, bundleLoc, kCFURLPOSIXPathStyle, NO);
112    bundleRef = CFBundleCreate(NULL, bundleURL);
113    CFRelease(bundleURL);
114
115    if (bundleRef == NULL) {
116        BOOL isDir;
117        if ([[NSFileManager defaultManager] fileExistsAtPath: [self loc] isDirectory: &isDir] && !isDir)
118            return [self loc];
119        return nil; // not a bundle or file
120    } else {
121        CFURLRef execURL = CFBundleCopyExecutableURL(bundleRef);
122        CFURLRef absURL = CFURLCopyAbsoluteURL(execURL);
123        CFStringRef execPath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle);
124
125        if (absURL != NULL) CFRelease(absURL);
126        if (execURL != NULL) CFRelease(execURL);
127        CFRelease(bundleRef);
128        return [(NSString *)execPath autorelease];
129    }
130}
131
132
133- (NSString*)loc
134{
135    unsigned char       buffer[1025];
136    FSRef               location;
137   
138   
139    if( !loc )
140    {
141        if( !GetProcessBundleLocation( &psn, &location) )
142        {
143            FSRefMakePath( &location, buffer, 1024);
144            loc = [NSString stringWithUTF8String:buffer];
145            [loc retain];
146        }
147    }
148   
149    return loc;
150}
151
152- (NSString*)name;
153{
154    char                buffer[1025];
155    CFStringRef         pName;
156   
157   
158    if( !name )
159    {
160        if( !name && (CopyProcessName( &psn, &pName) == noErr) )    // with thanks to Dylan Ashe
161        {
162            CFStringGetCString( pName, buffer, 256, CFStringConvertNSStringEncodingToEncoding( [NSString defaultCStringEncoding]));
163           
164            name = [NSString stringWithCString:buffer];
165            [name retain];
166           
167            CFRelease( pName);
168        }
169        // CFBundleName code demoted to alternate method because it was causing plist processing issues in Jaguar, yet CopyProcessName doesn't work for everything, e.g. Help Viewer - njr
170        else if( [self loc] )
171        {
172            NSBundle *b = [NSBundle bundleWithPath:loc];
173            if( b )
174            {
175                name = [b localizedStringForKey:@"CFBundleName" value:@"_AsM_nO_nAmE_" table:@"InfoPlist"];
176
177                if( [name isEqualToString:@"_AsM_nO_nAmE_"] )
178                    name = [[b infoDictionary] objectForKey:@"CFBundleName"];
179
180                if( name )
181                    [name retain];
182            }
183        }
184       
185   }
186
187    return name ? name : NSLocalizedString(@"<<unknown application>>", "Name used when application name cannot be determined");
188}
189
190- (NSImage*)img
191{
192    if( !img )
193    {
194        if( [self loc] )
195        {
196            img = [[NSWorkspace sharedWorkspace] iconForFile:loc];
197           
198            if( img )
199            {
200                [img setDataRetained:YES];
201//                [img setCachedSeparately:YES]; // added 8/26/01 by Frank
202                [img retain];
203            }
204        }
205    }
206   
207    return img;
208}
209
210- (NSImage *)cachedImage;
211{
212    return cachedImage;
213}
214
215- (void)setCachedImage:(NSImage *)anImage;
216{
217    if (anImage != cachedImage) {
218        [anImage retain];
219        [cachedImage release];
220        cachedImage = anImage;
221    }
222}
223
224
225- (ProcessSerialNumber*)psn
226{
227    return &psn;
228}
229
230- (UInt32)pid
231{
232    return pid;
233}
234
235- (UInt32)flavour
236{
237    return flavour;
238}
239
240- (UInt32)attributes
241{
242    CPSProcessInfoRec   pInfo;
243    int                 dummy;
244   
245   
246    if( CPSGetProcessInfo( (CPSProcessSerNum*) &psn, &pInfo, nil, 0, &dummy, nil, 0) == noErr )
247        attributes = pInfo.Attributes;
248   
249    return attributes;
250}
251
252- (UInt32)type
253{
254    return type;
255}
256
257- (UInt32)creator
258{
259    return creator;
260}
261
262- (NSString*)identifier
263{
264    if( !identifier )
265    {
266        identifier = [[NSString alloc] initWithFormat:@"%@%.8X%.8X",
267            [self bundleIdentifier], [self type] ? type : 'APPL', [self creator] ? creator : '\?\?\?\?'];
268    }
269   
270    return identifier;
271}
272
273- (NSString*)bundleIdentifier
274{
275    NSBundle    *b;
276   
277   
278    if( !bundleIdentifier && [self loc] && (b = [NSBundle bundleWithPath:loc]) )
279        bundleIdentifier = [[b bundleIdentifier] retain];
280   
281    return bundleIdentifier ? bundleIdentifier : @"";
282}
283
284
285- (unsigned)hash
286{
287    return psn.lowLongOfPSN;
288//    return pid;
289}
290
291- (BOOL)isEqual:(id)anObject
292{
293    if( anObject )
294        return CPSEqualProcess( (CPSProcessSerNum*) &psn, (CPSProcessSerNum*) [anObject psn]);
295    else
296        return NO;
297}
298
299- (BOOL)isEqualToCurrent
300{
301    return [self isEqual:[ProcessMgr currentProcess]];
302}
303
304- (BOOL)isEqualToFront
305{
306    return [self isEqual:[ProcessMgr frontProcess]];
307}
308
309- (BOOL)isStillRunning
310{
311    CPSProcessInfoRec   pInfo;
312    int                 dummy;
313   
314   
315    if( CPSGetProcessInfo( (CPSProcessSerNum*) &psn, &pInfo, nil, 0, &dummy, nil, 0) == noErr )
316        return YES;
317    else
318        return NO;
319}
320
321- (BOOL)isBackgroundOnly
322{
323    return (((attributes & kCPSBGOnlyAttr) | (attributes & kCPSUIElementAttr)) != 0);
324}
325
326- (BOOL)isHidden
327{
328    return (([self attributes] & kCPSHiddenAttr) != 0);
329}
330
331
332- (BOOL)isClassic
333{
334    return (flavour == kCPSBlueApp);
335}
336
337- (BOOL)isCarbon
338{
339    return (flavour == kCPSCarbonApp);
340}
341
342- (BOOL)isCocoa
343{
344    return (flavour == kCPSYellowApp);
345}
346
347
348- (void)show
349{
350    if( [self isStillRunning] )
351        CPSPostShowReq( (CPSProcessSerNum*) &psn);
352}
353
354- (void)hide
355{
356    if( [self isStillRunning] )
357        CPSPostHideReq( (CPSProcessSerNum*) &psn);
358}
359
360- (void)makeFront
361{
362    if( [self isStillRunning] )
363    {
364        CPSSetFrontProcess( (CPSProcessSerNum*) &psn);
365        CPSPostShowReq( (CPSProcessSerNum*) &psn);
366    }
367}
368
369- (void)kill
370{
371    [self kill:NO];
372}
373
374- (void)kill:(BOOL)hard
375{
376    if( [self isStillRunning] )
377        CPSPostKillRequest( (CPSProcessSerNum*) &psn, hard ? bfCPSKillHard : 0 );
378}
379
380- (NSString *)description;
381{
382    return [NSString stringWithFormat: @"%@ pid %d: '%@' (%@)", [super description], [self pid], [self name], [self identifier]];
383}
384
385@end
Note: See TracBrowser for help on using the repository browser.