diff options
author | Brian Cully <bjc@kublai.com> | 2008-04-14 21:45:08 -0400 |
---|---|---|
committer | Brian Cully <github.20.shmit@spamgourmet.com> | 2008-04-14 21:45:08 -0400 |
commit | 17349a5e426dc7acf1216a3767a22f69974cbca0 (patch) | |
tree | 20029d02f07ab6257cccec36d34fb312f796e1d1 /Plugins/BuiltInFunctions | |
download | liaison-17349a5e426dc7acf1216a3767a22f69974cbca0.tar.gz liaison-17349a5e426dc7acf1216a3767a22f69974cbca0.zip |
Initial commit.
Diffstat (limited to 'Plugins/BuiltInFunctions')
40 files changed, 4612 insertions, 0 deletions
diff --git a/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.h b/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.h new file mode 100644 index 0000000..7d923df --- /dev/null +++ b/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.h @@ -0,0 +1,72 @@ +/* + Copyright (c) 2001-2002, bDistributed.com, Inc. + 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 bDistributed.com, 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, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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 <Foundation/Foundation.h> +#import <CoreServices/CoreServices.h> + +@interface BDAlias : NSObject +{ + AliasHandle _alias; +} + +- (id)initWithAliasHandle:(AliasHandle)alias; // designated initializer +- (id)initWithData:(NSData *)data; +- (id)initWithPath:(NSString *)fullPath; +- (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath; +- (id)initWithFSRef:(FSRef *)ref; +- (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef; + +- (void)dealloc; + +- (AliasHandle)alias; +- (void)setAlias:(AliasHandle)newAlias; + +- (NSData *)aliasData; +- (void)setAliasData:(NSData *)newAliasData; + +- (NSString *)fullPath; +- (NSString *)fullPathRelativeToPath:(NSString *)relPath; + ++ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias; ++ (BDAlias *)aliasWithData:(NSData *)data; ++ (BDAlias *)aliasWithPath:(NSString *)fullPath; ++ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath; ++ (BDAlias *)aliasWithFSRef:(FSRef *)ref; ++ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef; + +@property (getter=alias) AliasHandle _alias; +@end diff --git a/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.m b/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.m new file mode 100644 index 0000000..2cf7d1d --- /dev/null +++ b/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.m @@ -0,0 +1,316 @@ +/* + Copyright (c) 2001-2002, bDistributed.com, Inc. + 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 bDistributed.com, 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, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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. +*/ + +#include <assert.h> + +#import "BDAlias.h" + + +static Handle DataToHandle(CFDataRef inData); +static CFDataRef HandleToData(Handle inHandle); + +static OSStatus PathToFSRef(CFStringRef inPath, FSRef *outRef); +static CFStringRef FSRefToPathCopy(const FSRef *inRef); + + +static Handle DataToHandle(CFDataRef inData) +{ + CFIndex len; + Handle handle = NULL; + + if (inData == NULL) { + return NULL; + } + + len = CFDataGetLength(inData); + + handle = NewHandle(len); + + if ((handle != NULL) && (len > 0)) { + HLock(handle); + BlockMoveData(CFDataGetBytePtr(inData), *handle, len); + HUnlock(handle); + } + + return handle; +} + +static CFDataRef HandleToData(Handle inHandle) +{ + CFDataRef data = NULL; + CFIndex len; + SInt8 handleState; + + if (inHandle == NULL) { + return NULL; + } + + len = GetHandleSize(inHandle); + + handleState = HGetState(inHandle); + + HLock(inHandle); + + data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *) *inHandle, len); + + HSetState(inHandle, handleState); + + return data; +} + +static OSStatus PathToFSRef(CFStringRef inPath, FSRef *outRef) +{ + CFURLRef tempURL = NULL; + Boolean gotRef = false; + + tempURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, inPath, + kCFURLPOSIXPathStyle, false); + + if (tempURL == NULL) { + return fnfErr; + } + + gotRef = CFURLGetFSRef(tempURL, outRef); + + CFRelease(tempURL); + + if (gotRef == false) { + return fnfErr; + } + + return noErr; +} + +static CFStringRef FSRefToPathCopy(const FSRef *inRef) +{ + CFURLRef tempURL = NULL; + CFStringRef result = NULL; + + if (inRef != NULL) { + tempURL = CFURLCreateFromFSRef(kCFAllocatorDefault, inRef); + + if (tempURL == NULL) { + return NULL; + } + + result = CFURLCopyFileSystemPath(tempURL, kCFURLPOSIXPathStyle); + + CFRelease(tempURL); + } + + return result; +} + + +@implementation BDAlias + +- (id)initWithAliasHandle:(AliasHandle)alias +{ + id ret = [super init]; + + if (ret != nil) { + _alias = alias; + } + + return ret; +} + +- (id)initWithData:(NSData *)data +{ + return [self initWithAliasHandle:(AliasHandle)DataToHandle((CFDataRef) data)]; +} + +- (id)initWithPath:(NSString *)fullPath +{ + OSStatus anErr = noErr; + FSRef ref; + + anErr = PathToFSRef((CFStringRef) fullPath, &ref); + + if (anErr != noErr) { + return nil; + } + + return [self initWithFSRef:&ref];; +} + +- (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath +{ + OSStatus anErr = noErr; + FSRef ref, relRef; + + anErr = PathToFSRef((CFStringRef) [relPath stringByAppendingPathComponent:path], + &ref); + + if (anErr != noErr) { + return nil; + } + + anErr = PathToFSRef((CFStringRef) relPath, &relRef); + + if (anErr != noErr) { + return nil; + } + + return [self initWithFSRef:&ref relativeToFSRef:&relRef]; +} + +- (id)initWithFSRef:(FSRef *)ref +{ + return [self initWithFSRef:ref relativeToFSRef:NULL]; +} + +- (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef +{ + OSStatus anErr = noErr; + AliasHandle alias = NULL; + + anErr = FSNewAlias(relRef, ref, &alias); + + if (anErr != noErr) { + return nil; + } + + return [self initWithAliasHandle:alias]; +} + +- (void)dealloc +{ + if (_alias != NULL) { + DisposeHandle((Handle) _alias); + _alias = NULL; + } + + [super dealloc]; +} + +- (AliasHandle)alias +{ + return _alias; +} + +- (void)setAlias:(AliasHandle)newAlias +{ + if (_alias != NULL) { + DisposeHandle((Handle) _alias); + } + + _alias = newAlias; +} + +- (NSData *)aliasData +{ + NSData *result; + + result = (NSData *)HandleToData((Handle) _alias); + + return [result autorelease]; +} + +- (void)setAliasData:(NSData *)newAliasData +{ + [self setAlias:(AliasHandle) DataToHandle((CFDataRef) newAliasData)]; +} + +- (NSString *)fullPath +{ + return [self fullPathRelativeToPath:nil]; +} + +- (NSString *)fullPathRelativeToPath:(NSString *)relPath +{ + OSStatus anErr = noErr; + FSRef relPathRef; + FSRef tempRef; + NSString *result = nil; + Boolean wasChanged; + + if (_alias != NULL) { + if (relPath != nil) { + anErr = PathToFSRef((CFStringRef)relPath, &relPathRef); + + if (anErr != noErr) { + return NULL; + } + + anErr = FSResolveAlias(&relPathRef, _alias, &tempRef, &wasChanged); + } else { + anErr = FSResolveAlias(NULL, _alias, &tempRef, &wasChanged); + } + + if (anErr != noErr) { + return NULL; + } + + result = (NSString *)FSRefToPathCopy(&tempRef); + } + + return [result autorelease]; +} + ++ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias +{ + return [[[BDAlias alloc] initWithAliasHandle:alias] autorelease]; +} + ++ (BDAlias *)aliasWithData:(NSData *)data +{ + return [[[BDAlias alloc] initWithData:data] autorelease]; +} + ++ (BDAlias *)aliasWithPath:(NSString *)fullPath +{ + return [[[BDAlias alloc] initWithPath:fullPath] autorelease]; +} + ++ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath +{ + return [[[BDAlias alloc] initWithPath:path relativeToPath:relPath] autorelease]; +} + ++ (BDAlias *)aliasWithFSRef:(FSRef *)ref +{ + return [[[BDAlias alloc] initWithFSRef:ref] autorelease]; +} + ++ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef +{ + return [[[BDAlias alloc] initWithFSRef:ref relativeToFSRef:relRef] autorelease]; +} + +@synthesize _alias; +@end diff --git a/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.rtf b/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.rtf new file mode 100644 index 0000000..a32ca81 --- /dev/null +++ b/Plugins/BuiltInFunctions/BDAlias/BDAlias/BDAlias.rtf @@ -0,0 +1,162 @@ +{\rtf1\mac\ansicpg10000\cocoartf102 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fswiss\fcharset77 Helvetica-Bold;} +{\colortbl;\red255\green255\blue255;\red255\green0\blue0;} +\margl1440\margr1440\vieww9000\viewh9000\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\fs24 \cf0 +\f1\b\fs28 \cf2 b\cf0 Distributed.com, Inc. +\f0\b0\fs24 \ + +\fs20 2549 W. Golf Rd. #348\ + Hoffman Estates, IL 60194\ + Phone: (847) 372-3955\ + Fax: (847) 589-3738\ + Web: bdistributed.com\ + Email: info@bdistributed.com\ + +\fs24 \ +Below is a quick reference for the BDAlias class.\ +\ + +\f1\b Instance Methods +\f0\b0 \ +initWithAliasHandle:\ +initWithData:\ +initWithPath:\ +initWithPath:relativeToPath:\ +initWithFSRef:\ +initWithFSRef:relativeToFSRef:\ +dealloc\ +alias\ +setAlias:\ +aliasData\ +setAliasData:\ +fullPath\ +fullPathRelativeToPath:\ +\ + +\f1\b Class Methods +\f0\b0 \ +aliasWithAliasHandle:\ +aliasWithData:\ +aliasWithPath:\ +aliasWithPath:relativeToPath:\ +aliasWithFSRef:\ +aliasWithFSRef:relativeToFSRef:\ +\ + +\f1\b - (id)initWithAliasHandle:(AliasHandle)alias +\f0\b0 \ +Initializes an alias object with the contents of a Carbon alias handle. This is the designated initializer.\ +\ + +\f1\b - (id)initWithData:(NSData *)data +\f0\b0 \ +Initializes an alias object with the contents of a data object.\ +\ + +\f1\b - (id)initWithPath:(NSString *)fullPath +\f0\b0 \ +Initializes an alias object to point to the object at the given path in the filesystem.\ +\ + +\f1\b - (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath +\f0\b0 \ +Initializes an alias object to point to the object at the given path in the filesystem, relative to the given relative path.\ +\ + +\f1\b - (id)initWithFSRef:(FSRef *)ref +\f0\b0 \ +Initializes an alias object to point to the object represented by the given Carbon FSRef.\ +\ + +\f1\b - (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef +\f0\b0 \ +Initializes an alias object to point to the object represented by the given Carbon FSRef, relative to the given relative Carbon FSRef.\ +\ + +\f1\b - (void)dealloc +\f0\b0 \ +Releases resources held by an instance.\ +\ + +\f1\b - (AliasHandle)alias +\f0\b0 \ +Returns the internal Carbon alias handle used by an instance.\ +\ + +\f1\b - (void)setAlias:(AliasHandle)newAlias +\f0\b0 \ +Sets the internal Carbon alias handle used by an instance, releasing the previous alias handle (if any).\ +\ + +\f1\b - (NSData *)aliasData +\f0\b0 \ +Returns an autoreleased data object containing a copy of the alias data in this object.\ +\ + +\f1\b - (void)setAliasData:(NSData *)newAliasData +\f0\b0 \ +Sets the alias to use the alias record stored in the given data object. Discards any previous data.\ +\ + +\f1\b - (NSString *)fullPath +\f0\b0 \ +Returns an autoreleased string containing the full path of the object pointed to by an alias.\ +\ + +\f1\b - (NSString *)fullPathRelativeToPath:(NSString *)relPath +\f0\b0 \ +Returns an autoreleased string containing the full path of the object pointed to by an alias, resolved relative to the other given full path.\ +\ + +\f1\b + (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias\ + +\f0\b0 Creates an autoreleased alias object with the contents of the given Carbon alias handle.\ +\ + +\f1\b + (BDAlias *)aliasWithData:(NSData *)data\ + +\f0\b0 Creates an autoreleased alias object with the contents of the given NSData object.\ +\ + +\f1\b + (BDAlias *)aliasWithPath:(NSString *)fullPath\ + +\f0\b0 Creates an autoreleased alias object pointing to the object at the given full path.\ +\ + +\f1\b + (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath\ + +\f0\b0 Creates an autoreleased alias object pointing to the object at the given path, relative to the given relative path.\ +\ + +\f1\b + (BDAlias *)aliasWithFSRef:(FSRef *)ref\ + +\f0\b0 Creates an autoreleased alias object pointing to the object at the given Carbon FSRef.\ +\ + +\f1\b + (BDAlias *)aliasWithFSRef:(FSREf *)ref relativeToFSRef:(FSRef *)relRef\ + +\f0\b0 Creates an autoreleased alias object pointing to the object at the given Carbon FSRef, relative to the given relative Carbon FSRef.\ +\ + +\f1\b License Agreement\ + +\f0\b0 By using or downloading this software, you agree to be bound by the following license. If you do not agree to be bound by the license, please destroy all copies of this software.\ +\ +Copyright \'a9 2001-2002, bDistributed.com, Inc.\ +All rights reserved.\ +\ +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\ +\ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li580\fi-580\ql\qnatural +\cf0 * 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 bDistributed.com, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural +\cf0 \ +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 REGENTS 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. \ +}
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/BDAlias/BDAlias/License.rtf b/Plugins/BuiltInFunctions/BDAlias/BDAlias/License.rtf new file mode 100644 index 0000000..3bbbb7b --- /dev/null +++ b/Plugins/BuiltInFunctions/BDAlias/BDAlias/License.rtf @@ -0,0 +1,21 @@ +{\rtf1\mac\ansicpg10000\cocoartf102 +{\fonttbl\f0\froman\fcharset77 TimesNewRomanPSMT;} +{\colortbl;\red255\green255\blue255;} +\vieww9000\viewh9000\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\fs24 \cf0 Copyright \'a9 2001-2002, bDistributed.com, Inc.\ +All rights reserved.\ +\ +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\ +\ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li580\fi-580\ql\qnatural +\cf0 * 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 bDistributed.com, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural +\cf0 \ +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 REGENTS 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. \ +}
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/BuiltInFunctions.h b/Plugins/BuiltInFunctions/BuiltInFunctions.h new file mode 100644 index 0000000..ad4208e --- /dev/null +++ b/Plugins/BuiltInFunctions/BuiltInFunctions.h @@ -0,0 +1,12 @@ +/* + * BuiltInFunctions.h + * BuiltInFunctions + * + * Created by Brian Cully on Sun Aug 17 2003. + * Copyright (c) 2003 Brian Cully. All rights reserved. + * + */ + +#import <LiPlugin/LiPlugin.h> +#import <Carbon/Carbon.h> +#import <Cocoa/Cocoa.h>
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/BuiltInFunctions.xcodeproj/project.pbxproj b/Plugins/BuiltInFunctions/BuiltInFunctions.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2c7562f --- /dev/null +++ b/Plugins/BuiltInFunctions/BuiltInFunctions.xcodeproj/project.pbxproj @@ -0,0 +1,514 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + F7D397E40546864600BD181E /* BDAlias.h in Headers */ = {isa = PBXBuildFile; fileRef = F790687704EF3DE200000104 /* BDAlias.h */; }; + F7D397E50546864600BD181E /* IconFamily.h in Headers */ = {isa = PBXBuildFile; fileRef = F790688104EF3DEB00000104 /* IconFamily.h */; }; + F7D397E60546864600BD181E /* NSString+CarbonFSSpecCreation.h in Headers */ = {isa = PBXBuildFile; fileRef = F790688304EF3DEB00000104 /* NSString+CarbonFSSpecCreation.h */; }; + F7D397E70546864600BD181E /* LiImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = F790689404EF3E3900000104 /* LiImageView.h */; }; + F7D397E80546864600BD181E /* FileSizeFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = F790689804EF3E3900000104 /* FileSizeFormatter.h */; }; + F7D397E90546864600BD181E /* HFSCodeFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = F790689904EF3E3900000104 /* HFSCodeFormatter.h */; }; + F7D397EA0546864600BD181E /* InspectorViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = F790689B04EF3E3900000104 /* InspectorViewController.h */; }; + F7D397EB0546864600BD181E /* LiBuiltInFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = F790689C04EF3E3900000104 /* LiBuiltInFunctions.h */; }; + F7D397EC0546864600BD181E /* BuiltInFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = F75ACF1C04EF584E00000104 /* BuiltInFunctions.h */; }; + F7D397ED0546864600BD181E /* NaturalDateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = F71CA8EF0502854900000104 /* NaturalDateFormatter.h */; }; + F7D397EF0546864600BD181E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; }; + F7D397F00546864600BD181E /* BDAlias.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F790687904EF3DE200000104 /* BDAlias.rtf */; }; + F7D397F10546864600BD181E /* License.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F790687A04EF3DE200000104 /* License.rtf */; }; + F7D397F20546864600BD181E /* local.tiff in Resources */ = {isa = PBXBuildFile; fileRef = F790688A04EF3E0D00000104 /* local.tiff */; }; + F7D397F30546864600BD181E /* LocalAccountLarge.tiff in Resources */ = {isa = PBXBuildFile; fileRef = F790688B04EF3E0D00000104 /* LocalAccountLarge.tiff */; }; + F7D397F40546864600BD181E /* Network (Large).tiff in Resources */ = {isa = PBXBuildFile; fileRef = F790688C04EF3E0D00000104 /* Network (Large).tiff */; }; + F7D397F50546864600BD181E /* Network (Small).tiff in Resources */ = {isa = PBXBuildFile; fileRef = F790688D04EF3E0D00000104 /* Network (Small).tiff */; }; + F7D397F60546864600BD181E /* NotThere.icns in Resources */ = {isa = PBXBuildFile; fileRef = F790688E04EF3E0D00000104 /* NotThere.icns */; }; + F7D397F70546864600BD181E /* InspectorViews.nib in Resources */ = {isa = PBXBuildFile; fileRef = F79068AC04EF3EED00000104 /* InspectorViews.nib */; }; + F7D397F80546864600BD181E /* BuiltInFunctions.strings in Resources */ = {isa = PBXBuildFile; fileRef = F79068AE04EF3EED00000104 /* BuiltInFunctions.strings */; }; + F7D397F90546864600BD181E /* ErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = F79068B004EF3EED00000104 /* ErrorMessages.strings */; }; + F7D397FB0546864600BD181E /* BDAlias.m in Sources */ = {isa = PBXBuildFile; fileRef = F790687804EF3DE200000104 /* BDAlias.m */; }; + F7D397FC0546864600BD181E /* IconFamily.m in Sources */ = {isa = PBXBuildFile; fileRef = F790688204EF3DEB00000104 /* IconFamily.m */; }; + F7D397FD0546864600BD181E /* NSString+CarbonFSSpecCreation.m in Sources */ = {isa = PBXBuildFile; fileRef = F790688404EF3DEC00000104 /* NSString+CarbonFSSpecCreation.m */; }; + F7D397FE0546864600BD181E /* FileSizeFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F790689504EF3E3900000104 /* FileSizeFormatter.m */; }; + F7D397FF0546864600BD181E /* InspectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F790689604EF3E3900000104 /* InspectorViewController.m */; }; + F7D398000546864600BD181E /* LiBuiltInFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = F790689704EF3E3900000104 /* LiBuiltInFunctions.m */; }; + F7D398010546864600BD181E /* HFSCodeFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F790689A04EF3E3900000104 /* HFSCodeFormatter.m */; }; + F7D398020546864600BD181E /* LiImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = F790689D04EF3E3900000104 /* LiImageView.m */; }; + F7D398030546864600BD181E /* NaturalDateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F71CA8F00502854900000104 /* NaturalDateFormatter.m */; }; + F7D398050546864600BD181E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; + F7D398060546864600BD181E /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F79068CA04EF42F700000104 /* Carbon.framework */; }; + F7D398070546864600BD181E /* LiBackend.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7D6587904F356ED00000104 /* LiBackend.framework */; }; + F7D398080546864600BD181E /* LiPlugin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7D6587A04F356ED00000104 /* LiPlugin.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; + 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + 089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; + 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; + F71CA8EF0502854900000104 /* NaturalDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NaturalDateFormatter.h; sourceTree = "<group>"; }; + F71CA8F00502854900000104 /* NaturalDateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NaturalDateFormatter.m; sourceTree = "<group>"; }; + F75ACF1C04EF584E00000104 /* BuiltInFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltInFunctions.h; sourceTree = "<group>"; }; + F790687704EF3DE200000104 /* BDAlias.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BDAlias.h; sourceTree = "<group>"; }; + F790687804EF3DE200000104 /* BDAlias.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = BDAlias.m; sourceTree = "<group>"; }; + F790687904EF3DE200000104 /* BDAlias.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = BDAlias.rtf; sourceTree = "<group>"; }; + F790687A04EF3DE200000104 /* License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = License.rtf; sourceTree = "<group>"; }; + F790688104EF3DEB00000104 /* IconFamily.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IconFamily.h; sourceTree = "<group>"; }; + F790688204EF3DEB00000104 /* IconFamily.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = IconFamily.m; sourceTree = "<group>"; }; + F790688304EF3DEB00000104 /* NSString+CarbonFSSpecCreation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "NSString+CarbonFSSpecCreation.h"; sourceTree = "<group>"; }; + F790688404EF3DEC00000104 /* NSString+CarbonFSSpecCreation.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = "NSString+CarbonFSSpecCreation.m"; sourceTree = "<group>"; }; + F790688A04EF3E0D00000104 /* local.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = local.tiff; sourceTree = "<group>"; }; + F790688B04EF3E0D00000104 /* LocalAccountLarge.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = LocalAccountLarge.tiff; sourceTree = "<group>"; }; + F790688C04EF3E0D00000104 /* Network (Large).tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "Network (Large).tiff"; sourceTree = "<group>"; }; + F790688D04EF3E0D00000104 /* Network (Small).tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "Network (Small).tiff"; sourceTree = "<group>"; }; + F790688E04EF3E0D00000104 /* NotThere.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = NotThere.icns; sourceTree = "<group>"; }; + F790689404EF3E3900000104 /* LiImageView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LiImageView.h; sourceTree = "<group>"; }; + F790689504EF3E3900000104 /* FileSizeFormatter.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = FileSizeFormatter.m; sourceTree = "<group>"; }; + F790689604EF3E3900000104 /* InspectorViewController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = InspectorViewController.m; sourceTree = "<group>"; }; + F790689704EF3E3900000104 /* LiBuiltInFunctions.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = LiBuiltInFunctions.m; sourceTree = "<group>"; }; + F790689804EF3E3900000104 /* FileSizeFormatter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FileSizeFormatter.h; sourceTree = "<group>"; }; + F790689904EF3E3900000104 /* HFSCodeFormatter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HFSCodeFormatter.h; sourceTree = "<group>"; }; + F790689A04EF3E3900000104 /* HFSCodeFormatter.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = HFSCodeFormatter.m; sourceTree = "<group>"; }; + F790689B04EF3E3900000104 /* InspectorViewController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InspectorViewController.h; sourceTree = "<group>"; }; + F790689C04EF3E3900000104 /* LiBuiltInFunctions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LiBuiltInFunctions.h; sourceTree = "<group>"; }; + F790689D04EF3E3900000104 /* LiImageView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = LiImageView.m; sourceTree = "<group>"; }; + F79068AD04EF3EED00000104 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/InspectorViews.nib; sourceTree = "<group>"; }; + F79068AF04EF3EED00000104 /* English */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/BuiltInFunctions.strings; sourceTree = "<group>"; }; + F79068B104EF3EED00000104 /* English */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/ErrorMessages.strings; sourceTree = "<group>"; }; + F79068B504EF3F0D00000104 /* chef */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = chef; path = chef.lproj/InspectorViews.nib; sourceTree = "<group>"; }; + F79068B604EF3F1700000104 /* chef */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = chef; path = chef.lproj/BuiltInFunctions.strings; sourceTree = "<group>"; }; + F79068B704EF3F2600000104 /* chef */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = chef; path = chef.lproj/ErrorMessages.strings; sourceTree = "<group>"; }; + F79068B804EF3F5800000104 /* chef */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = chef; path = chef.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F79068CA04EF42F700000104 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; }; + F7D3980B0546864600BD181E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + F7D3980C0546864600BD181E /* Built In Functions.liaisonplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Built In Functions.liaisonplugin"; sourceTree = BUILT_PRODUCTS_DIR; }; + F7D6587904F356ED00000104 /* LiBackend.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LiBackend.framework; path = ../../Frameworks/build/Development/LiBackend.framework; sourceTree = "<group>"; }; + F7D6587A04F356ED00000104 /* LiPlugin.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LiPlugin.framework; path = ../../Frameworks/build/Development/LiPlugin.framework; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + F7D398040546864600BD181E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F7D398050546864600BD181E /* Cocoa.framework in Frameworks */, + F7D398060546864600BD181E /* Carbon.framework in Frameworks */, + F7D398070546864600BD181E /* LiBackend.framework in Frameworks */, + F7D398080546864600BD181E /* LiPlugin.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 089C166AFE841209C02AAC07 /* Built In Functions */ = { + isa = PBXGroup; + children = ( + 08FB77AFFE84173DC02AAC07 /* Classes */, + 089C167CFE841241C02AAC07 /* Resources */, + 089C1671FE841209C02AAC07 /* Frameworks and Libraries */, + 19C28FB8FE9D52D311CA2CBB /* Products */, + ); + name = "Built In Functions"; + sourceTree = "<group>"; + }; + 089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + F7D6587904F356ED00000104 /* LiBackend.framework */, + F7D6587A04F356ED00000104 /* LiPlugin.framework */, + F79068CA04EF42F700000104 /* Carbon.framework */, + 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */, + 1058C7AEFEA557BF11CA2CBB /* Other Frameworks */, + ); + name = "Frameworks and Libraries"; + sourceTree = "<group>"; + }; + 089C167CFE841241C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + F7D3980B0546864600BD181E /* Info.plist */, + F79068AC04EF3EED00000104 /* InspectorViews.nib */, + F79068AE04EF3EED00000104 /* BuiltInFunctions.strings */, + F79068B004EF3EED00000104 /* ErrorMessages.strings */, + 089C167DFE841241C02AAC07 /* InfoPlist.strings */, + F790688904EF3E0D00000104 /* Images */, + ); + name = Resources; + sourceTree = "<group>"; + }; + 08FB77AFFE84173DC02AAC07 /* Classes */ = { + isa = PBXGroup; + children = ( + F75ACF1C04EF584E00000104 /* BuiltInFunctions.h */, + F790689C04EF3E3900000104 /* LiBuiltInFunctions.h */, + F790689704EF3E3900000104 /* LiBuiltInFunctions.m */, + F790689B04EF3E3900000104 /* InspectorViewController.h */, + F790689604EF3E3900000104 /* InspectorViewController.m */, + F790689404EF3E3900000104 /* LiImageView.h */, + F790689D04EF3E3900000104 /* LiImageView.m */, + F790689904EF3E3900000104 /* HFSCodeFormatter.h */, + F790689A04EF3E3900000104 /* HFSCodeFormatter.m */, + F790689804EF3E3900000104 /* FileSizeFormatter.h */, + F790689504EF3E3900000104 /* FileSizeFormatter.m */, + F71CA8EF0502854900000104 /* NaturalDateFormatter.h */, + F71CA8F00502854900000104 /* NaturalDateFormatter.m */, + F790688004EF3DEB00000104 /* IconFamily */, + F790687604EF3DE200000104 /* BDAlias */, + ); + name = Classes; + sourceTree = "<group>"; + }; + 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = "<group>"; + }; + 1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 089C1672FE841209C02AAC07 /* Foundation.framework */, + 089C167FFE841241C02AAC07 /* AppKit.framework */, + ); + name = "Other Frameworks"; + sourceTree = "<group>"; + }; + 19C28FB8FE9D52D311CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + F7D3980C0546864600BD181E /* Built In Functions.liaisonplugin */, + ); + name = Products; + sourceTree = "<group>"; + }; + F790687604EF3DE200000104 /* BDAlias */ = { + isa = PBXGroup; + children = ( + F790687704EF3DE200000104 /* BDAlias.h */, + F790687804EF3DE200000104 /* BDAlias.m */, + F790687904EF3DE200000104 /* BDAlias.rtf */, + F790687A04EF3DE200000104 /* License.rtf */, + ); + name = BDAlias; + path = BDAlias/BDAlias; + sourceTree = "<group>"; + }; + F790688004EF3DEB00000104 /* IconFamily */ = { + isa = PBXGroup; + children = ( + F790688104EF3DEB00000104 /* IconFamily.h */, + F790688204EF3DEB00000104 /* IconFamily.m */, + F790688304EF3DEB00000104 /* NSString+CarbonFSSpecCreation.h */, + F790688404EF3DEC00000104 /* NSString+CarbonFSSpecCreation.m */, + ); + name = IconFamily; + path = IconFamily/IconFamily; + sourceTree = "<group>"; + }; + F790688904EF3E0D00000104 /* Images */ = { + isa = PBXGroup; + children = ( + F790688A04EF3E0D00000104 /* local.tiff */, + F790688B04EF3E0D00000104 /* LocalAccountLarge.tiff */, + F790688C04EF3E0D00000104 /* Network (Large).tiff */, + F790688D04EF3E0D00000104 /* Network (Small).tiff */, + F790688E04EF3E0D00000104 /* NotThere.icns */, + ); + path = Images; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + F7D397E30546864600BD181E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F7D397E40546864600BD181E /* BDAlias.h in Headers */, + F7D397E50546864600BD181E /* IconFamily.h in Headers */, + F7D397E60546864600BD181E /* NSString+CarbonFSSpecCreation.h in Headers */, + F7D397E70546864600BD181E /* LiImageView.h in Headers */, + F7D397E80546864600BD181E /* FileSizeFormatter.h in Headers */, + F7D397E90546864600BD181E /* HFSCodeFormatter.h in Headers */, + F7D397EA0546864600BD181E /* InspectorViewController.h in Headers */, + F7D397EB0546864600BD181E /* LiBuiltInFunctions.h in Headers */, + F7D397EC0546864600BD181E /* BuiltInFunctions.h in Headers */, + F7D397ED0546864600BD181E /* NaturalDateFormatter.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + F7D397E20546864600BD181E /* Built In Functions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 28986764095DAB7900B5DC99 /* Build configuration list for PBXNativeTarget "Built In Functions" */; + buildPhases = ( + F7D397E30546864600BD181E /* Headers */, + F7D397EE0546864600BD181E /* Resources */, + F7D397FA0546864600BD181E /* Sources */, + F7D398040546864600BD181E /* Frameworks */, + F7D398090546864600BD181E /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Built In Functions"; + productInstallPath = "@executable_path/../Plugins"; + productName = "Built In Functions"; + productReference = F7D3980C0546864600BD181E /* Built In Functions.liaisonplugin */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 089C1669FE841209C02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 28986768095DAB7900B5DC99 /* Build configuration list for PBXProject "BuiltInFunctions" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + chef, + ); + mainGroup = 089C166AFE841209C02AAC07 /* Built In Functions */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + F7D397E20546864600BD181E /* Built In Functions */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + F7D397EE0546864600BD181E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F7D397EF0546864600BD181E /* InfoPlist.strings in Resources */, + F7D397F00546864600BD181E /* BDAlias.rtf in Resources */, + F7D397F10546864600BD181E /* License.rtf in Resources */, + F7D397F20546864600BD181E /* local.tiff in Resources */, + F7D397F30546864600BD181E /* LocalAccountLarge.tiff in Resources */, + F7D397F40546864600BD181E /* Network (Large).tiff in Resources */, + F7D397F50546864600BD181E /* Network (Small).tiff in Resources */, + F7D397F60546864600BD181E /* NotThere.icns in Resources */, + F7D397F70546864600BD181E /* InspectorViews.nib in Resources */, + F7D397F80546864600BD181E /* BuiltInFunctions.strings in Resources */, + F7D397F90546864600BD181E /* ErrorMessages.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXRezBuildPhase section */ + F7D398090546864600BD181E /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXRezBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + F7D397FA0546864600BD181E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F7D397FB0546864600BD181E /* BDAlias.m in Sources */, + F7D397FC0546864600BD181E /* IconFamily.m in Sources */, + F7D397FD0546864600BD181E /* NSString+CarbonFSSpecCreation.m in Sources */, + F7D397FE0546864600BD181E /* FileSizeFormatter.m in Sources */, + F7D397FF0546864600BD181E /* InspectorViewController.m in Sources */, + F7D398000546864600BD181E /* LiBuiltInFunctions.m in Sources */, + F7D398010546864600BD181E /* HFSCodeFormatter.m in Sources */, + F7D398020546864600BD181E /* LiImageView.m in Sources */, + F7D398030546864600BD181E /* NaturalDateFormatter.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 089C167DFE841241C02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C167EFE841241C02AAC07 /* English */, + F79068B804EF3F5800000104 /* chef */, + ); + name = InfoPlist.strings; + sourceTree = "<group>"; + }; + F79068AC04EF3EED00000104 /* InspectorViews.nib */ = { + isa = PBXVariantGroup; + children = ( + F79068AD04EF3EED00000104 /* English */, + F79068B504EF3F0D00000104 /* chef */, + ); + name = InspectorViews.nib; + sourceTree = "<group>"; + }; + F79068AE04EF3EED00000104 /* BuiltInFunctions.strings */ = { + isa = PBXVariantGroup; + children = ( + F79068AF04EF3EED00000104 /* English */, + F79068B604EF3F1700000104 /* chef */, + ); + name = BuiltInFunctions.strings; + sourceTree = "<group>"; + }; + F79068B004EF3EED00000104 /* ErrorMessages.strings */ = { + isa = PBXVariantGroup; + children = ( + F79068B104EF3EED00000104 /* English */, + F79068B704EF3F2600000104 /* chef */, + ); + name = ErrorMessages.strings; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 28986765095DAB7900B5DC99 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ../../Frameworks/build/Development; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = BuiltInFunctions.h; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = NO; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Plugins"; + LIBRARY_SEARCH_PATHS = ""; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-seg1addr", + 0x20000000, + ); + PRODUCT_NAME = "Built In Functions"; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost"; + WRAPPER_EXTENSION = liaisonplugin; + ZERO_LINK = YES; + }; + name = Development; + }; + 28986766095DAB7900B5DC99 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + CC = "/usr/bin/gcc-3.3"; + COPY_PHASE_STRIP = YES; + CPLUSPLUS = "/usr/bin/g++-3.3"; + FRAMEWORK_SEARCH_PATHS = ../../Frameworks/build; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PREFIX_HEADER = BuiltInFunctions.h; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = NO; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Plugins"; + LIBRARY_SEARCH_PATHS = ""; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-seg1addr", + 0x20000000, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = "Built In Functions"; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost"; + WRAPPER_EXTENSION = liaisonplugin; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 28986767095DAB7900B5DC99 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + CC = "/usr/bin/gcc-3.3"; + CPLUSPLUS = "/usr/bin/g++-3.3"; + FRAMEWORK_SEARCH_PATHS = ../../Frameworks/build; + GCC_PREFIX_HEADER = BuiltInFunctions.h; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = NO; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Plugins"; + LIBRARY_SEARCH_PATHS = ""; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-seg1addr", + 0x20000000, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = "Built In Functions"; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost"; + WRAPPER_EXTENSION = liaisonplugin; + }; + name = Default; + }; + 28986769095DAB7900B5DC99 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Development; + }; + 2898676A095DAB7900B5DC99 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Deployment; + }; + 2898676B095DAB7900B5DC99 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Default; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 28986764095DAB7900B5DC99 /* Build configuration list for PBXNativeTarget "Built In Functions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 28986765095DAB7900B5DC99 /* Development */, + 28986766095DAB7900B5DC99 /* Deployment */, + 28986767095DAB7900B5DC99 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 28986768095DAB7900B5DC99 /* Build configuration list for PBXProject "BuiltInFunctions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 28986769095DAB7900B5DC99 /* Development */, + 2898676A095DAB7900B5DC99 /* Deployment */, + 2898676B095DAB7900B5DC99 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; +/* End XCConfigurationList section */ + }; + rootObject = 089C1669FE841209C02AAC07 /* Project object */; +} diff --git a/Plugins/BuiltInFunctions/English.lproj/BuiltInFunctions.strings b/Plugins/BuiltInFunctions/English.lproj/BuiltInFunctions.strings new file mode 100644 index 0000000..5d0a940 --- /dev/null +++ b/Plugins/BuiltInFunctions/English.lproj/BuiltInFunctions.strings @@ -0,0 +1,26 @@ +/* Headers for columns. */ +IconHeader = "Icon"; +FilenameHeader = "Filename"; +TypeHeader = "Type"; +LastModifiedTimeHeader = "Last Modified"; +CreatedTimeHeader = "Created"; +FileSizeHeader = "Size"; + +/* Error messages. */ +UnableToResolveAlias = "unable to resolve alias"; + +/* Default library name. */ +LiLibraryName = "My Library"; + +/* Names for filters. */ +LiFilenameAttribute = "filename"; +LiTypeAttribute = "type"; + +/* Names for operators. */ +LiEqualsOperator = "is"; +LiContainsOperator = "contains"; + +/* For the natural language formatter. */ +Today = "Today"; +Yesterday = "Yesterday"; +Tomorrow = "Tomorrow";
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/English.lproj/ErrorMessages.strings b/Plugins/BuiltInFunctions/English.lproj/ErrorMessages.strings new file mode 100644 index 0000000..edc17d9 --- /dev/null +++ b/Plugins/BuiltInFunctions/English.lproj/ErrorMessages.strings @@ -0,0 +1,10 @@ +/* Errors for file rename operations. */ +LiGenericRenameErrorHeader = "The file couldn't be renamed."; +LiGenericRenameErrorContents = "Try shaking a dead chicken (or chicken substitute) at the screen."; + +LiBadFilenameErrorHeader = "The file couldn't be renamed because it contained an illegal character."; +LiBadFilenameErrorContents = "You can try to rename the file without the slash \"/\" or colon \":\" characters."; +LiReadOnlyFileSytemErrorHeader = "The file couldn't be modified because the filesystem is read-only."; +LiReadOnlyFileSytemErrorContents = "You need to talk to your system administrator to fix this."; +LiPermissionDeniedErrorHeader = "The file couldn't be modified because you lack permission to change the file."; +LiPermissionDeniedErrorContents = "You can modify your folder permissions in the Finder."; diff --git a/Plugins/BuiltInFunctions/English.lproj/InfoPlist.strings b/Plugins/BuiltInFunctions/English.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 0000000..dd02662 --- /dev/null +++ b/Plugins/BuiltInFunctions/English.lproj/InfoPlist.strings diff --git a/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/classes.nib b/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/classes.nib new file mode 100644 index 0000000..5cbffd3 --- /dev/null +++ b/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/classes.nib @@ -0,0 +1,38 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = HFSCodeFormatter; LANGUAGE = ObjC; SUPERCLASS = NSFormatter; }, + { + ACTIONS = { + setApplication = id; + setFilename = id; + setHFSCreatorField = id; + setHFSTypeField = id; + setIcon = id; + setType = id; + }; + CLASS = InspectorViewController; + LANGUAGE = ObjC; + OUTLETS = { + hfsCreatorField = NSTextField; + hfsTypeField = NSTextField; + iconView = NSImageView; + pathField = NSTextField; + theApplicationButton = NSPopUpButton; + theFileTabView = NSView; + theFilenameField = NSTextField; + theHFSTabView = NSView; + theTypeField = NSTextField; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = LiBuiltInFunctions; + LANGUAGE = ObjC; + OUTLETS = {theController = InspectorViewController; }; + SUPERCLASS = NSObject; + }, + {CLASS = LiImageView; LANGUAGE = ObjC; SUPERCLASS = NSImageView; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/info.nib b/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/info.nib new file mode 100644 index 0000000..a3a74f1 --- /dev/null +++ b/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/info.nib @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>69 167 356 240 0 0 1600 1178 </string> + <key>IBEditorPositions</key> + <dict> + <key>48</key> + <string>682 743 235 123 0 0 1600 1178 </string> + <key>5</key> + <string>604 657 392 277 0 0 1600 1178 </string> + </dict> + <key>IBFramework Version</key> + <string>349.0</string> + <key>IBGroupedObjects</key> + <dict> + <key>1</key> + <array> + <string>28</string> + <string>27</string> + </array> + <key>2</key> + <array> + <string>36</string> + <string>37</string> + </array> + <key>3</key> + <array> + <string>30</string> + <string>31</string> + </array> + <key>4</key> + <array> + <string>41</string> + <string>33</string> + </array> + <key>5</key> + <array> + <string>75</string> + <string>77</string> + </array> + <key>6</key> + <array> + <string>76</string> + <string>78</string> + </array> + </dict> + <key>IBLastGroupID</key> + <string>8</string> + <key>IBOldestOS</key> + <integer>3</integer> + <key>IBOpenObjects</key> + <array> + <integer>48</integer> + <integer>5</integer> + </array> + <key>IBSystem Version</key> + <string>7B85</string> +</dict> +</plist> diff --git a/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/keyedobjects.nib b/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..2e6ed0c --- /dev/null +++ b/Plugins/BuiltInFunctions/English.lproj/InspectorViews.nib/keyedobjects.nib diff --git a/Plugins/BuiltInFunctions/FileSizeFormatter.h b/Plugins/BuiltInFunctions/FileSizeFormatter.h new file mode 100644 index 0000000..25f08ae --- /dev/null +++ b/Plugins/BuiltInFunctions/FileSizeFormatter.h @@ -0,0 +1,10 @@ +// +// FileSizeFormatter.h +// Liaison +// +// Created by Brian Cully on Fri May 09 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +@interface FileSizeFormatter : NSNumberFormatter +@end diff --git a/Plugins/BuiltInFunctions/FileSizeFormatter.m b/Plugins/BuiltInFunctions/FileSizeFormatter.m new file mode 100644 index 0000000..c6971e6 --- /dev/null +++ b/Plugins/BuiltInFunctions/FileSizeFormatter.m @@ -0,0 +1,47 @@ +// +// FileSizeFormatter.m +// Liaison +// +// Created by Brian Cully on Fri May 09 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +#import "FileSizeFormatter.h" + +@implementation FileSizeFormatter +- (NSString *)stringForObjectValue: (id)anObject +{ + if ([anObject isKindOfClass: [NSNumber class]]) { + NSString *suffix; + int shownSize; + unsigned long size; + + size = [anObject unsignedLongValue]; + if (size > 1024 * 1024 * 1024) { + shownSize = size / 1024 / 1024 / 1024; + suffix = @" G"; + } else if (size > 1024 * 1024) { + shownSize = size / 1024 / 1024; + suffix = @" M"; + } else if (size > 1024) { + shownSize = size / 1024; + suffix = @" K"; + } else { + shownSize = size; + suffix = @" B"; + } + + return [NSString stringWithFormat: @"%ld%@", shownSize, suffix]; + } + + return [super stringForObjectValue: anObject]; +} + +- (BOOL)getObjectValue: (id *)anObject + forString: (NSString *)string + errorDescription: (NSString **)error +{ + *anObject = string; + return YES; +} +@end diff --git a/Plugins/BuiltInFunctions/HFSCodeFormatter.h b/Plugins/BuiltInFunctions/HFSCodeFormatter.h new file mode 100644 index 0000000..1cd59fb --- /dev/null +++ b/Plugins/BuiltInFunctions/HFSCodeFormatter.h @@ -0,0 +1,4 @@ +/* HFSCodeFormatter */ + +@interface HFSCodeFormatter : NSFormatter +@end diff --git a/Plugins/BuiltInFunctions/HFSCodeFormatter.m b/Plugins/BuiltInFunctions/HFSCodeFormatter.m new file mode 100644 index 0000000..4c3d0c1 --- /dev/null +++ b/Plugins/BuiltInFunctions/HFSCodeFormatter.m @@ -0,0 +1,46 @@ +#import "HFSCodeFormatter.h" + +@implementation HFSCodeFormatter +- (NSString *)stringForObjectValue: (id)anObject +{ + unsigned long longValue; + char a, b, c, d; + + if ([anObject isKindOfClass: [NSNumber class]]) + longValue = [anObject unsignedLongValue]; + else + longValue = 0; + + a = (longValue >> 24) & 0xff; + b = (longValue >> 16) & 0xff; + c = (longValue >> 8) & 0xff; + d = longValue & 0xff; + + return [NSString stringWithFormat: @"%c%c%c%c", a, b, c, d]; +} + +- (BOOL)getObjectValue: (id *)anObject + forString: (NSString *)string + errorDescription: (NSString **)error +{ + unsigned long objectValue; + unsigned int i, bitNo; + + bitNo = 24; + objectValue = 0; + for (i = 0; i < [string length] && i < 4; i++) { + objectValue += ([string characterAtIndex: i] & 0xff) << bitNo; + bitNo -= 8; + } + *anObject = [NSNumber numberWithUnsignedLong: objectValue]; + + return YES; +} + +- (BOOL)isPartialStringValid: (NSString *)partialString + newEditingString: (NSString **)newString + errorDescription: (NSString **)error +{ + return [partialString length] <= 4; +} +@end diff --git a/Plugins/BuiltInFunctions/IconFamily/IconFamily/IconFamily.h b/Plugins/BuiltInFunctions/IconFamily/IconFamily/IconFamily.h new file mode 100644 index 0000000..443ee13 --- /dev/null +++ b/Plugins/BuiltInFunctions/IconFamily/IconFamily/IconFamily.h @@ -0,0 +1,184 @@ +// IconFamily.h +// IconFamily class interface +// by Troy Stephens, Thomas Schnitzer, David Remahl, Nathan Day and Ben Haller +// version 0.5 +// +// Project Home Page: +// http://homepage.mac.com/troy_stephens/software/objects/IconFamily/ +// +// Problems, shortcomings, and uncertainties that I'm aware of are flagged +// with "NOTE:". Please address bug reports, bug fixes, suggestions, etc. +// to me at troy_stephens@mac.com +// +// This code is provided as-is, with no warranty, in the hope that it will be +// useful. However, it appears to work fine on Mac OS X 10.1.4. :-) + +#import <Cocoa/Cocoa.h> +#import <Carbon/Carbon.h> + +// This class is a Cocoa/Objective-C wrapper for the Mac OS X Carbon API's +// "icon family" data type. Its main purpose is to enable Cocoa applications +// to easily create custom file icons from NSImage instances, and thus take +// advantage of Mac OS X's new 128x128 RGBA "thumbnail" icon format to provide +// richly detailed thumbnail previews of the files' contents. +// +// Using IconFamily, this becomes as simple as: +// +// id iconFamily = [IconFamily iconFamilyWithThumbnailsOfImage:anImage]; +// [iconFamily setAsCustomIconForFile:anExistingFile]; +// +// You can also write an icon family to an .icns file using the -writeToFile: +// method. + +@interface IconFamily : NSObject +{ + IconFamilyHandle hIconFamily; +} + +// Convenience methods. These use the corresponding -init methods to return +// an autoreleased IconFamily instance. +// +// NOTE: +iconFamily relies on -init, which is currently broken (see -init). + ++ (IconFamily*) iconFamily; ++ (IconFamily*) iconFamilyWithContentsOfFile:(NSString*)path; ++ (IconFamily*) iconFamilyWithIconOfFile:(NSString*)path; ++ (IconFamily*) iconFamilyWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily; ++ (IconFamily*) iconFamilyWithSystemIcon:(int)fourByteCode; ++ (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image; ++ (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation; + +// Initializes as a new, empty IconFamily. This is IconFamily's designated +// initializer method. +// +// NOTE: This method is broken until we figure out how to create a valid new +// IconFamilyHandle! In the meantime, use -initWithContentsOfFile: to +// load an existing .icns file that you can use as a starting point, and +// use -setIconFamilyElement:fromBitmapImageRep: to replace its +// elements. This is what the "MakeThumbnail" demo app does. + +- init; + +// Initializes an IconFamily by loading the contents of an .icns file. + +- initWithContentsOfFile:(NSString*)path; + +// Initializes an IconFamily from an existing Carbon IconFamilyHandle. + +- initWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily; + +// Initializes an IconFamily by loading the Finder icon that's assigned to a +// file. + +- initWithIconOfFile:(NSString*)path; + +// Initializes an IconFamily by referencing a standard system icon. + +- initWithSystemIcon:(int)fourByteCode; + +// Initializes an IconFamily by creating its elements from a resampled +// NSImage. The second form of this method allows you to specify the degree +// of antialiasing to be used in resampling the image, by passing in one of +// the NSImageInterpolation... constants that are defined in +// NSGraphicsContext.h. The first form of this initializer simply calls the +// second form with imageInterpolation set to NSImageInterpolationHigh, which +// produces highly smoothed thumbnails. + +- initWithThumbnailsOfImage:(NSImage*)image; +- initWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation; + +// Writes the icon family to an .icns file. + +- (BOOL) writeToFile:(NSString*)path; + +// Sets the image data for one of the icon family's elements from an +// NSBitmapImageRep. The "elementType" parameter must be one of the icon +// family element types listed below, and the format of the "bitmapImageRep" +// must match the corresponding requirements specified below. Regardless of +// the elementType, the bitmapImageRep must also be non-planar and have 8 bits +// per sample. +// +// elementType dimensions format +// ------------------- ---------- --------------------------------------- +// kThumbnail32BitData 128 x 128 32-bit RGBA, 32-bit RGB, or 24-bit RGB +// kThumbnail8BitMask 128 x 128 32-bit RGBA or 8-bit intensity +// kLarge32BitData 32 x 32 32-bit RGBA, 32-bit RGB, or 24-bit RGB +// kLarge8BitMask 32 x 32 32-bit RGBA or 8-bit intensity +// kLarge1BitMask 32 x 32 32-bit RGBA, 8-bit intensity, or 1-bit +// kSmall32BitData 16 x 16 32-bit RGBA, 32-bit RGB, or 24-bit RGB +// kSmall8BitMask 16 x 16 32-bit RGBA or 8-bit intensity +// kSmall1BitMask 16 x 16 32-bit RGBA, 8-bit intensity, or 1-bit +// +// When an RGBA image is supplied to set a "Mask" element, the mask data is +// taken from the image's alpha channel. +// +// NOTE: Setting an IconFamily's kLarge1BitMask seems to damage the IconFamily +// for some as yet unknown reason. (If you then assign the icon family +// as a file's custom icon using -setAsCustomIconForFile:, the custom +// icon doesn't appear for the file in the Finder.) However, both +// custom icon display and mouse-click hit-testing in the Finder seem to +// work fine when we only set the other four elements (thus keeping the +// existing kLarge1BitMask from the valid icon family from which we +// initialized the IconFamily via -initWithContentsOfFile:, since +// IconFamily's -init method is currently broken...), so it seems safe +// to just leave the kLarge1BitMask alone. + +- (BOOL) setIconFamilyElement:(OSType)elementType + fromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep; + +// Gets the image data for one of the icon family's elements as a new, 32-bit +// RGBA NSBitmapImageRep. The specified elementType should be one of +// kThumbnail32BitData, kLarge32BitData, or kSmall32BitData. +// +// The returned NSBitmapImageRep will have the corresponding 8-bit mask data +// in its alpha channel, or a fully opaque alpha channel if the icon family +// has no 8-bit mask data for the specified alpha channel. +// +// Returns nil if the requested element cannot be retrieved (e.g. if the +// icon family has no such 32BitData element). + +- (NSBitmapImageRep*) bitmapImageRepWithAlphaForIconFamilyElement:(OSType)elementType; + +// Creates and returns an NSImage that contains the icon family's various +// elements as its NSImageReps. + +- (NSImage*) imageWithAllReps; + +// NOTE: Planned method -- not yet implemented. +// +// Gets the image data for one of the icon family's elements as a new +// NSBitmapImageRep. The specified elementType should be one of +// kThumbnail32BitData, kThumbnail32BitMask, kLarge32BitData, kLarge8BitMask, +// kLarge1BitMask, kSmall32BitData, kSmall8BitMask, or kSmall1BitMask. + +// - (NSBitmapImageRep*) bitmapImageRepForIconFamilyElement:(OSType)elementType; + +// Writes the icon family to the resource fork of the specified file as its +// kCustomIconResource, and sets the necessary Finder bits so the icon will +// be displayed for the file in Finder views. + +- (BOOL) setAsCustomIconForFile:(NSString*)path; +- (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat; + +// Same as the -setAsCustomIconForFile:... methods, but for folders (directories). + +- (BOOL) setAsCustomIconForDirectory:(NSString*)path; +- (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)compat; + +// Removes the custom icon (if any) from the specified file's resource fork, +// and clears the necessary Finder bits for the file. (Note that this is a +// class method, so you don't need an instance of IconFamily to invoke it.) + ++ (BOOL) removeCustomIconFromFile:(NSString*)path; + +@property IconFamilyHandle hIconFamily; +@end + +// Methods for interfacing with the Carbon Scrap Manager (analogous to and +// interoperable with the Cocoa Pasteboard). +@interface IconFamily (ScrapAdditions) ++ (BOOL) canInitWithScrap; ++ (IconFamily*) iconFamilyWithScrap; +- initWithScrap; +- (BOOL) putOnScrap; +@end diff --git a/Plugins/BuiltInFunctions/IconFamily/IconFamily/IconFamily.m b/Plugins/BuiltInFunctions/IconFamily/IconFamily/IconFamily.m new file mode 100644 index 0000000..2ce64f4 --- /dev/null +++ b/Plugins/BuiltInFunctions/IconFamily/IconFamily/IconFamily.m @@ -0,0 +1,1426 @@ +// IconFamily.m +// IconFamily class implementation +// by Troy Stephens, Thomas Schnitzer, David Remahl, Nathan Day and Ben Haller +// version 0.5 +// +// Project Home Page: +// http://homepage.mac.com/troy_stephens/software/objects/IconFamily/ +// +// Problems, shortcomings, and uncertainties that I'm aware of are flagged +// with "NOTE:". Please address bug reports, bug fixes, suggestions, etc. +// to me at troy_stephens@mac.com +// +// This code is provided as-is, with no warranty, in the hope that it will be +// useful. However, it appears to work fine on Mac OS X 10.1.5 and 10.2. :-) + +#import "IconFamily.h" +#import "NSString+CarbonFSSpecCreation.h" + +#define unknownOSType 0x3f3f3f3f + +@interface IconFamily (Internals) + ++ (NSImage*) resampleImage:(NSImage*)image toIconWidth:(int)width usingImageInterpolation:(NSImageInterpolation)imageInterpolation; + ++ (Handle) get32BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; + ++ (Handle) get8BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; + ++ (Handle) get8BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; + ++ (Handle) get1BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize; + +- (BOOL) addResourceType:(OSType)type asResID:(int)resID; + +@end + +@implementation IconFamily + ++ (IconFamily*) iconFamily +{ + return [[[IconFamily alloc] init] autorelease]; +} + ++ (IconFamily*) iconFamilyWithContentsOfFile:(NSString*)path +{ + return [[[IconFamily alloc] initWithContentsOfFile:path] autorelease]; +} + ++ (IconFamily*) iconFamilyWithIconOfFile:(NSString*)path +{ + return [[[IconFamily alloc] initWithIconOfFile:path] autorelease]; +} + ++ (IconFamily*) iconFamilyWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily +{ + return [[[IconFamily alloc] initWithIconFamilyHandle:hNewIconFamily] autorelease]; +} + ++ (IconFamily*) iconFamilyWithSystemIcon:(int)fourByteCode +{ + return [[[IconFamily alloc] initWithSystemIcon:fourByteCode] autorelease]; +} + ++ (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image +{ + return [[[IconFamily alloc] initWithThumbnailsOfImage:image] autorelease]; +} + ++ (IconFamily*) iconFamilyWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation +{ + return [[[IconFamily alloc] initWithThumbnailsOfImage:image usingImageInterpolation:imageInterpolation] autorelease]; +} + +// This is IconFamily's designated initializer. It creates a new IconFamily that initially has no elements. +// +// The proper way to do this is to simply allocate a zero-sized handle (not to be confused with an empty handle) and assign it to hIconFamily. This technique works on Mac OS X 10.2 as well as on 10.0.x and 10.1.x. Our previous technique of allocating an IconFamily struct with a resourceSize of 0 no longer works as of Mac OS X 10.2. +- init +{ + self = [super init]; + if (self) { + hIconFamily = (IconFamilyHandle) NewHandle( 0 ); + if (hIconFamily == NULL) { + [self autorelease]; + return nil; + } + } + return self; +} + +- initWithContentsOfFile:(NSString*)path +{ + FSSpec fsSpec; + OSErr result; + + self = [self init]; + if (self) { + if (hIconFamily) { + DisposeHandle( (Handle)hIconFamily ); + hIconFamily = NULL; + } + if (![path getFSSpec:&fsSpec createFileIfNecessary:NO]) { + [self autorelease]; + return nil; + } + result = ReadIconFile( &fsSpec, &hIconFamily ); + if (result != noErr) { + [self autorelease]; + return nil; + } + } + return self; +} + +- initWithIconFamilyHandle:(IconFamilyHandle)hNewIconFamily +{ + self = [self init]; + if (self) { + if (hIconFamily) { + DisposeHandle( (Handle)hIconFamily ); + hIconFamily = NULL; + } + // NOTE: Do we have to somehow "retain" the handle + // (increment its reference count)? + hIconFamily = hNewIconFamily; + } + return self; +} + +- initWithIconOfFile:(NSString*)path +{ + IconRef iconRef; + OSErr result; + SInt16 label; + FSSpec fileSpec; + + self = [self init]; + if (self) + { + if (hIconFamily) + { + DisposeHandle( (Handle)hIconFamily ); + hIconFamily = NULL; + } + + if( ![path getFSSpec:&fileSpec createFileIfNecessary:NO] ) + { + [self autorelease]; + return nil; + } + + result = GetIconRefFromFile( + &fileSpec, + &iconRef, + &label ); + + if (result != noErr) + { + [self autorelease]; + return nil; + } + + result = IconRefToIconFamily( + iconRef, + kSelectorAllAvailableData, + &hIconFamily ); + + if (result != noErr || !hIconFamily) + { + [self autorelease]; + return nil; + } + + ReleaseIconRef( iconRef ); + } + return self; +} + +- initWithSystemIcon:(int)fourByteCode +{ + IconRef iconRef; + OSErr result; + + self = [self init]; + if (self) + { + if (hIconFamily) + { + DisposeHandle( (Handle)hIconFamily ); + hIconFamily = NULL; + } + + result = GetIconRef(kOnSystemDisk, kSystemIconsCreator, fourByteCode, &iconRef); + + if (result != noErr) + { + [self autorelease]; + return nil; + } + + result = IconRefToIconFamily( + iconRef, + kSelectorAllAvailableData, + &hIconFamily ); + + if (result != noErr || !hIconFamily) + { + [self autorelease]; + return nil; + } + + ReleaseIconRef( iconRef ); + } + return self; +} + +- initWithThumbnailsOfImage:(NSImage*)image +{ + // The default is to use a high degree of antialiasing, producing a smooth image. + return [self initWithThumbnailsOfImage:image usingImageInterpolation:NSImageInterpolationHigh]; +} + +- initWithThumbnailsOfImage:(NSImage*)image usingImageInterpolation:(NSImageInterpolation)imageInterpolation +{ + NSImage* iconImage128x128; + NSImage* iconImage32x32; + NSImage* iconImage16x16; + NSBitmapImageRep* iconBitmap128x128; + NSBitmapImageRep* iconBitmap32x32; + NSBitmapImageRep* iconBitmap16x16; + NSImage* bitmappedIconImage128x128; + + // Start with a new, empty IconFamily. + self = [self init]; + if (self == nil) + return nil; + + // Resample the given image to create a 128x128 pixel, 32-bit RGBA + // version, and use that as our "thumbnail" (128x128) icon and mask. + // + // Our +resampleImage:toIconWidth:... method, in its present form, + // returns an NSImage that contains an NSCacheImageRep, rather than + // an NSBitmapImageRep. We convert to an NSBitmapImageRep, so that + // our methods can scan the image data, using initWithFocusedViewRect:. + iconImage128x128 = [IconFamily resampleImage:image toIconWidth:128 usingImageInterpolation:imageInterpolation]; + [iconImage128x128 lockFocus]; + iconBitmap128x128 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 128, 128)]; + [iconImage128x128 unlockFocus]; + if (iconBitmap128x128) { + [self setIconFamilyElement:kThumbnail32BitData fromBitmapImageRep:iconBitmap128x128]; + [self setIconFamilyElement:kThumbnail8BitMask fromBitmapImageRep:iconBitmap128x128]; + } + + // Create an NSImage with the iconBitmap128x128 NSBitmapImageRep, that we + // can resample to create the smaller icon family elements. (This is + // most likely more efficient than resampling from the original image again, + // particularly if it is large. It produces a slightly different result, but + // the difference is minor and should not be objectionable...) + bitmappedIconImage128x128 = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; + [bitmappedIconImage128x128 addRepresentation:iconBitmap128x128]; + + // Resample the 128x128 image to create a 32x32 pixel, 32-bit RGBA version, + // and use that as our "large" (32x32) icon and 8-bit mask. + iconImage32x32 = [IconFamily resampleImage:bitmappedIconImage128x128 toIconWidth:32 usingImageInterpolation:imageInterpolation]; + [iconImage32x32 lockFocus]; + iconBitmap32x32 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 32, 32)]; + [iconImage32x32 unlockFocus]; + if (iconBitmap32x32) { + [self setIconFamilyElement:kLarge32BitData fromBitmapImageRep:iconBitmap32x32]; + [self setIconFamilyElement:kLarge8BitData fromBitmapImageRep:iconBitmap32x32]; + [self setIconFamilyElement:kLarge8BitMask fromBitmapImageRep:iconBitmap32x32]; + [self setIconFamilyElement:kLarge1BitMask fromBitmapImageRep:iconBitmap32x32]; + } + + // Resample the 128x128 image to create a 16x16 pixel, 32-bit RGBA version, + // and use that as our "small" (16x16) icon and 8-bit mask. + iconImage16x16 = [IconFamily resampleImage:bitmappedIconImage128x128 toIconWidth:16 usingImageInterpolation:imageInterpolation]; + [iconImage16x16 lockFocus]; + iconBitmap16x16 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, 16, 16)]; + [iconImage16x16 unlockFocus]; + if (iconBitmap16x16) { + [self setIconFamilyElement:kSmall32BitData fromBitmapImageRep:iconBitmap16x16]; + [self setIconFamilyElement:kSmall8BitData fromBitmapImageRep:iconBitmap16x16]; + [self setIconFamilyElement:kSmall8BitMask fromBitmapImageRep:iconBitmap16x16]; + [self setIconFamilyElement:kSmall1BitMask fromBitmapImageRep:iconBitmap16x16]; + } + + // Release all of the images that we created and no longer need. + [bitmappedIconImage128x128 release]; + [iconBitmap128x128 release]; + [iconBitmap32x32 release]; + [iconBitmap16x16 release]; + + // Return the new icon family! + return self; +} + +- (void) dealloc +{ + DisposeHandle( (Handle)hIconFamily ); + [super dealloc]; +} + +- (NSBitmapImageRep*) bitmapImageRepWithAlphaForIconFamilyElement:(OSType)elementType; +{ + NSBitmapImageRep* bitmapImageRep; + int pixelsWide; + Handle hRawBitmapData; + Handle hRawMaskData; + OSType maskElementType; + OSErr result; + unsigned long* pRawBitmapData; + unsigned long* pRawBitmapDataEnd; + unsigned char* pRawMaskData; + unsigned char* pBitmapImageRepBitmapData; + + // Make sure elementType is a valid type that we know how to handle, and + // figure out the dimensions and bit depth of the bitmap for that type. + switch (elementType) { + // 'it32' 128x128 32-bit RGB image + case kThumbnail32BitData: + maskElementType = kThumbnail8BitMask; + pixelsWide = 128; + break; + + // 'il32' 32x32 32-bit RGB image + case kLarge32BitData: + maskElementType = kLarge8BitMask; + pixelsWide = 32; + break; + + // 'is32' 16x16 32-bit RGB image + case kSmall32BitData: + maskElementType = kSmall8BitMask; + pixelsWide = 16; + break; + + default: + return nil; + } + + // Get the raw, uncompressed bitmap data for the requested element. + hRawBitmapData = NewHandle( pixelsWide * pixelsWide * 4 ); + result = GetIconFamilyData( hIconFamily, elementType, hRawBitmapData ); + if (result != noErr) { + DisposeHandle( hRawBitmapData ); + return nil; + } + + // Get the corresponding raw, uncompressed 8-bit mask data. + hRawMaskData = NewHandle( pixelsWide * pixelsWide ); + result = GetIconFamilyData( hIconFamily, maskElementType, hRawMaskData ); + if (result != noErr) { + DisposeHandle( hRawMaskData ); + hRawMaskData = NULL; + } + + // The retrieved raw bitmap data is stored at 32 bits per pixel: 3 bytes + // for the RGB color of each pixel, plus an extra unused byte. We can + // therefore fold the mask data into the color data in-place (though + // getting the proper byte ordering requires some bit-shifting). + HLock( hRawBitmapData ); + pRawBitmapData = (unsigned long*) *hRawBitmapData; + pRawBitmapDataEnd = pRawBitmapData + pixelsWide * pixelsWide; + if (hRawMaskData) { + HLock( hRawMaskData ); + pRawMaskData = *hRawMaskData; + while (pRawBitmapData < pRawBitmapDataEnd) { + //*pRawBitmapData++ = (*pRawBitmapData << 8) | *pRawMaskData++; + pRawBitmapData++; + *pRawBitmapData = (*pRawBitmapData << 8) | *pRawMaskData++; + } + HUnlock( hRawMaskData ); + } else { + while (pRawBitmapData < pRawBitmapDataEnd) { + //*pRawBitmapData++ = (*pRawBitmapData << 8) | 0xff; + pRawBitmapData++; + *pRawBitmapData = (*pRawBitmapData << 8) | 0xff; + } + } + + // Create a new NSBitmapImageRep with the given bitmap data. Note that + // when creating the NSBitmapImageRep we pass in NULL for the "planes" + // parameter. This causes the new NSBitmapImageRep to allocate its own + // buffer for the bitmap data (which it will own and release when the + // NSBitmapImageRep is released), rather than referencing the bitmap + // data we pass in (which will soon disappear when we call + // DisposeHandle() below!). (See the NSBitmapImageRep documentation for + // the -initWithBitmapDataPlanes:... method, where this is explained.) + // + // Once we have the new NSBitmapImageRep, we get a pointer to its + // bitmapData and copy our bitmap data in. + bitmapImageRep = [[[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:NULL + pixelsWide:pixelsWide + pixelsHigh:pixelsWide + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace // NOTE: is this right? + bytesPerRow:0 + bitsPerPixel:0] autorelease]; + pBitmapImageRepBitmapData = [bitmapImageRep bitmapData]; + if (pBitmapImageRepBitmapData) { + memcpy( pBitmapImageRepBitmapData, *hRawBitmapData, + pixelsWide * pixelsWide * 4 ); + } + HUnlock( hRawBitmapData ); + + // Free the retrieved raw data. + DisposeHandle( hRawBitmapData ); + if (hRawMaskData) + DisposeHandle( hRawMaskData ); + + // Return nil if the NSBitmapImageRep didn't give us a buffer to copy into. + if (pBitmapImageRepBitmapData == NULL) + return nil; + + // Return the new NSBitmapImageRep. + return bitmapImageRep; +} + +- (NSImage*) imageWithAllReps +{ + NSImage* image = NULL; + image = [[[NSImage alloc] initWithData:[NSData dataWithBytes:*hIconFamily length:GetHandleSize((Handle)hIconFamily)]] autorelease]; + + return image; + + //investigate optimisations (dataWithBytesNoCopy:length: for example...) +} + +- (BOOL) setIconFamilyElement:(OSType)elementType fromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep +{ + Handle hRawData = NULL; + OSErr result; + + switch (elementType) { + // 'it32' 128x128 32-bit RGB image + case kThumbnail32BitData: + hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:128]; + break; + + // 't8mk' 128x128 8-bit alpha mask + case kThumbnail8BitMask: + hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:128]; + break; + + // 'il32' 32x32 32-bit RGB image + case kLarge32BitData: + hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; + break; + + // 'l8mk' 32x32 8-bit alpha mask + case kLarge8BitMask: + hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; + break; + + // 'ICN#' 32x32 1-bit alpha mask + case kLarge1BitMask: + hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; + break; + + // 'icl8' 32x32 8-bit indexed image data + case kLarge8BitData: + hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:32]; + break; + + // 'is32' 16x16 32-bit RGB image + case kSmall32BitData: + hRawData = [IconFamily get32BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; + break; + + // 's8mk' 16x16 8-bit alpha mask + case kSmall8BitMask: + hRawData = [IconFamily get8BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; + break; + + // 'ics#' 16x16 1-bit alpha mask + case kSmall1BitMask: + hRawData = [IconFamily get1BitMaskFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; + break; + + // 'ics8' 16x16 8-bit indexed image data + case kSmall8BitData: + hRawData = [IconFamily get8BitDataFromBitmapImageRep:bitmapImageRep requiredPixelSize:16]; + break; + + default: + return NO; + } + + // NSLog(@"setIconFamilyElement:%@ fromBitmapImageRep:%@ generated handle %p of size %d", NSFileTypeForHFSTypeCode(elementType), bitmapImageRep, hRawData, GetHandleSize(hRawData)); + + if (hRawData == NULL) + { + NSLog(@"Null data returned to setIconFamilyElement:fromBitmapImageRep:"); + return NO; + } + + result = SetIconFamilyData( hIconFamily, elementType, hRawData ); + DisposeHandle( hRawData ); + + if (result != noErr) + { + NSLog(@"SetIconFamilyData() returned error %d", result); + return NO; + } + + return YES; +} + +- (BOOL) setAsCustomIconForFile:(NSString*)path +{ + return( [self setAsCustomIconForFile:path withCompatibility:NO] ); +} + +- (BOOL) setAsCustomIconForFile:(NSString*)path withCompatibility:(BOOL)compat +{ + FSSpec targetFileFSSpec; + FSRef targetFileFSRef; + FSRef parentDirectoryFSRef; + SInt16 file; + OSErr result; + FInfo finderInfo; + Handle hExistingCustomIcon; + Handle hIconFamilyCopy; + NSDictionary *fileAttributes; + OSType existingType = unknownOSType, existingCreator = unknownOSType; + + // Get an FSRef and an FSSpec for the target file, and an FSRef for its parent directory that we can use in the FNNotify() call below. + if (![path getFSRef:&targetFileFSRef createFileIfNecessary:NO]) + return NO; + result = FSGetCatalogInfo( &targetFileFSRef, kFSCatInfoNone, NULL, NULL, &targetFileFSSpec, &parentDirectoryFSRef ); + if (result != noErr) + return NO; + + // Get the file's type and creator codes. + fileAttributes = [[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:NO]; + if (fileAttributes) + { + existingType = [fileAttributes fileHFSTypeCode]; + existingCreator = [fileAttributes fileHFSCreatorCode]; + } + + // Make sure the file has a resource fork that we can open. (Although + // this sounds like it would clobber an existing resource fork, the Carbon + // Resource Manager docs for this function say that's not the case. If + // the file already has a resource fork, we receive a result code of + // dupFNErr, which is not really an error per se, but just a notification + // to us that creating a new resource fork for the file was not necessary.) + FSpCreateResFile( &targetFileFSSpec, existingCreator, existingType, smRoman ); + result = ResError(); + if (!(result == noErr || result == dupFNErr)) + return NO; + + // Open the file's resource fork. + file = FSpOpenResFile( &targetFileFSSpec, fsRdWrPerm ); + if (file == -1) + return NO; + + // Make a copy of the icon family data to pass to AddResource(). + // (AddResource() takes ownership of the handle we pass in; after the + // CloseResFile() call its master pointer will be set to 0xffffffff. + // We want to keep the icon family data, so we make a copy.) + // HandToHand() returns the handle of the copy in hIconFamily. + hIconFamilyCopy = (Handle) hIconFamily; + result = HandToHand( &hIconFamilyCopy ); + if (result != noErr) { + CloseResFile( file ); + return NO; + } + + // Remove the file's existing kCustomIconResource of type kIconFamilyType + // (if any). + hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource ); + if( hExistingCustomIcon ) + RemoveResource( hExistingCustomIcon ); + + // Now add our icon family as the file's new custom icon. + AddResource( (Handle)hIconFamilyCopy, kIconFamilyType, + kCustomIconResource, "\p"); + if (ResError() != noErr) { + CloseResFile( file ); + return NO; + } + + if( compat ) + { + [self addResourceType:kLarge8BitData asResID:kCustomIconResource]; + [self addResourceType:kLarge1BitMask asResID:kCustomIconResource]; + [self addResourceType:kSmall8BitData asResID:kCustomIconResource]; + [self addResourceType:kSmall1BitMask asResID:kCustomIconResource]; + } + + // Close the file's resource fork, flushing the resource map and new icon + // data out to disk. + CloseResFile( file ); + if (ResError() != noErr) + return NO; + + // Now we need to set the file's Finder info so the Finder will know that + // it has a custom icon. Start by getting the file's current finder info: + result = FSpGetFInfo( &targetFileFSSpec, &finderInfo ); + if (result != noErr) + return NO; + + // Set the kHasCustomIcon flag, and clear the kHasBeenInited flag. + // + // From Apple's "CustomIcon" code sample: + // "set bit 10 (has custom icon) and unset the inited flag + // kHasBeenInited is 0x0100 so the mask will be 0xFEFF:" + // finderInfo.fdFlags = 0xFEFF & (finderInfo.fdFlags | kHasCustomIcon ) ; + finderInfo.fdFlags = (finderInfo.fdFlags | kHasCustomIcon ) & ~kHasBeenInited; + + // Now write the Finder info back. + result = FSpSetFInfo( &targetFileFSSpec, &finderInfo ); + if (result != noErr) + return NO; + + // Notify the system that the directory containing the file has changed, to give Finder the chance to find out about the file's new custom icon. + result = FNNotify( &parentDirectoryFSRef, kFNDirectoryModifiedMessage, kNilOptions ); + if (result != noErr) + return NO; + + return YES; +} + ++ (BOOL) removeCustomIconFromFile:(NSString*)path +{ + FSSpec targetFileFSSpec; + FSRef targetFileFSRef; + FSRef parentDirectoryFSRef; + SInt16 file; + OSErr result; + FInfo finderInfo; + Handle hExistingCustomIcon; + + // Get an FSRef and an FSSpec for the target file, and an FSRef for its parent directory that we can use in the FNNotify() call below. + if (![path getFSRef:&targetFileFSRef createFileIfNecessary:NO]) + return NO; + result = FSGetCatalogInfo( &targetFileFSRef, kFSCatInfoNone, NULL, NULL, &targetFileFSSpec, &parentDirectoryFSRef ); + if (result != noErr) + return NO; + + // Open the file's resource fork, if it has one. + file = FSpOpenResFile( &targetFileFSSpec, fsRdWrPerm ); + if (file == -1) + return NO; + + // Remove the file's existing kCustomIconResource of type kIconFamilyType + // (if any). + hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource ); + if( hExistingCustomIcon ) + RemoveResource( hExistingCustomIcon ); + + // Close the file's resource fork, flushing the resource map out to disk. + CloseResFile( file ); + if (ResError() != noErr) + return NO; + + // Now we need to set the file's Finder info so the Finder will know that + // it has no custom icon. Start by getting the file's current finder info: + result = FSpGetFInfo( &targetFileFSSpec, &finderInfo ); + if (result != noErr) + return NO; + + // Clear the kHasCustomIcon flag and the kHasBeenInited flag. + finderInfo.fdFlags = finderInfo.fdFlags & ~(kHasCustomIcon | kHasBeenInited); + + // Now write the Finder info back. + result = FSpSetFInfo( &targetFileFSSpec, &finderInfo ); + if (result != noErr) + return NO; + + // Notify the system that the directory containing the file has changed, to give Finder the chance to find out about the file's new custom icon. + result = FNNotify( &parentDirectoryFSRef, kFNDirectoryModifiedMessage, kNilOptions ); + if (result != noErr) + return NO; + + return YES; +} + +- (BOOL) setAsCustomIconForDirectory:(NSString*)path +{ + return [self setAsCustomIconForDirectory:path withCompatibility:NO]; +} + +- (BOOL) setAsCustomIconForDirectory:(NSString*)path withCompatibility:(BOOL)compat +{ + NSFileManager *fm = [NSFileManager defaultManager]; + BOOL isDir; + BOOL exists; + NSString *iconrPath = [path stringByAppendingPathComponent:@"Icon\r"]; + FSSpec targetFileFSSpec, targetFolderFSSpec; + FSRef targetFolderFSRef; + SInt16 file; + OSErr result; + FInfo finderInfo; + FSCatalogInfo catInfo; + Handle hExistingCustomIcon; + Handle hIconFamilyCopy; + + exists = [fm fileExistsAtPath:path isDirectory:&isDir]; + + if( !isDir || !exists ) + return NO; + + if( [fm fileExistsAtPath:iconrPath] ) + { + if( ![fm removeFileAtPath:iconrPath handler:nil] ) + return NO; + } + + if (![iconrPath getFSSpec:&targetFileFSSpec createFileIfNecessary:YES]) + return NO; + + if( ![path getFSSpec:&targetFolderFSSpec createFileIfNecessary:YES] ) + return NO; + + if( ![path getFSRef:&targetFolderFSRef createFileIfNecessary:NO] ) + return NO; + + // Make sure the file has a resource fork that we can open. (Although + // this sounds like it would clobber an existing resource fork, the Carbon + // Resource Manager docs for this function say that's not the case.) + FSpCreateResFile( &targetFileFSSpec, unknownOSType, unknownOSType, smRoman ); + if (ResError() != noErr) + return NO; + + // Open the file's resource fork. + file = FSpOpenResFile( &targetFileFSSpec, fsRdWrPerm ); + if (file == -1) + return NO; + + // Make a copy of the icon family data to pass to AddResource(). + // (AddResource() takes ownership of the handle we pass in; after the + // CloseResFile() call its master pointer will be set to 0xffffffff. + // We want to keep the icon family data, so we make a copy.) + // HandToHand() returns the handle of the copy in hIconFamily. + hIconFamilyCopy = (Handle) hIconFamily; + result = HandToHand( &hIconFamilyCopy ); + if (result != noErr) { + CloseResFile( file ); + return NO; + } + + // Remove the file's existing kCustomIconResource of type kIconFamilyType + // (if any). + hExistingCustomIcon = GetResource( kIconFamilyType, kCustomIconResource ); + if( hExistingCustomIcon ) + RemoveResource( hExistingCustomIcon ); + + // Now add our icon family as the file's new custom icon. + AddResource( (Handle)hIconFamilyCopy, kIconFamilyType, + kCustomIconResource, "\p"); + + if (ResError() != noErr) { + CloseResFile( file ); + return NO; + } + + if( compat ) + { + [self addResourceType:kLarge8BitData asResID:kCustomIconResource]; + [self addResourceType:kLarge1BitMask asResID:kCustomIconResource]; + [self addResourceType:kSmall8BitData asResID:kCustomIconResource]; + [self addResourceType:kSmall1BitMask asResID:kCustomIconResource]; + } + + // Close the file's resource fork, flushing the resource map and new icon + // data out to disk. + CloseResFile( file ); + if (ResError() != noErr) + return NO; + + // Make folder icon file invisible + result = FSpGetFInfo( &targetFileFSSpec, &finderInfo ); + if (result != noErr) + return NO; + finderInfo.fdFlags = (finderInfo.fdFlags | kIsInvisible ) & ~kHasBeenInited; + // And write info back + result = FSpSetFInfo( &targetFileFSSpec, &finderInfo ); + if (result != noErr) + return NO; + + result = FSGetCatalogInfo( &targetFolderFSRef, + kFSCatInfoFinderInfo, + &catInfo, nil, nil, nil); + if( result != noErr ) + return NO; + + ((DInfo*)catInfo.finderInfo)->frFlags = ( ((DInfo*)catInfo.finderInfo)->frFlags | kHasCustomIcon ) & ~kHasBeenInited; + + FSSetCatalogInfo( &targetFolderFSRef, + kFSCatInfoFinderInfo, + &catInfo); + if( result != noErr ) + return NO; + + // Notify the system that the target directory has changed, to give Finder the chance to find out about its new custom icon. + result = FNNotify( &targetFolderFSRef, kFNDirectoryModifiedMessage, kNilOptions ); + if (result != noErr) + return NO; + + return YES; +} + +/*- (BOOL) writeToFile:(NSString*)path +{ + FSSpec fsSpec; + OSErr result; + + if (![path getFSSpec:&fsSpec createFileIfNecessary:YES]) + return NO; + result = WriteIconFile( hIconFamily, &fsSpec ); + if (result != noErr) + return NO; + + return YES; +} This method has a problem with files not representable as an FSSpec.*/ + +- (BOOL) writeToFile:(NSString*)path +{ + NSData* iconData = NULL; + + HLock((Handle)hIconFamily); + + iconData = [NSData dataWithBytes:*hIconFamily length:GetHandleSize((Handle)hIconFamily)]; + [iconData writeToFile:path atomically:NO]; + + HUnlock((Handle)hIconFamily); + + return YES; +} + +@synthesize hIconFamily; +@end + +@implementation IconFamily (Internals) + ++ (NSImage*) resampleImage:(NSImage*)image toIconWidth:(int)iconWidth usingImageInterpolation:(NSImageInterpolation)imageInterpolation +{ + NSGraphicsContext* graphicsContext; + BOOL wasAntialiasing; + NSImageInterpolation previousImageInterpolation; + NSImage* newImage; +// NSBitmapImageRep* newBitmapImageRep; +// unsigned char* bitmapData; +// NSImageRep* originalImageRep; + NSImage* workingImage; + NSImageRep* workingImageRep; + NSSize size, pixelSize, newSize; + NSRect iconRect; + NSRect targetRect; + + // Create a working copy of the image and scale its size down to fit in + // the square area of the icon. + // + // It seems like there should be a more memory-efficient alternative to + // first duplicating the entire original image, but I don't know what it + // is. We need to change some properties ("size" and "scalesWhenResized") + // of the original image, but we shouldn't change the original, so a copy + // is necessary. + workingImage = [image copyWithZone:[image zone]]; + [workingImage setScalesWhenResized:YES]; + size = [workingImage size]; + workingImageRep = [workingImage bestRepresentationForDevice:nil]; + if ([workingImageRep isKindOfClass:[NSBitmapImageRep class]]) { + pixelSize.width = [workingImageRep pixelsWide]; + pixelSize.height = [workingImageRep pixelsHigh]; + if (!NSEqualSizes( size, pixelSize )) { + [workingImage setSize:pixelSize]; + [workingImageRep setSize:pixelSize]; + size = pixelSize; + } + } + if (size.width >= size.height) { + newSize.width = iconWidth; + newSize.height = floor( (float) iconWidth * size.height / size.width + 0.5 ); + } else { + newSize.height = iconWidth; + newSize.width = floor( (float) iconWidth * size.width / size.height + 0.5 ); + } + [workingImage setSize:newSize]; + +#if 1 // This is the way that works. It gives the newImage an NSCachedImageRep. + + // Create a new image the size of the icon, and clear it to transparent. + newImage = [[NSImage alloc] initWithSize:NSMakeSize(iconWidth,iconWidth)]; + [newImage lockFocus]; + iconRect.origin.x = iconRect.origin.y = 0; + iconRect.size.width = iconRect.size.height = iconWidth; + [[NSColor clearColor] set]; + NSRectFill( iconRect ); + + // Set current graphics context to use antialiasing and high-quality + // image scaling. + graphicsContext = [NSGraphicsContext currentContext]; + wasAntialiasing = [graphicsContext shouldAntialias]; + previousImageInterpolation = [graphicsContext imageInterpolation]; + [graphicsContext setShouldAntialias:YES]; + [graphicsContext setImageInterpolation:imageInterpolation]; + + // Composite the working image into the icon bitmap, centered. + targetRect.origin.x = ((float)iconWidth - newSize.width ) / 2.0; + targetRect.origin.y = ((float)iconWidth - newSize.height) / 2.0; + targetRect.size.width = newSize.width; + targetRect.size.height = newSize.height; + [workingImageRep drawInRect:targetRect]; + + // Restore previous graphics context settings. + [graphicsContext setShouldAntialias:wasAntialiasing]; + [graphicsContext setImageInterpolation:previousImageInterpolation]; + + [newImage unlockFocus]; + + [workingImage release]; + +#else // This was an attempt at explicitly giving the NSImage an NSBitmapImageRep + // and drawing to that NSBitmapImageRep. It doesn't work. (See comments + // in -initWithThumbnailsOfImage:) + +// // Create a new 32-bit RGBA bitmap that is width x width pixels. + originalImageRep = [image bestRepresentationForDevice:nil]; + newImage = [[NSImage alloc] initWithSize:NSMakeSize(iconWidth,iconWidth)]; + [newImage setDataRetained:YES]; +// [newImage setCachedSeparately:YES]; + newBitmapImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:iconWidth + pixelsHigh:iconWidth +// bitsPerSample:8 +// samplesPerPixel:4 + bitsPerSample:[originalImageRep bitsPerSample] + samplesPerPixel:[(NSBitmapImageRep*)originalImageRep samplesPerPixel] + hasAlpha:[originalImageRep hasAlpha] + isPlanar:NO + colorSpaceName:[originalImageRep colorSpaceName] + bytesPerRow:0 + bitsPerPixel:0]; + [newImage addRepresentation:newBitmapImageRep]; + [newImage setScalesWhenResized:YES]; + [newBitmapImageRep release]; +// bitmapData = [newBitmapImageRep bitmapData]; +// if (bitmapData) +// memset( bitmapData, 128, iconWidth * iconWidth * 4 ); + // Copy the original image into the new bitmap, rescaling it to fit. +// [newImage lockFocus]; + [newImage lockFocusOnRepresentation:newBitmapImageRep]; +// [image compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver]; +// iconRect.origin.x = iconRect.origin.y = 0; +// iconRect.size.width = iconRect.size.height = iconWidth; +// [[NSColor clearColor] set]; +// NSRectFill( iconRect ); + [workingImage compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver]; + [newImage unlockFocus]; + + [workingImage release]; +#endif + + // Return the new image! + return [newImage autorelease]; +} + ++ (Handle) get32BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize +{ + Handle hRawData; + unsigned char* pRawData; + Size rawDataSize; + unsigned char* pSrc; + unsigned char* pDest; + int x, y; + unsigned char alphaByte; + float oneOverAlpha; + + // Get information about the bitmapImageRep. + int pixelsWide = [bitmapImageRep pixelsWide]; + int pixelsHigh = [bitmapImageRep pixelsHigh]; + int bitsPerSample = [bitmapImageRep bitsPerSample]; + int samplesPerPixel = [bitmapImageRep samplesPerPixel]; + int bitsPerPixel = [bitmapImageRep bitsPerPixel]; +// BOOL hasAlpha = [bitmapImageRep hasAlpha]; + BOOL isPlanar = [bitmapImageRep isPlanar]; +// int numberOfPlanes = [bitmapImageRep numberOfPlanes]; + int bytesPerRow = [bitmapImageRep bytesPerRow]; +// int bytesPerPlane = [bitmapImageRep bytesPerPlane]; + unsigned char* bitmapData = [bitmapImageRep bitmapData]; + + // Make sure bitmap has the required dimensions. + if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) + return NULL; + + // So far, this code only handles non-planar 32-bit RGBA and 24-bit RGB source bitmaps. + // This could be made more flexible with some additional programming to accommodate other possible + // formats... + if (isPlanar) + { + NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); + return NULL; + } + if (bitsPerSample != 8) + { + NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %d", bitsPerSample); + return NULL; + } + + if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32))) + { + rawDataSize = pixelsWide * pixelsHigh * 4; + hRawData = NewHandle( rawDataSize ); + if (hRawData == NULL) + return NULL; + pRawData = *hRawData; + + pSrc = bitmapData; + pDest = pRawData; + + if (bitsPerPixel == 32) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x++) { + // Each pixel is 3 bytes of RGB data, followed by 1 byte of + // alpha. The RGB values are premultiplied by the alpha (so + // that Quartz can save time when compositing the bitmap to a + // destination), and we undo this premultiplication (with some + // lossiness unfortunately) when retrieving the bitmap data. + *pDest++ = alphaByte = *(pSrc+3); + if (alphaByte) { + oneOverAlpha = 255.0f / (float)alphaByte; + *pDest++ = *(pSrc+0) * oneOverAlpha; + *pDest++ = *(pSrc+1) * oneOverAlpha; + *pDest++ = *(pSrc+2) * oneOverAlpha; + } else { + *pDest++ = 0; + *pDest++ = 0; + *pDest++ = 0; + } + pSrc+=4; + } + } + } else if (bitsPerPixel == 24) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x++) { + *pDest++ = 0; + *pDest++ = *pSrc++; + *pDest++ = *pSrc++; + *pDest++ = *pSrc++; + } + } + } + } + else + { + NSLog(@"get32BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %d, bitsPerPixel == %", samplesPerPixel, bitsPerPixel); + return NULL; + } + + return hRawData; +} + ++ (Handle) get8BitDataFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize +{ + Handle hRawData; + unsigned char* pRawData; + Size rawDataSize; + unsigned char* pSrc; + unsigned char* pDest; + int x, y; + + // Get information about the bitmapImageRep. + int pixelsWide = [bitmapImageRep pixelsWide]; + int pixelsHigh = [bitmapImageRep pixelsHigh]; + int bitsPerSample = [bitmapImageRep bitsPerSample]; + int samplesPerPixel = [bitmapImageRep samplesPerPixel]; + int bitsPerPixel = [bitmapImageRep bitsPerPixel]; + BOOL isPlanar = [bitmapImageRep isPlanar]; + int bytesPerRow = [bitmapImageRep bytesPerRow]; + unsigned char* bitmapData = [bitmapImageRep bitmapData]; + + // Make sure bitmap has the required dimensions. + if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) + return NULL; + + // So far, this code only handles non-planar 32-bit RGBA and 24-bit RGB source bitmaps. + // This could be made more flexible with some additional programming... + if (isPlanar) + { + NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); + return NULL; + } + if (bitsPerSample != 8) + { + NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %d", bitsPerSample); + return NULL; + } + + if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32))) + { + CGDirectPaletteRef cgPal; + CGDeviceColor cgCol; + + rawDataSize = pixelsWide * pixelsHigh; + hRawData = NewHandle( rawDataSize ); + if (hRawData == NULL) + return NULL; + pRawData = *hRawData; + + cgPal = CGPaletteCreateDefaultColorPalette(); + + pSrc = bitmapData; + pDest = pRawData; + if (bitsPerPixel == 32) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x++) { + cgCol.red = ((float)*(pSrc)) / 255; + cgCol.green = ((float)*(pSrc+1)) / 255; + cgCol.blue = ((float)*(pSrc+2)) / 255; + + *pDest++ = CGPaletteGetIndexForColor(cgPal, cgCol); + + pSrc+=4; + } + } + } else if (bitsPerPixel == 24) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x++) { + cgCol.red = ((float)*(pSrc)) / 255; + cgCol.green = ((float)*(pSrc+1)) / 255; + cgCol.blue = ((float)*(pSrc+2)) / 255; + + *pDest++ = CGPaletteGetIndexForColor(cgPal, cgCol); + + pSrc+=3; + } + } + } + + CGPaletteRelease(cgPal); + } + else + { + NSLog(@"get8BitDataFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %d, bitsPerPixel == %", samplesPerPixel, bitsPerPixel); + return NULL; + } + + return hRawData; +} + ++ (Handle) get8BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize +{ + Handle hRawData; + unsigned char* pRawData; + Size rawDataSize; + unsigned char* pSrc; + unsigned char* pDest; + int x, y; + + // Get information about the bitmapImageRep. + int pixelsWide = [bitmapImageRep pixelsWide]; + int pixelsHigh = [bitmapImageRep pixelsHigh]; + int bitsPerSample = [bitmapImageRep bitsPerSample]; + int samplesPerPixel = [bitmapImageRep samplesPerPixel]; + int bitsPerPixel = [bitmapImageRep bitsPerPixel]; +// BOOL hasAlpha = [bitmapImageRep hasAlpha]; + BOOL isPlanar = [bitmapImageRep isPlanar]; +// int numberOfPlanes = [bitmapImageRep numberOfPlanes]; + int bytesPerRow = [bitmapImageRep bytesPerRow]; +// int bytesPerPlane = [bitmapImageRep bytesPerPlane]; + unsigned char* bitmapData = [bitmapImageRep bitmapData]; + + // Make sure bitmap has the required dimensions. + if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) + return NULL; + + // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB and 8-bit grayscale source bitmaps. + // This could be made more flexible with some additional programming... + if (isPlanar) + { + NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); + return NULL; + } + if (bitsPerSample != 8) + { + NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %d", bitsPerSample); + return NULL; + } + + if (((samplesPerPixel == 1) && (bitsPerPixel == 8)) || ((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32))) + { + rawDataSize = pixelsWide * pixelsHigh; + hRawData = NewHandle( rawDataSize ); + if (hRawData == NULL) + return NULL; + pRawData = *hRawData; + + pSrc = bitmapData; + pDest = pRawData; + + if (bitsPerPixel == 32) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x++) { + pSrc += 3; + *pDest++ = *pSrc++; + } + } + } + else if (bitsPerPixel == 24) { + memset( pDest, 255, rawDataSize ); + } + else if (bitsPerPixel == 8) { + for (y = 0; y < pixelsHigh; y++) { + memcpy( pDest, pSrc, pixelsWide ); + pSrc += bytesPerRow; + pDest += pixelsWide; + } + } + } + else + { + NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %d, bitsPerPixel == %", samplesPerPixel, bitsPerPixel); + return NULL; + } + + return hRawData; +} + +// NOTE: This method hasn't been fully tested yet. ++ (Handle) get1BitMaskFromBitmapImageRep:(NSBitmapImageRep*)bitmapImageRep requiredPixelSize:(int)requiredPixelSize +{ + Handle hRawData; + unsigned char* pRawData; + Size rawDataSize; + unsigned char* pSrc; + unsigned char* pDest; + int x, y; + unsigned char maskByte; + + // Get information about the bitmapImageRep. + int pixelsWide = [bitmapImageRep pixelsWide]; + int pixelsHigh = [bitmapImageRep pixelsHigh]; + int bitsPerSample = [bitmapImageRep bitsPerSample]; + int samplesPerPixel = [bitmapImageRep samplesPerPixel]; + int bitsPerPixel = [bitmapImageRep bitsPerPixel]; +// BOOL hasAlpha = [bitmapImageRep hasAlpha]; + BOOL isPlanar = [bitmapImageRep isPlanar]; +// int numberOfPlanes = [bitmapImageRep numberOfPlanes]; + int bytesPerRow = [bitmapImageRep bytesPerRow]; +// int bytesPerPlane = [bitmapImageRep bytesPerPlane]; + unsigned char* bitmapData = [bitmapImageRep bitmapData]; + + // Make sure bitmap has the required dimensions. + if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize) + return NULL; + + // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB, 8-bit grayscale, and 1-bit source bitmaps. + // This could be made more flexible with some additional programming... + if (isPlanar) + { + NSLog(@"get1BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES"); + return NULL; + } + + if (((bitsPerPixel == 1) && (samplesPerPixel == 1) && (bitsPerSample == 1)) || ((bitsPerPixel == 8) && (samplesPerPixel == 1) && (bitsPerSample == 8)) || + ((bitsPerPixel == 24) && (samplesPerPixel == 3) && (bitsPerSample == 8)) || ((bitsPerPixel == 32) && (samplesPerPixel == 4) && (bitsPerSample == 8))) + { + rawDataSize = (pixelsWide * pixelsHigh)/4; + hRawData = NewHandle( rawDataSize ); + if (hRawData == NULL) + return NULL; + pRawData = *hRawData; + + pSrc = bitmapData; + pDest = pRawData; + + if (bitsPerPixel == 32) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x += 8) { + maskByte = 0; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x80 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x40 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x20 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x10 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x08 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x04 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x02 : 0; pSrc += 4; + maskByte |= (*(unsigned*)pSrc & 0xff) ? 0x01 : 0; pSrc += 4; + *pDest++ = maskByte; + } + } + } + else if (bitsPerPixel == 24) { + memset( pDest, 255, rawDataSize ); + } + else if (bitsPerPixel == 8) { + for (y = 0; y < pixelsHigh; y++) { + pSrc = bitmapData + y * bytesPerRow; + for (x = 0; x < pixelsWide; x += 8) { + maskByte = 0; + maskByte |= *pSrc++ ? 0x80 : 0; + maskByte |= *pSrc++ ? 0x40 : 0; + maskByte |= *pSrc++ ? 0x20 : 0; + maskByte |= *pSrc++ ? 0x10 : 0; + maskByte |= *pSrc++ ? 0x08 : 0; + maskByte |= *pSrc++ ? 0x04 : 0; + maskByte |= *pSrc++ ? 0x02 : 0; + maskByte |= *pSrc++ ? 0x01 : 0; + *pDest++ = maskByte; + } + } + } + else if (bitsPerPixel == 1) { + for (y = 0; y < pixelsHigh; y++) { + memcpy( pDest, pSrc, pixelsWide / 8 ); + pDest += pixelsWide / 8; + pSrc += bytesPerRow; + } + } + + memcpy( pRawData+(pixelsWide*pixelsHigh)/8, pRawData, (pixelsWide*pixelsHigh)/8 ); + } + else + { + NSLog(@"get1BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerPixel == %d, samplesPerPixel== %d, bitsPerSample == %d", bitsPerPixel, samplesPerPixel, bitsPerSample); + return NULL; + } + + return hRawData; +} + +- (BOOL) addResourceType:(OSType)type asResID:(int)resID +{ + Handle hIconRes = NewHandle(0); + OSErr err; + + err = GetIconFamilyData( hIconFamily, type, hIconRes ); + + if( !GetHandleSize(hIconRes) || err != noErr ) + return NO; + + AddResource( hIconRes, type, resID, "\p" ); + + return YES; +} + +@end + +// Methods for interfacing with the Carbon Scrap Manager (analogous to and +// interoperable with the Cocoa Pasteboard). + +@implementation IconFamily (ScrapAdditions) + ++ (BOOL) canInitWithScrap +{ + ScrapRef scrap = NULL; + ScrapFlavorInfo* scrapInfos = NULL; + UInt32 numInfos = 0; + unsigned int i = 0; + BOOL canInit = NO; + + GetCurrentScrap(&scrap); + + GetScrapFlavorCount(scrap,&numInfos); + scrapInfos = malloc( sizeof(ScrapFlavorInfo)*numInfos ); + + GetScrapFlavorInfoList(scrap, &numInfos, scrapInfos); + + for( i=0; i<numInfos; i++ ) + { + if( scrapInfos[i].flavorType == 'icns' ) + canInit = YES; + } + + free( scrapInfos ); + + return canInit; +} + ++ (IconFamily*) iconFamilyWithScrap +{ + return [[[IconFamily alloc] initWithScrap] autorelease]; +} + +- initWithScrap +{ + Handle storageMem = NULL; + Size amountMem = 0; + ScrapRef scrap; + + self = [super init]; + + if( self ) + { + GetCurrentScrap(&scrap); + + GetScrapFlavorSize( scrap, 'icns', &amountMem ); + + storageMem = NewHandle(amountMem); + + GetScrapFlavorData( scrap, 'icns', &amountMem, *storageMem ); + + hIconFamily = (IconFamilyHandle)storageMem; + } + return self; +} + +- (BOOL) putOnScrap +{ + ScrapRef scrap = NULL; + + ClearCurrentScrap(); + GetCurrentScrap(&scrap); + + HLock((Handle)hIconFamily); + PutScrapFlavor( scrap, 'icns', kScrapFlavorMaskNone, GetHandleSize((Handle)hIconFamily), *hIconFamily); + HUnlock((Handle)hIconFamily); + return YES; +} + +@end + + diff --git a/Plugins/BuiltInFunctions/IconFamily/IconFamily/NSString+CarbonFSSpecCreation.h b/Plugins/BuiltInFunctions/IconFamily/IconFamily/NSString+CarbonFSSpecCreation.h new file mode 100644 index 0000000..13cd3b9 --- /dev/null +++ b/Plugins/BuiltInFunctions/IconFamily/IconFamily/NSString+CarbonFSSpecCreation.h @@ -0,0 +1,20 @@ +#import <Foundation/Foundation.h> +#import <Carbon/Carbon.h> + +@interface NSString (CarbonFSSpecCreation) + +// Fills in the given FSRef struct so it specifies the file whose path is in this string. +// If the file doesn't exist, and "createFile" is YES, this method will attempt to create +// an empty file with the specified path. (The caller should insure that the directory +// the file is to be placed in already exists.) + +- (BOOL) getFSRef:(FSRef*)fsRef createFileIfNecessary:(BOOL)createFile; + +// Fills in the given FSSpec struct so it specifies the file whose path is in this string. +// If the file doesn't exist, and "createFile" is YES, this method will attempt to create +// an empty file with the specified path. (The caller should insure that the directory +// the file is to be placed in already exists.) + +- (BOOL) getFSSpec:(FSSpec*)fsSpec createFileIfNecessary:(BOOL)createFile; + +@end diff --git a/Plugins/BuiltInFunctions/IconFamily/IconFamily/NSString+CarbonFSSpecCreation.m b/Plugins/BuiltInFunctions/IconFamily/IconFamily/NSString+CarbonFSSpecCreation.m new file mode 100644 index 0000000..711df94 --- /dev/null +++ b/Plugins/BuiltInFunctions/IconFamily/IconFamily/NSString+CarbonFSSpecCreation.m @@ -0,0 +1,66 @@ +#import "NSString+CarbonFSSpecCreation.h" + +@implementation NSString (CarbonFSSpecCreation) + +- (BOOL) getFSRef:(FSRef*)fsRef createFileIfNecessary:(BOOL)createFile +{ + NSFileManager* fileManager = [NSFileManager defaultManager]; + CFURLRef urlRef; + Boolean gotFSRef; + + // Check whether the file exists already. If not, create an empty file if requested. + if (![fileManager fileExistsAtPath:self]) { + if (createFile) { + if (![@"" writeToFile:self atomically:YES]) { + return NO; + } + } else { + return NO; + } + } + + // Create a CFURL with the specified POSIX path. + urlRef = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, + (CFStringRef) self, + kCFURLPOSIXPathStyle, + FALSE /* isDirectory */ ); + if (urlRef == NULL) { +// printf( "** Couldn't make a CFURLRef for the file.\n" ); + return NO; + } + + // Try to create an FSRef from the URL. (If the specified file doesn't exist, this + // function will return false, but if we've reached this code we've already insured + // that the file exists.) + gotFSRef = CFURLGetFSRef( urlRef, fsRef ); + CFRelease( urlRef ); + + if (!gotFSRef) { +// printf( "** Couldn't get an FSRef for the file.\n" ); + return NO; + } + + return YES; +} + +- (BOOL) getFSSpec:(FSSpec*)fsSpec createFileIfNecessary:(BOOL)createFile +{ + FSRef fsRef; + + if (![self getFSRef:&fsRef createFileIfNecessary:createFile]) + return NO; + + if (FSGetCatalogInfo( &fsRef, + kFSCatInfoNone, + NULL, + NULL, + fsSpec, + NULL ) != noErr) { + // printf( "** Couldn't get an FSSpec for the file.\n" ); + return NO; + } + + return YES; +} + +@end diff --git a/Plugins/BuiltInFunctions/Images/LocalAccountLarge.tiff b/Plugins/BuiltInFunctions/Images/LocalAccountLarge.tiff Binary files differnew file mode 100644 index 0000000..823d17a --- /dev/null +++ b/Plugins/BuiltInFunctions/Images/LocalAccountLarge.tiff diff --git a/Plugins/BuiltInFunctions/Images/Network (Large).tiff b/Plugins/BuiltInFunctions/Images/Network (Large).tiff Binary files differnew file mode 100644 index 0000000..2fe42dc --- /dev/null +++ b/Plugins/BuiltInFunctions/Images/Network (Large).tiff diff --git a/Plugins/BuiltInFunctions/Images/Network (Small).tiff b/Plugins/BuiltInFunctions/Images/Network (Small).tiff Binary files differnew file mode 100644 index 0000000..09601e4 --- /dev/null +++ b/Plugins/BuiltInFunctions/Images/Network (Small).tiff diff --git a/Plugins/BuiltInFunctions/Images/NotThere.icns b/Plugins/BuiltInFunctions/Images/NotThere.icns Binary files differnew file mode 100644 index 0000000..77869e3 --- /dev/null +++ b/Plugins/BuiltInFunctions/Images/NotThere.icns diff --git a/Plugins/BuiltInFunctions/Images/local.tiff b/Plugins/BuiltInFunctions/Images/local.tiff Binary files differnew file mode 100644 index 0000000..6f3ecd6 --- /dev/null +++ b/Plugins/BuiltInFunctions/Images/local.tiff diff --git a/Plugins/BuiltInFunctions/Info.plist b/Plugins/BuiltInFunctions/Info.plist new file mode 100644 index 0000000..d8e9aef --- /dev/null +++ b/Plugins/BuiltInFunctions/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>Built In Functions</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.kublai.Liaison.BuiltInFunctions</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>0.4</string> + <key>NSPrincipalClass</key> + <string>LiBuiltInFunctions</string> +</dict> +</plist> diff --git a/Plugins/BuiltInFunctions/InspectorViewController.h b/Plugins/BuiltInFunctions/InspectorViewController.h new file mode 100644 index 0000000..bba68ef --- /dev/null +++ b/Plugins/BuiltInFunctions/InspectorViewController.h @@ -0,0 +1,52 @@ +// +// InspectorViewController.h +// Liaison +// +// Created by Brian Cully on Wed May 21 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +@interface LiFileHandle (LiLocationStuff) +- (NSString *)location; +@end + +@interface InspectorViewController : NSObject +{ + IBOutlet NSView *theFileTabView; + IBOutlet NSView *theHFSTabView; + + IBOutlet NSTextField *theFilenameField; + IBOutlet NSTextField *theTypeField; + IBOutlet NSPopUpButton *theApplicationButton; + + IBOutlet NSImageView *iconView; + IBOutlet NSTextField *pathField; + IBOutlet NSTextField *hfsTypeField; + IBOutlet NSTextField *hfsCreatorField; + + LiFileHandle *theFile; +} +- (IBAction)setIcon:(id)sender; +- (IBAction)setFilename:(id)sender; +- (IBAction)setType:(id)sender; +- (IBAction)setApplication:(id)sender; +- (IBAction)setHFSTypeField:(id)sender; +- (IBAction)setHFSCreatorField:(id)sender; +@property (retain) NSPopUpButton *theApplicationButton; +@property (retain) NSImageView *iconView; +@property (retain) NSTextField *hfsCreatorField; +@property (retain,getter=hfsView) NSView *theHFSTabView; +@property (retain) NSTextField *theTypeField; +@property (retain,getter=fileView) NSView *theFileTabView; +@property (retain,getter=file) LiFileHandle *theFile; +@property (retain) NSTextField *pathField; +@property (retain) NSTextField *theFilenameField; +@property (retain) NSTextField *hfsTypeField; +@end + +@interface InspectorViewController (Accessors) +- (NSView *)fileView; +- (NSView *)hfsView; +- (LiFileHandle *)file; +- (void)setFile: (LiFileHandle *)aFile; +@end diff --git a/Plugins/BuiltInFunctions/InspectorViewController.m b/Plugins/BuiltInFunctions/InspectorViewController.m new file mode 100644 index 0000000..54d0d4e --- /dev/null +++ b/Plugins/BuiltInFunctions/InspectorViewController.m @@ -0,0 +1,193 @@ +// +// InspectorViewController.m +// Liaison +// +// Created by Brian Cully on Wed May 21 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +#import "InspectorViewController.h" + +#import "BDAlias.h" +#import "LiBuiltInFunctions.h" + +static NSString * +myLocalizedString(NSString *aString) +{ + return NSLocalizedStringFromTableInBundle(aString, @"BuiltInFunctions", + [LiBuiltInFunctions bundle], @""); +} + +@implementation LiFileHandle (LiLocationStuff) +- (NSString *)location +{ + NSData *aliasData; + NSString *location; + + aliasData = [self valueForAttribute: LiAliasDataAttribute]; + if (aliasData != nil) { + BDAlias *alias; + + alias = [[BDAlias alloc] initWithData: aliasData]; + if (alias != nil) + location = [alias fullPath]; + else + location = myLocalizedString(@"UnableToResolveAlias"); + } else { + location = [[self url] absoluteString]; + } + + return location; +} +@end + +@implementation InspectorViewController +- (IBAction)setIcon:(id)sender +{ + [[sender cell] setHighlighted: NO]; +} + +- (IBAction)setFilename:(id)sender +{ + NSString *filename; + + filename = [theFilenameField stringValue]; + if ([filename compare: [[self file] filename]]) { + [[self file] setFilename: filename]; + } +} + +- (IBAction)setType:(id)sender +{ + NSString *type; + + type = [theTypeField stringValue]; + if ([type compare: [[self file] type]]) { + [[self file] setType: type]; + } +} + +- (IBAction)setApplication:(id)sender +{ + [LiLog logAsDebug: @"[InspectorViewController setApplication:]"]; +} + +- (IBAction)setHFSTypeField:(id)sender +{ + NSNumber *hfsType; + + hfsType = [hfsTypeField objectValue]; + if ([hfsType compare: [[self file] hfsType]]) { + [[self file] setHFSType: hfsType]; + } +} + +- (IBAction)setHFSCreatorField:(id)sender +{ + NSNumber *hfsCreator; + + hfsCreator = [hfsCreatorField objectValue]; + if ([hfsCreator compare: [[self file] hfsCreator]]) { + [[self file] setHFSCreator: hfsCreator]; + } +} +@synthesize hfsTypeField; +@synthesize theFileTabView; +@synthesize theTypeField; +@synthesize theHFSTabView; +@synthesize hfsCreatorField; +@synthesize iconView; +@synthesize theApplicationButton; +@synthesize theFilenameField; +@synthesize pathField; +@synthesize theFile; +@end + +@implementation InspectorViewController (Accessors) +- (NSView *)fileView +{ + return theFileTabView; +} + +- (NSView *)hfsView +{ + return theHFSTabView; +} + +- (LiFileHandle *)file +{ + return theFile; +} + +- (void)initHFSFields +{ + [hfsCreatorField setObjectValue: [[self file] hfsCreator]]; + [hfsTypeField setObjectValue: [[self file] hfsType]]; +} + +- (void)setFile: (LiFileHandle *)aFile +{ + NSImage *icon; + NSMutableArray *applications; + NSString *filename, *type, *location; + NSSize iconSize; + + [aFile retain]; + [theFile release]; + theFile = aFile; + + icon = [theFile icon]; + iconSize = [iconView bounds].size; + iconSize.width -= 16.0; + iconSize.height -= 16.0; + [icon setSize: iconSize]; + [iconView setImage: icon]; + + if ([theFile isEditable]) { + [theFilenameField setEnabled: YES]; + [theTypeField setEnabled: YES]; + [theApplicationButton setEnabled: YES]; + [iconView setEditable: YES]; + [hfsCreatorField setEditable: YES]; + [hfsTypeField setEditable: YES]; + } else { + [theFilenameField setEnabled: NO]; + [theTypeField setEnabled: NO]; + [theApplicationButton setEnabled: NO]; + [iconView setEditable: NO]; + [hfsCreatorField setEditable: NO]; + [hfsTypeField setEditable: NO]; + } + + filename = [theFile filename]; + if (filename != nil) + [theFilenameField setStringValue: filename]; + else + [theFilenameField setStringValue: @""]; + + type = [theFile type]; + if (type != nil) + [theTypeField setStringValue: type]; + else + [theTypeField setStringValue: @""]; + + location = [aFile location]; + if (location != nil) + [pathField setStringValue: location]; + else + [pathField setStringValue: @"Couldn't locate file."]; + + + applications = [NSMutableArray array]; + if ([theFile application] != nil) + [applications addObject: [[theFile application] lastPathComponent]]; + + [theApplicationButton removeAllItems]; + if ([applications count] > 0) + [theApplicationButton addItemsWithTitles: applications]; + else + [theApplicationButton addItemWithTitle: @"None"]; + + [self initHFSFields]; +} +@end diff --git a/Plugins/BuiltInFunctions/LiBuiltInFunctions.h b/Plugins/BuiltInFunctions/LiBuiltInFunctions.h new file mode 100644 index 0000000..b3bc479 --- /dev/null +++ b/Plugins/BuiltInFunctions/LiBuiltInFunctions.h @@ -0,0 +1,41 @@ +// +// LiBuiltInFunctions.h +// Liaison +// +// Created by Brian Cully on Tue May 13 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +#import "BDAlias.h" + +#define LiAliasDataAttribute @"LiAliasAttribute" + +@class InspectorViewController; + +@interface LiBuiltInFunctions : NSObject +<LiBrowserPlugin, LiInspectorPlugin, LiFileStorePlugin, LiFileStoreDelegate> +{ + IBOutlet InspectorViewController *theController; + LiFileStore *theFileStore; + + NSMutableDictionary *theDefaultAttributes; +} +@property (retain) InspectorViewController *theController; +@property (retain,getter=fileStore) LiFileStore *theFileStore; +@property (retain,getter=defaultAttributes) NSMutableDictionary *theDefaultAttributes; +@end + +@interface LiBuiltInFunctions (Accessors) +- (void)setFileStore: (LiFileStore *)aFileStore; +- (InspectorViewController *)viewController; +- (NSMutableDictionary *)defaultAttributes; +- (void)setDefaultAttributes: (NSMutableDictionary *)someAttributes; +@end + +@interface LiFileHandle (LiBuiltInFunctions) +- (NSImage *)icon; +- (NSString *)path; +- (NSString *)directory; +- (BDAlias *)alias; +- (void)setAlias: (BDAlias *)anAlias; +@end
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/LiBuiltInFunctions.m b/Plugins/BuiltInFunctions/LiBuiltInFunctions.m new file mode 100644 index 0000000..a7c3fed --- /dev/null +++ b/Plugins/BuiltInFunctions/LiBuiltInFunctions.m @@ -0,0 +1,1027 @@ +// +// LiBuiltInFunctions.m +// Liaison +// +// Created by Brian Cully on Tue May 13 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +#import "LiBuiltInFunctions.h" + +#import "FileSizeFormatter.h" +#import "InspectorViewController.h" +#import "NaturalDateFormatter.h" + +#import "IconFamily.h" + +static NSString * +myLocalizedString(NSString *aString) +{ + return NSLocalizedStringFromTableInBundle(aString, @"BuiltInFunctions", + [LiBuiltInFunctions bundle], @""); +} + +static NSString * +myLocalizedErrorString(NSString *aString) +{ + return NSLocalizedStringFromTableInBundle(aString, @"ErrorMessages", + [LiBuiltInFunctions bundle], @""); +} + +@implementation LiBuiltInFunctions +static NSBundle *theBundle = nil; + ++ (NSBundle *)bundle +{ + return theBundle; +} + ++ (void)setBundle: (NSBundle *)aBundle +{ + [aBundle retain]; + [theBundle release]; + theBundle = aBundle; +} + +- (void)convertGroupDict: (NSDictionary *)someGroups +{ + NSArray *groupNames; + NSMutableDictionary *defaultGroups; + NSMutableSet *myGroups; + NSString *libraryName; + + libraryName = [someGroups objectForKey: @"name"]; + groupNames = [someGroups objectForKey: @"children"]; + + myGroups = [NSMutableSet setWithArray: groupNames]; + + if (libraryName != nil) + [[self fileStore] setName: libraryName]; + + defaultGroups = [NSMutableDictionary dictionaryWithObject: myGroups forKey: LiGroupsAttribute]; + [self setDefaultAttributes: defaultGroups]; +} + +- (void)loadDefaultAttrs +{ + NSDictionary *defaultAttrDict; + + defaultAttrDict = [NSDictionary dictionaryWithContentsOfFile: [[Preferences sharedPreferences] groupPath]]; + if (defaultAttrDict != nil) { + NSNumber *versionNumber; + + versionNumber = [defaultAttrDict objectForKey: @"LiDBVersion"]; + if ([versionNumber intValue] == 1) { + NSDictionary *flattenedDefaults; + NSEnumerator *defaultEnum; + NSMutableDictionary *myDefaults; + NSString *attr; + + [LiLog logAsDebug: @"Load my version group dict"]; + myDefaults = [NSMutableDictionary dictionary]; + flattenedDefaults = [defaultAttrDict objectForKey: @"LiDefaultAttributes"]; + defaultEnum = [flattenedDefaults keyEnumerator]; + while ((attr = [defaultEnum nextObject]) != nil) { + NSMutableSet *values; + + values = [NSMutableSet setWithArray: [flattenedDefaults objectForKey: attr]]; + [myDefaults setObject: values forKey: attr]; + } + [self setDefaultAttributes: myDefaults]; + } else { + [self convertGroupDict: defaultAttrDict]; + } + } +} + +- (BOOL)synchronizeDefaultAttrs +{ + NSDictionary *defaultDict; + NSEnumerator *defaultEnum; + NSMutableDictionary *flattenedDefaults; + NSString *attr; + + flattenedDefaults = [NSMutableDictionary dictionary]; + defaultEnum = [[self defaultAttributes] keyEnumerator]; + while ((attr = [defaultEnum nextObject]) != nil) { + NSArray *values; + + values = [[[self defaultAttributes] objectForKey: attr] allObjects]; + [flattenedDefaults setObject: values forKey: attr]; + } + + defaultDict = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: [NSNumber numberWithInt: 1], flattenedDefaults, nil] + forKeys: + [NSArray arrayWithObjects: @"LiDBVersion", @"LiDefaultAttributes", nil]]; + + return [defaultDict writeToFile: [[Preferences sharedPreferences] groupPath] atomically: YES]; +} + +- (id)init +{ + NSImage *image; + NSString *iconPath; + + self = [super init]; + + [self loadDefaultAttrs]; + + // Register often-used images. + iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"NotThere" ofType: @"icns"]; + image = [[NSImage alloc] initWithContentsOfFile: iconPath]; + [image setName: @"LiBuiltInFunctions NotThereImage"]; + + iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"local" ofType: @"tiff"]; + image = [[NSImage alloc] initWithContentsOfFile: iconPath]; + [image setName: @"LiBuiltInFunctions FileStoreIcon"]; + + return self; +} + +- (void)dealloc +{ + NSImage *image; + + [self setDefaultAttributes: nil]; + + // XXX - should this be done this way? + image = [NSImage imageNamed: @"LiBuiltInFunctions NotThereImage"]; + [image setName: nil]; + [image release]; + image = [NSImage imageNamed: @"LiBuiltInFunctions FileStoreIcon"]; + [image setName: nil]; + [image release]; + + [super dealloc]; +} + +- (LiBrowserColumn *)columnForIcon +{ + LiBrowserColumn *col; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"icon"]; + [col setName: myLocalizedString(@"IconHeader")]; + [col setCell: [[[NSImageCell alloc] init] autorelease]]; + [col setWidth: [NSNumber numberWithFloat: 16.0]]; + [col setEditable: NO]; + [col setResizable: NO]; + [col setShowsHeader: NO]; + [col setGetMethod: @selector(icon)]; + + return col; +} + +- (LiBrowserColumn *)columnForFilename +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"filename"]; + [col setName: myLocalizedString(@"FilenameHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setEditable: YES]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(filename)]; + [col setSetMethod: @selector(setFilename:)]; + [col setCompareMethod: @selector(caseInsensitiveCompare:)]; + + return col; +} + +- (LiFilterDescription *)descriptionForFilename +{ + LiFilterDescription *description; + NSCell *cell; + NSDictionary *compareOps; + + compareOps = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: @"isEqualToString:", + @"containsString:", nil] + forKeys: + [NSArray arrayWithObjects: myLocalizedString(@"LiEqualsOperator"), + myLocalizedString(@"LiContainsOperator"), nil]]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setEditable: YES]; + description = [LiFilterDescription descriptionForMethod: @selector(filename) + name: myLocalizedString(LiFilenameAttribute) + compareOperators: compareOps + valueEditorCell: cell]; + + return description; +} + +- (LiBrowserColumn *)columnForType +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"type"]; + [col setName: myLocalizedString(@"TypeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setEditable: YES]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(type)]; + [col setSetMethod: @selector(setType:)]; + [col setCompareMethod: @selector(caseInsensitiveCompare:)]; + + return col; +} + +- (LiBrowserColumn *)columnForLastModified +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"lastModified"]; + [col setName: myLocalizedString(@"LastModifiedTimeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setFormatter: [[[NaturalDateFormatter alloc] initWithNaturalLanguage: YES] autorelease]]; + [cell setEditable: YES]; + [cell setAlignment: NSRightTextAlignment]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(lastModifiedTime)]; + [col setSetMethod: @selector(setLastModifiedTime:)]; + [col setCompareMethod: @selector(compare:)]; + + return col; +} + +- (LiBrowserColumn *)columnForCreation +{ + LiBrowserColumn *col; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"creation"]; + [col setName: myLocalizedString(@"CreatedTimeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + [cell setFormatter: [[[NaturalDateFormatter alloc] initWithNaturalLanguage: YES] autorelease]]; + [cell setEditable: YES]; + [cell setAlignment: NSRightTextAlignment]; + [col setCell: cell]; + [col setEditable: YES]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(creationTime)]; + [col setSetMethod: @selector(setCreationTime:)]; + [col setCompareMethod: @selector(compare:)]; + + return col; +} + +- (LiBrowserColumn *)columnForSize +{ + LiBrowserColumn *col; + FileSizeFormatter *cellFormatter; + NSCell *cell; + + col = [[[LiBrowserColumn alloc] init] autorelease]; + [col setIdentifier: @"size"]; + [col setName: myLocalizedString(@"FileSizeHeader")]; + cell = [[[NSTextFieldCell alloc] init] autorelease]; + cellFormatter = [[[FileSizeFormatter alloc] init] autorelease]; + [cellFormatter setAllowsFloats: NO]; + [cell setFormatter: cellFormatter]; + [cell setAlignment: NSRightTextAlignment]; + [col setCell: cell]; + [col setEditable: NO]; + [col setShowsHeader: YES]; + [col setGetMethod: @selector(fileSize)]; + [col setCompareMethod: @selector(compare:)]; + + return col; +} + +- (NSArray *)columns +{ + NSArray *columns; + + columns = [NSArray arrayWithObjects: + [self columnForIcon], [self columnForFilename], [self columnForType], + [self columnForLastModified], [self columnForCreation], + [self columnForSize], nil]; + + return columns; +} + +- (NSDictionary *)filterDescriptions +{ + NSDictionary *descriptions; + + descriptions = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: [self descriptionForFilename], nil] + forKeys: + [NSArray arrayWithObjects: LiFilenameAttribute, nil]]; + + return descriptions; +} + +- (LiInspectorView *)viewForFile +{ + LiInspectorView *view; + + view = [[[LiInspectorView alloc] init] autorelease]; + [view setIdentifier: @"file"]; + [view setName: @"File"]; + [view setImage: nil]; + [view setView: [[self viewController] fileView]]; + [view setIsVerticallyResizable: NO]; + [view setIsHorizontallyResizable: YES]; + [view setViewSize: [[view view] frame].size]; + + return view; +} + +- (LiInspectorView *)viewForHFS +{ + LiInspectorView *view; + + view = [[[LiInspectorView alloc] init] autorelease]; + [view setIdentifier: @"hfs"]; + [view setName: @"HFS"]; + [view setImage: nil]; + [view setIsVerticallyResizable: NO]; + [view setIsHorizontallyResizable: NO]; + [view setView: [[self viewController] hfsView]]; + [view setViewSize: [[view view] frame].size]; + + return view; +} + +- (NSArray *)allInspectorViews +{ + return [NSArray arrayWithObjects: [self viewForFile], [self viewForHFS], nil]; +} + +- (NSArray *)inspectorViewsForFile: (LiFileHandle *)aFile +{ + if (aFile != nil) { + NSMutableArray *viewArray; + + viewArray = [NSMutableArray arrayWithObject: [self viewForFile]]; + [viewArray addObject: [self viewForHFS]]; + return viewArray; + } + return nil; +} + +- (void)setFile: (LiFileHandle *)aFile +{ + if (aFile != nil) { + [[self viewController] setFile: aFile]; + } +} + +// +// File store delegate stuff. +// +- (void)openFileHandle: (LiFileHandle *)aFileHandle +{ + NSString *path; + + path = [aFileHandle path]; + if (path != nil) { + [[NSWorkspace sharedWorkspace] openFile: [aFileHandle path]]; + [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: [NSURL fileURLWithPath: [aFileHandle path]]]; + } else { + [LiLog alertWithHeader: @"Couldn't locate file" contents: @"This message sucks and will be changed so you can locate the file again."]; + } +} + +- (void)copyFile: (LiFileHandle *)aFileHandle +{ + [LiLog logAsDebug: @"should copy %@", [aFileHandle filename]]; +} + +- (NSDictionary *)fileSystemAttributesForPath: (NSString *)aPath +{ + NSMutableDictionary *tmpAttributes; + + tmpAttributes = nil; + if (aPath != nil) { + BDAlias *alias; + NSString *filename, *filetype, *dir; + + // Set the attributes that are valid for every file with a path. + tmpAttributes = [NSMutableDictionary dictionary]; + filename = [[aPath lastPathComponent] stringByDeletingPathExtension]; + filetype = [aPath pathExtension]; + dir = [aPath stringByDeletingLastPathComponent]; + [tmpAttributes setObject: filename forKey: LiFilenameAttribute]; + [tmpAttributes setObject: filetype forKey: LiTypeAttribute]; + [tmpAttributes setObject: dir forKey: LiDirectoryAttribute]; + + // Test if the file is resolvable by getting its alias. + alias = [BDAlias aliasWithPath: aPath]; + if (alias != nil) { + NSDate *modifiedTime, *createdTime; + NSDictionary *fileAttrs; + NSFileWrapper *file; + NSNumber *fileSize, *hfsCreator, *hfsType; + NSString *application; + + [tmpAttributes setObject: [alias aliasData] + forKey: LiAliasDataAttribute]; + + file = [[NSFileWrapper alloc] initWithPath: aPath]; + fileAttrs = [[NSFileManager defaultManager] fileAttributesAtPath: aPath traverseLink: YES]; + + // Load attributes from disk. + modifiedTime = [fileAttrs objectForKey: NSFileModificationDate]; + createdTime = [fileAttrs objectForKey: NSFileCreationDate]; + fileSize = [fileAttrs objectForKey: NSFileSize]; + hfsCreator = [fileAttrs objectForKey: NSFileHFSCreatorCode]; + hfsType = [fileAttrs objectForKey: NSFileHFSTypeCode]; + [[NSWorkspace sharedWorkspace] getInfoForFile: aPath + application: &application + type: &filetype]; + if (modifiedTime != nil) + [tmpAttributes setObject: modifiedTime + forKey: LiLastModifiedDateAttribute]; + if (createdTime != nil) + [tmpAttributes setObject: createdTime + forKey: LiCreationDateAttribute]; + if (fileSize != nil) + [tmpAttributes setObject: fileSize + forKey: LiFileSizeAttribute]; + if (application != nil) + [tmpAttributes setObject: application + forKey: LiApplicationAttribute]; + if (hfsCreator != nil) + [tmpAttributes setObject: hfsCreator + forKey: LiHFSCreatorAttribute]; + if (hfsType != nil) + [tmpAttributes setObject: hfsType + forKey: LiHFSTypeAttribute]; + [tmpAttributes setObject: [NSNumber numberWithBool: YES] + forKey: LiIsEditableAttribute]; + + [file release]; + } else { + [tmpAttributes setObject: [NSNumber numberWithBool: NO] + forKey: LiIsEditableAttribute]; + } + } + + return tmpAttributes; +} + +- (NSDictionary *)fileSystemAttributesForAliasData: (NSData *)aliasData +{ + BDAlias *alias; + + alias = [BDAlias aliasWithData: aliasData]; + return [self fileSystemAttributesForPath: [alias fullPath]]; +} + +- (void)convertFirstVersionDict: (NSDictionary *)fileDict + fileStore: (LiFileStore *)aFileStore +{ + NSDictionary *filesInDict, *attrDict; + NSEnumerator *fileEnum; + + filesInDict = [fileDict objectForKey: @"files"]; + fileEnum = [filesInDict objectEnumerator]; + while ((attrDict = [fileEnum nextObject]) != nil) { + NSData *fileAlias; + NSDictionary *fileAttrs; + NSEnumerator *groupEnum; + NSMutableArray *fileGroups; + NSMutableDictionary *myFileAttrs; + NSNumber *fileHandle; + NSString *groupname; + + fileHandle = [attrDict objectForKey: @"filehandle"]; + fileAlias = [attrDict objectForKey: @"alias"]; + + fileAttrs = [self fileSystemAttributesForAliasData: + fileAlias]; + if (fileAttrs == nil) { + [LiLog logAsWarning: @"Couldn't load attributes for %@: abandoning.", + [attrDict objectForKey: @"path"]]; + } + myFileAttrs = [NSMutableDictionary dictionaryWithDictionary: fileAttrs]; + [myFileAttrs setObject: fileHandle forKey: LiFileHandleAttribute]; + + fileGroups = [NSMutableArray array]; + groupEnum = [[attrDict objectForKey: @"groups"] objectEnumerator]; + while ((groupname = [groupEnum nextObject]) != nil) { + if ([groupname isEqualToString: @"/"] == NO) + [fileGroups addObject: groupname]; + } + [myFileAttrs setObject: fileGroups forKey: LiGroupsAttribute]; + + [aFileStore addFileWithAttributes: myFileAttrs]; + } +} + +- (BOOL)loadFileStore: (LiFileStore *)aFileStore +{ + NSDictionary *fileStoreDict; + + // Make sure we have the right indexes. + [aFileStore addIndexForAttribute: LiGroupsAttribute]; + [aFileStore addIndexForAttribute: LiAliasDataAttribute]; + + fileStoreDict = [NSDictionary dictionaryWithContentsOfFile: [[Preferences sharedPreferences] libraryPath]]; + if (fileStoreDict != nil) { + NSNumber *versionNumber; + + versionNumber = [fileStoreDict objectForKey: @"LiDBVersion"]; + if ([versionNumber intValue] == 1) { + NSArray *allFiles; + NSDictionary *fileDict; + + allFiles = [fileStoreDict objectForKey: @"LiFileStore"]; + for (fileDict in allFiles) { + BDAlias *alias; + NSMutableDictionary *baseAttrs; + + baseAttrs = [[NSMutableDictionary alloc] initWithDictionary: fileDict]; + + alias = [[BDAlias alloc] initWithData: [fileDict objectForKey: LiAliasDataAttribute]]; + if ([alias fullPath] == nil) { + NSString *path, *filename, *directory; + + directory = [fileDict objectForKey: LiDirectoryAttribute]; + filename = [[fileDict objectForKey: LiFilenameAttribute] stringByAppendingPathExtension: [fileDict objectForKey: LiTypeAttribute]]; + path = [directory stringByAppendingPathComponent: filename]; + + [LiLog logAsDebug: @"Couldn't locate file: %@ - (dir: %@, path: %@)", filename, directory, path]; + + alias = [[BDAlias alloc] initWithPath: path]; + if ([alias fullPath] != nil) { + [baseAttrs setObject: [[alias fullPath] stringByDeletingLastPathComponent] forKey: LiDirectoryAttribute]; + [baseAttrs setObject: [alias aliasData] forKey: LiAliasDataAttribute]; + } + } + + if ([alias aliasData] == nil) { + [baseAttrs setObject: [NSNumber numberWithBool: NO] forKey: LiIsEditableAttribute]; + } else { + [baseAttrs setObject: [NSNumber numberWithBool: YES] forKey: LiIsEditableAttribute]; + } + + [aFileStore addFileWithAttributes: baseAttrs]; + + [baseAttrs release]; + [alias release]; + } + } else { + [self convertFirstVersionDict: fileStoreDict + fileStore: aFileStore]; + } + } + + [aFileStore synchronize]; + return YES; +} + +- (BOOL)synchronizeFileStore +{ + LiFileHandle *fileHandle; + NSArray *allFileHandles; + NSMutableArray *allFiles; + NSDictionary *fileDict; + NSString *path; + + [LiLog logAsDebug: @"[LiBuiltInFunctions synchronizeFileStore]"]; + [LiLog indentDebugLog]; + + path = [[Preferences sharedPreferences] libraryPath]; + + allFiles = [NSMutableArray array]; + allFileHandles = [[self fileStore] allFileHandles]; + for (fileHandle in allFileHandles) { + NSMutableDictionary *filteredAttrs; + + filteredAttrs = [NSMutableDictionary dictionaryWithDictionary: + [fileHandle dictionary]]; + [allFiles addObject: filteredAttrs]; + } + + fileDict = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: + [NSNumber numberWithInt: 1], allFiles, nil] + forKeys: + [NSArray arrayWithObjects: + @"LiDBVersion", @"LiFileStore", nil]]; + [LiLog logAsDebug: @"writing to: %@", path]; + [fileDict writeToFile: path atomically: YES]; + [LiLog logAsDebug: @"done!"]; + + [LiLog unindentDebugLog]; + return YES; +} + +- (void)synchronizeFileHandle: (LiFileHandle *)aFileHandle + withNewAttributes: (NSMutableDictionary *)someAttributes +{ + NSDictionary *fileAttrDict; + NSEnumerator *attrEnum; + NSMutableDictionary *fileAttrs; + NSSet *pathSet; + NSString *attr; + BOOL pathDone; + + [LiLog logAsDebug: @"[LiBuiltInFunctions synchronizeFileHandle: (fh) withNewAttributes: %@]", someAttributes]; + [LiLog indentDebugLog]; + + pathDone = NO; + pathSet = [NSSet setWithArray: + [NSArray arrayWithObjects: + LiDirectoryAttribute, LiFilenameAttribute, LiTypeAttribute, nil]]; + fileAttrDict = [NSDictionary dictionaryWithObjects: + [NSArray arrayWithObjects: + NSFileModificationDate, NSFileCreationDate, + NSFileHFSCreatorCode, NSFileHFSTypeCode, + nil] + forKeys: + [NSArray arrayWithObjects: + LiLastModifiedDateAttribute, LiCreationDateAttribute, + LiHFSCreatorAttribute, LiHFSTypeAttribute, + nil]]; + + fileAttrs = [NSMutableDictionary dictionary]; + attrEnum = [someAttributes keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + if (pathDone == NO && [pathSet containsObject: attr]) { + NSString *filename, *type; + NSString *path, *oldPath; + + filename = [someAttributes objectForKey: LiFilenameAttribute]; + if (filename == nil) + filename = [aFileHandle filename]; + + type = [someAttributes objectForKey: LiTypeAttribute]; + if (type == nil) + type = [aFileHandle type]; + + path = [someAttributes objectForKey: LiDirectoryAttribute]; + if (path == nil) + path = [aFileHandle directory]; + + if (type && [type length] > 0) { + filename = [filename stringByAppendingPathExtension: type]; + } + path = [path stringByAppendingPathComponent: filename]; + + oldPath = [[aFileHandle alias] fullPath]; + if ([oldPath isEqualToString: path] == NO) { + int rc; + + rc = 0; + rc = rename([oldPath UTF8String], [path UTF8String]); + if (rc == -1) { + NSString *header, *contents; + + switch (errno) { + case ENOENT: + header = myLocalizedErrorString(@"LiBadFilenameErrorHeader"); + contents = myLocalizedErrorString(@"LiBadFilenameErrorContents"); + break; + + case EROFS: + header = myLocalizedErrorString(@"LiReadOnlyFileSytemErrorHeader"); + contents = myLocalizedErrorString(@"LiReadOnlyFileSytemErrorContents"); + break; + + case EPERM: + case EACCES: + header = myLocalizedErrorString(@"LiPermissionDeniedErrorHeader"); + contents = myLocalizedErrorString(@"LiPermissionDeniedErrorContents"); + break; + + default: + header = myLocalizedErrorString(@"LiGenericRenameErrorHeader"); + contents = myLocalizedErrorString(@"LiGenericRenameErrorContents"); + } + [LiLog alertWithHeader: header contents: contents]; + } + } + + pathDone = YES; + } else if ([fileAttrDict objectForKey: attr] != nil) { + [fileAttrs setObject: [someAttributes objectForKey: attr] + forKey: attr]; + } + } + + if ([fileAttrs count] > 0) { + NSFileManager *defaultManager; + + defaultManager = [NSFileManager defaultManager]; + [defaultManager changeFileAttributes: fileAttrs + atPath: [[aFileHandle alias] fullPath]]; + } + + // XXX - should flag to see if the icon needs updating and + // do it here, since we can't scan for that change. + + [LiLog unindentDebugLog]; +} + +- (BOOL)shouldUpdateFileHandle: (LiFileHandle *)aFileHandle +{ + NSDate *handleDate, *fileDate; + NSFileWrapper *file; + NSString *newPath; + + newPath = [[aFileHandle alias] fullPath]; + if ([newPath compare: [aFileHandle path]] != 0) + return YES; + + file = [[[NSFileWrapper alloc] initWithPath: newPath] autorelease]; + fileDate = [[file fileAttributes] objectForKey: + NSFileModificationDate]; + handleDate = [aFileHandle lastModifiedTime]; + + if ([fileDate compare: handleDate] == 0) + return NO; + else + return YES; +} + +- (void)updateFileHandle: (LiFileHandle *)aFileHandle +{ + NSMutableDictionary *fileAttrs; + + [LiLog logAsDebug: @"[LiBuiltInFunctions updateFileHandle: %@]", [aFileHandle description]]; + fileAttrs = [NSMutableDictionary dictionaryWithDictionary: + [self fileSystemAttributesForAliasData: + [aFileHandle valueForAttribute: LiAliasDataAttribute]]]; + [LiLog logAsDebug: @"fileAttrs: %@", [fileAttrs description]]; + + // Attempt path resolution if alias resolution fails. + if ([fileAttrs count] == 0) { + NSString *filePath, *filename; + + filename = [[aFileHandle filename] stringByAppendingPathExtension: [aFileHandle type]]; + filePath = [[aFileHandle directory] stringByAppendingPathComponent: filename]; + [LiLog logAsDebug: @"Attempting to resolve path %@ to alias", filePath]; + fileAttrs = [NSMutableDictionary dictionaryWithDictionary: + [self fileSystemAttributesForPath: filePath]]; + [LiLog logAsDebug: @"\tresolved to: %@", fileAttrs]; + } + + if (fileAttrs != nil) { + NSDictionary *myAttrs; + NSEnumerator *keyEnum; + NSString *key; + + myAttrs = [[aFileHandle fileStore] attributesForFileHandle: + aFileHandle]; + keyEnum = [fileAttrs keyEnumerator]; + while ((key = [keyEnum nextObject]) != nil) { + id myValue; + + myValue = [myAttrs objectForKey: key]; + if (myValue != nil) { + id value; + + value = [fileAttrs objectForKey: key]; + if (myValue == value) { + [fileAttrs removeObjectForKey: key]; + } else { + if ([myValue respondsToSelector: @selector(compare:)]) { + if ([myValue performSelector: @selector(compare:) withObject: value] == 0) { + [fileAttrs removeObjectForKey: key]; + } + } else { + // XXX + // Disabled because the icon keeps changing + // on every check. + [fileAttrs removeObjectForKey: key]; + } + } + } + } + + if ([fileAttrs count] > 0) { + [LiLog logAsDebug: @"fileAttrs: %@", [fileAttrs description]]; + [[aFileHandle fileStore] updateFileHandle: aFileHandle + withAttributes: fileAttrs]; + } + } +} + +- (LiFileHandle *)addURL: (NSURL *)anURL + toFileStore: (LiFileStore *)aFileStore +{ + if ([anURL isFileURL] == YES) { + BDAlias *alias; + NSArray *existingFiles; + NSDictionary *fileAttrs; + + // Attempt resolution of the file handle to determine uniqueness. + // If it's not there, it's automatically unique. + alias = [BDAlias aliasWithPath: [anURL path]]; + if (alias != nil) { + LiFilter *filter; + + filter = [LiFilter filterWithAttribute: LiAliasDataAttribute + compareSelector: @selector(isEqual:) + value: [alias aliasData]]; + + existingFiles = [[self fileStore] filesMatchingFilter: filter]; + if ([existingFiles count] > 0) { + return [existingFiles objectAtIndex: 0]; + } + } + + fileAttrs = [self fileSystemAttributesForPath: [anURL path]]; + return [[self fileStore] addFileWithAttributes: fileAttrs]; + } + return nil; +} + +- (NSURL *)urlForFileHandle: (LiFileHandle *)aFileHandle +{ + NSString *path; + NSURL *url; + + url = nil; + path = [aFileHandle path]; + if (path != nil) + url = [NSURL fileURLWithPath: path]; + return url; +} + +- (NSArray *)defaultValuesForAttribute: (NSString *)anAttribute +{ + NSMutableSet *values; + + values = [[self defaultAttributes] objectForKey: anAttribute]; + return [values allObjects]; +} + +- (BOOL)addDefaultAttribute: (NSDictionary *)anAttribute toFileStore: (LiFileStore *)aFileStore +{ + NSEnumerator *attrEnum; + NSMutableDictionary *defaultAttrs; + NSMutableSet *values; + NSString *attr; + + [LiLog logAsDebug: @"[LiBuiltInFunctions addDefaultAttribute: %@ toFileStore: %@]", anAttribute, aFileStore]; + [LiLog indentDebugLog]; + defaultAttrs = [self defaultAttributes]; + attrEnum = [anAttribute keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + values = [defaultAttrs objectForKey: attr]; + if (values == nil) { + values = [NSMutableSet set]; + [defaultAttrs setObject: values forKey: attr]; + } + [values addObject: [anAttribute objectForKey: attr]]; + } + + [LiLog unindentDebugLog]; + + return [self synchronizeDefaultAttrs]; +} + +- (BOOL)changeDefaultValueForAttribute: (NSDictionary *)anAttribute toValue: (id)aValue inFileStore: (LiFileStore *)aFileStore +{ + NSEnumerator *attrEnum; + NSMutableDictionary *defaultAttrs; + NSMutableSet *values; + NSString *attr; + + defaultAttrs = [self defaultAttributes]; + attrEnum = [anAttribute keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + values = [defaultAttrs objectForKey: attr]; + if (values == nil) { + return NO; + } + [values removeObject: [anAttribute objectForKey: attr]]; + [values addObject: aValue]; + } + + return [self synchronizeDefaultAttrs]; +} + +- (BOOL)removeDefaultAttribute: (NSDictionary *)anAttribute fromFileStore: (LiFileStore *)aFileStore +{ + NSEnumerator *attrEnum; + NSMutableDictionary *defaultAttrs; + NSMutableSet *values; + NSString *attr; + + defaultAttrs = [self defaultAttributes]; + attrEnum = [anAttribute keyEnumerator]; + while ((attr = [attrEnum nextObject]) != nil) { + values = [defaultAttrs objectForKey: attr]; + [values removeObject: [anAttribute objectForKey: attr]]; + } + + return [self synchronizeDefaultAttrs]; +} + +- (void)initFileStore +{ + LiFileStore *tmpStore; + + tmpStore = [LiFileStore fileStoreWithName: myLocalizedString(@"LiLibraryName")]; + [tmpStore setEditable: YES]; + [tmpStore setIcon: [NSImage imageNamed: @"LiBuiltInFunctions FileStoreIcon"]]; + [tmpStore setDelegate: self]; + [self setFileStore: tmpStore]; + [self loadFileStore: [self fileStore]]; +} + +- (LiFileStore *)fileStore +{ + return theFileStore; +} +@synthesize theController; +@synthesize theDefaultAttributes; +@synthesize theFileStore; +@end + +@implementation LiBuiltInFunctions (Accessors) +- (void)setFileStore: (LiFileStore *)aFileStore +{ + [aFileStore retain]; + [theFileStore release]; + theFileStore = aFileStore; + + [theFileStore setDelegate: self]; +} + +- (InspectorViewController *)viewController +{ + if (theController == nil) { + if ([NSBundle loadNibNamed: @"InspectorViews.nib" owner: self] == NO) { + [LiLog logAsError: @"Couldn't open inspector view nib file."]; + return nil; + } + } + return theController; +} + +- (NSMutableDictionary *)defaultAttributes +{ + return theDefaultAttributes; +} + +- (void)setDefaultAttributes: (NSMutableDictionary *)someAttributes +{ + [someAttributes retain]; + [theDefaultAttributes release]; + theDefaultAttributes = someAttributes; +} +@end + +@implementation LiFileHandle (LiBuiltInFunctions) +- (NSImage *)icon +{ + NSImage *icon; + NSURL *myURL; + + myURL = [self url]; + if ([myURL isFileURL] == YES) + icon = [[NSWorkspace sharedWorkspace] iconForFile: [self path]]; + else if (myURL == nil) + icon = [NSImage imageNamed: @"LiBuiltInFunctions NotThereImage"]; + else + icon = [[NSWorkspace sharedWorkspace] iconForFileType: [self type]]; + return icon; +} + +- (BDAlias *)alias +{ + BDAlias *tmpAlias; + + tmpAlias = [BDAlias aliasWithData: + [self valueForAttribute: LiAliasDataAttribute]]; + + return tmpAlias; +} + +- (void)setAlias: (BDAlias *)anAlias +{ + [self setValue: [anAlias aliasData] + forAttribute: LiAliasDataAttribute]; +} + +- (NSString *)path +{ + return [[self alias] fullPath]; +} + +- (NSString *)directory +{ + return [self valueForAttribute: LiDirectoryAttribute]; +} +@end
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/LiImageView.h b/Plugins/BuiltInFunctions/LiImageView.h new file mode 100644 index 0000000..6a14bea --- /dev/null +++ b/Plugins/BuiltInFunctions/LiImageView.h @@ -0,0 +1,6 @@ +/* LiImageView */ + +@interface LiImageView : NSImageView +{ +} +@end diff --git a/Plugins/BuiltInFunctions/LiImageView.m b/Plugins/BuiltInFunctions/LiImageView.m new file mode 100644 index 0000000..57bc46f --- /dev/null +++ b/Plugins/BuiltInFunctions/LiImageView.m @@ -0,0 +1,59 @@ +#import "LiImageView.h" + +@implementation LiImageView +- (NSArray *)namesOfPromisedFilesDroppedAtDestination: (NSURL *)dropDestination +{ + NSFileManager *defaultManager; + NSString *imageDir, *path, *filename; + int suffix; + + [LiLog logAsDebug: @"[LiImageView names..Desitination: %@]", dropDestination]; + + imageDir = [dropDestination path]; + defaultManager = [NSFileManager defaultManager]; + for (suffix = 0; suffix < 100; suffix++) { + filename = [NSString stringWithFormat: @"LiaisonIcon%02d.tiff", suffix]; + path = [imageDir stringByAppendingPathComponent: filename]; + if ([defaultManager fileExistsAtPath: path] == NO) { + [LiLog logAsDebug: @"\tsaving to path: %@", path]; + break; + } + } + + if (suffix < 100) { + if ([defaultManager createFileAtPath: path + contents: [[self image] TIFFRepresentation] + attributes: nil] == NO) { + return nil; + } + } else + return nil; + + return [NSArray arrayWithObject: filename]; +} + +- (void)mouseDown: (NSEvent *)theEvent +{ + NSPoint dragPosition; + NSRect imageLocation; + + [[NSApp keyWindow] makeFirstResponder: self]; + + dragPosition = [self convertPoint: [theEvent locationInWindow] + fromView: nil]; + dragPosition.x -= 16; + dragPosition.y -= 16; + imageLocation.origin = dragPosition; + imageLocation.size = NSMakeSize(32,32); + [self dragPromisedFilesOfTypes: [NSArray arrayWithObject: @"tiff"] + fromRect: imageLocation source: self + slideBack: YES event: theEvent]; +} + +- (void)mouseDragged: (NSEvent *)anEvent +{ + [LiLog logAsDebug: @"[LiImageView mouseDragged]"]; + + [super mouseDragged: anEvent]; +} +@end diff --git a/Plugins/BuiltInFunctions/NaturalDateFormatter.h b/Plugins/BuiltInFunctions/NaturalDateFormatter.h new file mode 100644 index 0000000..76ac5ac --- /dev/null +++ b/Plugins/BuiltInFunctions/NaturalDateFormatter.h @@ -0,0 +1,11 @@ +// +// NaturalDateFormatter.h +// BuiltInFunctions +// +// Created by Brian Cully on Sun Aug 31 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +@interface NaturalDateFormatter : NSDateFormatter +- (id)initWithNaturalLanguage: (BOOL)flag; +@end diff --git a/Plugins/BuiltInFunctions/NaturalDateFormatter.m b/Plugins/BuiltInFunctions/NaturalDateFormatter.m new file mode 100644 index 0000000..da83ee6 --- /dev/null +++ b/Plugins/BuiltInFunctions/NaturalDateFormatter.m @@ -0,0 +1,58 @@ +// +// NaturalDateFormatter.m +// BuiltInFunctions +// +// Created by Brian Cully on Sun Aug 31 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// + +#import "NaturalDateFormatter.h" + +#import "LiBuiltInFunctions.h" + +static NSString * +myLocalizedString(NSString *aString) +{ + return NSLocalizedStringFromTableInBundle(aString, @"BuiltInFunctions", + [LiBuiltInFunctions bundle], @""); +} + +@implementation NaturalDateFormatter +- (id)initWithNaturalLanguage: (BOOL)flag +{ + NSString *format; + + format = [[NSUserDefaults standardUserDefaults] objectForKey: NSShortDateFormatString]; + + self = [super initWithDateFormat: format allowNaturalLanguage: flag]; + return self; +} + +- (NSString *)stringForObjectValue: (id)anObject +{ + NSString *stringValue; + + if ([anObject isKindOfClass: [NSDate class]]) { + NSCalendarDate *testDate; + int todayNum, myNum; + + testDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate: + [(NSDate *)anObject timeIntervalSinceReferenceDate]]; + myNum = [[NSCalendarDate calendarDate] dayOfCommonEra]; + todayNum = [testDate dayOfCommonEra]; + if (myNum == todayNum) + stringValue = myLocalizedString(@"Today"); + else if (todayNum == (myNum - 1)) + stringValue = myLocalizedString(@"Yesterday"); + else if (todayNum == (myNum + 1)) + stringValue = myLocalizedString(@"Tomorrow"); + else { + stringValue = [testDate descriptionWithCalendarFormat: + [self dateFormat]]; + } + } else + stringValue = [super stringForObjectValue: anObject]; + + return stringValue; +} +@end diff --git a/Plugins/BuiltInFunctions/chef.lproj/BuiltInFunctions.strings b/Plugins/BuiltInFunctions/chef.lproj/BuiltInFunctions.strings new file mode 100644 index 0000000..4881c4c --- /dev/null +++ b/Plugins/BuiltInFunctions/chef.lproj/BuiltInFunctions.strings @@ -0,0 +1,26 @@ +/* Headers for columns. */ +IconHeader = "Icun"; +FilenameHeader = "Feeleneme-a"; +TypeHeader = "Type-a"; +LastModifiedTimeHeader = "Lest Mudeeffied"; +CreatedTimeHeader = "Creeted"; +FileSizeHeader = "Seeze-a"; + +/* Error messages. */ +UnableToResolveAlias = "uneble-a tu resulfe-a eleees"; + +/* Default library name. */ +LiLibraryName = "My Leebrery"; + +/* Names for filters. */ +LiFilenameAttribute = "feeleneme-a"; +LiTypeAttribute = "type-a"; + +/* Names for operators. */ +LiEqualsOperator = "is"; +LiContainsOperator = "cunteeens"; + +/* For the natural language formatter. */ +Today = "Tudey"; +Yesterday = "Yesterdey"; +Tomorrow = "Tumurroo";
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/chef.lproj/ErrorMessages.strings b/Plugins/BuiltInFunctions/chef.lproj/ErrorMessages.strings new file mode 100644 index 0000000..94dd413 --- /dev/null +++ b/Plugins/BuiltInFunctions/chef.lproj/ErrorMessages.strings @@ -0,0 +1,10 @@ +/* Errors for file rename operations. */ +LiGenericRenameErrorHeader = "Zee feele-a cuooldn't be-a renemed."; +LiGenericRenameErrorContents = "Try shekeeng a deed cheeckee (oor cheeckee soobsteetoote-a) et zee screee."; + +LiBadFilenameErrorHeader = "Zee feele-a cuooldn't be-a renemed becoose-a it cunteeened un illegel cherecter."; +LiBadFilenameErrorContents = "Yuoo cun try tu reneme-a zee feele-a veethuoot zee slesh \"/\" oor culun \":\" cherecters."; +LiReadOnlyFileSytemErrorHeader = "Zee feele-a cuooldn't be-a mudeeffied becoose-a zee feelesystem is reed-oonly."; +LiReadOnlyFileSytemErrorContents = "Yuoo need tu telk tu yuoor system edmeenistretur tu feex thees."; +LiPermissionDeniedErrorHeader = "Zee feele-a cuooldn't be-a mudeeffied becoose-a yuoo leck permeessiun tu chunge-a zee feele-a."; +LiPermissionDeniedErrorContents = "Yuoo cun mudeeffy yuoor fulder permeessiuns in zee Feender."; diff --git a/Plugins/BuiltInFunctions/chef.lproj/InfoPlist.strings b/Plugins/BuiltInFunctions/chef.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 0000000..9ac3304 --- /dev/null +++ b/Plugins/BuiltInFunctions/chef.lproj/InfoPlist.strings diff --git a/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/classes.nib b/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/classes.nib new file mode 100644 index 0000000..5cbffd3 --- /dev/null +++ b/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/classes.nib @@ -0,0 +1,38 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = HFSCodeFormatter; LANGUAGE = ObjC; SUPERCLASS = NSFormatter; }, + { + ACTIONS = { + setApplication = id; + setFilename = id; + setHFSCreatorField = id; + setHFSTypeField = id; + setIcon = id; + setType = id; + }; + CLASS = InspectorViewController; + LANGUAGE = ObjC; + OUTLETS = { + hfsCreatorField = NSTextField; + hfsTypeField = NSTextField; + iconView = NSImageView; + pathField = NSTextField; + theApplicationButton = NSPopUpButton; + theFileTabView = NSView; + theFilenameField = NSTextField; + theHFSTabView = NSView; + theTypeField = NSTextField; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = LiBuiltInFunctions; + LANGUAGE = ObjC; + OUTLETS = {theController = InspectorViewController; }; + SUPERCLASS = NSObject; + }, + {CLASS = LiImageView; LANGUAGE = ObjC; SUPERCLASS = NSImageView; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/info.nib b/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/info.nib new file mode 100644 index 0000000..d875328 --- /dev/null +++ b/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/info.nib @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>37 90 356 240 0 0 1024 746 </string> + <key>IBEditorPositions</key> + <dict> + <key>48</key> + <string>394 455 235 123 0 0 1024 746 </string> + <key>5</key> + <string>345 428 334 178 0 0 1024 746 </string> + </dict> + <key>IBFramework Version</key> + <string>291.0</string> + <key>IBGroupedObjects</key> + <dict> + <key>0</key> + <array> + <string>27</string> + <string>28</string> + <string>30</string> + <string>31</string> + <string>33</string> + </array> + </dict> + <key>IBLastGroupID</key> + <string>1</string> + <key>IBSystem Version</key> + <string>6L60</string> +</dict> +</plist> diff --git a/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/objects.nib b/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/objects.nib Binary files differnew file mode 100644 index 0000000..688b472 --- /dev/null +++ b/Plugins/BuiltInFunctions/chef.lproj/InspectorViews.nib/objects.nib |