source: trunk/Cocoa/F-Script Anywhere/Source/FSAApp.m@ 16

Last change on this file since 16 was 16, checked in by Nicholas Riley, 22 years ago

F-Script Anywhere 1.1.5

File size: 8.2 KB
RevLine 
[7]1//
2// FSAApp.m
3// F-Script Anywhere
4//
5// Created by Nicholas Riley on Fri Feb 01 2002.
6// Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9/*
10
11 F-Script Anywhere is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 F-Script Anywhere is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with F-Script Anywhere; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25*/
26
27#import <PatchCocoa.h>
28#import "FSAApp.h"
29#import "FSAnywhere.h"
30
31NSString * const PatchBundleIdentifier = @"net.sabi.FScriptAnywhere";
32
33typedef struct {
34 OSStatus status;
35 NSString * const desc;
36} errRec, errList[];
37
38// These are just educated guesses based on the errors I've seen; I haven't seen these documented anywhere!
39static errList ERRS = {
40 { 5, @"F-Script Anywhere must be installed in a Cocoa application running as the current user.\n\nYou may be attempting to install in a setuid application, which is not supported" },
41 { 11, @"F-Script Anywhere cannot be installed in itself.\n\nIf you wish to install F-Script Anywhere in itself, make a copy of the F-Script Anywhere application and install one copy into the other" },
42 { smUnExBusErr, @"a bus error occurred.\n\nTry switching to the application first then using F-Script AnywhereÕs dock menu to install" },
43 { fnfErr, @"F-Script Anywhere was unable to locate its component to install in the application. Please try reinstalling F-Script Anywhere" },
44 { cfragDupRegistrationErr, @"another running copy of F-Script Anywhere is already installed in the application"},
45 { 0, nil }
46};
47
48NSMutableDictionary *FSA_errors;
49
50NSString * FSA_descriptionForOSStatus(OSStatus status)
51{
52 NSString *desc = nil;
53
54 if (FSA_errors != nil)
55 desc = [FSA_errors objectForKey: [NSNumber numberWithLong: status]];
56
57 if (desc != nil)
58 return desc;
59
60 return [NSString stringWithFormat: @"an error of type %ld occurred", status];
61}
62
63
64@implementation FSAApp
65
66+ (void)initialize;
67{
68 errRec *rec;
69
70 FSA_errors = [[NSMutableDictionary alloc] init];
71 for (rec = &(ERRS[0]) ; rec->status != 0 ; rec++)
72 [FSA_errors setObject: rec->desc forKey: [NSNumber numberWithLong: rec->status]];
73}
74
75- (void)finishLaunching
76{
77 // yes, someone could move the framework while the app is running, but they deserve what they get.
78 NSFileManager *fileMgr = [NSFileManager defaultManager];
79 NSArray *libraryDirectories =
80 NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSAllDomainsMask, TRUE);
81 NSEnumerator *e = [libraryDirectories objectEnumerator];
82 NSString *libPath;
83 NSString *frameworkPath;
84 BOOL isDirectory;
85 BOOL found = NO;
86
87 while ( (libPath = [e nextObject]) != nil) {
88 frameworkPath = [libPath stringByAppendingPathComponent: @"Frameworks"];
89 if ([fileMgr fileExistsAtPath: [frameworkPath stringByAppendingPathComponent: @"FScript.framework"]
90 isDirectory: &isDirectory] && isDirectory) {
91 found = YES;
92 }
93 }
94 [super finishLaunching];
95 if (!found) {
96 int result = NSRunInformationalAlertPanel(@"F-Script Framework Not Found", @"F-Script Anywhere requires the F-Script framework be installed in a Frameworks directory, such as ~/Library/Frameworks or /Library/Frameworks.\n\nTo download F-Script, please visit its Web site %@.\n\nIf you believe this message is in error, click ÒContinueÓ.", @"Quit", @"Get F-Script", @"Continue", FSA_FScriptURL);
97 switch (result) {
98 case NSAlertOtherReturn:
99 break;
100 case NSAlertAlternateReturn:
101 [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: FSA_FScriptURL]];
102 case NSAlertDefaultReturn:
103 default:
104 [self terminate: self];
105 return;
106 }
107 }
[16]108 [[PatchController sharedPatchController] setDelegate: self];
109 // In Jaguar 6C115, libPatch no longer delivers process death notifications to the application unless it registers for NSWorkspaceDidTerminateApplicationNotification. (Process launch notifications are still received.)
110 [[[NSWorkspace sharedWorkspace] notificationCenter]
111 addObserver: self
112 selector: @selector(applicationDidTerminate:)
113 name: NSWorkspaceDidTerminateApplicationNotification
114 object: nil];
[7]115}
116
117// This method causes the selected applications to quit, because the Objective-C runtime in Mac OS X does not support unloading of classes.
118- (void)unloadBundles:(id)sender
119{
120 UInt32 index,count;
121 NSArray *pids;
122
123
124 pids = [[PatchController sharedPatchController] processPIDsForPatchWithIdentifier:PatchBundleIdentifier];
125 count = [pids count];
126 for (index = 0 ; index < count ; index ++)
127 {
128 [[PatchController sharedPatchController] messagePatchForProcessWithPID:[[pids objectAtIndex:index] longValue]
129 identifier:PatchBundleIdentifier message:'bye ' data:NULL length:0];
130
131 [[PatchController sharedPatchController] unloadPatchForProcessWithPID:[[pids objectAtIndex:index] longValue]
132 identifier:PatchBundleIdentifier];
133 }
134
135}
136
137- (void)installBundleInAppWithPID:(pid_t)pid;
138{
139 OSStatus err;
140
141 if (pid == -1) return;
142
143 // XXX Switch to application first, resolves crash in Project Builder.
144 // XXX Fix window closing problem.
145
146 err = [[PatchController sharedPatchController] loadPatchForProcessWithPID:pid identifier:PatchBundleIdentifier
147 path:[NSString stringWithFormat:@"%@/F-Script Anywhere",
148 [[NSBundle mainBundle] resourcePath]]
149 detached:NO];
150 if (err == noErr) {
151 [[PatchController sharedPatchController] messagePatchForProcessWithPID:pid identifier:PatchBundleIdentifier
152 message:'helo' data:NULL length:0];
153 [appList didPatchProcessID: pid];
154 }
155 else {
156 NSBeginAlertSheet(@"Installation failed", @"OK", nil, nil, appListPanel, self, nil, nil, nil,
157 @"F-Script Anywhere was unable to install itself in the selected application (process ID %d), because %@.\n\nThe application may have crashed; restart it if needed.", pid, FSA_descriptionForOSStatus(err));
158 }
159}
160
161- (IBAction)installBundleInSelectedApp:(id)sender;
162{
163 [self installBundleInAppWithPID: [appList selectedProcessID]];
164}
165
166// from dock menu only!
167- (IBAction)installBundleInFrontmostApp:(id)sender;
168{
169 NSAssert1([sender tag] > 0, @"Unable to determine frontmost application from %@", sender);
170 [self installBundleInAppWithPID: (pid_t)[sender tag]];
171}
172
173@end
174
[16]175@implementation FSAApp (NSWorkspaceNotifications)
176
177- (void)applicationDidTerminate:(NSNotification *)notification;
178{
179 NSDictionary *userInfo = [notification userInfo];
180 FSALog(@"Process terminated (pid %6d): %@\n",
181 [[userInfo objectForKey: @"NSApplicationProcessIdentifier"] intValue],
182 [userInfo objectForKey: @"NSApplicationName"]);
183 // Don't do anything here, this is a dummy method triggered by a NSWorkspaceDidTerminateApplicationNotification
184}
185
186@end
187
[7]188@implementation FSAApp (PatchControllerDelegate)
189
190- (void) notifyProcessLaunch:(pid_t)pid info:(NSDictionary*)info
191{
192 [appList applicationLaunchedWithProcessID: pid];
193}
194
[16]195// this delegate method is never invoked in Mac OS X 10.2 unless I register for NSWorkspaceDidTerminateApplicationNotification
[7]196- (void) notifyProcessDeath:(pid_t)pid info:(NSDictionary*)info
197{
198 FSALog(@"Process exited (pid %6d): %@\n", pid, [info objectForKey: PatchControllerNameKey]);
199 [appList applicationQuitWithProcessID: pid];
200}
201
202@end
Note: See TracBrowser for help on using the repository browser.