/* Copyright (c) 2004, Stˇphane Sudre All rights reserved. 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, 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 and/or other materials provided with the distribution. - Neither the name of the WhiteBox 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, 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "WBOpenWithMenu.h" @interface NSMutableDictionary(OpenWithMenu) - (NSComparisonResult) compareNameAndVersion:(NSMutableDictionary *) other; @end @implementation NSMutableDictionary(OpenWithMenu) - (NSComparisonResult) compareNameAndVersion:(NSMutableDictionary *) other { NSComparisonResult tResult; tResult=[[self objectForKey:@"Display Name"] caseInsensitiveCompare:[other objectForKey:@"Display Name"]]; if (tResult==NSOrderedSame) { // Compare version tResult=[[self objectForKey:@"Version"] caseInsensitiveCompare:[other objectForKey:@"Version"]]; if (tResult==NSOrderedAscending) { [other setObject:[NSString stringWithFormat:@"%@ (%@)",[other objectForKey:@"Display Name"],[other objectForKey:@"Version"]] forKey:@"Display Name"]; return NSOrderedDescending; } else if (tResult==NSOrderedDescending) { [self setObject:[NSString stringWithFormat:@"%@ (%@)",[self objectForKey:@"Display Name"],[self objectForKey:@"Version"]] forKey:@"Display Name"]; return NSOrderedAscending; } else { // Same version, we will only keep one (the one on the boot volume preferably) NSString * tPath=[self objectForKey:@"Path"]; if ([tPath hasPrefix:@"/Volumes"]==YES) { [self removeObjectForKey:@"Path"]; } else { [other removeObjectForKey:@"Path"]; } } } return tResult; } @end @implementation WBOpenWithMenu + (WBOpenWithMenu *) sharedOpenWithMenu { static WBOpenWithMenu * sSharedOpenWithMenu=nil; if (sSharedOpenWithMenu==nil) { sSharedOpenWithMenu=[WBOpenWithMenu new]; } return sSharedOpenWithMenu; } - (id) init { self=[super init]; if (self!=nil) { if (NSAppKitVersionNumber>=663.0) { CFBundleRef tBundleRef; CFURLRef tURLRef; tURLRef=CFURLCreateWithFileSystemPath(kCFAllocatorDefault,CFSTR("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/LaunchServices.framework"), kCFURLPOSIXPathStyle,TRUE); if (tURLRef!=nil) { tBundleRef=CFBundleCreate(kCFAllocatorDefault,tURLRef); if (tBundleRef!=NULL) { LSInit(kLSInitializeDefaults); if (CFBundleLoadExecutable(tBundleRef)==TRUE) { function_=CFBundleGetFunctionPointerForName(tBundleRef,CFSTR("LSCopyApplicationURLsForURL")/*_LSCopyApplicationURLsForItemURL*/); } } // Release Memory CFRelease(tURLRef); } } } return self; } - (WBGetApplicationsListForURL) function { return function_; } - (void) setFilePath:(NSString *) inPath { if (filePath_!=inPath) { [filePath_ release]; filePath_=[inPath copy]; } } - (NSString *) filePath { return [[filePath_ retain] autorelease]; } - (void) setTarget:(id) target { target_=target; } - (void) setAction:(SEL) inAction { action_=inAction; } - (void) setApplications:(NSArray *) inApplications { if (applications_!=inApplications) { [applications_ release]; applications_=[inApplications copy]; } } #pragma mark - - (IBAction) selectApplication:(id) sender { if (target_!=nil && action_!=nil) { int tTag=[sender tag]; if (tTag<[applications_ count]) { [target_ performSelector:action_ withObject:[applications_ objectAtIndex:tTag] withObject:filePath_]; } } } + (NSMenu *) openWithMenuForFile:(NSString *) inString target:(id) target action:(SEL) action { NSArray * tArray; NSURL * tURL; WBOpenWithMenu * tOpenWithMenu; WBGetApplicationsListForURL tFunction; tURL=[NSURL fileURLWithPath:inString]; tOpenWithMenu=[WBOpenWithMenu sharedOpenWithMenu]; tFunction=[tOpenWithMenu function]; if (tFunction==NULL) { return nil; } tArray=(NSArray *) tFunction((CFURLRef) tURL,kLSRolesAll); [tArray autorelease]; if (tArray!=nil) { NSURL * tPreferedApplicaton; if (LSGetApplicationForURL((CFURLRef) tURL,kLSRolesAll,NULL,(CFURLRef *) &tPreferedApplicaton)!=kLSApplicationNotFoundErr) { NSMenu * tMenu; // Create the Menu tMenu=[[NSMenu alloc] initWithTitle:@""]; if (tMenu!=nil) { CFIndex i,tCount; NSMenuItem * tMenuItem; NSString * tPreferredPath; NSMutableArray * tMutableArray; NSWorkspace * tWorkspace; NSFileManager * tFileManager; int tTag=0; NSMutableArray * tApplications; tWorkspace=[NSWorkspace sharedWorkspace]; tFileManager=[NSFileManager defaultManager]; tPreferredPath=[tPreferedApplicaton path]; tCount=[tArray count]; tMutableArray=[NSMutableArray arrayWithCapacity:tCount]; for(i=0;inumericVersion)); if ((tNumVersion & 0x00040000)!=0) { tVersion=[NSString stringWithFormat:@"%d.%d.%d",(tNumVersion & 0xFF000000)>>24, (tNumVersion & 0x00F00000)>>20, (tNumVersion & 0x000F0000)>>16]; } else { tVersion=[NSString stringWithFormat:@"%d.%d",(tNumVersion & 0xFF000000)>>24, (tNumVersion & 0x00F00000)>>20]; } } if (tBundleRef!=NULL) { CFBundleCloseBundleResourceMap(tBundleRef,resNum); // Release Memory CFRelease(tBundleRef); } } } [tMutableDictionary setObject:tVersion forKey:@"Version"]; [tMutableArray addObject:tMutableDictionary]; } // Sort the array [tMutableArray sortUsingSelector:@selector(compareNameAndVersion:)]; // Set the value for the shared WBOpenWithMenu controller [tOpenWithMenu setTarget:target]; [tOpenWithMenu setAction:action]; [tOpenWithMenu setFilePath:inString]; // Add the Separator [tMenu addItem:[NSMenuItem separatorItem]]; // Create the other applications tApplications=[NSMutableArray arrayWithCapacity:tCount]; for(i=0;i