Index: trunk/Cocoa/F-Script Anywhere/Source/FSAAppList.m
===================================================================
--- trunk/Cocoa/F-Script Anywhere/Source/FSAAppList.m	(revision 19)
+++ trunk/Cocoa/F-Script Anywhere/Source/FSAAppList.m	(revision 153)
@@ -25,7 +25,6 @@
 */
 
+#import "FSAAppList.h"
 #import "FSAnywhere.h"
-#import "FSAAppList.h"
-#import "FSAApp.h"
 #import "libMatch.h"
 #import "DeVercruesseProcessManager.h"
@@ -43,4 +42,7 @@
 NSString *FSACheckMarkCharacter;
 NSImage *FSACheckMarkImage;
+
+NSString *FSAEllipsisCharacter;
+NSImage *FSAEllipsisImage;
 
 static const char *FSACocoaFrameworks[] = {
@@ -65,4 +67,10 @@
         FSALog(@"Falling back to checkmark image from bundle: %@", FSACheckMarkImage);
     }
+    FSAEllipsisCharacter = [[NSString alloc] initWithCharacters: (const unichar *)"\x20\x26" length: 1];
+    FSAEllipsisImage = [[NSImage alloc] initByReferencingFile: [[NSBundle mainBundle] pathForResource: @"Ellipsis" ofType: @"tiff"]];
+    if (FSAEllipsisImage != nil && ![FSAEllipsisImage isValid]) {
+        [FSAEllipsisImage release];
+        FSAEllipsisImage = nil;
+    }
 }
 
@@ -74,4 +82,5 @@
     cocoaApps = [[NSMutableArray alloc] init];
     patchedApps = [[NSMutableSet alloc] init];
+    patchingApps = [[NSMutableSet alloc] init];
     appsByPID = [[NSMutableDictionary alloc] init];
 
@@ -85,5 +94,4 @@
     [self update];
     [window makeFirstResponder: tableView];
-    [window makeKeyAndOrderFront: self];
 }
 
@@ -105,9 +113,27 @@
 }
 
+- (void)_processStatusChanged;
+{
+    [tableView reloadData];
+    [self tableView: tableView shouldSelectRow: [tableView selectedRow]];
+}
+
+- (DeVercruesseProcess *)_applicationForPID:(pid_t)pid;
+{
+    return [appsByPID objectForKey: [NSNumber numberWithInt: pid]];
+}
+
 - (void)didPatchProcessID:(pid_t)pid;
 {
-    [patchedApps addObject: [appsByPID objectForKey: [NSNumber numberWithInt: pid]]];
-    [tableView reloadData];
-    [installButton setEnabled: NO];
+    DeVercruesseProcess *app = [self _applicationForPID: pid];
+    [patchingApps removeObject: app];
+    [patchedApps addObject: app];
+    [self _processStatusChanged];
+}
+
+- (void)isPatchingProcessID:(pid_t)pid;
+{
+    [patchingApps addObject: [self _applicationForPID: pid]];
+    [self _processStatusChanged];
 }
 
@@ -201,5 +227,5 @@
     [cocoaApps removeAllObjects];
     [appsByPID removeAllObjects];
-    // [processManager update]; // [processManager processes] sends update
+    // [processManager update] unneeded: [processManager processes] sends update
 
     allApps = [processManager processes];
@@ -211,15 +237,21 @@
 
     [tableView noteNumberOfRowsChanged];
