X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Flinkback%2FLinkBackServer.m;h=d089fca7715b126c19f4830a111c4cff4315a12b;hb=37f987afc981ae8dfbf697e097b7b18c7404f544;hp=84e224745f69c2148b9f97ddf92b503efcae8140;hpb=4b6fe4247524a4f365e12b2c227ba7c56686620e;p=lyx.git diff --git a/src/support/linkback/LinkBackServer.m b/src/support/linkback/LinkBackServer.m index 84e224745f..d089fca771 100644 --- a/src/support/linkback/LinkBackServer.m +++ b/src/support/linkback/LinkBackServer.m @@ -6,30 +6,30 @@ // Copyright (c) 2004, Nisus Software, Inc. // All rights reserved. -// Redistribution and use in source and binary forms, with or without +// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // -// Redistributions of source code must retain the above copyright notice, +// Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // -// Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -// Neither the name of the Nisus Software, Inc. nor the names of its -// contributors may be used to endorse or promote products derived from this +// Neither the name of the Nisus Software, Inc. nor the names of its +// contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // @@ -50,18 +50,18 @@ NSMutableDictionary* LinkBackServers = nil ; static BOOL inited = NO ; if (inited) return ; - [super initialize] ; + [super initialize] ; inited = YES ; - + if (!LinkBackServers) LinkBackServers = [[NSMutableDictionary alloc] init]; } -+ (LinkBackServer*)LinkBackServerWithName:(NSString*)aName ++ (LinkBackServer*)LinkBackServerWithName:(NSString*)aName { return [LinkBackServers objectForKey: aName] ; } -+ (BOOL)publishServerWithName:(NSString*)aName delegate:(id)del ++ (BOOL)publishServerWithName:(NSString*)aName delegate:(id)del { LinkBackServer* serv = [[LinkBackServer alloc] initWithName: aName delegate: del] ; BOOL ret = [serv publish] ; // retains if successful @@ -72,20 +72,24 @@ NSMutableDictionary* LinkBackServers = nil ; BOOL LinkBackServerIsSupported(NSString* name, id supportedServers) { BOOL ret = NO ; +#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050) + NSUInteger idx ; +#else int idx ; +#endif NSString* curServer = supportedServers ; - + // NOTE: supportedServers may be nil, an NSArray, or NSString. if (supportedServers) { if ([supportedServers isKindOfClass: [NSArray class]]) { idx = [supportedServers count] ; - while((NO==ret) && (--idx >= 0)) { - curServer = [supportedServers objectAtIndex: idx] ; + while((NO==ret) && (idx > 0)) { + curServer = [supportedServers objectAtIndex: --idx] ; ret = [curServer isEqualToString: name] ; } - } else ret = [curServer isEqualToString: name] ; + } else ret = [curServer isEqualToString: name] ; } - + return ret ; } @@ -94,48 +98,49 @@ NSString* FindLinkBackServer(NSString* bundleIdentifier, NSString* serverName, N NSString* ret = nil ; NSFileManager* fm = [NSFileManager defaultManager] ; -#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) +#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1050) NSArray* contents = [fm contentsOfDirectoryAtPath: dir error: nil] ; + NSUInteger idx ; #else NSArray* contents = [fm directoryContentsAtPath: dir] ; -#endif int idx ; +#endif - NSLog(@"searching for %@ in folder: %@", serverName, dir) ; - // working info NSString* cpath ; NSBundle* cbundle ; NSString* cbundleIdentifier ; id supportedServers ; + NSLog(@"searching for %@ in folder: %@", serverName, dir) ; + // resolve any symlinks, expand tildes. dir = [dir stringByStandardizingPath] ; - + // find all .app bundles in the directory and test them. idx = (contents) ? [contents count] : 0 ; - while((nil==ret) && (--idx >= 0)) { - cpath = [contents objectAtIndex: idx] ; - + while((nil==ret) && (idx > 0)) { + cpath = [contents objectAtIndex: --idx] ; + if ([[cpath pathExtension] isEqualToString: @"app"]) { cpath = [dir stringByAppendingPathComponent: cpath] ; cbundle = [NSBundle bundleWithPath: cpath] ; cbundleIdentifier = [cbundle bundleIdentifier] ; - + if ([cbundleIdentifier isEqualToString: bundleIdentifier]) { supportedServers = [[cbundle infoDictionary] objectForKey: @"LinkBackServer"] ; ret= (LinkBackServerIsSupported(serverName, supportedServers)) ? cpath : nil ; } } } - + // if the app was not found, descend into non-app dirs. only descend 4 levels to avoid taking forever. if ((nil==ret) && (level<4)) { idx = (contents) ? [contents count] : 0 ; - while((nil==ret) && (--idx >= 0)) { + while((nil==ret) && (idx > 0)) { BOOL isdir ; - - cpath = [contents objectAtIndex: idx] ; + + cpath = [contents objectAtIndex: --idx] ; [fm fileExistsAtPath: cpath isDirectory: &isdir] ; if (isdir && (![[cpath pathExtension] isEqualToString: @"app"])) { cpath = [dir stringByAppendingPathComponent: cpath] ; @@ -143,63 +148,68 @@ NSString* FindLinkBackServer(NSString* bundleIdentifier, NSString* serverName, N } } } - + return ret ; } void LinkBackRunAppNotFoundPanel(NSString* appName, NSURL* url) { - int result ; - + // strings for panel NSBundle* b = [NSBundle bundleForClass: [LinkBack class]] ; NSString* title ; NSString* msg ; NSString* ok ; NSString* urlstr ; - + title = NSLocalizedStringFromTableInBundle(@"_AppNotFoundTitle", @"Localized", b, @"app not found title") ; ok = NSLocalizedStringFromTableInBundle(@"_OK", @"Localized", b, @"ok") ; msg = (url) ? NSLocalizedStringFromTableInBundle(@"_AppNotFoundMessageWithURL", @"Localized", b, @"app not found msg") : NSLocalizedStringFromTableInBundle(@"_AppNotFoundMessageNoURL", @"Localized", b, @"app not found msg") ; - + urlstr = (url) ? NSLocalizedStringFromTableInBundle(@"_GetApplication", @"Localized", b, @"Get application") : nil ; title = [NSString stringWithFormat: title, appName] ; - - result = NSRunCriticalAlertPanel(title, msg, ok, urlstr, nil) ; - if (NSAlertAlternateReturn == result) { - [[NSWorkspace sharedWorkspace] openURL: url] ; - } + + NSAlert* alert = [[NSAlert alloc] init]; + [alert setAlertStyle:NSAlertStyleCritical]; + [alert setMessageText:title]; + [alert setInformativeText:[NSString stringWithFormat:@"%@", msg]]; + [alert addButtonWithTitle:ok]; + [alert addButtonWithTitle:urlstr]; + [alert beginSheetModalForWindow:[NSApp mainWindow] completionHandler:^(NSModalResponse returnCode) { + if (returnCode == NSAlertSecondButtonReturn) + [[NSWorkspace sharedWorkspace] openURL: url] ; + }]; } -+ (LinkBackServer*)LinkBackServerWithName:(NSString*)aName inApplication:(NSString*)bundleIdentifier launchIfNeeded:(BOOL)flag fallbackURL:(NSURL*)url appName:(NSString*)appName ; ++ (LinkBackServer*)LinkBackServerWithName:(NSString*)aName inApplication:(NSString*)bundleIdentifier launchIfNeeded:(BOOL)flag fallbackURL:(NSURL*)url appName:(NSString*)appName { BOOL connect = YES ; NSString* serverName = MakeLinkBackServerName(bundleIdentifier, aName) ; id ret = nil ; NSTimeInterval tryMark ; - + // Try to connect ret = [NSConnection rootProxyForConnectionWithRegisteredName: serverName host: nil] ; - + // if launchIfNeeded, and the connection was not available, try to launch. if((!ret) && (flag)) { NSString* appPath ; id linkBackServers ; - + // first, try to find the app with the bundle identifier appPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier: bundleIdentifier] ; - linkBackServers = [[[NSBundle bundleWithPath: appPath] infoDictionary] objectForKey: @"LinkBackServer"] ; + linkBackServers = [[[NSBundle bundleWithPath: appPath] infoDictionary] objectForKey: @"LinkBackServer"] ; appPath = (LinkBackServerIsSupported(aName, linkBackServers)) ? appPath : nil ; - + // if the found app is not supported, we will need to search for the app ourselves. if (nil==appPath) appPath = FindLinkBackServer(bundleIdentifier, aName, @"/Applications",0); - + if (nil==appPath) appPath = FindLinkBackServer(bundleIdentifier, aName, @"~/Applications",0); - + if (nil==appPath) appPath = FindLinkBackServer(bundleIdentifier, aName, @"/Network/Applications",0); - + // if app path has been found, launch the app. if (appPath) { [[NSWorkspace sharedWorkspace] launchApplication: appName] ; @@ -208,15 +218,15 @@ void LinkBackRunAppNotFoundPanel(NSString* appName, NSURL* url) connect = NO ; } } - - // if needed, try to connect. + + // if needed, try to connect. // retry connection for a while if we did not succeed at first. This gives the app time to launch. if (connect && (nil==ret)) { tryMark = [NSDate timeIntervalSinceReferenceDate] ; do { ret = [NSConnection rootProxyForConnectionWithRegisteredName: serverName host: nil] ; } while ((!ret) && (([NSDate timeIntervalSinceReferenceDate]-tryMark)<10)) ; - + } // setup protocol and return @@ -232,7 +242,7 @@ void LinkBackRunAppNotFoundPanel(NSString* appName, NSURL* url) delegate = aDel ; listener = nil ; } - + return self ; } @@ -247,40 +257,40 @@ void LinkBackRunAppNotFoundPanel(NSString* appName, NSURL* url) { NSString* serverName = MakeLinkBackServerName([[NSBundle mainBundle] bundleIdentifier], name) ; BOOL ret = YES ; - + // create listener and connect NSPort* port = [NSPort port] ; listener = [NSConnection connectionWithReceivePort: port sendPort:port] ; [listener setRootObject: self] ; ret = [listener registerName: serverName] ; - + // if successful, retain connection and add self to list of servers. if (ret) { [listener retain] ; [LinkBackServers setObject: self forKey: name] ; - } else listener = nil ; // listener will dealloc on its own. - + } else listener = nil ; // listener will dealloc on its own. + return ret ; } -- (void)retract +- (void)retract { if (listener) { [listener invalidate] ; [listener release] ; listener = nil ; } - + [LinkBackServers removeObjectForKey: name] ; } -- (LinkBack*)initiateLinkBackFromClient:(LinkBack*)clientLinkBack +- (LinkBack*)initiateLinkBackFromClient:(LinkBack*)clientLinkBack { LinkBack* ret = [[LinkBack alloc] initServerWithClient: clientLinkBack delegate: delegate] ; - + // NOTE: we do not release because LinkBack will release itself when it the link closes. (caj) - - return ret ; + + return ret ; } @end