first attempt at implementing -openURL: for NSWorkspace

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27846 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-02-11 13:13:19 +00:00
parent 25dc9dc650
commit ec51f7feaf
3 changed files with 154 additions and 3 deletions

View file

@ -1,3 +1,11 @@
2009-02-11 Richard Frith-Macdonald <rfm@gnu.org>
* Tools/make_services.m: Check applications for CFBundleURLTypes
(see http://developer.apple.com/documentation/MacOSX/conceptual/BPRuntimeConfig/Articles/PListKeys.html)
* Source/NSWorkspace.m: ([-openURL:]) try to open non-file URLs using
an app found based on CFBundleURLTypes, and if that fails try to use
any available 'OpenURL' service.
2009-02-11 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSTheme.m: Fix typo in include

View file

@ -65,6 +65,7 @@
#include "AppKit/NSWorkspace.h"
#include "AppKit/NSApplication.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSPasteboard.h"
#include "AppKit/NSView.h"
#include "AppKit/NSPanel.h"
#include "AppKit/NSWindow.h"
@ -803,7 +804,55 @@ static NSString *_rootPath = @"/";
}
else
{
return NO;
NSDictionary *map;
NSString *appName;
/* Look up an application to handle this URL scheme.
*/
map = [applications objectForKey: @"GSSchemesMap"];
appName = [map objectForKey: [[url scheme] lowercaseString]];
if (appName != nil)
{
NSString *urlString = [url absoluteString];
id app;
/* Now try to get the application to open the URL.
*/
app = [self _connectApplication: appName];
if (app == nil)
{
NSArray *args;
args = [NSArray arrayWithObjects: @"-GSFilePath", urlString, nil];
return [self _launchApplication: appName arguments: args];
}
else
{
NS_DURING
{
[app application: NSApp openFile: urlString];
}
NS_HANDLER
{
NSWarnLog(@"Failed to contact '%@' to open file", appName);
return NO;
}
NS_ENDHANDLER
}
[NSApp deactivate];
return YES;
}
else
{
NSPasteboard *pb;
/* No application found to open the URL.
* Try any OpenURL service available.
*/
pb = [NSPasteboard pasteboardWithUniqueName];
[url writeToPasteboard: pb];
return NSPerformService(@"OpenURL", pb);
}
}
}

View file

@ -57,6 +57,7 @@ static NSMutableDictionary *printMap;
static NSMutableDictionary *spellMap;
static NSMutableDictionary *applicationMap;
static NSMutableDictionary *extensionsMap;
static NSMutableDictionary *schemesMap;
static Class aClass;
static Class dClass;
@ -132,6 +133,7 @@ main(int argc, char** argv, char **env_c)
spellMap = [NSMutableDictionary dictionaryWithCapacity: 8];
applicationMap = [NSMutableDictionary dictionaryWithCapacity: 64];
extensionsMap = [NSMutableDictionary dictionaryWithCapacity: 64];
schemesMap = [NSMutableDictionary dictionaryWithCapacity: 64];
env = [proc environment];
args = [proc arguments];
@ -280,6 +282,7 @@ main(int argc, char** argv, char **env_c)
oldMap = nil;
}
[applicationMap setObject: extensionsMap forKey: @"GSExtensionsMap"];
[applicationMap setObject: schemesMap forKey: @"GSSchemesMap"];
if ([applicationMap isEqual: oldMap] == NO)
{
data = [NSSerializer serializePropertyList: applicationMap];
@ -296,6 +299,95 @@ main(int argc, char** argv, char **env_c)
exit(EXIT_SUCCESS);
}
/*
* Load information about the shemes of URLs that an application supports.
* For each scheme found, produce a dictionary, keyed by app name, that
* contains dictionaries giving scheme info for that extension.
* NB. in order to make schemes case-insensiteve - we always convert
* to lowercase.
*/
static void addSchemesForApplication(NSDictionary *info, NSString *app)
{
unsigned int i;
id o0;
NSArray *a0;
o0 = [info objectForKey: @"CFBundleURLTypes"];
if (o0)
{
if ([o0 isKindOfClass: aClass] == NO)
{
if (verbose > 0)
NSLog(@"bad app CFBundleURLTypes (not an array) - %@", app);
return;
}
a0 = (NSArray*)o0;
i = [a0 count];
while (i-- > 0)
{
NSDictionary *t;
NSArray *a1;
id o1 = [a0 objectAtIndex: i];
unsigned int j;
if ([o1 isKindOfClass: dClass] == NO)
{
if (verbose > 0)
NSLog(@"bad app CFBundleURLTypes (type not a dictionary) - %@",
app);
return;
}
/*
* Set 't' to the dictionary defining a particular file type.
*/
t = (NSDictionary*)o1;
if (o1 == nil)
{
o1 = [t objectForKey: @"CFBundleURLSchemes"];
}
if (o1 == nil)
{
continue;
}
if ([o1 isKindOfClass: aClass] == NO)
{
if (verbose > 0)
NSLog(@"bad app CFBundleURLTypes (schemes not an array) - %@",
app);
return;
}
a1 = (NSArray*)o1;
j = [a1 count];
while (j-- > 0)
{
NSString *e;
NSMutableDictionary *d;
e = [[a1 objectAtIndex: j] lowercaseString];
if ([e length] == 0)
{
if (verbose > 0)
NSLog(@"Illegal (nul) scheme ignored for - %@", app);
return;
}
d = [schemesMap objectForKey: e];
if (d == nil)
{
d = [NSMutableDictionary dictionaryWithCapacity: 1];
[schemesMap setObject: d forKey: e];
}
if ([d objectForKey: app] == nil)
{
[d setObject: t forKey: app];
}
}
}
}
}
/*
* Load information about the types of files that an application supports.
* For each extension found, produce a dictionary, keyed by app name, that
@ -345,7 +437,7 @@ static void addExtensionsForApplication(NSDictionary *info, NSString *app)
t = (NSDictionary*)o1;
o1 = [t objectForKey: @"NSUnixExtensions"];
if(o1 == nil)
if (o1 == nil)
{
o1 = [t objectForKey: @"CFBundleTypeExtensions"];
}
@ -391,7 +483,7 @@ static void addExtensionsForApplication(NSDictionary *info, NSString *app)
NSDictionary *extensions;
o0 = [info objectForKey: @"NSExtensions"];
if(o0 == nil)
if (o0 == nil)
{
o0 = [info objectForKey: @"CFBundleTypeExtensions"];
}
@ -511,6 +603,7 @@ scanDirectory(NSMutableDictionary *services, NSString *path)
}
addExtensionsForApplication(info, name);
addSchemesForApplication(info, name);
}
else if (verbose > 0)
{
@ -653,6 +746,7 @@ scanApplications(NSMutableDictionary *services, NSString *path)
}
addExtensionsForApplication(info, name);
addSchemesForApplication(info, name);
}
else if (verbose > 0)
{