-    [tableView reloadData];
-    // XXX this is broken, it doesn't update properly
-    [self tableView: tableView shouldSelectRow: [tableView selectedRow]];
+    [self _processStatusChanged];
+}
+
+- (NSArray *)cocoaAppProcessIDs;
+{
+    NSEnumerator *e = [cocoaApps objectEnumerator];
+    NSMutableArray *pids = [NSMutableArray arrayWithCapacity: [cocoaApps count]];
+    DeVercruesseProcess *app;
+    while ( (app = [e nextObject]) != nil) {
+        [pids addObject: [NSNumber numberWithInt: [app pid]]];
+    }
+    return pids;
 }
 
 - (void)applicationLaunchedWithProcessID:(pid_t)pid;
 {
-    NSNumber *pidNum = [NSNumber numberWithInt: pid];
-    DeVercruesseProcess *app = [appsByPID objectForKey: pidNum];
-
-    if (app == nil) {
+    if ([self _applicationForPID: pid] == nil) {
         [self update];
     }
@@ -228,14 +260,14 @@
 - (void)applicationQuitWithProcessID:(pid_t)pid;
 {
-    NSNumber *pidNum = [NSNumber numberWithInt: pid];
-    DeVercruesseProcess *app = [appsByPID objectForKey: pidNum];
+    DeVercruesseProcess *app = [self _applicationForPID: pid];
 
     if (app != nil) {
         [cocoaApps removeObject: app];
-        [appsByPID removeObjectForKey: pidNum];
+        [appsByPID removeObjectForKey: [NSNumber numberWithLong: pid]];
         [patchedApps removeObject: app];
     }
 
-    [tableView reloadData];
+    [tableView noteNumberOfRowsChanged];
+    [self _processStatusChanged];
 }
 
@@ -260,5 +292,7 @@
 
     if (row != -1) {
-        canInstall = ![patchedApps containsObject: [cocoaApps objectAtIndex: row]];
+        DeVercruesseProcess *app = [cocoaApps objectAtIndex: row];
+        canInstall = !([patchedApps containsObject: app] ||
+                       [patchingApps containsObject: app]);
     }
 
@@ -286,9 +320,17 @@
         return [(DeVercruesseProcess *)[cocoaApps objectAtIndex: rowIndex] name];
     } else if ([columnIdentifier isEqualToString: FSATableColumnIdentifier_checkMark]) {
-        BOOL isPatched = [patchedApps containsObject: [cocoaApps objectAtIndex: rowIndex]];
-        if (FSACheckMarkImage == nil)
-            return isPatched ? FSACheckMarkCharacter : @"";
-        else
-            return isPatched ? FSACheckMarkImage : nil;
+        DeVercruesseProcess *app = [cocoaApps objectAtIndex: rowIndex];
+        if ([patchedApps containsObject: app]) {
+            if (FSACheckMarkImage == nil)
+                return FSACheckMarkCharacter;
+            else
+                return FSACheckMarkImage;
+        }
+        if ([patchingApps containsObject: app]) {
+            if (FSAEllipsisImage == nil)
+                return FSAEllipsisCharacter;
+            else
+                return FSAEllipsisImage;
+        }
     }
     return nil;
@@ -327,29 +369,4 @@
 }
 
-- (BOOL)windowShouldClose:(id)sender;
-{
-    if ([patchedApps count] != 0) {
-        NSMutableString *message =  [@"F-Script Anywhere is installed in the following applications:\n\n" mutableCopy];
-        NSEnumerator *e = [patchedApps objectEnumerator];
-        DeVercruesseProcess *app;
-        int retval;
-
-        while ( (app = [e nextObject]) != nil) {
-            [message appendFormat: @"    ¥ %@\n", [app name]];
-        }
-
-        [message appendString: @"\nIf F-Script Anywhere quits now, these applications will be forced to quit, and any changes you have made in them will be lost.\n\nPlease quit these applications before quitting F-Script Anywhere, or click Force Quit to continue."];
-
-        retval = NSRunAlertPanel(@"Force applications to quit?", message, @"DonÕt Quit", @"Force Quit", nil);
-        if (retval != NSAlertAlternateReturn) {
-            return NO;
-        }
-
-        [(FSAApp *)NSApp unloadBundles: self];
-    }
-
-    return YES;
-}
-
 @end
 
@@ -359,5 +376,5 @@
 {
     static NSMenu *dockMenu = nil;
-    NSMenuItem *menuItem;
+    id<NSMenuItem> menuItem;
     DeVercruesseProcess *frontApp = [processManager frontProcess];
     NSString *appName = [frontApp name];
@@ -375,14 +392,14 @@
     }
 
-    NSAssert(frontApp != nil && appName != nil, @"CanÕt obtain information on the frontmost application");
+    NSAssert(frontApp != nil && appName != nil, @"Can't obtain information on the frontmost application");
 
     if ([patchedApps containsObject: frontApp]) {
-        status = [NSString stringWithFormat: @"Installed in Ò%@Ó", appName];
+        status = [NSString stringWithFormat: NSLocalizedString(@"Installed in '%@'", "Dock menu disabled item displayed when FSA already installed, app name parameter"), appName];
     } else if (![cocoaApps containsObject: frontApp]) {
-        status = [NSString stringWithFormat: @"CanÕt install because Ò%@Ó is not a Cocoa application", appName];
+        status = [NSString stringWithFormat: NSLocalizedString(@"Can't install because '%@' is not a Cocoa application", "Dock menu disabled item displayed when frontmost app not Cocoa, app name parameter"), appName];
     }
 
     if (status == nil) {
-        menuItem = [dockMenu addItemWithTitle: [NSString stringWithFormat: @"Install in Ò%@Ó", appName]
+        menuItem = [dockMenu addItemWithTitle: [NSString stringWithFormat: NSLocalizedString(@"Install in '%@'", "Dock menu item to install FSA in frontmost app"), appName]
                                        action: @selector(invoke)
                                 keyEquivalent: @""];
@@ -406,8 +423,3 @@
 }
 
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
-{
-    return ([self windowShouldClose: self] ? NSTerminateNow : NSTerminateCancel);
-}
-
 @end
