diff options
Diffstat (limited to 'packaging/macosx/ScriptExec/main.c')
| -rw-r--r-- | packaging/macosx/ScriptExec/main.c | 274 |
1 files changed, 39 insertions, 235 deletions
diff --git a/packaging/macosx/ScriptExec/main.c b/packaging/macosx/ScriptExec/main.c index f413d438a..e3f066d70 100644 --- a/packaging/macosx/ScriptExec/main.c +++ b/packaging/macosx/ScriptExec/main.c @@ -6,6 +6,7 @@ With modifications by Aaron Voisine for gimp.app With modifications by Marianne gagnon for Wilber-loves-apple With modifications by Michael Wybrow for Inkscape.app + With modifications by ~suv for Inkscape.app This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,7 +28,7 @@ /* * This app laucher basically takes care of: - * - launching Inkscape and X11 when double-clicked + * - launching Inkscape when double-clicked * - bringing X11 to the top when its icon is clicked in the dock (via a small applescript) * - catch file dropped on icon events (and double-clicked gimp documents) and notify gimp. * - catch quit events performed outside gimp, e.g. on the dock icon. @@ -39,7 +40,12 @@ #pragma mark Includes // Apple stuff + +// Note: including Carbon prevents building the launcher app in x86_64 +// used for StandardAlert in RequestUserAttention(), +// RedFatalAlert() #include <Carbon/Carbon.h> + #include <CoreFoundation/CoreFoundation.h> #include <Security/Authorization.h> #include <Security/AuthorizationTags.h> @@ -67,7 +73,6 @@ #define kEventClassRedFatalAlert 911 // custom carbon event types -#define kEventKindX11Failed 911 #define kEventKindFCCacheFailed 912 //maximum arguments the script accepts @@ -83,15 +88,14 @@ static void *OpenDoc(void *arg); static OSErr ExecuteScript(char *script, pid_t *pid); static void GetParameters(void); -static char* GetScript(void); -static char* GetOpenDoc(void); +static unsigned char* GetScript(void); +static unsigned char* GetOpenDoc(void); OSErr LoadMenuBar(char *appName); -static OSStatus FSMakePath(FSSpec file, char *path, long maxPathSize); +static OSStatus FSMakePath(FSRef fileRef, unsigned char *path, long maxPathSize); static void RedFatalAlert(Str255 errorString, Str255 expStr); -static short DoesFileExist(char *path); -static OSStatus FixFCCache(void); +static short DoesFileExist(unsigned char *path); static OSErr AppQuitAEHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon); @@ -99,8 +103,6 @@ static OSErr AppOpenDocAEHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon); static OSErr AppOpenAppAEHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon); -static OSStatus X11FailedHandler(EventHandlerCallRef theHandlerCall, - EventRef theEvent, void *userData); static OSStatus FCCacheFailedHandler(EventHandlerCallRef theHandlerCall, EventRef theEvent, void *userData); static OSErr AppReopenAppAEHandler(const AppleEvent *theAppleEvent, @@ -109,7 +111,7 @@ static OSErr AppReopenAppAEHandler(const AppleEvent *theAppleEvent, static OSStatus CompileAppleScript(const void* text, long textLength, AEDesc *resultData); static OSStatus SimpleCompileAppleScript(const char* theScript); -static void runScript(); +static OSErr runScript(); /////////////////////////////////////// // Globals @@ -144,7 +146,6 @@ extern char **environ; int main(int argc, char* argv[]) { OSErr err = noErr; - EventTypeSpec X11events = { kEventClassRedFatalAlert, kEventKindX11Failed }; EventTypeSpec FCCacheEvents = { kEventClassRedFatalAlert, kEventKindFCCacheFailed }; InitCursor(); @@ -165,9 +166,6 @@ int main(int argc, char* argv[]) 0, false); err += InstallEventHandler(GetApplicationEventTarget(), - NewEventHandlerUPP(X11FailedHandler), 1, - &X11events, NULL, NULL); - err += InstallEventHandler(GetApplicationEventTarget(), NewEventHandlerUPP(FCCacheFailedHandler), 1, &FCCacheEvents, NULL, NULL); @@ -181,7 +179,7 @@ int main(int argc, char* argv[]) GetParameters(); //load data from files containing exec settings // compile "icon clicked" script so it's ready to execute - SimpleCompileAppleScript("tell application \"X11\" to activate"); + SimpleCompileAppleScript("tell application \"XQuartz\" to activate"); RunApplicationEventLoop(); //Run the event loop return 0; @@ -229,6 +227,7 @@ static void ShowFirstStartWarningDialog(void) ////////////////////////////////// // Handler for when fontconfig caches need to be generated +// TODO: remove (alert and touch moved to launcher script) ////////////////////////////////// static OSStatus FCCacheFailedHandler(EventHandlerCallRef theHandlerCall, EventRef theEvent, void *userData) @@ -243,8 +242,8 @@ static OSStatus FCCacheFailedHandler(EventHandlerCallRef theHandlerCall, ShowFirstStartWarningDialog(); // Note that we've seen the warning. - system("test -d \"$HOME/.inkscape-etc\" || mkdir -p \"$HOME/.inkscape-etc\"; " - "touch \"$HOME/.inkscape-etc/.fccache-new\""); + system("test -d \"$HOME/.cache/inkscape\" || mkdir -p \"$HOME/.cache/inkscape\"; " + "touch \"$HOME/.cache/inkscape/.fccache-new\""); // Rerun now. OSErr err = ExecuteScript(scriptPath, &pid); ExitToShell(); @@ -253,116 +252,6 @@ static OSStatus FCCacheFailedHandler(EventHandlerCallRef theHandlerCall, } -static size_t safeRead(int d, void *buf, size_t nbytes) -{ - ssize_t bytesToRead = nbytes; - ssize_t bytesRead = 0; - char *offset = (char *) buf; - - while ((bytesToRead > 0)) - { - bytesRead = read(d, offset, bytesToRead); - if (bytesRead > 0) - { - offset += bytesRead; - bytesToRead -= bytesRead; - } - else if (bytesRead == 0) - { - // Reached EOF. - break; - } - else if (bytesRead == -1) - { - if ((errno == EINTR) || (errno == EAGAIN)) - { - // Try again. - continue; - } - return 0; - } - } - return bytesRead; -} - - -///////////////////////////////////// -// Code to run fc-cache on first run -///////////////////////////////////// -static OSStatus FixFCCache (void) -{ - FILE *fileConnToChild = NULL; - int fdConnToChild = 0; - pid_t childPID = WAIT_ANY; - size_t bytesChildPID; - size_t bytesRead; - int status; - - char commandStr[] = "/usr/X11R6/bin/fc-cache"; - char *commandArgs[] = { "-f", NULL }; - - // Run fc-cache - AuthorizationItem authItems[] = - { - { - kAuthorizationRightExecute, - strlen(commandStr), - commandStr, - 0 - } - }; - AuthorizationItemSet authItemSet = - { - 1, - authItems - }; - AuthorizationRef authRef = NULL; - OSStatus err = AuthorizationCreate (NULL, &authItemSet, - kAuthorizationFlagInteractionAllowed | - kAuthorizationFlagExtendRights, &authRef); - - if (err == errAuthorizationSuccess) - { - err = AuthorizationExecuteWithPrivileges(authRef, commandStr, - kAuthorizationFlagDefaults, commandArgs, - &fileConnToChild); - - if (err == errAuthorizationSuccess) - { - // Unfortunately, AuthorizationExecuteWithPrivileges - // does not return the process ID associated with the - // process it runs. The best solution we have it to - // try and get the process ID from the file descriptor. - // This is based on example code from Apple's - // MoreAuthSample. - - fdConnToChild = fileno(fileConnToChild); - - // Try an get the process ID of the fc-cache command - bytesChildPID = sizeof(childPID); - bytesRead = safeRead(fdConnToChild, &childPID, - bytesChildPID); - if (bytesRead != bytesChildPID) - { - // If we can't get it the best alternative - // is to wait for any child to finish. - childPID = WAIT_ANY; - } - - if (fileConnToChild != NULL) { - fclose(fileConnToChild); - } - - // Wait for child process to finish. - waitpid(childPID, &status, 0); - } - } - AuthorizationFree(authRef, kAuthorizationFlagDestroyRights); - - return err; -} - - /////////////////////////////////// // Execution thread starts here /////////////////////////////////// @@ -373,12 +262,7 @@ static void *Execute (void *arg) taskDone = false; OSErr err = ExecuteScript(scriptPath, &pid); - if (err == (OSErr)11) { - CreateEvent(NULL, kEventClassRedFatalAlert, kEventKindX11Failed, 0, - kEventAttributeNone, &event); - PostEventToQueue(GetMainEventQueue(), event, kEventPriorityStandard); - } - else if (err == (OSErr)12) { + if (err == (OSErr)12) { CreateEvent(NULL, kEventClassRedFatalAlert, kEventKindFCCacheFailed, 0, kEventAttributeNone, &event); PostEventToQueue(GetMainEventQueue(), event, kEventPriorityHigh); @@ -448,14 +332,13 @@ static void GetParameters (void) /////////////////////////////////////// // Get path to the script in Resources folder /////////////////////////////////////// -static char* GetScript (void) +static unsigned char* GetScript (void) { CFStringRef fileName; CFBundleRef appBundle; CFURLRef scriptFileURL; FSRef fileRef; - FSSpec fileSpec; - char *path; + unsigned char *path; //get CF URL for script if (! (appBundle = CFBundleGetMainBundle())) return NULL; @@ -472,13 +355,9 @@ static char* GetScript (void) CFRelease(scriptFileURL); CFRelease(fileName); - //convert FSRef to FSSpec - if (FSGetCatalogInfo(&fileRef, kFSCatInfoNone, NULL, NULL, &fileSpec, - NULL)) return NULL; - //create path string if (! (path = malloc(kMaxPathLength))) return NULL; - if (FSMakePath(fileSpec, path, kMaxPathLength)) return NULL; + if (FSMakePath(fileRef, path, kMaxPathLength)) return NULL; if (! DoesFileExist(path)) return NULL; return path; @@ -487,14 +366,13 @@ static char* GetScript (void) /////////////////////////////////////// // Gets the path to openDoc in Resources folder /////////////////////////////////////// -static char* GetOpenDoc (void) +static unsigned char* GetOpenDoc (void) { CFStringRef fileName; CFBundleRef appBundle; CFURLRef openDocFileURL; FSRef fileRef; - FSSpec fileSpec; - char *path; + unsigned char *path; //get CF URL for openDoc if (! (appBundle = CFBundleGetMainBundle())) return NULL; @@ -511,13 +389,9 @@ static char* GetOpenDoc (void) CFRelease(openDocFileURL); CFRelease(fileName); - //convert FSRef to FSSpec - if (FSGetCatalogInfo(&fileRef, kFSCatInfoNone, NULL, NULL, &fileSpec, - NULL)) return NULL; - //create path string if (! (path = malloc(kMaxPathLength))) return NULL; - if (FSMakePath(fileSpec, path, kMaxPathLength)) return NULL; + if (FSMakePath(fileRef, path, kMaxPathLength)) return NULL; if (! DoesFileExist(path)) return NULL; return path; @@ -545,14 +419,8 @@ OSErr LoadMenuBar (char *appName) /////////////////////////////////////// // Generate path string from FSSpec record /////////////////////////////////////// -static OSStatus FSMakePath(FSSpec file, char *path, long maxPathSize) +static OSStatus FSMakePath(FSRef fileRef, unsigned char *path, long maxPathSize) { - OSErr err = noErr; - FSRef fileRef; - - //create file reference from file spec - if (err = FSpMakeFSRef(&file, &fileRef)) return err; - // and then convert the FSRef to a path return FSRefMakePath(&fileRef, path, maxPathSize); } @@ -569,9 +437,9 @@ static void RedFatalAlert (Str255 errorString, Str255 expStr) /////////////////////////////////////// // Determines whether file exists at path or not /////////////////////////////////////// -static short DoesFileExist (char *path) +static short DoesFileExist (unsigned char *path) { - if (access(path, F_OK) == -1) return false; + if (access((char *)path, F_OK) == -1) return false; return true; } @@ -590,7 +458,7 @@ static OSErr AppQuitAEHandler(const AppleEvent *theAppleEvent, if (! taskDone && pid) { //kill the script process brutally kill(pid, 9); - printf("Platypus App: PID %d killed brutally\n", pid); + printf("Inkscape.app: PID %d killed brutally\n", pid); } pthread_cancel(tid); @@ -610,31 +478,31 @@ static OSErr AppOpenDocAEHandler(const AppleEvent *theAppleEvent, #pragma unused (reply, refCon) OSErr err = noErr; - AEDescList fileSpecList; + AEDescList fileRefList; AEKeyword keyword; DescType type; short i; long count, actualSize; - FSSpec fileSpec; - char path[kMaxPathLength]; + FSRef fileRef; + unsigned char path[kMaxPathLength]; while (numArgs > 0) free(fileArgs[numArgs--]); //Read the AppleEvent err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, - &fileSpecList); + &fileRefList); - err = AECountItems(&fileSpecList, &count); //Count number of files + err = AECountItems(&fileRefList, &count); //Count number of files for (i = 1; i <= count; i++) { //iteratively process each file - //get fsspec from apple event - if (! (err = AEGetNthPtr(&fileSpecList, i, typeFSS, &keyword, &type, - (Ptr)&fileSpec, sizeof(FSSpec), &actualSize))) + //get fsref from apple event + if (! (err = AEGetNthPtr(&fileRefList, i, typeFSRef, &keyword, &type, + (Ptr)&fileRef, sizeof(FSRef), &actualSize))) { - //get path from file spec - if ((err = FSMakePath(fileSpec, (unsigned char *)&path, + //get path from file ref + if ((err = FSMakePath(fileRef, (unsigned char *)&path, kMaxPathLength))) return err; if (numArgs == kMaxArgumentsToScript) break; @@ -659,7 +527,7 @@ static OSErr AppOpenDocAEHandler(const AppleEvent *theAppleEvent, static OSErr AppReopenAppAEHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) { - runScript(); + return runScript(); } // if app is being opened @@ -675,70 +543,6 @@ static OSErr AppOpenAppAEHandler(const AppleEvent *theAppleEvent, } -static void OpenURL(Str255 url) -{ - // Use Internet Config to hand the URL to the appropriate application, as - // set by the user in the Internet Preferences pane. - ICInstance icInstance; - // Applications creator code: - OSType signature = 'Inks'; - OSStatus error = ICStart( &icInstance, signature ); - if ( error == noErr ) - { - ConstStr255Param hint = 0x0; - const char* data = url; - long length = strlen(url); - long start = 0; - long end = length; - // Don't bother testing return value (error); launched application will - // report problems. - ICLaunchURL( icInstance, hint, data, length, &start, &end ); - ICStop( icInstance ); - } -} - - -////////////////////////////////// -// Handler for when X11 fails to start -////////////////////////////////// -static OSStatus X11FailedHandler(EventHandlerCallRef theHandlerCall, - EventRef theEvent, void *userData) -{ - #pragma unused(theHanderCall, theEvent, userData) - - pthread_join(tid, NULL); - if (odtid) pthread_join(odtid, NULL); - - SInt16 itemHit; - const char *getX11 = "\pGet X11 for Panther"; - - AlertStdAlertParamRec params; - params.movable = true; - params.helpButton = false; - params.filterProc = NULL; - params.defaultText = (StringPtr) kAlertDefaultOKText; - params.cancelText = getX11; - params.otherText = NULL; - params.defaultButton = kAlertStdAlertOKButton; - params.cancelButton = kAlertStdAlertCancelButton; - params.position = kWindowDefaultPosition; - - StandardAlert(kAlertStopAlert, "\pFailed to start X11", - "\pInkscape.app requires Apple's X11, which is freely downloadable from Apple's website for Panther (10.3.x) users and available as an optional install from the installation DVD for Tiger (10.4.x) users.\n\nPlease install X11 and restart Inkscape.", - ¶ms, &itemHit); - - if (itemHit == kAlertStdAlertCancelButton) - { - OpenURL("http://www.apple.com/downloads/macosx/apple/macosx_updates/x11formacosx.html"); - } - - ExitToShell(); - - - return noErr; -} - - // Compile and run a small AppleScript. The code below does no cleanup and no proper error checks // but since it's there until the app is shut down, and since we know the script is okay, // there should not be any problems. @@ -774,7 +578,7 @@ static OSStatus CompileAppleScript(const void* text, long textLength, } /* runs the compiled applescript */ -static void runScript() +static OSErr runScript() { /* run the script */ err = OSAExecute(theComponent, scriptID, kOSANullScript, |
