From f2ef92cee70de65f6f963fc4ffd3ac5729a19d90 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Fri, 2 May 2008 21:42:35 +0000 Subject: [PATCH] Fix for #1905: PythonLauncher not working correctly on OSX 10.5/Leopard This fixes both Python Launchar and the terminalcommand module. --- Lib/plat-mac/Carbon/AppleEvents.py | 1 + Lib/plat-mac/terminalcommand.py | 2 +- Mac/PythonLauncher/MyDocument.m | 4 +- Mac/PythonLauncher/doscript.m | 141 +++++++++-------------------- 4 files changed, 45 insertions(+), 103 deletions(-) diff --git a/Lib/plat-mac/Carbon/AppleEvents.py b/Lib/plat-mac/Carbon/AppleEvents.py index e23c0797a5d..a4d7dcf903c 100644 --- a/Lib/plat-mac/Carbon/AppleEvents.py +++ b/Lib/plat-mac/Carbon/AppleEvents.py @@ -1,6 +1,7 @@ # Generated from 'AEDataModel.h' def FOUR_CHAR_CODE(x): return x +typeApplicationBundleID = FOUR_CHAR_CODE('bund') typeBoolean = FOUR_CHAR_CODE('bool') typeChar = FOUR_CHAR_CODE('TEXT') typeSInt16 = FOUR_CHAR_CODE('shor') diff --git a/Lib/plat-mac/terminalcommand.py b/Lib/plat-mac/terminalcommand.py index 292f09c7d80..480797b42ae 100644 --- a/Lib/plat-mac/terminalcommand.py +++ b/Lib/plat-mac/terminalcommand.py @@ -27,7 +27,7 @@ SEND_MODE = kAENoReply # kAEWaitReply hangs when run from Terminal.app itself def run(command): """Run a shell command in a new Terminal.app window.""" - termAddress = AE.AECreateDesc(typeApplSignature, TERMINAL_SIG) + termAddress = AE.AECreateDesc(typeApplicationBundleID, "com.apple.Terminal") theEvent = AE.AECreateAppleEvent(kAECoreSuite, kAEDoScript, termAddress, kAutoGenerateReturnID, kAnyTransactionID) commandDesc = AE.AECreateDesc(typeChar, command) diff --git a/Mac/PythonLauncher/MyDocument.m b/Mac/PythonLauncher/MyDocument.m index 5acc2dcc90c..86112c4b15d 100755 --- a/Mac/PythonLauncher/MyDocument.m +++ b/Mac/PythonLauncher/MyDocument.m @@ -121,8 +121,8 @@ return YES; } else { [self run]; - [self close]; - return NO; + [self performSelector:@selector(close) withObject:nil afterDelay:0.0]; + return YES; } } diff --git a/Mac/PythonLauncher/doscript.m b/Mac/PythonLauncher/doscript.m index 3e4e22393c0..024b883f190 100644 --- a/Mac/PythonLauncher/doscript.m +++ b/Mac/PythonLauncher/doscript.m @@ -11,108 +11,49 @@ #import #import "doscript.h" -/* I assume I could pick these up from somewhere, but where... */ -#define CREATOR 'trmx' - -#define ACTIVATE_CMD 'misc' -#define ACTIVATE_SUITE 'actv' - -#define DOSCRIPT_CMD 'dosc' -#define DOSCRIPT_SUITE 'core' -#define WITHCOMMAND 'cmnd' - -/* ... and there's probably also a better way to do this... */ -#define START_TERMINAL "/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal &" - extern int doscript(const char *command) { - OSErr err; - AppleEvent theAEvent, theReply; - AEAddressDesc terminalAddress; - AEDesc commandDesc; - OSType terminalCreator = CREATOR; - - /* set up locals */ - AECreateDesc(typeNull, NULL, 0, &theAEvent); - AECreateDesc(typeNull, NULL, 0, &terminalAddress); - AECreateDesc(typeNull, NULL, 0, &theReply); - AECreateDesc(typeNull, NULL, 0, &commandDesc); - - /* create the "activate" event for Terminal */ - err = AECreateDesc(typeApplSignature, (Ptr) &terminalCreator, - sizeof(terminalCreator), &terminalAddress); - if (err != noErr) { - NSLog(@"doscript: AECreateDesc: error %d\n", err); - goto bail; - } - err = AECreateAppleEvent(ACTIVATE_SUITE, ACTIVATE_CMD, - &terminalAddress, kAutoGenerateReturnID, - kAnyTransactionID, &theAEvent); - - if (err != noErr) { - NSLog(@"doscript: AECreateAppleEvent(activate): error %d\n", err); - goto bail; - } - /* send the event */ - err = AESend(&theAEvent, &theReply, kAEWaitReply, - kAENormalPriority, kAEDefaultTimeout, NULL, NULL); - if ( err == -600 ) { - int count=10; - /* If it failed with "no such process" try to start Terminal */ - err = system(START_TERMINAL); - if ( err ) { - NSLog(@"doscript: system(): %s\n", strerror(errno)); - goto bail; - } - do { - sleep(1); - /* send the event again */ - err = AESend(&theAEvent, &theReply, kAEWaitReply, - kAENormalPriority, kAEDefaultTimeout, NULL, NULL); - } while (err == -600 && --count > 0); - if ( err == -600 ) - NSLog(@"doscript: Could not activate Terminal\n"); - } - if (err != noErr) { - NSLog(@"doscript: AESend(activate): error %d\n", err); - goto bail; - } - - /* create the "doscript with command" event for Terminal */ - err = AECreateAppleEvent(DOSCRIPT_SUITE, DOSCRIPT_CMD, - &terminalAddress, kAutoGenerateReturnID, - kAnyTransactionID, &theAEvent); - if (err != noErr) { - NSLog(@"doscript: AECreateAppleEvent(doscript): error %d\n", err); - goto bail; - } - - /* add the command to the apple event */ - err = AECreateDesc(typeChar, command, strlen(command), &commandDesc); - if (err != noErr) { - NSLog(@"doscript: AECreateDesc(command): error %d\n", err); - goto bail; - } - err = AEPutParamDesc(&theAEvent, WITHCOMMAND, &commandDesc); - if (err != noErr) { - NSLog(@"doscript: AEPutParamDesc: error %d\n", err); - goto bail; - } + char *bundleID = "com.apple.Terminal"; + AppleEvent evt, res; + AEDesc desc; + OSStatus err; - /* send the command event to Terminal.app */ - err = AESend(&theAEvent, &theReply, kAEWaitReply, - kAENormalPriority, kAEDefaultTimeout, NULL, NULL); - - if (err != noErr) { - NSLog(@"doscript: AESend(docommand): error %d\n", err); - goto bail; - } - /* clean up and leave */ -bail: - AEDisposeDesc(&commandDesc); - AEDisposeDesc(&theAEvent); - AEDisposeDesc(&terminalAddress); - AEDisposeDesc(&theReply); - return err; + [[NSWorkspace sharedWorkspace] launchApplication:@"/Applications/Utilities/Terminal.app/"]; + + // Build event + err = AEBuildAppleEvent(kAECoreSuite, kAEDoScript, + typeApplicationBundleID, + bundleID, strlen(bundleID), + kAutoGenerateReturnID, + kAnyTransactionID, + &evt, NULL, + "'----':utf8(@)", strlen(command), + command); + if (err) { + NSLog(@"AEBuildAppleEvent failed: %d\n", err); + return err; + } + + // Send event and check for any Apple Event Manager errors + err = AESendMessage(&evt, &res, kAEWaitReply, kAEDefaultTimeout); + AEDisposeDesc(&evt); + if (err) { + NSLog(@"AESendMessage failed: %d\n", err); + return err; + } + // Check for any application errors + err = AEGetParamDesc(&res, keyErrorNumber, typeSInt32, &desc); + AEDisposeDesc(&res); + if (!err) { + AEGetDescData(&desc, &err, sizeof(err)); + NSLog(@"Terminal returned an error: %d", err); + AEDisposeDesc(&desc); + } else if (err == errAEDescNotFound) { + err = noErr; + } else { + NSLog(@"AEGetPArmDesc returned an error: %d", err); + } + + return err; }