From 7f491cbb39b6615dbd01c495df0bd5e24686fdbc Mon Sep 17 00:00:00 2001 From: Nicholas Shanks Date: Thu, 31 Jul 2008 20:27:55 +0000 Subject: [PATCH] Changes accumulated on my G5 while repository was inaccessible. --- .../Categories/NSOutlineView-SelectedItems.m | 2 +- Cocoa/Categories/NSString-FSSpec.h | 8 + Cocoa/Categories/NSString-FSSpec.m | 39 +- Cocoa/Classes/ApplicationDelegate.h | 117 +- Cocoa/Classes/ApplicationDelegate.m | 218 ++- Cocoa/Classes/CreateResourceSheetController.m | 81 +- Cocoa/Classes/InfoWindowController.h | 4 +- Cocoa/Classes/InfoWindowController.m | 90 +- Cocoa/Classes/NameFormatter.m | 3 + Cocoa/Classes/OpenFileDataSource.h | 19 - Cocoa/Classes/OpenFileDataSource.m | 113 -- Cocoa/Classes/OpenPanelDelegate.h | 43 + Cocoa/Classes/OpenPanelDelegate.m | 131 ++ Cocoa/Classes/OutlineViewDelegate.h | 19 +- Cocoa/Classes/OutlineViewDelegate.m | 263 ++-- Cocoa/Classes/PasteboardDocument.m | 54 +- Cocoa/Classes/PrefsWindowController.h | 7 - Cocoa/Classes/PrefsWindowController.m | 26 +- Cocoa/Classes/RKDocumentController.m | 35 +- Cocoa/Classes/RKEditorRegistry.h | 11 +- Cocoa/Classes/RKEditorRegistry.m | 227 +-- Cocoa/Classes/RKSupportResourceRegistry.h | 7 +- Cocoa/Classes/RKSupportResourceRegistry.m | 56 +- Cocoa/Classes/Resource.h | 17 +- Cocoa/Classes/Resource.m | 122 +- Cocoa/Classes/ResourceDataSource.h | 56 +- Cocoa/Classes/ResourceDataSource.m | 188 +-- Cocoa/Classes/ResourceDocument.h | 31 +- Cocoa/Classes/ResourceDocument.m | 1300 ++++++++++------- Cocoa/Classes/ResourceNameCell.m | 30 +- Cocoa/Classes/SizeFormatter.m | 2 +- Cocoa/English.lproj/AboutPanel.nib/info.nib | 12 +- .../English.lproj/AboutPanel.nib/objects.nib | Bin 2228 -> 4905 bytes .../English.lproj/Application.nib/classes.nib | 30 +- Cocoa/English.lproj/Application.nib/info.nib | 15 +- .../Application.nib/keyedobjects.nib | Bin 0 -> 26686 bytes .../English.lproj/Application.nib/objects.nib | Bin 9377 -> 11162 bytes .../CreateResourceSheet.nib/info.nib | 8 +- .../CreateResourceSheet.nib/keyedobjects.nib | Bin 0 -> 9039 bytes Cocoa/English.lproj/Credits.rtf | 30 + Cocoa/English.lproj/InfoPlist.strings | Bin 236 -> 508 bytes .../English.lproj/InfoWindow.nib/classes.nib | 3 +- Cocoa/English.lproj/InfoWindow.nib/info.nib | 14 +- .../InfoWindow.nib/keyedobjects.nib | Bin 0 -> 10492 bytes .../English.lproj/InfoWindow.nib/objects.nib | Bin 3985 -> 4034 bytes Cocoa/English.lproj/Localizable.strings | Bin 3338 -> 4484 bytes .../ResourceDocument.nib/classes.nib | 8 +- .../ResourceDocument.nib/info.nib | 10 +- .../ResourceDocument.nib/objects.nib | Bin 2848 -> 2719 bytes .../Categories/NSData-HexRepresentation.h | 11 + .../Categories/NSData-HexRepresentation.m | 95 ++ .../English.lproj/HexWindow.nib/classes.nib | 21 +- .../English.lproj/HexWindow.nib/info.nib | 28 +- .../HexWindow.nib/keyedobjects.nib | Bin 0 -> 12717 bytes .../English.lproj/HexWindow.nib/objects.nib | Bin 5909 -> 0 bytes .../Plug-Ins/Hex Editor/FindSheetController.m | 2 +- Cocoa/Plug-Ins/Hex Editor/HexEditorDelegate.h | 29 +- Cocoa/Plug-Ins/Hex Editor/HexEditorDelegate.m | 219 +-- Cocoa/Plug-Ins/Hex Editor/HexTextView.h | 16 +- Cocoa/Plug-Ins/Hex Editor/HexTextView.m | 527 +++---- .../Plug-Ins/Hex Editor/HexWindowController.h | 40 +- .../Plug-Ins/Hex Editor/HexWindowController.m | 262 ++-- Cocoa/Plug-Ins/Hex Editor/Info.plist | 27 +- Cocoa/Resources/Apply3.png | Bin 0 -> 3341 bytes Cocoa/Resources/Button_certified.png | Bin 0 -> 1653 bytes Cocoa/Resources/Button_reload.png | Bin 0 -> 1420 bytes Cocoa/Resources/Create48.png | Bin 0 -> 4750 bytes Cocoa/Resources/Delete.png | Bin 0 -> 2367 bytes Cocoa/Resources/Delete.svg | 93 ++ Cocoa/Resources/Delete3.png | Bin 0 -> 3590 bytes Cocoa/Resources/Go3.png | Bin 0 -> 3276 bytes Cocoa/Resources/Help.png | Bin 0 -> 2622 bytes Cocoa/Resources/Help3.png | Bin 0 -> 3870 bytes Cocoa/Resources/ResKnife-old.icns | Bin 0 -> 61179 bytes Cocoa/Resources/ResKnife.icns | Bin 61179 -> 39176 bytes .../Resources/Resource Type Mappings.strings | 43 + Cocoa/Resources/Resource file-old.icns | Bin 0 -> 58820 bytes Cocoa/Resources/Resource file.icns | Bin 58820 -> 6918 bytes Cocoa/Resources/Search3.png | Bin 0 -> 2906 bytes Cocoa/Resources/add.png | Bin 0 -> 3579 bytes Cocoa/Resources/defaults.plist | 2 +- Cocoa/Resources/delete-1.png | Bin 0 -> 3788 bytes Cocoa/cy.lproj/Application.nib/classes.nib | 88 ++ Cocoa/cy.lproj/Application.nib/info.nib | 27 + .../cy.lproj/Application.nib/keyedobjects.nib | Bin 0 -> 26672 bytes Cocoa/cy.lproj/Application.nib/objects.nib | Bin 0 -> 11347 bytes Cocoa/cy.lproj/InfoPlist.strings | 6 + Cocoa/cy.lproj/Localizable.strings | Bin 0 -> 4416 bytes Cocoa/gd.lproj/Application.nib/classes.nib | 88 ++ Cocoa/gd.lproj/Application.nib/info.nib | 27 + .../gd.lproj/Application.nib/keyedobjects.nib | Bin 0 -> 26900 bytes Cocoa/gd.lproj/Application.nib/objects.nib | Bin 0 -> 11342 bytes Cocoa/gd.lproj/InfoPlist.strings | 6 + Cocoa/gd.lproj/Localizable.strings | Bin 0 -> 5126 bytes Cocoa/ja.lproj/Application.nib/classes.nib | 50 + Cocoa/ja.lproj/Application.nib/info.nib | 23 + .../ja.lproj/Application.nib/keyedobjects.nib | Bin 0 -> 25589 bytes Cocoa/main.m | 4 + ICONEditor/ICONWindowController.m | 2 +- .../{TEMPLATE EDITOR.txt => Read Me.txt} | 32 +- NuTemplateEditor/Resources/DisplayTMPL.png | Bin 0 -> 274 bytes NuTemplateEditor/TMPLs.rsrc | Bin 0 -> 15074 bytes NuTemplateEditor/Templates.rsrc | Bin 0 -> 22260 bytes ResKnife.xcodeproj/project.pbxproj | 292 ++-- 104 files changed, 3328 insertions(+), 2181 deletions(-) delete mode 100644 Cocoa/Classes/OpenFileDataSource.h delete mode 100644 Cocoa/Classes/OpenFileDataSource.m create mode 100644 Cocoa/Classes/OpenPanelDelegate.h create mode 100644 Cocoa/Classes/OpenPanelDelegate.m create mode 100644 Cocoa/English.lproj/Application.nib/keyedobjects.nib create mode 100644 Cocoa/English.lproj/CreateResourceSheet.nib/keyedobjects.nib create mode 100644 Cocoa/English.lproj/Credits.rtf create mode 100644 Cocoa/English.lproj/InfoWindow.nib/keyedobjects.nib create mode 100644 Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.h create mode 100644 Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.m create mode 100644 Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/keyedobjects.nib delete mode 100644 Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/objects.nib create mode 100644 Cocoa/Resources/Apply3.png create mode 100644 Cocoa/Resources/Button_certified.png create mode 100644 Cocoa/Resources/Button_reload.png create mode 100644 Cocoa/Resources/Create48.png create mode 100644 Cocoa/Resources/Delete.png create mode 100644 Cocoa/Resources/Delete.svg create mode 100644 Cocoa/Resources/Delete3.png create mode 100644 Cocoa/Resources/Go3.png create mode 100644 Cocoa/Resources/Help.png create mode 100644 Cocoa/Resources/Help3.png create mode 100644 Cocoa/Resources/ResKnife-old.icns create mode 100644 Cocoa/Resources/Resource Type Mappings.strings create mode 100644 Cocoa/Resources/Resource file-old.icns create mode 100644 Cocoa/Resources/Search3.png create mode 100644 Cocoa/Resources/add.png create mode 100644 Cocoa/Resources/delete-1.png create mode 100644 Cocoa/cy.lproj/Application.nib/classes.nib create mode 100644 Cocoa/cy.lproj/Application.nib/info.nib create mode 100644 Cocoa/cy.lproj/Application.nib/keyedobjects.nib create mode 100644 Cocoa/cy.lproj/Application.nib/objects.nib create mode 100644 Cocoa/cy.lproj/InfoPlist.strings create mode 100644 Cocoa/cy.lproj/Localizable.strings create mode 100644 Cocoa/gd.lproj/Application.nib/classes.nib create mode 100644 Cocoa/gd.lproj/Application.nib/info.nib create mode 100644 Cocoa/gd.lproj/Application.nib/keyedobjects.nib create mode 100644 Cocoa/gd.lproj/Application.nib/objects.nib create mode 100644 Cocoa/gd.lproj/InfoPlist.strings create mode 100644 Cocoa/gd.lproj/Localizable.strings create mode 100644 Cocoa/ja.lproj/Application.nib/classes.nib create mode 100644 Cocoa/ja.lproj/Application.nib/info.nib create mode 100644 Cocoa/ja.lproj/Application.nib/keyedobjects.nib rename NuTemplateEditor/{TEMPLATE EDITOR.txt => Read Me.txt} (75%) create mode 100644 NuTemplateEditor/Resources/DisplayTMPL.png create mode 100644 NuTemplateEditor/TMPLs.rsrc create mode 100644 NuTemplateEditor/Templates.rsrc diff --git a/Cocoa/Categories/NSOutlineView-SelectedItems.m b/Cocoa/Categories/NSOutlineView-SelectedItems.m index 00c3b84..d768516 100644 --- a/Cocoa/Categories/NSOutlineView-SelectedItems.m +++ b/Cocoa/Categories/NSOutlineView-SelectedItems.m @@ -10,7 +10,7 @@ else return [self itemAtRow:[self selectedRow]]; } -- (NSArray *)selectedItems; +- (NSArray *)selectedItems { NSNumber *row; NSMutableArray *items = [NSMutableArray array]; diff --git a/Cocoa/Categories/NSString-FSSpec.h b/Cocoa/Categories/NSString-FSSpec.h index 1d9bf7f..8255ebe 100644 --- a/Cocoa/Categories/NSString-FSSpec.h +++ b/Cocoa/Categories/NSString-FSSpec.h @@ -6,3 +6,11 @@ - (FSSpec *)createFSSpec; @end + + +@interface NSString (ResKnifeBooleanExtensions) + +- (BOOL)boolValue; ++ (NSString *)stringWithBool:(BOOL)boolean; + +@end \ No newline at end of file diff --git a/Cocoa/Categories/NSString-FSSpec.m b/Cocoa/Categories/NSString-FSSpec.m index 5bcb098..267ac96 100644 --- a/Cocoa/Categories/NSString-FSSpec.m +++ b/Cocoa/Categories/NSString-FSSpec.m @@ -4,25 +4,46 @@ - (FSRef *)createFSRef { - FSRef *fsRef = NULL; - OSStatus error = FSPathMakeRef( [self fileSystemRepresentation], fsRef, NULL ); - if( error == noErr ) + // caller is responsible for disposing of the FSRef (method is a 'create' method) + FSRef *fsRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + OSStatus error = FSPathMakeRef([self fileSystemRepresentation], fsRef, NULL); + if(error == noErr) return fsRef; return NULL; } - (FSSpec *)createFSSpec { - FSRef *fsRef = NULL; - FSSpec *fsSpec = NULL; - OSStatus error = FSPathMakeRef( [self fileSystemRepresentation], fsRef, NULL ); - if( error == noErr ) + // caller is responsible for disposing of the FSSpec (method is a 'create' method) + FSRef *fsRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + FSSpec *fsSpec = (FSSpec *) NewPtrClear(sizeof(FSSpec)); + OSStatus error = FSPathMakeRef([self fileSystemRepresentation], fsRef, NULL); + if(error == noErr) { - error = FSGetCatalogInfo( fsRef, kFSCatInfoNone, NULL, NULL, fsSpec, NULL ); - if( error == noErr ) + error = FSGetCatalogInfo(fsRef, kFSCatInfoNone, NULL, NULL, fsSpec, NULL); + if(error == noErr) + { + DisposePtr((Ptr) fsRef); return fsSpec; + } } + DisposePtr((Ptr) fsRef); return NULL; } @end + +@implementation NSString (ResKnifeBooleanExtensions) + +- (BOOL)boolValue +{ + return ![self isEqualToString:@"NO"]; +// return [self isEqualToString:@"YES"]; +} + ++ (NSString *)stringWithBool:(BOOL)boolean +{ + return boolean? @"YES" : @"NO"; +} + +@end diff --git a/Cocoa/Classes/ApplicationDelegate.h b/Cocoa/Classes/ApplicationDelegate.h index ef9bd40..4bd0144 100644 --- a/Cocoa/Classes/ApplicationDelegate.h +++ b/Cocoa/Classes/ApplicationDelegate.h @@ -1,75 +1,100 @@ #import -/*! @header ApplicationDelegate.h - * @discussion This class is the delegate object for NSApp. - */ +/*! +@header ApplicationDelegate.h +@abstract This class is the delegate object for NSApp. +*/ -/*! @class ApplicationDelegate - * @discussion This class is the delegate object for NSApp. - */ +/*! +@class ApplicationDelegate +@abstract This class is the delegate object for NSApp. +*/ +@class OpenPanelDelegate; @interface ApplicationDelegate : NSObject { -/*! @var openAuxView Accessory view for NSOpenPanels. */ - IBOutlet NSView *openAuxView; -/*! @var forkTableView Table view inside openAuxView. */ - IBOutlet NSTableView *forkTableView; -/*! @var icons A dictionary within which to cache icons. Keys are four-character NSStrings representing ResTypes. */ - NSMutableDictionary *icons; +/*! @var openPanelDelegate Delegate for NSOpenPanels. */ + IBOutlet OpenPanelDelegate *openPanelDelegate; +/*! @var icons A dictionary within which to cache icons. Keys are four-character NSStrings representing ResTypes. */ + NSMutableDictionary *_icons; } -/*! @function showAbout: - * @discussion Displays the about box located in AboutPanel.nib. - */ +/*! +@method showAbout: +@abstract Displays the about box located in AboutPanel.nib. +*/ - (IBAction)showAbout:(id)sender; -/*! @function visitWebsite: - * @discussion Takes the user to http://web.nickshanks.com/resknife/. - */ +/*! +@method visitWebsite: +@abstract Takes the user to http://web.nickshanks.com/resknife/. +*/ - (IBAction)visitWebsite:(id)sender; -/*! @function visitSourceforge: - * @discussion Takes the user to http://resknife.sourceforge.net/. - */ +/*! +@method visitSourceforge: +@abstract Takes the user to http://resknife.sourceforge.net/. +*/ - (IBAction)visitSourceforge:(id)sender; -/*! @function emailDeveloper: - * @discussion Launches email client and inserts resknife@nickshanks.com into To field. - */ +/*! +@method emailDeveloper: +@abstract Launches email client and inserts resknife@nickshanks.com into To field. +*/ - (IBAction)emailDeveloper:(id)sender; -/*! @function showInfo: - * @discussion Displays the Info panel stored in InfoWindow.nib - */ +/*! +@method showInfo: +@abstract Displays the Info panel stored in InfoWindow.nib +*/ - (IBAction)showInfo:(id)sender; -/*! @function showPasteboard: - * @discussion Displays the pasteboard document, a singleton instance of class PasteboardDocument - */ +/*! +@method showPasteboard: +@abstract Displays the pasteboard document, a singleton instance of class PasteboardDocument +*/ - (IBAction)showPasteboard:(id)sender; -/*! @function showPrefs: - * @discussion Displays the preferences panel stored in PrefsWindow.nib - */ +/*! +@method showPrefs: +@abstract Displays the preferences panel stored in PrefsWindow.nib +*/ - (IBAction)showPrefs:(id)sender; -/*! @function initUserDefaults - * @discussion Initalises any unset user preferences to default values as read in from defaults.plist. - */ +/*! +@method initUserDefaults +@abstract Initalises any unset user preferences to default values as read in from defaults.plist. +*/ - (void)initUserDefaults; -/*! @function openAuxView - * @discussion Accessor method for the openAuxView instance variable. - */ -- (NSView *)openAuxView; +/* accessors */ -/*! @function icons - * @discussion Accessor method for the icons instance variable. - */ +/*! +@method openPanelDelegate +@abstract Accessor method for the openPanelDelegate instance variable. +*/ +- (OpenPanelDelegate *)openPanelDelegate; + +/*! +@@method iconForResourceType: +@abstract Returns the icon to be used throughout the UI for any given resource type. +*/ +- (NSImage *)iconForResourceType:(NSString *)resourceType; + +/*! +@@method _icons +@abstract Private accessor method for the _icons instance variable. +*/ +- (NSMutableDictionary *)_icons; + +/*! +@method icons +@abstract Accessor method for the _icons instance variable. Returns an immutable dictionary. +*/ - (NSDictionary *)icons; -@end - -@interface NSSavePanel (PackageBrowser) +/* utility methods */ + +- (NSArray *)forksForFile:(FSRef *)fileRef; @end \ No newline at end of file diff --git a/Cocoa/Classes/ApplicationDelegate.m b/Cocoa/Classes/ApplicationDelegate.m index 148af01..2b232af 100644 --- a/Cocoa/Classes/ApplicationDelegate.m +++ b/Cocoa/Classes/ApplicationDelegate.m @@ -1,4 +1,5 @@ #import "ApplicationDelegate.h" +#import "OpenPanelDelegate.h" #import "RKDocumentController.h" #import "InfoWindowController.h" #import "PasteboardWindowController.h" @@ -6,8 +7,9 @@ #import "CreateResourceSheetController.h" #import "ResourceDocument.h" #import "ResourceDataSource.h" +#import "RKEditorRegistry.h" -#import "ResknifePluginProtocol.h" +#import "ResKnifePluginProtocol.h" #import "RKSupportResourceRegistry.h" @@ -23,49 +25,103 @@ - (void)applicationWillFinishLaunching:(NSNotification *)notification { // instanciate my own subclass of NSDocumentController so I can override the open dialog - RKDocumentController *docController = [[RKDocumentController alloc] init]; - - [RKSupportResourceRegistry scanForSupportResources: [NSDocumentController sharedDocumentController]]; + [[RKDocumentController alloc] init]; + [RKSupportResourceRegistry scanForSupportResources]; } +/*! +@method awakeFromNib +@updated 2003-10-24 NGS: moved icon caching into method called by timer (to speed up app launch time) +*/ + - (void)awakeFromNib { - NSTableColumn *tableColumn; - NSButtonCell *buttonCell; - // Part of my EvilPlanª to find out how many people use ResKnife and how often! int launchCount = [[NSUserDefaults standardUserDefaults] integerForKey:@"LaunchCount"]; [[NSUserDefaults standardUserDefaults] setInteger:launchCount + 1 forKey:@"LaunchCount"]; - // save a number of icons - icons = [[NSMutableDictionary alloc] init]; - [icons setObject:[[NSWorkspace sharedWorkspace] iconForFileType:@"TEXT"] forKey:@"TEXT"]; - [icons setObject:[[NSWorkspace sharedWorkspace] iconForFileType:@"PICT"] forKey:@"PICT"]; - [icons setObject:[[NSWorkspace sharedWorkspace] iconForFileType:@"icns"] forKey:@"icns"]; - - // set up open dialog's aux table view - tableColumn = [forkTableView tableColumnWithIdentifier:@"parse"]; - buttonCell = [[[NSButtonCell alloc] initTextCell:@""] autorelease]; - [buttonCell setEditable:YES]; - [buttonCell setButtonType:NSSwitchButton]; - [tableColumn setDataCell:buttonCell]; + // initalise an empty icon cache and create timer used to pre-cache a number of common icons + _icons = [[NSMutableDictionary alloc] init]; + [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(precacheIcons:) userInfo:nil repeats:NO]; + // set default preferences [self initUserDefaults]; } - (void)dealloc { - [icons release]; + [_icons release]; [super dealloc]; } +/*! +@method precacheIcons: +@author Nicholas Shanks +@created 2003-10-24 +@abstract Pre-caches the icons for a number of common resource types. +@description Icon pre-caching now uses the more sophisticated iconForResourceType: instead of obtaining the images directly from the file system (otherwise pre-cached icons would not be overridable by plug-ins). In addition it has been moved from the awakeFromNib: method into one called by a timer. This method should not be called until after the editor registry has been built. +*/ + +- (void)precacheIcons:(NSTimer *)timer +{ + // pre-cache a number of common icons (ignores return value, relies on iconForResourceType: to do the actual caching) + [self iconForResourceType:@" "]; + [self iconForResourceType:@"CODE"]; + [self iconForResourceType:@"icns"]; + [self iconForResourceType:@"PICT"]; + [self iconForResourceType:@"plst"]; + [self iconForResourceType:@"snd "]; + [self iconForResourceType:@"TEXT"]; +} + +- (NSArray *)forksForFile:(FSRef *)fileRef +{ + if(!fileRef) return nil; + + FSCatalogInfo catalogInfo; + FSCatalogInfoBitmap whichInfo = kFSCatInfoNodeFlags; + CatPositionRec forkIterator = { 0 }; + NSMutableArray *forks = [NSMutableArray array]; + + // check we have a file, not a folder + OSErr error = FSGetCatalogInfo(fileRef, whichInfo, &catalogInfo, NULL, NULL, NULL); + if(!error && !(catalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) + { + // iterate over file and populate forks array + while(error == noErr) + { + HFSUniStr255 forkName; + SInt64 forkSize; + UInt64 forkPhysicalSize; // used if opening selected fork fails to find empty forks + + error = FSIterateForks(fileRef, &forkIterator, &forkName, &forkSize, &forkPhysicalSize); + if(!error) + { + NSString *fName = [NSString stringWithCharacters:forkName.unicode length:forkName.length]; + NSNumber *fSize = [NSNumber numberWithLongLong:forkSize]; + NSNumber *fAlloc = [NSNumber numberWithUnsignedLongLong:forkPhysicalSize]; + [forks addObject:[NSDictionary dictionaryWithObjectsAndKeys:fName, @"forkname", fSize, @"forksize", fAlloc, @"forkallocation", nil]]; + } + else if(error != errFSNoMoreItems) + { + NSLog(@"FSIterateForks() error: %d", error); + } + } + } + else if(error) + { + NSLog(@"FSGetCatalogInfo() error: %d", error); + } + return forks; +} + - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender { -#pragma unused( sender ) +#pragma unused(sender) NSString *launchAction = [[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchAction"]; - if( [launchAction isEqualToString:@"OpenUntitledFile"] ) + if([launchAction isEqualToString:@"OpenUntitledFile"]) return YES; - else if( [launchAction isEqualToString:@"DisplayOpenPanel"] ) + else if([launchAction isEqualToString:@"DisplayOpenPanel"]) { [[NSDocumentController sharedDocumentController] openDocument:sender]; return NO; @@ -75,7 +131,7 @@ - (BOOL)application:(NSApplication *)application openFile:(NSString *)file { -#pragma unused( application ) +#pragma unused(application) // bug: check if application was an external editor (e.g. Iconographer) and update existing open file instead [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:file display:YES]; return YES; @@ -83,14 +139,20 @@ - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag { -#pragma unused( sender ) +#pragma unused(sender) return !flag; } - (IBAction)showAbout:(id)sender { - [NSApp orderFrontStandardAboutPanel:sender]; - // get about box code from http://cocoadevcentral.com/tutorials/showpage.php?show=00000041.php + // could do with a better about box +/* NSWindowController *wc = [[NSWindowController alloc] initWithWindowNibName:@"AboutPanel"]; + if([(NSTextView *)[[wc window] initialFirstResponder] readRTFDFromFile:[[NSBundle mainBundle] pathForResource:@"Credits" ofType:@"rtf"]]) + { + [[wc window] center]; + [[wc window] orderFront:nil]; + } + else*/ [NSApp orderFrontStandardAboutPanel:sender]; } - (IBAction)visitWebsite:(id)sender @@ -145,12 +207,12 @@ // enumerate over all the keys in the dictionary overDefaults = [[defaultsPlist allKeys] objectEnumerator]; - while( eachDefault = [overDefaults nextObject] ) + while(eachDefault = [overDefaults nextObject]) { // for each key in the dictionary // check if there is a value already registered for it // and if there isn't, then register the value that was in the file - if( ![defaults stringForKey:eachDefault] ) + if(![defaults stringForKey:eachDefault]) { [defaults setObject:[defaultsPlist objectForKey:eachDefault] forKey:eachDefault]; } @@ -160,26 +222,94 @@ [defaults synchronize]; } -- (NSView *)openAuxView +- (OpenPanelDelegate *)openPanelDelegate { - return openAuxView; + return openPanelDelegate; +} + +/*! +@method iconForResourceType: +@author Nicholas Shanks +@created 2003-10-24 +@abstract Manages the cache of icons used for representing resource types. +@description This method loads icons for each resource type from a variety of places and caches them for faster access. Your plug-in may be asked to return an icon for any resource type it declares it can edit. To implement this, your plug should respond to the iconForResourceType: selector with the same method signature as this method. The icons can be in any format recognised by NSImage. Alternativly, just leave your icons in "Your.plugin/Contents/Resources/Resource Type Icons/" (or any equivalent localised directory) with a name like "TYPE.tiff" and ResKnife will retreive them automatically. +@pending I don't like the name I chose here for the resource type icons directory. Can anyone think of something better? +*/ + +- (NSImage *)iconForResourceType:(NSString *)resourceType +{ + // check if we have image in cache already + NSImage *icon = nil; + if([resourceType isEqualToString:@""]) + resourceType = nil; + + if(resourceType); + icon = [[self _icons] valueForKey:resourceType]; + if(!icon) + { + NSString *iconPath = nil; + + // try to load icon from the default editor for that type + Class editor = [[RKEditorRegistry defaultRegistry] editorForType:resourceType]; + if(editor && resourceType) + { + // ask politly for icon + if([editor respondsToSelector:@selector(iconForResourceType:)]) + icon = [editor iconForResourceType:resourceType]; + + // try getting it myself + if(!icon) + { + iconPath = [[NSBundle bundleForClass:editor] pathForResource:resourceType ofType:nil inDirectory:@"Resource Type Icons"]; + if(iconPath) + icon = [[[NSImage alloc] initWithContentsOfFile:iconPath] autorelease]; + } + } + + // try to load icon from the ResKnife app bundle itself + if(!icon && resourceType) + { + iconPath = [[NSBundle mainBundle] pathForResource:resourceType ofType:nil inDirectory:@"Resource Type Icons"]; + if(iconPath) + icon = [[[NSImage alloc] initWithContentsOfFile:iconPath] autorelease]; + } + + // try to retreive from file system (after first mangling the type through our converter strings file) + if(!icon && resourceType) + { + NSString *fileType = [[NSBundle mainBundle] localizedStringForKey:resourceType value:@"" table:@"Resource Type Mappings"]; + NSRange range = [fileType rangeOfString:@"."]; + if(range.location == NSNotFound) + icon = [[NSWorkspace sharedWorkspace] iconForFileType:fileType]; + else // a '.' character in a file type means ResKnife should look for a bundle icon with fileType as the bundle's identifier + { + NSString *bundlePath = [[NSBundle bundleWithIdentifier:fileType] bundlePath]; + if(bundlePath) + icon = [[NSWorkspace sharedWorkspace] iconForFile:bundlePath]; + } + } + + // if we still don't have an icon, try to get the generic one - this is what icon represented forks get +// if(!icon) icon = [NSImage imageNamed:@"NSMysteryDocument"]; + if(!icon) icon = [[NSWorkspace sharedWorkspace] iconForFileType:@"' '"]; + + // save the newly retreived icon in the cache + if(icon && resourceType) + [[self _icons] setObject:icon forKey:resourceType]; + } + + // return the cached icon, or nil if none was found + return icon; +} + +- (NSMutableDictionary *)_icons +{ + return _icons; } - (NSDictionary *)icons { - return icons; + return [NSDictionary dictionaryWithDictionary:[self _icons]]; } -@end - -@implementation NSSavePanel (PackageBrowser) - -/* Don't tell anyone I did this... */ - -/*- (void)setTreatsFilePackagesAsDirectories:(BOOL)flag -{ -#pragma unused( flag ) - _spFlags.treatsFilePackagesAsDirectories = YES; -}*/ - @end \ No newline at end of file diff --git a/Cocoa/Classes/CreateResourceSheetController.m b/Cocoa/Classes/CreateResourceSheetController.m index ed7470d..71ff787 100644 --- a/Cocoa/Classes/CreateResourceSheetController.m +++ b/Cocoa/Classes/CreateResourceSheetController.m @@ -5,62 +5,55 @@ @implementation CreateResourceSheetController -/* ----------------------------------------------------------------------------- - controlTextDidChange: - Someone changed the control ID edit field. Check whether this is - a unique ID and appropriately enable the "create" button. - - Check "notification" against being nil, which is how we call it when - we need to explicitly update the enabled state of the "create" button. - - - REVISIONS: - 2003-08-01 UK Commented, changed to use data source's resourceOfType - instead of directly messing with the resource list's - enumerator Removed ID > 0 check -- negative IDs are - allowed as well. - -------------------------------------------------------------------------- */ +/*! +@method controlTextDidChange: +@abstract Handles updating of the 'Create' button when valid values are present in the sheet's fields. +@updated 2003-08-01 UK: Changed to use data source's resourceOfType instead of directly messing with the resource list's enumerator. +@updated 2003-08-01 UK: Removed ID > 0 check -- negative IDs are allowed as well.
Note from Nick: IIRC this was there as a workaround for another bug which prohibited negative IDs from being used. Not sure if that got fixed though :) +@description Someone changed the control ID edit field. Check whether this is a unique ID and appropriately enable the "create" button.

Check "notification" against being nil, which is how we call it when we need to explicitly update the enabled state of the "create" button. +*/ --(void) controlTextDidChange: (NSNotification*)notification +- (void)controlTextDidChange:(NSNotification *)notification { BOOL enableButton = NO; NSString *type = [typeView stringValue]; NSNumber *resID = [NSNumber numberWithInt:[resIDView intValue]]; - if( [type length] == 4 ) + if([type length] == 4) { // I could use +[Resource getResourceOfType:andID:inDocument:] != nil, but that would be much slower Resource *resource = [[document dataSource] resourceOfType:type andID:resID]; - if( resource == nil ) // No resource with that type and ID yet? + if(resource == nil) // No resource with that type and ID yet? enableButton = YES; } [createButton setEnabled:enableButton]; } +/*! +@method showCreateResourceSheet: +@abstract Shows the sheet allowing the user to define the properties of a new resource. +@updated 2003-08-01 UK: Made it "fake" a popup selection so type field and popup match. +@updated 2003-08-01 UK: Made it suggest an unused resource ID. +*/ -/* ----------------------------------------------------------------------------- - showCreateResourceSheet: - Show our sheet and set it up before that. - - REVISIONS: - 2003-08-01 UK Commented, made it "fake" a popup selection so - type field and popup match. Made it suggest an unused - resource ID. - -------------------------------------------------------------------------- */ - --(void) showCreateResourceSheet: (ResourceDocument*)sheetDoc +- (void)showCreateResourceSheet:(ResourceDocument *)sheetDoc { // bug: didEndSelector could be better employed than using the button's targets from interface builder document = sheetDoc; [NSApp beginSheet:[self window] modalForWindow:[document mainWindow] modalDelegate:self didEndSelector:NULL contextInfo:nil]; - [resIDView setObjectValue: [[document dataSource] uniqueIDForType: [typeView stringValue]]]; - [self typePopupSelection: typePopup]; // Puts current popup value in text field and updates state of "create" button. + [resIDView setObjectValue:[[document dataSource] uniqueIDForType:[typeView stringValue]]]; + + // put current popup value in text field and updates state of "create" button. + [self typePopupSelection:typePopup]; } - (IBAction)hideCreateResourceSheet:(id)sender { - if( sender == createButton ) + if(sender == createButton) { + // bug should be using cell's tag rather than position (so cells can be moved around if needed) + // attributes ^= [[attributesMatrix cellAtRow:0 column:0] intValue]? [[attributesMatrix cellAtRow:0 column:0] tag]:0; + unsigned short attributes = 0; attributes ^= [[attributesMatrix cellAtRow:0 column:0] intValue]? resPreload:0; attributes ^= [[attributesMatrix cellAtRow:1 column:0] intValue]? resPurgeable:0; @@ -68,28 +61,26 @@ attributes ^= [[attributesMatrix cellAtRow:0 column:1] intValue]? resSysHeap:0; attributes ^= [[attributesMatrix cellAtRow:1 column:1] intValue]? resProtected:0; + Resource *resource = [Resource resourceOfType:[typeView stringValue] andID:[NSNumber numberWithShort:(short) [resIDView intValue]] withName:[nameView stringValue] andAttributes:[NSNumber numberWithUnsignedShort:attributes]]; + [resource setDocumentName:[document displayName]]; [[document undoManager] beginUndoGrouping]; - [[document dataSource] addResource:[Resource resourceOfType:[typeView stringValue] andID:[NSNumber numberWithShort:(short) [resIDView intValue]] withName:[nameView stringValue] andAttributes:[NSNumber numberWithUnsignedShort:attributes]]]; - if( [[nameView stringValue] length] == 0 ) + [[document dataSource] addResource:resource]; + if([[nameView stringValue] length] == 0) [[document undoManager] setActionName:NSLocalizedString(@"Create Resource", nil)]; - else [[document undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Create Resource Ò%@Ó", nil), [nameView stringValue]]]; + else [[document undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Create Resource '%@'", nil), [nameView stringValue]]]; [[document undoManager] endUndoGrouping]; } [[self window] orderOut:nil]; [NSApp endSheet:[self window]]; } +/*! +@method typePopupSelection: +@abstract Updates the edit text field when the type pop-up selection is changed. +@updated 2003-08-01 UK: Commented, made it update state of "create" button. +*/ -/* ----------------------------------------------------------------------------- - typePopupSelection: - Someone chose an item from our "res type" popup menu. Update our - edit field to show that. - - REVISIONS: - 2003-08-01 UK Commented, made it update state of "create" button.. - -------------------------------------------------------------------------- */ - --(IBAction) typePopupSelection:(id)sender +- (IBAction)typePopupSelection:(id)sender { [typeView setStringValue:[typePopup titleOfSelectedItem]]; [typeView selectText:sender]; diff --git a/Cocoa/Classes/InfoWindowController.h b/Cocoa/Classes/InfoWindowController.h index 772cf99..4b3863f 100644 --- a/Cocoa/Classes/InfoWindowController.h +++ b/Cocoa/Classes/InfoWindowController.h @@ -35,7 +35,7 @@ enum Attributes - (void)updateInfoWindow; - (void)setMainWindow:(NSWindow *)mainWindow; - (IBAction)attributesChanged:(id)sender; -- (IBAction)nameChanged: (id)sender; +- (IBAction)nameDidChange:(id)sender; - (void)resourceAttributesDidChange:(NSNotification *)notification; - (void)documentInfoDidChange:(NSNotification *)notification; @@ -46,7 +46,7 @@ enum Attributes @interface NSWindowController (InfoWindowAdditions) /*! @function resource - @discussion Your plug-in should override this method to return the resource it's editing. Default implementation returns nil. + @discussion Your plug-in should override this method to return the primary resource it's editing. Default implementation returns nil. */ - (Resource *)resource; diff --git a/Cocoa/Classes/InfoWindowController.m b/Cocoa/Classes/InfoWindowController.m index b6560e2..f1374ff 100644 --- a/Cocoa/Classes/InfoWindowController.m +++ b/Cocoa/Classes/InfoWindowController.m @@ -2,18 +2,12 @@ #import // Actually I only need CarbonCore.framework, but and don't work, so I don't know what else to do #import "ResourceDocument.h" #import "Resource.h" +#import "ApplicationDelegate.h" #import "NSOutlineView-SelectedItems.h" #import "MoreFilesX.h" @implementation InfoWindowController -- (id)init -{ - self = [self initWithWindowNibName:@"InfoWindow"]; - if( self ) [self setWindowFrameAutosaveName:@"InfoWindow"]; - return self; -} - - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -40,59 +34,87 @@ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentInfoDidChange:) name:DocumentInfoDidChangeNotification object:nil]; } --(void) updateInfoWindow +/*! +@method updateInfoWindow +@updated 2003-11-06 NGS: Fixed creator/type handling. +@updated 2003-10-26 NGS: Now asks app delegate for icon instead of NSWorkspace. +@updated 2003-10-26 NGS: Improved document name & icon display. +*/ + +- (void)updateInfoWindow { [nameView setEditable:(selectedResource != nil)]; [nameView setDrawsBackground:(selectedResource != nil)]; - if( selectedResource ) + if(selectedResource) { - [[self window] setTitle:@"Resource Info"]; - [placeholderView setContentView:resourceView]; + // set UI values + [[self window] setTitle:NSLocalizedString(@"Resource Info",nil)]; [nameView setStringValue:[selectedResource name]]; - [iconView setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[selectedResource type]]]; + [iconView setImage:[(ApplicationDelegate *)[NSApp delegate] iconForResourceType:[selectedResource type]]]; [[attributesMatrix cellAtRow:changedBox column:0] setState:[[selectedResource attributes] shortValue] & resChanged]; [[attributesMatrix cellAtRow:preloadBox column:0] setState:[[selectedResource attributes] shortValue] & resPreload]; [[attributesMatrix cellAtRow:protectedBox column:0] setState:[[selectedResource attributes] shortValue] & resProtected]; [[attributesMatrix cellAtRow:lockedBox column:0] setState:[[selectedResource attributes] shortValue] & resLocked]; [[attributesMatrix cellAtRow:purgableBox column:0] setState:[[selectedResource attributes] shortValue] & resPurgeable]; [[attributesMatrix cellAtRow:systemHeapBox column:0] setState:[[selectedResource attributes] shortValue] & resSysHeap]; + + // swap box + [placeholderView setContentView:resourceView]; } - else if( currentDocument != nil ) + else if(currentDocument != nil) { // get sizes of forks as they are on disk UInt64 dataLogicalSize = 0, rsrcLogicalSize = 0; - FSRef *fileRef = (FSRef *) NewPtrClear( sizeof(FSRef) ); - if( fileRef && [currentDocument fileName] ) + FSRef *fileRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + if(fileRef && [currentDocument fileName]) { - OSStatus error = FSPathMakeRef( [[currentDocument fileName] cString], fileRef, nil ); - if( !error ) FSGetForkSizes( fileRef, &dataLogicalSize, &rsrcLogicalSize ); + OSStatus error = FSPathMakeRef([[currentDocument fileName] fileSystemRepresentation], fileRef, nil); + if(!error) FSGetForkSizes(fileRef, &dataLogicalSize, &rsrcLogicalSize); } - if( fileRef ) DisposePtr( (Ptr) fileRef ); + if(fileRef) DisposePtr((Ptr) fileRef); // set info window elements to correct values - [[self window] setTitle:@"Document Info"]; - [iconView setImage:[NSImage imageNamed:@"Resource file"]]; - [nameView setStringValue:[currentDocument fileName]? [[currentDocument fileName] lastPathComponent]:[currentDocument displayName]]; - [[filePropertyForm cellAtIndex:0] setStringValue:[currentDocument creator]]; - [[filePropertyForm cellAtIndex:1] setStringValue:[currentDocument type]]; + [[self window] setTitle:NSLocalizedString(@"Document Info",nil)]; + if([currentDocument fileName]) // document has been saved + { + [iconView setImage:[[NSWorkspace sharedWorkspace] iconForFile:[currentDocument fileName]]]; + [nameView setStringValue:[[currentDocument fileName] lastPathComponent]]; + } + else // new, untitled document + { + [iconView setImage:[NSImage imageNamed:@"Resource file"]]; + [nameView setStringValue:[currentDocument displayName]]; + } + [currentDocument creator]; + [[NSString alloc] initWithData:[currentDocument creator] encoding:NSMacOSRomanStringEncoding]; + [[filePropertyForm cellAtIndex:0] setStringValue:[[[NSString alloc] initWithData:[currentDocument creator] encoding:NSMacOSRomanStringEncoding] autorelease]]; + [[filePropertyForm cellAtIndex:1] setStringValue:[[[NSString alloc] initWithData:[currentDocument type] encoding:NSMacOSRomanStringEncoding] autorelease]]; // [[filePropertyForm cellAtIndex:2] setObjectValue:[NSNumber numberWithUnsignedLongLong:dataLogicalSize]]; // [[filePropertyForm cellAtIndex:3] setObjectValue:[NSNumber numberWithUnsignedLongLong:rsrcLogicalSize]]; [[filePropertyForm cellAtIndex:2] setStringValue:[[NSNumber numberWithUnsignedLongLong:dataLogicalSize] description]]; [[filePropertyForm cellAtIndex:3] setStringValue:[[NSNumber numberWithUnsignedLongLong:rsrcLogicalSize] description]]; + + // swap box [placeholderView setContentView:documentView]; } + else + { + [iconView setImage:nil]; + [nameView setStringValue:nil]; + [placeholderView setContentView:nil]; + } } - (void)setMainWindow:(NSWindow *)mainWindow { NSWindowController *controller = [mainWindow windowController]; - if( [[controller document] isKindOfClass:[ResourceDocument class]] ) + if([[controller document] isKindOfClass:[ResourceDocument class]]) currentDocument = [controller document]; else currentDocument = nil; - if( currentDocument ) + if(currentDocument) selectedResource = [[currentDocument outlineView] selectedItem]; else selectedResource = [controller resource]; [self updateInfoWindow]; @@ -105,15 +127,15 @@ - (void)selectedResourceChanged:(NSNotification *)notification { - if( ![[nameView stringValue] isEqualToString: [selectedResource name]] ) - [self nameChanged:nameView]; - selectedResource = [[notification object] selectedItem]; + if(![[nameView stringValue] isEqualToString:[selectedResource name]]) + [self nameDidChange:nameView]; + selectedResource = (Resource *) [[notification object] selectedItem]; [self updateInfoWindow]; } - (void)documentInfoDidChange:(NSNotification *)notification { -#pragma unused( notification ) +#pragma unused(notification) [self updateInfoWindow]; } @@ -124,23 +146,21 @@ [selectedResource setAttributes:[NSNumber numberWithShort:number]]; } --(IBAction) nameChanged: (id)sender +- (IBAction)nameDidChange:(id)sender { - [selectedResource setName: [nameView stringValue]]; + [selectedResource setName:[nameView stringValue]]; } - (void)resourceAttributesDidChange:(NSNotification *)notification; { - if( ![[nameView stringValue] isEqualToString: [selectedResource name]] ) - [self nameChanged:nameView]; [self updateInfoWindow]; } + (id)sharedInfoWindowController { static InfoWindowController *sharedInfoWindowController = nil; - if( !sharedInfoWindowController ) - sharedInfoWindowController = [[InfoWindowController allocWithZone:[self zone]] init]; + if(!sharedInfoWindowController) + sharedInfoWindowController = [[InfoWindowController allocWithZone:[self zone]] initWithWindowNibName:@"InfoWindow"]; return sharedInfoWindowController; } diff --git a/Cocoa/Classes/NameFormatter.m b/Cocoa/Classes/NameFormatter.m index 6a39ada..e235aa8 100644 --- a/Cocoa/Classes/NameFormatter.m +++ b/Cocoa/Classes/NameFormatter.m @@ -2,6 +2,9 @@ #import "NSOutlineView-SelectedItems.h" #import "Resource.h" +/* NameFormatter has been deprecated (it never did what I wanted anyway :-) */ +/* functionality is now in -outlineView:willDisplayCell:forTableColumn:item: */ + @implementation NameFormatter - (NSString *)stringForObjectValue:(id)obj diff --git a/Cocoa/Classes/OpenFileDataSource.h b/Cocoa/Classes/OpenFileDataSource.h deleted file mode 100644 index 2b91bef..0000000 --- a/Cocoa/Classes/OpenFileDataSource.h +++ /dev/null @@ -1,19 +0,0 @@ -/* OpenFileDataSource */ - -#import - -@interface OpenFileDataSource : NSObject -{ - IBOutlet NSTableView *forkTableView; -} -@end - -@interface OpenPanelDelegate : NSObject -{ - id originalDelegate; -} -@end - -@interface NSSavePanel (ResKnife) -- (NSBrowser *)browser; -@end \ No newline at end of file diff --git a/Cocoa/Classes/OpenFileDataSource.m b/Cocoa/Classes/OpenFileDataSource.m deleted file mode 100644 index 0233a02..0000000 --- a/Cocoa/Classes/OpenFileDataSource.m +++ /dev/null @@ -1,113 +0,0 @@ -#import "OpenFileDataSource.h" -#import -#import - -struct directoryinfo { - unsigned long length; - u_int32_t dirid; -}; - -struct dunnowhat -{ - unsigned long length; - u_int32_t data1; - u_int32_t data2; - u_int32_t data3; - u_int32_t data4; - u_int32_t data5; - u_int32_t data6; -}; - -@implementation OpenFileDataSource - -//get action method and target of browser, intercept (or re-route and call it myself) - -/* NSTableView data source protocol implementation */ -- (int)numberOfRowsInTableView:(NSTableView *)tableView -{ - //NSBrowser *browser = [(NSOpenPanel *)[tableView window] browser]; - //if( [[browser selectedCells] count] == 1 ) - { - // only one file is selected, parse it for forks -/* const char *path = [[browser path] cString]; - struct attrlist attributes; - struct directoryinfo fileinfo; - - NSLog( @"%s", path ); -// memset( &attributes, 0, sizeof(struct attrlist) ); - bzero( &attributes, sizeof(struct attrlist) ); - attributes.bitmapcount = ATTR_BIT_MAP_COUNT; -// attributes.fileattr = ATTR_FILE_FORKCOUNT; - attributes.commonattr = ATTR_CMN_OBJID; - int result = getattrlist( path, &attributes, &fileinfo, sizeof(struct directoryinfo), 0 ); - NSLog( @"%d", result ); - if( result != 0 ) return 0; - NSLog( @"%d", fileinfo.length ); - NSLog( @"%d", fileinfo.dirid ); -*/ - /*struct attrlist alist; - struct directoryinfo dirinfo; - char *path = [[browser path] cString]; - bzero(&alist, sizeof(alist)); - alist.bitmapcount = 5; - alist.commonattr = ATTR_CMN_OBJID; - int result = getattrlist(path, &alist, &dirinfo, sizeof(dirinfo), 0); - printf("result: %d; directory id: %lu; %s\n", result, dirinfo.dirid, path); - - return 3;*/ - } - - // multiple/no selected files, return nothing - /*else*/ return 0; -} - -- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row -{ - return nil; -} - -- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(int)row -{ - ; -} - -/* - NSLog( [browser path] ); - CatPositionRec forkIterator; - forkIterator.initialize = 0; - FSIterateForks( FSRef *ref, &forkIterator, NULL, NULL, NULL ); -*/ - -@end - -@implementation OpenPanelDelegate - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector -{ -/* NSMethodSignature *sig; - NS_DURING - sig = [super methodSignatureForSelector:selector]; - NS_HANDLER - sig = [originalDelegate methodSignatureForSelector:selector]; - NS_ENDHANDLER - return sig; */ - return [originalDelegate methodSignatureForSelector:selector]; -} - -- (void)forwardInvocation:(NSInvocation *)invocation -{ - if( [originalDelegate respondsToSelector:[invocation selector]] ) - [invocation invokeWithTarget:originalDelegate]; - else [self doesNotRecognizeSelector:[invocation selector]]; -} - -@end - -@implementation NSSavePanel (ResKnife) - -- (NSBrowser *)browser -{ - return nil; //return _browser; -} - -@end \ No newline at end of file diff --git a/Cocoa/Classes/OpenPanelDelegate.h b/Cocoa/Classes/OpenPanelDelegate.h new file mode 100644 index 0000000..a6035a6 --- /dev/null +++ b/Cocoa/Classes/OpenPanelDelegate.h @@ -0,0 +1,43 @@ +#import + +@interface OpenPanelDelegate : NSObject +{ +/*! @var openPanelAccessoryView Accessory view for NSOpenPanels. */ + IBOutlet NSView *openPanelAccessoryView; +/*! @var forkTableView Table view inside openPanelAccessoryView. */ + IBOutlet NSTableView *forkTableView; +/*! @var addForkButton Button for adding forks to a file. */ + IBOutlet NSButton *addForkButton; +/*! @var removeForkButton Button for removing forks from a file. */ + IBOutlet NSButton *removeForkButton; + +/*! @var forks Array of forks representing the currently selected file. */ + NSMutableArray *forks; +/*! @var readOpenPanelForFork Flag indicating whether ResKnife should ask for a fork to parse in a secondary dialog (false) or obtain it from the selected item in the open dialog (true). */ + BOOL readOpenPanelForFork; +} + +/* actions from aux view controls */ + +- (IBAction)addFork:(id)sender; +- (IBAction)removeFork:(id)sender; + +/* accessors */ + +/*! +@method openPanelAccessoryView +@abstract Accessor method for the openPanelAccessoryView instance variable. +*/ +- (NSView *)openPanelAccessoryView; + +/*! +@method forkTableView +@abstract Accessor method for the forkTableView instance variable. +*/ +- (NSTableView *)forkTableView; + +- (NSArray *)forks; +- (void)setReadOpenPanelForFork:(BOOL)flag; +- (BOOL)readOpenPanelForFork; + +@end \ No newline at end of file diff --git a/Cocoa/Classes/OpenPanelDelegate.m b/Cocoa/Classes/OpenPanelDelegate.m new file mode 100644 index 0000000..2b65e5f --- /dev/null +++ b/Cocoa/Classes/OpenPanelDelegate.m @@ -0,0 +1,131 @@ +#import "OpenPanelDelegate.h" +#import "ApplicationDelegate.h" +#import "SizeFormatter.h" +#import "../Categories/NSString-FSSpec.h" + +@implementation OpenPanelDelegate + +- (id)init +{ + self = [super init]; + if(self) + { + forks = [[NSMutableArray alloc] init]; + readOpenPanelForFork = NO; + } + return self; +} + +- (void)awakeFromNib +{ + // remove this when functionality actually works + [addForkButton setEnabled:NO]; + [removeForkButton setEnabled:NO]; +} + +- (void)dealloc +{ + [forks release]; + [super dealloc]; +} + +// open panel delegate method +- (void)panelSelectionDidChange:(id)sender +{ + [forks setArray:[(ApplicationDelegate *)[NSApp delegate] forksForFile:[[sender filename] createFSRef]]]; + [forkTableView reloadData]; +} + +- (BOOL)readOpenPanelForFork +{ + return readOpenPanelForFork; +} + +- (void)setReadOpenPanelForFork:(BOOL)flag +{ + readOpenPanelForFork = flag; +} + +// table view data source methods +- (int)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [forks count]; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + // return object in array + if(row < [forks count]) + { + if([[tableColumn identifier] isEqualToString:@"forkname"]) + { + NSString *forkName = nil; + HFSUniStr255 *resourceForkName = (HFSUniStr255 *) NewPtrClear(sizeof(HFSUniStr255)); + OSErr error = FSGetResourceForkName(resourceForkName); + forkName = [(NSDictionary *)[forks objectAtIndex:row] objectForKey:[tableColumn identifier]]; + + // return custom names for data and resource forks + if([forkName isEqualToString:@""]) + forkName = NSLocalizedString(@"Data Fork", nil); + else if(!error && [forkName isEqualToString:[NSString stringWithCharacters:resourceForkName->unicode length:resourceForkName->length]]) + forkName = NSLocalizedString(@"Resource Fork", nil); + + DisposePtr((Ptr) resourceForkName); + return forkName; + } + + // return default value otherwise + return [(NSDictionary *)[forks objectAtIndex:row] objectForKey:[tableColumn identifier]]; + } + else return nil; +} + +- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + if([[tableColumn identifier] isEqualToString:@"forkname"]) + { + // update forks array + // create fork with new name + } +} + +- (IBAction)addFork:(id)sender +{ + // add placeholder to forks array + [forks addObject:[NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"UNTITLED_FORK", nil), @"forkname", [NSNumber numberWithInt:0], @"forksize", [NSNumber numberWithInt:0], @"forkallocation", nil]]; + [forkTableView noteNumberOfRowsChanged]; + [forkTableView reloadData]; + + // start editing placeholder + [forkTableView selectRow:[forks count]-1 byExtendingSelection:NO]; + [forkTableView editColumn:0 row:[forks count]-1 withEvent:nil select:YES]; +} + +- (IBAction)removeFork:(id)sender +{ + // display warning + // delete fork + + // update table view + [forks removeObjectAtIndex:[forkTableView selectedRow]+1]; + [forkTableView noteNumberOfRowsChanged]; + [forkTableView reloadData]; +} + +- (NSArray *)forks +{ + // returns an immutable array + return [NSArray arrayWithArray:forks]; +} + +- (NSView *)openPanelAccessoryView +{ + return openPanelAccessoryView; +} + +- (NSTableView *)forkTableView +{ + return forkTableView; +} + +@end \ No newline at end of file diff --git a/Cocoa/Classes/OutlineViewDelegate.h b/Cocoa/Classes/OutlineViewDelegate.h index e652e34..6765e93 100644 --- a/Cocoa/Classes/OutlineViewDelegate.h +++ b/Cocoa/Classes/OutlineViewDelegate.h @@ -1,5 +1,4 @@ #import -#import "NameFormatter.h" #import "SizeFormatter.h" #import "AttributesFormatter.h" @@ -7,20 +6,16 @@ @interface OutlineViewDelegate : NSObject { - IBOutlet NSWindow *window; - IBOutlet NameFormatter *nameFormatter; - IBOutlet SizeFormatter *sizeFormatter; - IBOutlet AttributesFormatter *attributesFormatter; + IBOutlet NSWindow *window; + IBOutlet NSOutlineView *outlineView; + IBOutlet SizeFormatter *sizeFormatter; + IBOutlet AttributesFormatter *attributesFormatter; } -int compareResourcesAscending( Resource *r1, Resource *r2, void *context ); -int compareResourcesDescending( Resource *r1, Resource *r2, void *context ); +int compareResourcesAscending(Resource *r1, Resource *r2, void *context); +int compareResourcesDescending(Resource *r1, Resource *r2, void *context); @end -@interface NSOutlineView (OutlineSortView) -- (void)swapForOutlineSortView; -@end - -@interface OutlineSortView : NSOutlineView +@interface RKOutlineView : NSOutlineView @end \ No newline at end of file diff --git a/Cocoa/Classes/OutlineViewDelegate.m b/Cocoa/Classes/OutlineViewDelegate.m index 5a86d23..efae584 100644 --- a/Cocoa/Classes/OutlineViewDelegate.m +++ b/Cocoa/Classes/OutlineViewDelegate.m @@ -1,11 +1,42 @@ #import "OutlineViewDelegate.h" #import "Resource.h" +#import "ResourceDocument.h" #import "ResourceDataSource.h" #import "ResourceNameCell.h" #import "ApplicationDelegate.h" @implementation OutlineViewDelegate +- (id)init +{ + self = [super init]; + if(!self) return nil; + if(NSAppKitVersionNumber >= 700.0) // darwin 7.0 == Mac OS 10.3, needed for -setPlaceholderString: + { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceholder:) name:ResourceNameDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceholder:) name:ResourceTypeDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceholder:) name:ResourceIDDidChangeNotification object:nil]; + } + return self; +} + +- (void)updatePlaceholder:(NSNotification *)notification +{ + Resource *resource = [notification object]; + ResourceNameCell *cell = (ResourceNameCell *) [[outlineView tableColumnWithIdentifier:@"name"] dataCellForRow:[outlineView rowForItem:resource]]; + if([[resource name] isEqualToString:@""]) + { + if([[resource resID] shortValue] == -16455) + [cell setPlaceholderString:NSLocalizedString(@"Custom Icon", nil)]; + else [cell setPlaceholderString:NSLocalizedString(@"Untitled Resource", nil)]; + } +} + +/*! +@method tableView:didClickTableColumn: +@pending not needed in 10.3+, use existing sort functionality +*/ + - (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn { NSArray *newResources; @@ -14,111 +45,156 @@ // sort the array NSImage *indicator = [tableView indicatorImageInTableColumn:tableColumn]; NSImage *upArrow = [NSTableView _defaultTableHeaderSortImage]; - if( indicator == upArrow ) - { - newResources = [oldResources sortedArrayUsingFunction:compareResourcesAscending context:(void*)[tableColumn identifier]]; - } - else - { - newResources = [oldResources sortedArrayUsingFunction:compareResourcesDescending context:(void*)[tableColumn identifier]]; - } + if(indicator == upArrow) + newResources = [oldResources sortedArrayUsingFunction:compareResourcesAscending context:[tableColumn identifier]]; + else newResources = [oldResources sortedArrayUsingFunction:compareResourcesDescending context:[tableColumn identifier]]; // swap new array for old one [(ResourceDataSource *)[tableView dataSource] setResources:[NSMutableArray arrayWithArray:newResources]]; [tableView reloadData]; } -int compareResourcesAscending( Resource *r1, Resource *r2, void *context ) +/*! +@function compareResourcesAscending +@updated 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare +*/ + +int compareResourcesAscending(Resource *r1, Resource *r2, void *context) { NSString *key = (NSString *)context; - SEL sel = NSSelectorFromString(key); - - if( [key isEqualToString:@"name"] || [key isEqualToString:@"type"] ) - { - // compare two NSStrings (case-insensitive) - return [(NSString *)[r1 performSelector:sel] caseInsensitiveCompare: (NSString *)[r2 performSelector:sel]]; - } - else - { - // compare two NSNumbers (or any other class) - return [(NSNumber *)[r1 performSelector:sel] compare: (NSNumber *)[r2 performSelector:sel]]; - } + // compare two NSStrings (case-insensitive) + if([key isEqualToString:@"name"] || [key isEqualToString:@"type"]) + return [(NSString *)[r1 valueForKey:key] caseInsensitiveCompare:(NSString *)[r2 valueForKey:key]]; + // compare two NSNumbers (or any other class) + else return [(NSNumber *)[r1 valueForKey:key] compare:(NSNumber *)[r2 valueForKey:key]]; } -int compareResourcesDescending( Resource *r1, Resource *r2, void *context ) +/*! +@function compareResourcesDescending +@updated 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare +*/ + +int compareResourcesDescending(Resource *r1, Resource *r2, void *context) { NSString *key = (NSString *)context; - SEL sel = NSSelectorFromString(key); - - if( [key isEqualToString:@"name"] || [key isEqualToString:@"type"] ) - { - // compare two NSStrings (case-insensitive) - return -1 * [(NSString *)[r1 performSelector:sel] caseInsensitiveCompare: (NSString *)[r2 performSelector:sel]]; - } - else - { - // compare two NSNumbers (or any other class) - return -1 * [(NSNumber *)[r1 performSelector:sel] compare: (NSNumber *)[r2 performSelector:sel]]; - } + // compare two NSStrings (case-insensitive) + if([key isEqualToString:@"name"] || [key isEqualToString:@"type"]) + return -1 * [(NSString *)[r1 valueForKey:key] caseInsensitiveCompare: (NSString *)[r2 valueForKey:key]]; + // compare two NSNumbers (or any other class) + else return -1 * [(NSNumber *)[r1 valueForKey:key] compare: (NSNumber *)[r2 valueForKey:key]]; } - (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item { - return YES; + if([[tableColumn identifier] isEqualToString:@"size"] || [[tableColumn identifier] isEqualToString:@"attributes"]) + return NO; + else return YES; } +/*! +@method outlineView:willDisplayCell:forTableColumn:item: +@updated 2003-10-25 NGS: Moved functionality of NameFormatter into this method, removed NameFormatter class. +@updated 2003-10-24 NGS: Swapped row colours so first row is white (as per 10.3), conditionalised drawing line background colours to system versions < 10.3, since in 10.3 it is handled by the nib file. +@updated 2003-10-24 NGS: Added iconForResourceType method to app delegate instead of interrogating the cache here. +@pending remove setting of the cell formatter when that capability is in interface builder +*/ + - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { - int row = [outlineView rowForItem:item]; + Resource *resource = (Resource *)item; NSString *identifier = [tableColumn identifier]; - if( [identifier isEqualToString:@"name"] ) [cell setFormatter:nameFormatter]; - else if( [identifier isEqualToString:@"size"] ) [cell setFormatter:sizeFormatter]; - else if( [identifier isEqualToString:@"attributes"] ) [cell setFormatter:attributesFormatter]; + + // set formatters for cells (remove when IB can set a formatter for an entire table column) + if([identifier isEqualToString:@"size"]) [cell setFormatter:sizeFormatter]; + else if([identifier isEqualToString:@"attributes"]) [cell setFormatter:attributesFormatter]; // set resource icon - if( [identifier isEqualToString:@"name"] ) + if([identifier isEqualToString:@"name"]) { -// [(ResourceNameCell *)cell setImage:[NSImage imageNamed:@"Resource file"]]; -// [(ResourceNameCell *)cell setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[(Resource *)item type]]]; - [(ResourceNameCell *)cell setImage:[[(ApplicationDelegate *)[NSApp delegate] icons] valueForKey:[(Resource *)item type]]]; + if(![resource representedFork]) + [(ResourceNameCell *)cell setImage:[(ApplicationDelegate *)[NSApp delegate] iconForResourceType:[resource type]]]; + else [(ResourceNameCell *)cell setImage:[(ApplicationDelegate *)[NSApp delegate] iconForResourceType:nil]]; + + if([[resource name] isEqualToString:@""]) + { + if([cell respondsToSelector:@selector(setPlaceholderString:)]) // 10.3+ + { + // 10.3+ uses placeholder strings + if([[resource resID] shortValue] == -16455) // don't bother checking type since there are too many icon types + [cell setPlaceholderString:NSLocalizedString(@"Custom Icon", nil)]; + else if([[resource type] isEqualToString:@"carb"] && [[resource resID] shortValue] == 0) + [cell setPlaceholderString:NSLocalizedString(@"Carbon Identifier", nil)]; + else if([[resource type] isEqualToString:@"pnot"] && [[resource resID] shortValue] == 0) + [cell setPlaceholderString:NSLocalizedString(@"File Preview", nil)]; + else if([[resource type] isEqualToString:@"STR "] && [[resource resID] shortValue] == -16396) + [cell setPlaceholderString:NSLocalizedString(@"Creator Information", nil)]; + else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 1) + [cell setPlaceholderString:NSLocalizedString(@"File Version", nil)]; + else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 2) + [cell setPlaceholderString:NSLocalizedString(@"Package Version", nil)]; + else [cell setPlaceholderString:NSLocalizedString(@"Untitled Resource", nil)]; + } + else + { + // pre-10.3, set text colour to grey and set title accordingly + if([[resource resID] shortValue] == -16455) + [cell setTitle:NSLocalizedString(@"Custom Icon", nil)]; + else if([[resource type] isEqualToString:@"carb"] && [[resource resID] shortValue] == 0) + [cell setTitle:NSLocalizedString(@"Carbon Identifier", nil)]; + else if([[resource type] isEqualToString:@"pnot"] && [[resource resID] shortValue] == 0) + [cell setTitle:NSLocalizedString(@"File Preview", nil)]; + else if([[resource type] isEqualToString:@"STR "] && [[resource resID] shortValue] == -16396) + [cell setTitle:NSLocalizedString(@"Creator Information", nil)]; + else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 1) + [cell setTitle:NSLocalizedString(@"File Version", nil)]; + else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 2) + [cell setTitle:NSLocalizedString(@"Package Version", nil)]; + else [cell setTitle:NSLocalizedString(@"Untitled Resource", nil)]; + +// if([[outlineView selectedItems] containsObject:resource]) +// [cell setTextColor:[NSColor whiteColor]]; +// else [cell setTextColor:[NSColor grayColor]]; + } + } } - if( row % 2 ) + // draw alternating blue/white backgrounds (if pre-10.3) + if(NSAppKitVersionNumber < 700.0) { - [cell setDrawsBackground:NO]; - [cell setBackgroundColor:[NSColor whiteColor]]; - } - else - { - [cell setDrawsBackground:YES]; - [cell setBackgroundColor:[NSColor colorWithCalibratedRed:0.93 green:0.95 blue:1.0 alpha:1.0]]; + int row = [outlineView rowForItem:item]; + if(row % 2) [cell setBackgroundColor:[NSColor colorWithCalibratedRed:0.93 green:0.95 blue:1.0 alpha:1.0]]; + else [cell setBackgroundColor:[NSColor whiteColor]]; + [cell setDrawsBackground:YES]; } } @end -@implementation NSOutlineView (OutlineSortView) +@implementation RKOutlineView -- (void)swapForOutlineSortView +/*! +@method draggingSourceOperationMaskForLocal: +*/ +- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)local { - isa = [OutlineSortView class]; + if(local) return NSDragOperationEvery; + else return NSDragOperationCopy; } -@end - -@implementation OutlineSortView - - (void)keyDown:(NSEvent *)event { - if( [self selectedRow] != -1 && [[event characters] isEqualToString:[NSString stringWithCString:"\r"]] ) - [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; + int selectedRow = [self selectedRow]; + if(selectedRow != -1 && [[event characters] isEqualToString:[NSString stringWithCString:"\r"]]) + [self editColumn:0 row:selectedRow withEvent:nil select:YES]; + else if(selectedRow != -1 && [[event characters] isEqualToString:[NSString stringWithCString:"\x7F"]]) + [(ResourceDocument *)[[[self window] windowController] document] deleteSelectedResources]; else [super keyDown:event]; } - (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)selector { // pressed return, end editing - if( selector == @selector(insertNewline:) ) + if(selector == @selector(insertNewline:)) { [[self window] makeFirstResponder:self]; [self abortEditing]; @@ -126,15 +202,15 @@ int compareResourcesDescending( Resource *r1, Resource *r2, void *context ) } // pressed tab, move to next editable field - else if( selector == @selector(insertTab:) ) + else if(selector == @selector(insertTab:)) { int newColumn = ([self editedColumn] +1) % [self numberOfColumns]; NSString *newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier]; - if( [newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"] ) + if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"]) { newColumn = (newColumn +1) % [self numberOfColumns]; newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier]; - if( [newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"] ) + if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"]) newColumn = (newColumn +1) % [self numberOfColumns]; } @@ -143,15 +219,15 @@ int compareResourcesDescending( Resource *r1, Resource *r2, void *context ) } // pressed shift-tab, move to previous editable field - else if( selector == @selector(insertBacktab:) ) + else if(selector == @selector(insertBacktab:)) { int newColumn = ([self editedColumn] + [self numberOfColumns] -1) % [self numberOfColumns]; NSString *newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier]; - if( [newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"] ) + if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"]) { newColumn = (newColumn + [self numberOfColumns] -1) % [self numberOfColumns]; newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier]; - if( [newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"] ) + if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"]) newColumn = (newColumn + [self numberOfColumns] -1) % [self numberOfColumns]; } @@ -162,42 +238,43 @@ int compareResourcesDescending( Resource *r1, Resource *r2, void *context ) return NO; } +/*! +@method _sendDelegateDidClickColumn: +@pending not needed in 10.3+, use existing sort functionality +*/ + //- (void)_sendDelegateDidMouseDownInHeader:(int)columnIndex - (void)_sendDelegateDidClickColumn:(int)columnIndex { - NSTableColumn *tableColumn = [[self tableColumns] objectAtIndex:columnIndex]; - NSImage *indicator = [self indicatorImageInTableColumn:tableColumn]; - NSImage *upArrow = [NSTableView _defaultTableHeaderSortImage]; - NSImage *downArrow = [NSTableView _defaultTableHeaderReverseSortImage]; - if( indicator ) +// if(NSAppKitVersionNumber < 700.0) { - // column already selected - if( indicator == upArrow ) - [self setIndicatorImage:downArrow inTableColumn:tableColumn]; - else [self setIndicatorImage:upArrow inTableColumn:tableColumn]; - } - else - { - // new column selected - if( [self highlightedTableColumn] != nil ) + NSTableColumn *tableColumn = [[self tableColumns] objectAtIndex:columnIndex]; + NSImage *indicator = [self indicatorImageInTableColumn:tableColumn]; + NSImage *upArrow = [NSTableView _defaultTableHeaderSortImage]; + NSImage *downArrow = [NSTableView _defaultTableHeaderReverseSortImage]; + if(indicator) + { + // column already selected + if(indicator == upArrow) + [self setIndicatorImage:downArrow inTableColumn:tableColumn]; + else [self setIndicatorImage:upArrow inTableColumn:tableColumn]; + } + else // new column selected { // if there is an existing selection, clear it's image - [self setIndicatorImage:nil inTableColumn:[self highlightedTableColumn]]; - } - - if( [[tableColumn identifier] isEqualToString:@"name"] || [[tableColumn identifier] isEqualToString:@"type"] ) - { + if([self highlightedTableColumn] != nil) + [self setIndicatorImage:nil inTableColumn:[self highlightedTableColumn]]; + // sort name and type columns ascending by default - [self setIndicatorImage:upArrow inTableColumn:tableColumn]; - } - else - { + if([[tableColumn identifier] isEqualToString:@"name"] || [[tableColumn identifier] isEqualToString:@"type"]) + [self setIndicatorImage:upArrow inTableColumn:tableColumn]; // sort all other columns descending by default - [self setIndicatorImage:downArrow inTableColumn:tableColumn]; + else [self setIndicatorImage:downArrow inTableColumn:tableColumn]; + [self setHighlightedTableColumn:tableColumn]; } - [self setHighlightedTableColumn:tableColumn]; + [[self delegate] tableView:self didClickTableColumn:tableColumn]; } - [[self delegate] tableView:self didClickTableColumn:tableColumn]; +// else [super _sendDelegateDidClickColumn:columnIndex]; } @end \ No newline at end of file diff --git a/Cocoa/Classes/PasteboardDocument.m b/Cocoa/Classes/PasteboardDocument.m index f275c16..0071fef 100644 --- a/Cocoa/Classes/PasteboardDocument.m +++ b/Cocoa/Classes/PasteboardDocument.m @@ -1,6 +1,8 @@ #import "PasteboardDocument.h" #import "Resource.h" +extern NSString *RKResourcePboardType; + @implementation PasteboardDocument - (id)init @@ -13,40 +15,44 @@ return self; } --(void) readPasteboard:(NSString *)pbName +-(void)readPasteboard:(NSString *)pbName { - NSPasteboard *pb = [NSPasteboard pasteboardWithName:pbName]; - NSArray *types = [pb types]; - NSEnumerator *enumerator = [types objectEnumerator]; - NSString *currentType; + // this method is mostly a duplicate of -[ResourceDocument paste:] but takes a pasteboard name for an argument + NSPasteboard *pb = [NSPasteboard pasteboardWithName:pbName]; + NSEnumerator *enumerator = [[pb types] objectEnumerator]; + NSString *pbType; + // clear current pasteboard representation + [self selectAll:nil]; + [self clear:nil]; + + // set the window's title to represent the pasteboard being shown (at some point I anticipate having several of these) + [[self window] setTitle:pbName]; + + // disable undos during loading [[self undoManager] disableUndoRegistration]; - while( currentType = [enumerator nextObject] ) + + // get all types off the pasteboard + while( pbType = [enumerator nextObject] ) { - // create the resource & add it to the array - NSString *name = pbName; - NSString *type; - NSNumber *resID; - NSNumber *attributes; - NSData *data; - Resource *resource; - NS_DURING - type = [currentType substringToIndex:3]; - NS_HANDLER - type = currentType; - NS_ENDHANDLER - resID = [NSNumber numberWithShort:0]; - attributes = [NSNumber numberWithShort:0]; - data = [pb dataForType:type]; - resource = [Resource resourceOfType:type andID:resID withName:name andAttributes:attributes data:data]; - [resources addObject:resource]; // array retains resource + // 'paste' any resources into pbdoc's data source + if( [pbType isEqualToString:RKResourcePboardType] ) + [self pasteResources:[NSUnarchiver unarchiveObjectWithData:[pb dataForType:RKResourcePboardType]]]; + else + { + // create the faux resource & add it to the array + Resource *resource = [Resource resourceOfType:nil andID:nil withName:pbType andAttributes:nil data:[pb dataForType:pbType]]; + [resources addObject:resource]; // array retains resource + } } + + // re-enable undos [[self undoManager] enableUndoRegistration]; [outlineView reloadData]; } --(void) windowDidBecomeKey: (NSNotification*)notification +-(void)windowDidBecomeKey:(NSNotification *)notification { // This mess sponsored by Uli Kusterer ;-) generalChangeCount = [[NSPasteboard generalPasteboard] changeCount]; diff --git a/Cocoa/Classes/PrefsWindowController.h b/Cocoa/Classes/PrefsWindowController.h index e116df8..6c98d28 100644 --- a/Cocoa/Classes/PrefsWindowController.h +++ b/Cocoa/Classes/PrefsWindowController.h @@ -31,10 +31,3 @@ enum LaunchAction + (id)sharedPrefsWindowController; @end - -@interface NSString (BooleanSupport) - -- (BOOL)boolValue; -+ (NSString *)stringWithBool:(BOOL)boolean; - -@end \ No newline at end of file diff --git a/Cocoa/Classes/PrefsWindowController.m b/Cocoa/Classes/PrefsWindowController.m index c749013..c70295f 100644 --- a/Cocoa/Classes/PrefsWindowController.m +++ b/Cocoa/Classes/PrefsWindowController.m @@ -4,9 +4,7 @@ - (id)init { - self = [self initWithWindowNibName:@"PrefsWindow"]; - if( self ) [self setWindowFrameAutosaveName:@"ResKnife Preferences"]; - return self; + return [self initWithWindowNibName:@"PrefsWindow"]; } - (void)dealloc @@ -19,6 +17,7 @@ { // represent current prefs in window state [self updatePrefs:nil]; + [[self window] center]; // listen out for pref changes from elsewhere [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePrefs:) name:NSUserDefaultsDidChangeNotification object:nil]; @@ -63,8 +62,8 @@ [defaults setBool:autosave forKey:@"Autosave"]; [defaults setInteger:autosaveInterval forKey:@"AutosaveInterval"]; [defaults setBool:deleteResourceWarning forKey:@"DeleteResourceWarning"]; - if( createNewDocument ) [defaults setObject:@"OpenUntitledFile" forKey:@"LaunchAction"]; - else if( displayOpenPanel ) [defaults setObject:@"DisplayOpenPanel" forKey:@"LaunchAction"]; + if(createNewDocument) [defaults setObject:@"OpenUntitledFile" forKey:@"LaunchAction"]; + else if(displayOpenPanel) [defaults setObject:@"DisplayOpenPanel" forKey:@"LaunchAction"]; else [defaults setObject:@"None" forKey:@"LaunchAction"]; [defaults synchronize]; } @@ -101,26 +100,9 @@ + (id)sharedPrefsWindowController { static PrefsWindowController *sharedPrefsWindowController = nil; - if( !sharedPrefsWindowController ) - { sharedPrefsWindowController = [[PrefsWindowController allocWithZone:[self zone]] init]; - } return sharedPrefsWindowController; } @end - -@implementation NSString (BooleanSupport) - -- (BOOL)boolValue -{ - return [self isEqualToString:@"YES"]; -} - -+ (NSString *)stringWithBool:(BOOL)boolean -{ - return boolean? @"YES" : @"NO"; -} - -@end diff --git a/Cocoa/Classes/RKDocumentController.m b/Cocoa/Classes/RKDocumentController.m index 96bcb17..f25eb67 100644 --- a/Cocoa/Classes/RKDocumentController.m +++ b/Cocoa/Classes/RKDocumentController.m @@ -1,29 +1,26 @@ #import "RKDocumentController.h" #import "ApplicationDelegate.h" -#import "OpenFileDataSource.h" +#import "OpenPanelDelegate.h" @implementation RKDocumentController -// because I swap the isa pointer I can't add instance variables, so use statics instead (there will only ever be one RKDocumentController) -static id oldDelegate = nil; - -- (id)init -{ - self = [super init]; - if( self ) - { - // for some reason calling -[super init] causes a new instance of self to be returned (which is not of my subclass) so to get my overridden methods called again, I have to do this... - isa = [RKDocumentController class]; - oldDelegate = [[NSOpenPanel openPanel] delegate]; - [[NSOpenPanel openPanel] setDelegate:[[[OpenPanelDelegate alloc] init] autorelease]]; - } - return self; -} - - (int)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)extensions { - [openPanel setAccessoryView:[(ApplicationDelegate *)[NSApp delegate] openAuxView]]; - return [super runModalOpenPanel:openPanel forTypes:extensions]; + // set-up open panel (this happens every time, but no harm done) + ApplicationDelegate *appDelegate = [NSApp delegate]; + OpenPanelDelegate *openPanelDelegate = [appDelegate openPanelDelegate]; + NSView *openPanelAccessoryView = [openPanelDelegate openPanelAccessoryView]; + [openPanel setDelegate:openPanelDelegate]; + [openPanel setAccessoryView:openPanelAccessoryView]; + [openPanel setAllowsOtherFileTypes:YES]; + [openPanel setTreatsFilePackagesAsDirectories:YES]; + [openPanelAccessoryView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + + // run panel + int button = [super runModalOpenPanel:openPanel forTypes:extensions]; + if(button == NSOKButton) + [openPanelDelegate setReadOpenPanelForFork:YES]; + return button; } @end diff --git a/Cocoa/Classes/RKEditorRegistry.h b/Cocoa/Classes/RKEditorRegistry.h index e0e0f4b..42144db 100644 --- a/Cocoa/Classes/RKEditorRegistry.h +++ b/Cocoa/Classes/RKEditorRegistry.h @@ -32,13 +32,12 @@ @interface RKEditorRegistry : NSObject { - NSMutableDictionary* typeRegistry; // Private. Use editorForType: to access this. +@private + NSMutableDictionary *typeRegistry; } -+(RKEditorRegistry*) mainRegistry; // There's usually only one object, and this returns or creates it. - --(IBAction) scanForPlugins: (id)sender; // Called automatically by mainRegistry. --(Class) editorForType: (NSString*)typeStr; // You probably want to call this. - ++ (RKEditorRegistry *)defaultRegistry; // There's usually only one object, and this returns or creates it. +- (IBAction)scanForPlugins:(id)sender; // Called automatically by mainRegistry. +- (Class)editorForType:(NSString *)typeStr; // You probably want to call this. @end diff --git a/Cocoa/Classes/RKEditorRegistry.m b/Cocoa/Classes/RKEditorRegistry.m index d9fc994..52e2e75 100644 --- a/Cocoa/Classes/RKEditorRegistry.m +++ b/Cocoa/Classes/RKEditorRegistry.m @@ -22,130 +22,159 @@ -------------------------------------------------------------------------- */ #import "RKEditorRegistry.h" +#import "RKSupportResourceRegistry.h" +#import "NSString-FSSpec.h" // for ResKnifeBoolExtensions (in wrong file) - -/* ----------------------------------------------------------------------------- - Globals: - -------------------------------------------------------------------------- */ - -RKEditorRegistry* gRKEditorRegistryMainRegistry = nil; // Access through +mainRegistry! - +/*! +@class RKEditorRegistry +@author Uli Kusterer +@created 2003-07-31 +@description This is a registry where all our resource-editor plugins are looked + up and entered in a list, so you can ask for the editor for a specific + resource type and it is returned immediately. This registry reads the + types a plugin handles from their info.plist. This is better than + encoding the type in the plugin file name, as file names are not + guaranteed to be on a case-sensitive file system on Mac, and this also + allows an editor to register for several resource types. +*/ @implementation RKEditorRegistry -/* ----------------------------------------------------------------------------- - mainRegistry: - Returns the main plugin registry of this application, instantiating - it first if there is none yet. As soon as this is instantiated, the - plugins are loaded. - - REVISIONS: - 2003-07-31 UK Created. - -------------------------------------------------------------------------- */ - -+(RKEditorRegistry*) mainRegistry +/*! +@method +defaultRegistry +@author Uli Kusterer +@created 2003-07-31 +@updated 2003-10-28 NGS: Changed method name from +mainRegistry (so it more closly matchs +defaultCenter) and moved global var inside method, making it a static. +@description Returns the default plugin registry of this application, instantiating it first if there is none yet. As soon as this is instantiated, the plugins are loaded. +*/ ++ (RKEditorRegistry *)defaultRegistry { - if( !gRKEditorRegistryMainRegistry ) + static RKEditorRegistry *defaultRegistry = nil; + if(!defaultRegistry) { - gRKEditorRegistryMainRegistry = [[RKEditorRegistry alloc] init]; - [gRKEditorRegistryMainRegistry scanForPlugins: gRKEditorRegistryMainRegistry]; + defaultRegistry = [[RKEditorRegistry alloc] init]; + [defaultRegistry scanForPlugins:nil]; } - return gRKEditorRegistryMainRegistry; + return defaultRegistry; } - -/* ----------------------------------------------------------------------------- - awakeFromNib: - Makes sure that if an instance of this is instantiated from a NIB file, - it automatically loads the plugins. - - REVISIONS: - 2003-07-31 UK Created. - -------------------------------------------------------------------------- */ - --(void) awakeFromNib +/*! +@method awakeFromNib +@abstract Makes sure that if an instance of this is instantiated from a nib file, it automatically loads the plugins. +@author Uli Kusterer +@created 2003-07-31 +*/ +- (void)awakeFromNib { - [self scanForPlugins: self]; + [self scanForPlugins:nil]; } +/*! +@method scanForPlugins: +@abstract (Re)loads our list of plugins. You can use this as an action for a menu item, if you want. +@author Uli Kusterer +@created 2003-07-31 +@updated 2003-10-28 NGS: Updated to look for more sophisticated RKSupportedTypes key in addition to (the now deprecated) RKEditedTypes. +@pending Use NSSearchPathForDirectoriesInDomains() or equivalent to get folder paths instead of hard coding them. +@pending Currently, Cocoa classes can't be unloaded, which means we're + not leaking the NSBundles we load here. However, if this one + day shouldn't hold true anymore, we'll want to retain these + bundles in our dictionary and do the principalClass thingie + in editorForType: instead, which allows us to get rid of the + class and its bundle when reloading the plugin list by simply + relying on NSMutableDictionary to release it. -/* ----------------------------------------------------------------------------- - scanForPlugins: - (Re)loads our list of plugins. You can use this as an action for a menu - item, if you want. - - This scans the application's internal Plugins folder, - ~/Library/Application Support/ResKnife/Plugins/ and - /Library/Application Support/ResKnife/Plugins/ for plugins that have - the extension ".plugin" and implement initWithResource: (which means - this won't get into the way if you want to support other kinds of - plugins). - - It builds a registry of Class objects in an NSMutableDictionary, where - the key is the resource type. If a plugin supports several resource - types (as indicated by the RKEditedTypes key in its Info.plist), it - will be registered for these types as well. If several plugins register - for the same type, the last one loaded wins. - - To instantiate an object from a plugin, see the method below. - - TODO: - Currently, Cocoa classes can't be unloaded, which means we're not - leaking the NSBundles we load here. However, if this one day shouldn't - hold true anymore, we'll want to retain these bundles in our dictionary - and do the principalClass thingie in editorForType: instead, which - allows us to get rid of the class and its bundle when reloading the - plugin list by simply relying on NSMutableDictionary to release it. - - REVISIONS: - 2003-07-31 UK Created. - -------------------------------------------------------------------------- */ - --(IBAction) scanForPlugins: (id)sender +@description This scans the application's internal Plugins folder, + ~/Library/Application Support/ResKnife/Plugins/ and + /Library/Application Support/ResKnife/Plugins/ for + plugins that have the extension ".plugin" and implement + initWithResource: (which means this won't get into + the way if you want to support other kinds of plugins).

+ +

It builds a registry of Class objects in an NSMutableDictionary, + where the key is the resource type. If a plugin supports several + resource types (as indicated by the RKEditedTypes key in it's + Info.plist), it will be registered for these types as well. + If several plugins register for the same type, the last one + loaded wins.

+ +

To instantiate an object from a plugin, see editorForType: +*/ +- (IBAction)scanForPlugins:(id)sender { - // TODO: Instead of hard-coding sysPath we should use some FindFolder-like API! - Class pluginClass; NSString *appSupport = @"Library/Application Support/ResKnife/Plugins/"; NSString *appPath = [[NSBundle mainBundle] builtInPlugInsPath]; NSString *userPath = [NSHomeDirectory() stringByAppendingPathComponent:appSupport]; NSString *sysPath = [@"/" stringByAppendingPathComponent:appSupport]; - NSArray *paths = [NSArray arrayWithObjects:appPath, userPath, sysPath, nil]; - NSEnumerator *pathEnum = [paths objectEnumerator]; +// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory, NSAllDomainsMask, YES); + NSEnumerator *pathEnumerator = [[NSArray arrayWithObjects:appPath, userPath, sysPath, nil] objectEnumerator]; NSString *path; - if( typeRegistry ) - [typeRegistry release]; + // release any existing registry to clear old values + if(typeRegistry) [typeRegistry release]; typeRegistry = [[NSMutableDictionary alloc] init]; - while( path = [pathEnum nextObject] ) + // scan all paths + while(path = [pathEnumerator nextObject]) { - NSEnumerator *e = [[[NSFileManager defaultManager] directoryContentsAtPath:path] objectEnumerator]; - NSString *name; + NSEnumerator *fileEnumerator = [[[NSFileManager defaultManager] directoryContentsAtPath:path] objectEnumerator]; + NSString *pluginName; - while( name = [e nextObject] ) + // enumerate all files in this directory + while(pluginName = [fileEnumerator nextObject]) { - name = [path stringByAppendingPathComponent:name]; - NSLog(@"Examining %@", name); - if( [[name pathExtension] isEqualToString:@"plugin"] ) + NSString *pluginPath = [path stringByAppendingPathComponent:pluginName]; +// NSLog(@"Examining %@", pluginPath); + + // verify file is a plugin + if([[pluginName pathExtension] isEqualToString:@"plugin"]) { - NSBundle *plugin = [NSBundle bundleWithPath: name]; - - if( pluginClass = [plugin principalClass] ) + NSBundle *plugin = [NSBundle bundleWithPath:pluginPath]; + Class pluginClass = [plugin principalClass]; + if(plugin && pluginClass) { - if( [pluginClass instancesRespondToSelector:@selector(initWithResource:)] ) +// NSLog(@"Principal class %@ %@ to ResKnifePluginProtocol", NSStringFromClass(pluginClass), [pluginClass conformsToProtocol:@protocol(ResKnifePluginProtocol)]? @"conforms":@"does not conform"); + + // check principal class implements ResKnifePluginProtocol + if([pluginClass conformsToProtocol:@protocol(ResKnifePluginProtocol)]) { - NSString *resType; - NSArray *types = [[plugin infoDictionary] objectForKey:@"RKEditedTypes"]; - NSEnumerator *enny; - - if( types == nil ) - types = [NSArray arrayWithObject: [[plugin infoDictionary] objectForKey:@"RKEditedType"]]; - - for( enny = [types objectEnumerator]; resType = [enny nextObject]; ) + NSArray *supportedTypes = [[plugin infoDictionary] objectForKey:@"RKSupportedTypes"]; + if(supportedTypes) { - [typeRegistry setObject:pluginClass forKey:resType]; - NSLog(@"Registered for type %@.",resType); + NSDictionary *typeEntry; + NSEnumerator *typesEnumerator = [supportedTypes objectEnumerator]; + + // enumerate entries + while(typeEntry = [typesEnumerator nextObject]) + { + // get values for type entry + NSString *name = [typeEntry objectForKey:@"RKTypeName"]; + NSString *role = [typeEntry objectForKey:@"RKTypeRole"]; + BOOL isDefault = [(NSString *)[typeEntry objectForKey:@"IsResKnifeDefaultForType"] boolValue]; + + // register them + [typeRegistry setObject:pluginClass forKey:name]; // bug: very primative, doesn't use extra data +// NSLog(@"Plug-in class %@ registered as %@%@ for type %@.", NSStringFromClass(pluginClass), isDefault? @"default ":@"", role, name); + } } + else + { + // try the old way of looking up types + NSString *resType; + NSEnumerator *enny; + supportedTypes = [[plugin infoDictionary] objectForKey:@"RKEditedTypes"]; + if(supportedTypes == nil) + supportedTypes = [NSArray arrayWithObject: [[plugin infoDictionary] objectForKey:@"RKEditedType"]]; + + for(enny = [supportedTypes objectEnumerator]; resType = [enny nextObject];) + { + [typeRegistry setObject:pluginClass forKey:resType]; +// NSLog(@"Registered for type %@.",resType); + } + } + + // load any support resources in the plug-in + [RKSupportResourceRegistry scanForSupportResourcesInFolder:[[plugin resourcePath] stringByAppendingPathComponent:@"Support Resources"]]; } } } @@ -169,13 +198,11 @@ RKEditorRegistry* gRKEditorRegistryMainRegistry = nil; // Access through +mainR 2003-07-31 UK Created. -------------------------------------------------------------------------- */ --(Class) editorForType: (NSString*)typeStr +- (Class)editorForType:(NSString *)typeStr { - Class theClass = [typeRegistry objectForKey: typeStr]; - if( !theClass ) - return Nil; - - return theClass; + Class theClass = [typeRegistry objectForKey: typeStr]; + if(!theClass) return Nil; + else return theClass; } @end diff --git a/Cocoa/Classes/RKSupportResourceRegistry.h b/Cocoa/Classes/RKSupportResourceRegistry.h index d02231d..58ba0e2 100644 --- a/Cocoa/Classes/RKSupportResourceRegistry.h +++ b/Cocoa/Classes/RKSupportResourceRegistry.h @@ -11,10 +11,7 @@ @interface RKSupportResourceRegistry : NSObject { - } - -+(void) scanForSupportResources: (NSDocumentController*)c; - - ++ (void)scanForSupportResources; ++ (void)scanForSupportResourcesInFolder:(NSString *)path; @end diff --git a/Cocoa/Classes/RKSupportResourceRegistry.m b/Cocoa/Classes/RKSupportResourceRegistry.m index 4ec704a..a8b367a 100644 --- a/Cocoa/Classes/RKSupportResourceRegistry.m +++ b/Cocoa/Classes/RKSupportResourceRegistry.m @@ -1,44 +1,32 @@ -// -// RKSupportResourceRegistry.m -// ResKnife -// -// Created by Uli Kusterer on Mon Aug 18 2003. -// Copyright (c) 2003 __MyCompanyName__. All rights reserved. -// - #import "RKSupportResourceRegistry.h" - +#import "NGSCategories.h" @implementation RKSupportResourceRegistry -+(void) scanForSupportResources: (NSDocumentController*)c ++ (void)scanForSupportResources { // TODO: Instead of hard-coding sysPath we should use some FindFolder-like API! - NSString *appSupport = @"Library/Application Support/ResKnife/Support Resources/"; - NSString *appPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Support Resources"]; - NSString *userPath = [NSHomeDirectory() stringByAppendingPathComponent:appSupport]; - NSString *sysPath = [@"/" stringByAppendingPathComponent:appSupport]; - NSArray *paths = [NSArray arrayWithObjects:appPath, userPath, sysPath, nil]; - NSEnumerator *pathEnum = [paths objectEnumerator]; - NSString *path; - - while( path = [pathEnum nextObject] ) +#if MAC_OS_X_VERSION_10_4 <= MAC_OS_X_VERSION_MAX_ALLOWED + NSArray *dirsArray = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSAllDomainsMask, YES); + dirsArray = [dirsArray arrayByMakingObjectsPerformSelector:@selector(stringByAppendingPathComponent:) withObject:@"ResKnife/Support Resources"]; +#endif + [RKSupportResourceRegistry scanForSupportResourcesInFolder:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Support Resources"]]; + [RKSupportResourceRegistry scanForSupportResourcesInFolder:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/ResKnife/Support Resources"]]; + [RKSupportResourceRegistry scanForSupportResourcesInFolder:@"/Library/Application Support/ResKnife/Support Resources"]; + [RKSupportResourceRegistry scanForSupportResourcesInFolder:@"/Network/Library/Application Support/ResKnife/Support Resources"]; +} + ++ (void)scanForSupportResourcesInFolder:(NSString *)path +{ +// NSLog(@"Looking for resources in %@", path); + NSString *name; + NSEnumerator *enumerator = [[[NSFileManager defaultManager] directoryContentsAtPath:path] objectEnumerator]; + while(name = [enumerator nextObject]) { - NSEnumerator *e = [[[NSFileManager defaultManager] directoryContentsAtPath:path] objectEnumerator]; - NSString *name; - - NSLog(@"Looking for resources in %@", path); - - while( name = [e nextObject] ) - { - name = [path stringByAppendingPathComponent:name]; - NSLog(@"Examining %@", name); - if( [[name pathExtension] isEqualToString:@"rsrc"] ) - { - [c openDocumentWithContentsOfFile:name display:YES]; - //[[[[[c openDocumentWithContentsOfFile:name display:YES] windowControllers] objectAtIndex:0] window] orderOut: self]; - } - } +// NSLog(@"Examining %@", name); + if([[name pathExtension] isEqualToString:@"rsrc"]) + // FIXME: this method was deprecate in 10.4 in favour of - (id)openDocumentWithContentsOfURL:(NSURL *)absoluteURL display:(BOOL)displayDocument error:(NSError **)outError; + [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:[path stringByAppendingPathComponent:name] display:YES]; } } diff --git a/Cocoa/Classes/Resource.h b/Cocoa/Classes/Resource.h index df7f9f7..596e242 100644 --- a/Cocoa/Classes/Resource.h +++ b/Cocoa/Classes/Resource.h @@ -1,5 +1,12 @@ #import -#import "ResKnifeResourceProtocol.h" +#import "../Plug-Ins/ResKnifeResourceProtocol.h" + +/*! +@class Resource +@author Nicholas Shanks +@abstract Encapsulates a single resource and all associated meta-data. +@description The Resource class fully complies with key-value coding, with the keys @"name", @"type", @"resID", @"attributes", @"data", @"dirty" and @"representedFork" available. +*/ @interface Resource : NSObject { @@ -17,13 +24,16 @@ // the actual data NSData *data; - NSDocument *document; // Our owner. + // the document name for display to the user; updating this is the responsibility of the document itself + NSString *_docName; } // accessor methods not part of the protocol +- (void)_setName:(NSString *)newName; - (void)setDirty:(BOOL)newValue; - (NSString *)representedFork; - (void)setRepresentedFork:(NSString *)forkName; +- (void)setDocumentName:(NSString *)docName; // init methods - (id)initWithType:(NSString *)typeValue andID:(NSNumber *)resIDValue; @@ -35,7 +45,4 @@ + (id)resourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue withName:(NSString *)nameValue andAttributes:(NSNumber *)attributesValue; + (id)resourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue withName:(NSString *)nameValue andAttributes:(NSNumber *)attributesValue data:(NSData *)dataValue; --(void) setDocument: (NSDocument*)doc; --(NSDocument*) document; // Resource protocol guarantees this. - @end diff --git a/Cocoa/Classes/Resource.m b/Cocoa/Classes/Resource.m index 9541328..7c41543 100644 --- a/Cocoa/Classes/Resource.m +++ b/Cocoa/Classes/Resource.m @@ -2,7 +2,7 @@ #import "ResourceDocument.h" #import "ResourceDataSource.h" -NSString *RKResourcePboardType = @"RKResourcePboardType"; +NSString *RKResourcePboardType = @"RKResourcePboardType"; @implementation Resource @@ -58,17 +58,17 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; return [resource autorelease]; } -+ (Resource *)getResourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue inDocument:(NSDocument *)document ++ (Resource *)getResourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue inDocument:(NSDocument *)searchDoc { NSDocument *doc; NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; - while( doc = [enumerator nextObject] ) + while(doc = [enumerator nextObject]) { - if( document == nil || document == doc ) + if(searchDoc == nil || searchDoc == doc) { // parse document for correct resource Resource *resource = [[(ResourceDocument *)doc dataSource] resourceOfType:typeValue andID:resIDValue]; - if( resource ) return resource; + if(resource) return resource; } } return nil; @@ -76,47 +76,65 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; /* ResKnifeResourceProtocol implementation */ -+ (NSArray *)allResourcesOfType:(NSString *)typeValue inDocument:(NSDocument *)document ++ (NSArray *)allResourcesOfType:(NSString *)typeValue inDocument:(NSDocument *)searchDoc { NSMutableArray *array = [NSMutableArray array]; NSDocument *doc; NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; - while( doc = [enumerator nextObject] ) + while(doc = [enumerator nextObject]) { // parse document for resources - if( document == nil || document == doc ) + if(searchDoc == nil || searchDoc == doc) [array addObjectsFromArray:[[(ResourceDocument *)doc dataSource] allResourcesOfType:typeValue]]; } return [NSArray arrayWithArray:array]; } -+ (Resource *)resourceOfType:(NSString *)typeValue withName:(NSString *)nameValue inDocument:(NSDocument *)document ++ (Resource *)resourceOfType:(NSString *)typeValue withName:(NSString *)nameValue inDocument:(NSDocument *)searchDoc { NSDocument *doc; NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; - while( doc = [enumerator nextObject] ) + while(doc = [enumerator nextObject]) { - if( document == nil || document == doc ) + if(searchDoc == nil || searchDoc == doc) { // parse document for correct resource Resource *resource = [[(ResourceDocument *)doc dataSource] resourceOfType:typeValue withName:nameValue]; - if( resource ) return resource; + if(resource) return resource; } } return nil; } -+ (id)resourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue inDocument:(NSDocument *)document ++ (Resource *)resourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue inDocument:(NSDocument *)searchDoc { NSDocument *doc; NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; - while( doc = [enumerator nextObject] ) + while(doc = [enumerator nextObject]) { - if( document == nil || document == doc ) + if(searchDoc == nil || searchDoc == doc) { // parse document for correct resource Resource *resource = [[(ResourceDocument *)doc dataSource] resourceOfType:typeValue andID:resIDValue]; - if( resource ) return resource; + if(resource) return resource; + } + } + return nil; +} + +// should probably be in resource document, not resource, but it fits in with the above methods quite well ++ (NSDocument *)documentForResource:(Resource *)resource +{ + NSDocument *doc; + NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; + while(doc = [enumerator nextObject]) + { + Resource *res; + NSEnumerator *enumerator2 = [[(ResourceDocument *)doc resources] objectEnumerator]; + while(res = [enumerator2 nextObject]) + { + if([res isEqual:resource]) + return doc; } } return nil; @@ -130,16 +148,18 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; [resID release]; [attributes release]; [data release]; + [_docName release]; [super dealloc]; } - (id)copyWithZone:(NSZone *)zone { Resource *copy = [[Resource alloc] initWithType:type andID:resID withName:name andAttributes:attributes data:[data copy]]; + [copy setDocumentName:_docName]; return copy; } -/* Accessors */ +/* accessors */ - (void)touch { @@ -157,19 +177,16 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceDidChangeNotification object:self]; } - --(void) setDocument: (NSDocument*)doc +- (NSDocument *)document { - document = doc; // It owns us, so don't retain, or we could get a closed loop! + return [Resource documentForResource:self]; } - --(NSDocument*) document +- (void)setDocumentName:(NSString *)docName { - return document; + _docName = [docName copy]; } - - (NSString *)representedFork { return representedFork; @@ -185,31 +202,37 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; return name; } +// shouldn't need this - it's used by forks to give them alternate names - should use name formatter replacement instead +- (void)_setName:(NSString *)newName +{ + id old = name; + name = [newName copy]; + [old release]; +} + - (void)setName:(NSString *)newName { - if( ![name isEqualToString:newName] ) + if(![name isEqualToString:newName]) { [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillChangeNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceNameWillChangeNotification object:self]; - [name autorelease]; + id old = name; name = [newName copy]; + [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceNameDidChangeNotification object:self]; + // bug: this line is causing crashes! +// [[NSNotificationCenter defaultCenter] postNotificationName:ResourceNameDidChangeNotification object:self]; [self setDirty:YES]; } } - --(NSString*) nameForEditorWindow +- (NSString *)defaultWindowTitle { - if( [name length] > 0 ) - return [NSString stringWithFormat: @"%@: '%@' ID=%@ \"%@\"", [document displayName], type, resID, name]; - else - return [NSString stringWithFormat: @"%@: '%@' ID=%@", [document displayName], type, resID]; + if([name length] > 0) return [NSString stringWithFormat: NSLocalizedString(@"%@: %@ %@ '%@'", @"default window title format with resource name"), _docName, type, resID, name]; + else return [NSString stringWithFormat: NSLocalizedString(@"%@: %@ %@", @"default window title format without resource name"), _docName, type, resID]; } - - (NSString *)type { return type; @@ -217,15 +240,17 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; - (void)setType:(NSString *)newType { - if( ![type isEqualToString:newType] ) + if(![type isEqualToString:newType]) { [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillChangeNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceTypeWillChangeNotification object:self]; - [type autorelease]; + id old = type; type = [newType copy]; + [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceTypeDidChangeNotification object:self]; + // bug: this line is causing crashes! +// [[NSNotificationCenter defaultCenter] postNotificationName:ResourceTypeDidChangeNotification object:self]; [self setDirty:YES]; } } @@ -237,15 +262,17 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; - (void)setResID:(NSNumber *)newResID { - if( ![resID isEqualToNumber:newResID] ) + if(![resID isEqualToNumber:newResID]) { [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillChangeNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceIDWillChangeNotification object:self]; - [resID autorelease]; + id old = resID; resID = [newResID copy]; + [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceIDDidChangeNotification object:self]; + // bug: this line is causing crashes! +// [[NSNotificationCenter defaultCenter] postNotificationName:ResourceIDDidChangeNotification object:self]; [self setDirty:YES]; } } @@ -257,15 +284,17 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; - (void)setAttributes:(NSNumber *)newAttributes { - if( ![attributes isEqualToNumber:newAttributes] ) + if(![attributes isEqualToNumber:newAttributes]) { [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillChangeNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceAttributesWillChangeNotification object:self]; - [attributes autorelease]; + id old = attributes; attributes = [newAttributes copy]; + [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceAttributesDidChangeNotification object:self]; + // bug: this line is causing crashes! +// [[NSNotificationCenter defaultCenter] postNotificationName:ResourceAttributesDidChangeNotification object:self]; [self setDirty:YES]; } } @@ -282,14 +311,15 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; - (void)setData:(NSData *)newData { - if( ![data isEqualToData:newData] ) + if(![data isEqualToData:newData]) { [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillChangeNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceDataWillChangeNotification object:self]; // note: this function retains, rather than copies, the supplied data - [data autorelease]; + id old = data; data = [newData retain]; + [old release]; [[NSNotificationCenter defaultCenter] postNotificationName:ResourceDataDidChangeNotification object:self]; [self setDirty:YES]; @@ -301,7 +331,7 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; - (id)initWithCoder:(NSCoder *)decoder { self = [super init]; - if( self ) + if(self) { dirty = YES; name = [[decoder decodeObject] retain]; diff --git a/Cocoa/Classes/ResourceDataSource.h b/Cocoa/Classes/ResourceDataSource.h index 37c3abe..193eebc 100644 --- a/Cocoa/Classes/ResourceDataSource.h +++ b/Cocoa/Classes/ResourceDataSource.h @@ -2,6 +2,11 @@ @class ResourceDocument, Resource; +/*! +@class ResourceDataSource +@pending This class needs to be made KVC compliant. +*/ + @interface ResourceDataSource : NSObject { IBOutlet NSOutlineView *outlineView; @@ -11,18 +16,59 @@ NSMutableArray *resources; } +/*! +@method window +*/ - (NSWindow *)window; + +/*! +@method resources +*/ - (NSArray *)resources; + +/*! +@method setResources: +*/ - (void)setResources:(NSMutableArray *)newResources; + +/*! +@method addResource: +*/ - (void)addResource:(Resource *)resource; + +/*! +@method removeResource: +*/ - (void)removeResource:(Resource *)resource; + +/*! +@method uniqueIDForType: +*/ - (NSNumber *)uniqueIDForType:(NSString *)type; -// accessors --(Resource*) resourceOfType: (NSString*)type andID: (NSNumber*)resID; --(Resource*) resourceOfType: (NSString*)type withName: (NSString*)name; --(NSArray*) allResourcesOfType: (NSString*)type; --(NSArray*) allResourceIDsOfType: (NSString*)type; +/*! +@method defaultIDForType: +*/ +- (NSNumber *)defaultIDForType:(NSString *)type; +/*! +@method resourceOfType:andID: +*/ +- (Resource *)resourceOfType:(NSString *)type andID:(NSNumber *)resID; + +/*! +@method resourceOfType:withName: +*/ +- (Resource *)resourceOfType:(NSString *)type withName:(NSString *)name; + +/*! +@method allResourcesOfType: +*/ +- (NSArray *)allResourcesOfType:(NSString *)type; + +/*! +@method allResourceIDsOfType: +*/ +- (NSArray *)allResourceIDsOfType:(NSString *)type; @end diff --git a/Cocoa/Classes/ResourceDataSource.m b/Cocoa/Classes/ResourceDataSource.m index 6f3b918..3d127bf 100644 --- a/Cocoa/Classes/ResourceDataSource.m +++ b/Cocoa/Classes/ResourceDataSource.m @@ -1,37 +1,14 @@ -/* ============================================================================= - PROJECT: ResKnife - FILE: ResourceDataSource.m - - PURPOSE: - Dedicated data source for our resource list. Shares its list of - resources with ResourceDocument. I have no idea why Nick did this - split, though... - - AUTHORS: Nick Shanks, nick(at)nickshanks.com, (c) ~2001. - M. Uli Kusterer, witness(at)zathras.de, (c) 2003. - - REVISIONS: - 2003-07-31 UK Added storing document pointer in resource, commented. - ========================================================================== */ - -/* ----------------------------------------------------------------------------- - Headers: - -------------------------------------------------------------------------- */ - #import "ResourceDataSource.h" #import "ResourceDocument.h" #import "Resource.h" #import +NSString *DataSourceWillAddResourceNotification = @"DataSourceWillAddResource"; +NSString *DataSourceDidAddResourceNotification = @"DataSourceDidAddResource"; +NSString *DataSourceWillRemoveResourceNotification = @"DataSourceWillRemoveResource"; +NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResource"; -/* ----------------------------------------------------------------------------- - Notification names: - -------------------------------------------------------------------------- */ - -NSString *DataSourceWillAddResourceNotification = @"DataSourceWillAddResourceNotification"; -NSString *DataSourceDidAddResourceNotification = @"DataSourceDidAddResourceNotification"; -NSString *DataSourceWillRemoveResourceNotification = @"DataSourceWillRemoveResourceNotification"; -NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResourceNotification"; +extern NSString *RKResourcePboardType; @implementation ResourceDataSource @@ -60,8 +37,9 @@ NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResourc - (void)setResources:(NSMutableArray *)newResources { - [resources autorelease]; + id old = resources; resources = [newResources retain]; + [old release]; [outlineView reloadData]; } @@ -71,8 +49,7 @@ NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResourc [[NSNotificationCenter defaultCenter] postNotificationName:DataSourceWillAddResourceNotification object:dictionary]; // it seems very inefficient to reload the entire data source when just adding/removing one item - // for large resource files, the data source gets reloaded hundereds of times upon load - [resource setDocument:document]; + // for large resource files, the data source gets reloaded hundreds of times upon load [resources addObject:resource]; [outlineView reloadData]; @@ -93,67 +70,57 @@ NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResourc [[document undoManager] registerUndoWithTarget:self selector:@selector(addResource:) object:resource]; // NB: I hope the undo manager retains the resource, because it just got deleted :) - undo action name set by calling function } - -/* ----------------------------------------------------------------------------- - resourceDidChange: - Notification from the Resource class that we're registered to. It's - sent whenever the resource is "touch"ed. - - REVISIONS: - 2003-08-01 UK Commented, made this "touch" the document as well. - -------------------------------------------------------------------------- */ - --(void) resourceDidChange: (NSNotification*)notification +- (void)resourceDidChange:(NSNotification *)notification { // reload the data for the changed resource [outlineView reloadItem:[notification object]]; - [document updateChangeCount: NSChangeDone]; // TODO: We shouldn't need to do this, Undo should take care of this, according to the docs, but somehow the document always forgets its changes. } /* Data source protocol implementation */ - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item { - #pragma unused( outlineView, item ) + #pragma unused(outlineView, item) return [resources objectAtIndex:index]; } - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { - #pragma unused( outlineView, item ) + #pragma unused(outlineView, item) return NO; } - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { - #pragma unused( outlineView, item ) + #pragma unused(outlineView, item) return [resources count]; } - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { - #pragma unused( outlineView ) + #pragma unused(outlineView) return [item valueForKey:[tableColumn identifier]]; } - (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { - #pragma unused( outlineView ) + #pragma unused(outlineView) NSString *identifier = [tableColumn identifier]; - if( [identifier isEqualToString:@"resID"] ) - [item takeValue:[NSNumber numberWithInt:[object intValue]] forKey:identifier]; - else [item takeValue:object forKey:identifier]; + if([identifier isEqualToString:@"resID"]) + [item setValue:[NSNumber numberWithInt:[object intValue]] forKey:identifier]; + else [item setValue:object forKey:identifier]; } +#pragma mark - /* ACCESSORS */ - (Resource *)resourceOfType:(NSString *)type andID:(NSNumber *)resID { Resource *resource; NSEnumerator *enumerator = [resources objectEnumerator]; - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) { - if( resID && [[resource resID] isEqualToNumber:resID] && type && [[resource type] isEqualToString:type] ) + if(resID && [[resource resID] isEqualToNumber:resID] && type && [[resource type] isEqualToString:type]) return resource; } return nil; @@ -163,9 +130,9 @@ NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResourc { Resource *resource; NSEnumerator *enumerator = [resources objectEnumerator]; - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) { - if( [[resource name] isEqualToString:name] && [[resource type] isEqualToString:type] ) + if([[resource name] isEqualToString:name] && [[resource type] isEqualToString:type]) return resource; } return nil; @@ -173,65 +140,108 @@ NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResourc - (NSArray *)allResourcesOfType:(NSString *)type { - Resource *resource; - NSMutableArray *array = [NSMutableArray array]; - NSEnumerator *enumerator = [resources objectEnumerator]; - while( resource = [enumerator nextObject] ) + Resource *resource; + NSMutableArray *array = [NSMutableArray array]; + NSEnumerator *enumerator = [resources objectEnumerator]; + while(resource = [enumerator nextObject]) { - if( [[resource type] isEqualToString:type] ) + if([[resource type] isEqualToString:type]) [array addObject:resource]; } return [NSArray arrayWithArray:array]; } +/*! +@method allResourceIDsOfType: +@discussion Returns an NSArray full of NSNumber* objects containing the IDs of all resources of specified type. Used by uniqueIDForType:. +@updated 2003-08-01 UK Created based on allResourcesOfType: +*/ -/* ----------------------------------------------------------------------------- - allResourceIDsOfType: - Returns an NSArray full of NSNumber* objects containing the IDs of all - resources of specified type. Used by uniqueIDForType:. - - REVISIONS: - 2003-08-01 UK Created based on allResourcesOfType:. - -------------------------------------------------------------------------- */ - --(NSArray*) allResourceIDsOfType: (NSString*)type +- (NSArray*)allResourceIDsOfType:(NSString *)type { + if(!type || [type isEqualToString:@""]) + return [NSArray array]; + Resource *resource; NSMutableArray *array = [NSMutableArray array]; NSEnumerator *enumerator = [resources objectEnumerator]; - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) { - if( [[resource type] isEqualToString:type] ) + if([[resource type] isEqualToString:type]) [array addObject:[resource resID]]; } return [NSArray arrayWithArray:array]; } +/*! +@method uniqueIDForType: +@discussion Tries to return an unused resource ID for a new resource of specified type. If all IDs are used up (can't really happen, because the resource manager can't take more than 2727 resources per file without crashing, but just in theory...), this will return 128 no matter whether it's used or not. +@updated 2003-08-01 UK: Created. +@updated 2003-10-21 NGS: Changed to obtain initial ID from -[resource defaultIDForType:], so we can vary it on a pre-resource-type basis (like Resourcerer can) +*/ -/* ----------------------------------------------------------------------------- - uniqueIDForType: - Tries to return an unused resource ID for a new resource of specified - type. If all IDs are used up (can't really happen, because the resource - manager can't take more than 2727 resources per file without crashing, - but just in theory...), this will return 128 no matter whether it's - used or not. - - REVISIONS: - 2003-08-01 UK Created. - -------------------------------------------------------------------------- */ - --(NSNumber*) uniqueIDForType: (NSString*)type +- (NSNumber *)uniqueIDForType:(NSString *)type { - short theID = 128; - NSArray *array = [self allResourceIDsOfType: type]; + short theID = [[self defaultIDForType:type] shortValue]; + NSArray *array = [self allResourceIDsOfType:type]; - if( [array count] <= USHRT_MAX ) + if([array count] <= USHRT_MAX) { - while( [array containsObject: [NSNumber numberWithShort:theID]] ) + while([array containsObject:[NSNumber numberWithShort:theID]]) theID++; } return [NSNumber numberWithShort: theID]; } +/*! +@method defaultIDForType: +@pending Method should look for resources specifying what the initial ID is for this resource type (e.g. 'vers' resources start at 0) +*/ + +- (NSNumber *)defaultIDForType:(NSString *)type +{ + short defaultID = 128; + return [NSNumber numberWithShort:defaultID]; +} + +#pragma mark - + +/*! +@method outlineView:writeItems:toPasteboard: +@abstract Called at the start of a drag event. +*/ +- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pb +{ + [pb declareTypes:[NSArray arrayWithObject:RKResourcePboardType] owner:self]; + [pb setData:[NSArchiver archivedDataWithRootObject:items] forType:RKResourcePboardType]; + return YES; +} + +/*! +@method outlineView:validateDrop:proposedItem:proposedChildIndex: +@abstract Called when the user is hovering with a drop over our outline view. +*/ +- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)childIndex +{ + if([info draggingSource] != outlineView) + { + [outlineView setDropItem:nil dropChildIndex:NSOutlineViewDropOnItemIndex]; + return NSDragOperationCopy; + } + else return NSDragOperationNone; +} + +/*! +@method outlineView:acceptDrop:item:childIndex: +@abstract Called when the user drops something on our outline view. +*/ +- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)targetItem childIndex:(int)childIndex +{ + NSPasteboard *pb = [info draggingPasteboard]; + if([pb availableTypeFromArray:[NSArray arrayWithObject:RKResourcePboardType]]) + [document pasteResources:[NSUnarchiver unarchiveObjectWithData:[pb dataForType:RKResourcePboardType]]]; + return YES; +} + @end diff --git a/Cocoa/Classes/ResourceDocument.h b/Cocoa/Classes/ResourceDocument.h index 0dcceb4..b3dc791 100644 --- a/Cocoa/Classes/ResourceDocument.h +++ b/Cocoa/Classes/ResourceDocument.h @@ -12,10 +12,20 @@ NSMutableDictionary *toolbarItems; NSMutableArray *resources; HFSUniStr255 *fork; // name of fork to save to, usually empty string (data fork) or 'RESOURCE_FORK' as returned from FSGetResourceForkName() - NSString *creator; - NSString *type; + NSData *creator; + NSData *type; + BOOL _createFork; // file had no existing resource map when opened } +- (BOOL)readFork:(NSString *)forkName asStreamFromFile:(FSRef *)fileRef; +- (BOOL)readResourceMap:(SInt16)fileRefNum; +- (BOOL)writeResourceMap:(SInt16)fileRefNum; +- (BOOL)writeForkStreamsToFile:(NSString *)fileName; + +- (IBAction)exportResources:(id)sender; +- (void)exportResource:(Resource *)resource; +- (void)exportPanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; + - (void)setupToolbar:(NSWindowController *)windowController; - (IBAction)showCreateResourceSheet:(id)sender; @@ -29,9 +39,6 @@ - (IBAction)playSound:(id)sender; - (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finished; --(IBAction) exportResourceToFile: (id)sender; --(IBAction) exportResourceToImageFile: (id)sender; - - (IBAction)copy:(id)sender; - (IBAction)paste:(id)sender; - (void)pasteResources:(NSArray *)pastedResources; @@ -45,21 +52,17 @@ - (void)resourceTypeWillChange:(NSNotification *)notification; - (void)resourceAttributesWillChange:(NSNotification *)notification; -- (BOOL)readFork:(NSString *)forkName asStreamFromFile:(NSString *)fileName; -- (BOOL)readResourceMap:(SInt16)fileRefNum; -- (BOOL)writeResourceMap:(SInt16)fileRefNum; - - (NSWindow *)mainWindow; - (ResourceDataSource *)dataSource; - (NSOutlineView *)outlineView; - (NSArray *)resources; // return the array as non-mutable -- (NSString *)creator; -- (NSString *)type; +- (NSData *)creator; +- (NSData *)type; - (IBAction)creatorChanged:(id)sender; - (IBAction)typeChanged:(id)sender; -- (void)setCreator:(NSString *)oldCreator; -- (void)setType:(NSString *)oldType; -- (void)setCreator:(NSString *)newCreator andType:(NSString *)newType; +- (BOOL)setCreator:(NSData *)newCreator; +- (BOOL)setType:(NSData *)newType; +- (BOOL)setCreator:(NSData *)newCreator andType:(NSData *)newType; @end diff --git a/Cocoa/Classes/ResourceDocument.m b/Cocoa/Classes/ResourceDocument.m index ac8f8d2..c4d405d 100644 --- a/Cocoa/Classes/ResourceDocument.m +++ b/Cocoa/Classes/ResourceDocument.m @@ -1,46 +1,23 @@ -/* ============================================================================= - PROJECT: ResKnife - FILE: ResourceDocument.m - - PURPOSE: - This is a ResKnife document (I still write Resurrection occasionally, - sorry Nick...), it handles loading, display etc. of resources. - - It uses a separate object as the data source for its outline view, - though, ResourceDataSource. I'd better ask Nick why. - - AUTHORS: Nick Shanks, nick(at)nickshanks.com, (c) ~2001. - M. Uli Kusterer, witness(at)zathras.de, (c) 2003. - - REVISIONS: - 2003-07-31 UK Added support for plugin registry, commented. - ========================================================================== */ - -/* ----------------------------------------------------------------------------- - Headers: - -------------------------------------------------------------------------- */ - #import "ResourceDocument.h" #import "ResourceDataSource.h" #import "ResourceNameCell.h" #import "Resource.h" +#import "ApplicationDelegate.h" +#import "OpenPanelDelegate.h" +#import "OutlineViewDelegate.h" +#import "InfoWindowController.h" #import "PrefsWindowController.h" #import "CreateResourceSheetController.h" -#import "OutlineViewDelegate.h" -#import "NSOutlineView-SelectedItems.h" +#import "NGSCategories.h" +#import "../Categories/NSString-FSSpec.h" +#import "../Categories/NSOutlineView-SelectedItems.h" -#import "ResKnifePluginProtocol.h" +#import "../Plug-Ins/ResKnifePluginProtocol.h" #import "RKEditorRegistry.h" -/* ----------------------------------------------------------------------------- - Notification names: - -------------------------------------------------------------------------- */ - NSString *DocumentInfoWillChangeNotification = @"DocumentInfoWillChangeNotification"; NSString *DocumentInfoDidChangeNotification = @"DocumentInfoDidChangeNotification"; - - extern NSString *RKResourcePboardType; @implementation ResourceDocument @@ -48,20 +25,19 @@ extern NSString *RKResourcePboardType; - (id)init { self = [super init]; - if( !self ) - return nil; + if(!self) return nil; toolbarItems = [[NSMutableDictionary alloc] init]; resources = [[NSMutableArray alloc] init]; fork = nil; - creator = [@"ResK" retain]; - type = [@"rsrc" retain]; + creator = [[@"ResK" dataUsingEncoding:NSMacOSRomanStringEncoding] retain]; // should I be calling -setCreator & -setType here instead? + type = [[@"rsrc" dataUsingEncoding:NSMacOSRomanStringEncoding] retain]; return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - if( fork ) DisposePtr( (Ptr) fork ); + if(fork) DisposePtr((Ptr) fork); [resources release]; [toolbarItems release]; [type release]; @@ -69,8 +45,569 @@ extern NSString *RKResourcePboardType; [super dealloc]; } -/* WINDOW DELEGATION */ #pragma mark - +#pragma mark File Management + +/*! +@method readFromFile:ofType: +@abstract Open the specified file and read its resources. +@description Open the specified file and read its resources. This first tries to load the resources from the res fork, and failing that tries the data fork. +@author Nicholas Shanks +@updated 2003-11-08 NGS: Now handles opening user-selected forks. +*/ + +-(BOOL)readFromFile:(NSString *)fileName ofType:(NSString *)fileKind +{ + BOOL succeeded = NO; + OSStatus error = noErr; + FSRef *fileRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + SInt16 fileRefNum = 0; + OpenPanelDelegate *openPanelDelegate = [(ApplicationDelegate *)[NSApp delegate] openPanelDelegate]; + + // bug: need to handle error better here + error = FSPathMakeRef((const UInt8 *)[fileName fileSystemRepresentation], fileRef, nil); + if(error) return NO; + + // find out which fork to parse + if(NSAppKitVersionNumber < 700.0 || ![openPanelDelegate readOpenPanelForFork]) + { + // display second dialog to ask user to select a fork, pre-10.3 or if open command did not come via the open dialog + + // bug: unimplemented - always tells app to try resource fork first + fork = (HFSUniStr255 *) NewPtrClear(sizeof(HFSUniStr255)); + error = FSGetResourceForkName(fork); + if(error) return NO; + } + else + { + // get selected fork from open panel, 10.3+ + int row = [[openPanelDelegate forkTableView] selectedRow]; + NSString *selectedFork = [(NSDictionary *)[[openPanelDelegate forks] objectAtIndex:row] valueForKey:@"forkname"]; + fork = (HFSUniStr255 *) NewPtrClear(sizeof(HFSUniStr255)); + fork->length = ([selectedFork length] < 255)? [selectedFork length]:255; + if(fork->length > 0) + [selectedFork getCharacters:fork->unicode range:NSMakeRange(0,fork->length)]; + else fork->unicode[0] = 0; + + // clear so next document doesn't get confused + [openPanelDelegate setReadOpenPanelForFork:NO]; + } + + NSArray *forks = [(ApplicationDelegate *)[NSApp delegate] forksForFile:fileRef]; + + // attempt to open fork user selected as a resource map + SetResLoad(false); // don't load "preload" resources + error = FSOpenResourceFile(fileRef, fork->length, (UniChar *) &fork->unicode, fsRdPerm, &fileRefNum); + if(error || !fileRefNum) + { + // if opening the user-selected fork fails, try to open resource fork instead + error = FSGetResourceForkName(fork); + if(error) return NO; +/* HFSUniStr255 *rfork; + error = FSGetResourceForkName(rfork); + if(error) return NO; + + bool checkFork = true; + if(FSCreateStringFromHFSUniStr) // 10.4 only + { + if(CFStringCompare(FSCreateStringFromHFSUniStr(NULL, fork), FSCreateStringFromHFSUniStr(NULL, rfork), 0) == NSOrderedSame) + checkFork = false; // skip checking resource fork if it's the one the user chose + else fork = rfork; + } + if(checkFork) +*/ error = FSOpenResourceFile(fileRef, fork->length, (UniChar *) &fork->unicode, fsRdPerm, &fileRefNum); + if(error || !fileRefNum) + { + // if opening the resource fork fails, try to open data fork instead + error = FSGetDataForkName(fork); + if(error) return NO; + error = FSOpenResourceFile(fileRef, fork->length, (UniChar *) &fork->unicode, fsRdPerm, &fileRefNum); + if(error || !fileRefNum) + { + // bug: should check fork the user selected is empty before trying data fork + NSNumber *fAlloc = [[forks firstObjectReturningValue:[NSString stringWithCharacters:fork->unicode length:fork->length] forKey:@"forkname"] valueForKey:@"forkallocation"]; + if([fAlloc unsignedLongLongValue] > 0) + { + // data fork is not empty, check resource fork + error = FSGetResourceForkName(fork); + if(error) return NO; + fAlloc = [[forks firstObjectReturningValue:[NSString stringWithCharacters:fork->unicode length:fork->length] forKey:@"forkname"] valueForKey:@"forkallocation"]; + if([fAlloc unsignedLongLongValue] > 0) + { + // resource fork is not empty either, give up (ask user for a fork?) + NSLog(@"Could not find existing map nor create a new map in either the data or resource forks! Aborting."); + return NO; + } + } + + // note that map needs initalising on first save + _createFork = YES; + } + } + } + SetResLoad(true); // restore resource loading as soon as is possible + + if(!_createFork) + { + // disable undos during resource creation and setting of the creator and type + [[self undoManager] disableUndoRegistration]; + + // then read resources from the selected fork + succeeded = [self readResourceMap:fileRefNum]; + + // get creator and type + FSCatalogInfo info; + error = FSGetCatalogInfo(fileRef, kFSCatInfoFinderInfo, &info, nil, nil, nil); + if(!error) + { + [self setType:[NSData dataWithBytes:&((FileInfo *)info.finderInfo)->fileType length:4]]; + [self setCreator:[NSData dataWithBytes:&((FileInfo *)info.finderInfo)->fileCreator length:4]]; + } + + // restore undos + [[self undoManager] enableUndoRegistration]; + } + else succeeded = YES; + + // now read all other forks as streams + NSString *forkName; + NSEnumerator *forkEnumerator = [forks objectEnumerator]; + NSString *selectedFork = [NSString stringWithCharacters:fork->unicode length:fork->length]; + while(forkName = [[forkEnumerator nextObject] valueForKey:@"forkname"]) + { + // check current fork is not the fork we're going to parse + if(![forkName isEqualToString:selectedFork]) + [self readFork:forkName asStreamFromFile:fileRef]; + } + + // tidy up loose ends + if(fileRefNum) FSClose(fileRefNum); + DisposePtr((Ptr) fileRef); + return succeeded; +} + +/*! +@method readFork:asStreamFromFile: +@author Nicholas Shanks +@updated 2003-11-08 NGS: Now handles opening user-selected forks. +@description Note: there is a 2 GB limit to the size of forks that can be read in due to FSReaadFork() taking a 32-bit buffer length value. +*/ + +- (BOOL)readFork:(NSString *)forkName asStreamFromFile:(FSRef *)fileRef +{ + if(!fileRef) return NO; + + /* NTFS Note: When running SFM (Services for Macintosh) a Windows NT-based system (including 2000 & XP) serving NTFS-formatted drives stores Mac resource forks in a stream named "AFP_Resource". The finder info/attributes are stored in a stream called "AFP_AfpInfo". The default data fork stream is called "$DATA" and any of these can be accessed thus: "c:\filename.txt:forkname". Finder comments are stored in a stream called "Comments". + As a result, ResKnife prohibits creation of forks with the following names: "" (empty string, Mac data fork name), + "$DATA" (NTFS data fork name), + "AFP_Resource", "AFP_AfpInfo" and "Comments". + It is perfectly legal in ResKnife to read in forks of these names when accessing a shared NTFS drive via SMB. The server does not need to be running SFM since the file requests will appear to be coming from a PC. If the files are accessed via AFP on a server running SFM, SFM will automatically convert the files (and truncate the name to 31 chars). */ + + + // translate NSString into HFSUniStr255 -- in 10.4 this can be done with FSGetHFSUniStrFromString + HFSUniStr255 uniForkName = { 0 }; + uniForkName.length = ([forkName length] < 255)? [forkName length]:255; + if(uniForkName.length > 0) + [forkName getCharacters:uniForkName.unicode range:NSMakeRange(0, uniForkName.length)]; + else uniForkName.unicode[0] = 0; + + // get fork length and create empty buffer, bug: only sizeof(size_t) bytes long + ByteCount forkLength = (ByteCount) [[[[(ApplicationDelegate *)[NSApp delegate] forksForFile:fileRef] firstObjectReturningValue:forkName forKey:@"forkname"] valueForKey:@"forksize"] unsignedLongValue]; + void *buffer = malloc(forkLength); + if(!buffer) return NO; + + // read fork contents into buffer, bug: assumes no errors + SInt16 forkRefNum; + FSOpenFork(fileRef, uniForkName.length, uniForkName.unicode, fsRdPerm, &forkRefNum); + FSReadFork(forkRefNum, fsFromStart, 0, forkLength, buffer, &forkLength); + FSCloseFork(forkRefNum); + + // create data + NSData *data = [NSData dataWithBytesNoCopy:buffer length:forkLength freeWhenDone:YES]; + if(!data) return NO; + + // create resource + Resource *resource = [Resource resourceOfType:@"" andID:0 withName:forkName andAttributes:0 data:data]; + if(!resource) return NO; + + // customise fork name for default data & resource forks - bug: this should really be in resource data source!! + HFSUniStr255 resourceForkName; + OSErr error = FSGetResourceForkName(&resourceForkName); + if(!error && [[resource name] isEqualToString:@""]) // bug: should use FSGetDataForkName() + [resource _setName:NSLocalizedString(@"Data Fork", nil)]; + else if(!error && [[resource name] isEqualToString:[NSString stringWithCharacters:resourceForkName.unicode length:resourceForkName.length]]) + [resource _setName:NSLocalizedString(@"Resource Fork", nil)]; + + [resource setRepresentedFork:forkName]; + [resources addObject:resource]; + return YES; +} + +-(BOOL)readResourceMap:(SInt16)fileRefNum +{ + OSStatus error = noErr; + SInt16 oldResFile = CurResFile(); + UseResFile(fileRefNum); + + for(unsigned short i = 1; i <= Count1Types(); i++) + { + ResType resType; + Get1IndType(&resType, i); + ResType swappedType = EndianS32_NtoB(resType); // Swapped type for use as string (types are treated as numbers by the resource manager and swapped on Intel). + unsigned short n = Count1Resources(resType); + for(unsigned short j = 1; j <= n; j++) + { + Handle resourceHandle = Get1IndResource(resType, j); + error = ResError(); + if(error != noErr) + { + NSLog(@"Error %d reading resource map...", error); + UseResFile(oldResFile); + return NO; + } + + Str255 nameStr; + short resIDShort; + GetResInfo(resourceHandle, &resIDShort, &resType, nameStr); + long sizeLong = GetResourceSizeOnDisk(resourceHandle); + short attrsShort = GetResAttrs(resourceHandle); + HLockHi(resourceHandle); + + // cool: "The advantage of obtaining a methodÕs implementation and calling it as a function is that you can invoke the implementation multiple times within a loop, or similar C construct, without the overhead of Objective-C messaging." + + // create the resource & add it to the array + NSString *name = [[NSString alloc] initWithBytes:&nameStr[1] length:nameStr[0] encoding:NSMacOSRomanStringEncoding]; + NSString *resType = [[NSString alloc] initWithBytes:(char *) &swappedType length:4 encoding:NSMacOSRomanStringEncoding]; + NSNumber *resID = [NSNumber numberWithShort:resIDShort]; + NSNumber *attributes = [NSNumber numberWithShort:attrsShort]; + NSData *data = [NSData dataWithBytes:*resourceHandle length:sizeLong]; + Resource *resource = [Resource resourceOfType:resType andID:resID withName:name andAttributes:attributes data:data]; + [resource setDocumentName:[self displayName]]; + [resources addObject:resource]; // array retains resource + [name release]; + [resType release]; + + HUnlock(resourceHandle); + ReleaseResource(resourceHandle); + } + } + + // save resource map and clean up + UseResFile(oldResFile); + return YES; +} + +/*! +@pending Uli's changed this routine - see what I had and unify the two +@pending Doesn't write correct type/creator info - always ResKnife's! +*/ + +- (BOOL)writeToFile:(NSString *)fileName ofType:(NSString *)type +{ + OSStatus error = noErr; + SInt16 fileRefNum = 0; + FSRef *parentRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + FSRef *fileRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + + // create and open file for writing + // bug: doesn't set the cat info to the same as the old file + unichar *uniname = (unichar *) NewPtrClear(sizeof(unichar) *256); + [[fileName lastPathComponent] getCharacters:uniname]; + error = FSPathMakeRef((const UInt8 *)[[fileName stringByDeletingLastPathComponent] UTF8String], parentRef, nil); + if(fork) + error = FSCreateResourceFile(parentRef, [[fileName lastPathComponent] length], (UniChar *) uniname, kFSCatInfoNone, NULL, fork->length, (UniChar *) &fork->unicode, fileRef, NULL); + else error = FSCreateResourceFile(parentRef, [[fileName lastPathComponent] length], (UniChar *) uniname, kFSCatInfoNone, NULL, 0, NULL, fileRef, NULL); + + // write any data streams to file + BOOL succeeded = [self writeForkStreamsToFile:fileName]; +// FSRef *fileRef = [fileName createFSRef]; + +/* error = FSPathMakeRef((const UInt8 *)[fileName UTF8String], fileRef, nil); + if(_createFork) + { + error = FSCreateResourceFork(fileRef, fork->length, (UniChar *) &fork->unicode, 0); + _createFork = NO; + } +*/ + if(!error) + { + // set creator & type + // bug: due to a bug in AppKit, the temporary file that we are writing to (in /var/tmp, managed by NSDocument) does not get it's creator code copied over to the new document (it sets the new document's to nil). this timer sets the creator code after we have returned to the main loop and the buggy Apple code has been bypassed. + [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(setTypeCreatorAfterSave:) userInfo:nil repeats:NO]; + + // open fork as resource map + if(fork) + error = FSOpenResourceFile(fileRef, fork->length, (UniChar *) &fork->unicode, fsWrPerm, &fileRefNum); + else error = FSOpenResourceFile(fileRef, 0, NULL, fsWrPerm, &fileRefNum); + } +// else NSLog(@"error creating resource fork. (error=%d, spec=%d, ref=%d, parent=%d)", error, fileSpec, fileRef, parentRef); + else NSLog(@"error creating resource fork. (error=%d, ref=%d)", error, fileRef); + + // write resource array to file + if(fileRefNum && !error) + succeeded = [self writeResourceMap:fileRefNum]; + + // tidy up loose ends + if(fileRefNum) FSClose(fileRefNum); + DisposePtr((Ptr) fileRef); + + // update info window + [[InfoWindowController sharedInfoWindowController] updateInfoWindow]; + + return succeeded; +} + +- (BOOL)writeForkStreamsToFile:(NSString *)fileName +{ + // try and get an FSRef + OSStatus error; + FSRef *fileRef = [fileName createFSRef], *parentRef = nil; + if(!fileRef) + { + parentRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + fileRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + unichar *uniname = (unichar *) NewPtrClear(sizeof(unichar) *256); + [[fileName lastPathComponent] getCharacters:uniname]; + error = FSPathMakeRef((const UInt8 *)[[fileName stringByDeletingLastPathComponent] UTF8String], parentRef, nil); + if(error) return NO; + error = FSCreateFileUnicode(parentRef, 0, NULL, kFSCatInfoNone, NULL, fileRef, NULL); + if(error || !fileRef) return NO; + } + + Resource *resource; + NSEnumerator *enumerator = [resources objectEnumerator]; + while(resource = [enumerator nextObject]) + { + // if the resource object represents an actual resource, skip it + if([resource representedFork] == nil) continue; + unichar *uniname = (unichar *) NewPtrClear(sizeof(unichar) *256); + [[resource representedFork] getCharacters:uniname]; + SInt16 forkRefNum = 0; + error = FSOpenFork(fileRef, [[resource representedFork] length], (UniChar *) uniname, fsWrPerm, &forkRefNum); + if(!error && forkRefNum) + error = FSWriteFork(forkRefNum, fsFromStart, 0, [[resource data] length], [[resource data] bytes], NULL); + if(forkRefNum) FSClose(forkRefNum); + } + DisposePtr((Ptr) fileRef); + return YES; +} + +/*! +@method writeResourceMap: +@abstract Writes all resources (except the ones representing other forks of the file) to the specified resource file. +*/ + +- (BOOL)writeResourceMap:(SInt16)fileRefNum +{ + // make the resource file current + OSStatus error = noErr; + SInt16 oldResFile = CurResFile(); + UseResFile(fileRefNum); + + // loop over all our resources + Resource *resource; + NSEnumerator *enumerator = [resources objectEnumerator]; + while(resource = [enumerator nextObject]) + { + Str255 nameStr; + char resType[5]; // includes null char for getCString: + short resIDShort; + short attrsShort; + Handle resourceHandle; + + // if the resource represents another fork in the file, skip it + if([resource representedFork] != nil) continue; + + resIDShort = [[resource resID] shortValue]; + attrsShort = [[resource attributes] shortValue]; + resourceHandle = NewHandleClear([[resource data] length]); + + // convert unicode name to pascal string + nameStr[0] = [[resource name] lengthOfBytesUsingEncoding:NSMacOSRomanStringEncoding]; + BlockMoveData([[resource name] cStringUsingEncoding:NSMacOSRomanStringEncoding], &nameStr[1], nameStr[0]); + + // convert type string to ResType + [[resource type] getCString:resType maxLength:4]; + + // convert NSData to resource handle + HLockHi(resourceHandle); + [[resource data] getBytes:*resourceHandle]; + HUnlock(resourceHandle); + + // now that everything's converted, tell the resource manager we want to create this resource + AddResource(resourceHandle, *(ResType *)resType, resIDShort, nameStr); + if(ResError() == addResFailed) + { + NSLog(@"*Saving failed*; could not add resource ID %@ of type %@ to file.", [resource resID], [resource type]); + DisposeHandle(resourceHandle); + error = addResFailed; + } + else + { +// NSLog(@"Added resource ID %@ of type %@ to file.", [resource resID], [resource type]); + SetResAttrs(resourceHandle, attrsShort); + ChangedResource(resourceHandle); + // the resourceHandle memory is disposed of when calling CloseResFile() for the file to which the resource has been added + } + } + + // update the file on disk + UpdateResFile(fileRefNum); + + // restore original resource file + UseResFile(oldResFile); + return error? NO:YES; +} + +- (void)setTypeCreatorAfterSave:(id)userInfo +{ + FInfo finderInfo; + FSRef *fileRef = (FSRef *) NewPtrClear(sizeof(FSRef)); + FSSpec *fileSpec = (FSSpec *) NewPtrClear(sizeof(FSSpec)); + OSStatus error = FSPathMakeRef((const UInt8 *)[[self fileName] UTF8String], fileRef, nil); + if(!error) + { + error = FSGetCatalogInfo(fileRef, kFSCatInfoNone, NULL, NULL, fileSpec, NULL); + if(!error) + { + error = FSpGetFInfo(fileSpec, &finderInfo); + if(!error) + { + [[self type] getBytes:&finderInfo.fdType length:4]; + [[self creator] getBytes:&finderInfo.fdCreator length:4]; +// NSLog(@"setting finder info to type: %X; creator: %X", finderInfo.fdType, finderInfo.fdCreator); + error = FSpSetFInfo(fileSpec, &finderInfo); + FSpGetFInfo(fileSpec, &finderInfo); +// NSLog(@"finder info got set to type: %X; creator: %X", finderInfo.fdType, finderInfo.fdCreator); + } + else NSLog(@"error getting Finder info. (error=%d, spec=%d, ref=%d)", error, fileSpec, fileRef); + } + else NSLog(@"error converting fsref to fsspec. (error=%d, spec=%d, ref=%d)", error, fileSpec, fileRef); + } + else NSLog(@"error making fsref from file path. (error=%d, ref=%d, path=%@)", error, fileRef, [self fileName]); +} + +#pragma mark - +#pragma mark Export to File + +/*! +@method exportResources: +@author Nicholas Shanks +@created 24 October 2003 +@pending note that this method will cause a cascade of sheets to be displayed for each resource being exported! v.bad needs fixing +*/ + +- (IBAction)exportResources:(id)sender +{ + if ([outlineView numberOfSelectedRows] > 1) + { + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection:NO]; + [panel setCanChooseDirectories:YES]; + [panel setCanChooseFiles:NO]; + [panel beginSheetForDirectory:nil file:nil modalForWindow:mainWindow modalDelegate:self didEndSelector:@selector(folderChoosePanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; + } + else + { + [self exportResource:[outlineView selectedItem]]; + } +} + +/*! +@method exportResource: +@author Uli Kusterer +@updated 2003-10-24 NGS: moved IBAction target to exportResources: above, renamed this method +*/ + +#warning Note to Uli: how about changing the selector that the plug should implement to -(BOOL)dataForFileExport:(NSData **)fileData ofType:(NSString **)fileType. This is basically a concatenation of the two methods you came up with, but can allow the host app to specify a preferred file type (e.g. EPS) to a plug (say the PICT plug) and if the plug can't return data in that format, that's OK, it just returns the fileType of the associated data anyway. I would also recommend adding a plug method called something like availableTypesForFileExport: which returns a dictionary of file extensions and human-readable names (names should be overridden by system default names for that extension if present) that the plug can export data into, useful for say populating a pop-up menu in the export dialog. + +- (void)exportResource:(Resource *)resource +{ + Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType:[resource type]]; + NSData *exportData = [resource data]; + NSString *extension = [[[resource type] lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + // basic overrides for file name extensions (assume no plug-ins installed) + NSString *newExtension; + NSDictionary *adjustments = [NSDictionary dictionaryWithObjectsAndKeys: @"ttf", @"sfnt", nil]; + if(newExtension = [adjustments valueForKey:extension]) + extension = newExtension; + + // ask for data + if([editorClass respondsToSelector:@selector(dataForFileExport:)]) + exportData = [editorClass dataForFileExport:resource]; + + // ask for file extension + if([editorClass respondsToSelector:@selector(filenameExtensionForFileExport:)]) + extension = [editorClass filenameExtensionForFileExport:resource]; + + NSSavePanel *panel = [NSSavePanel savePanel]; + NSString *filename = [resource name] ? [resource name] : NSLocalizedString(@"Untitled Resource",nil); + filename = [filename stringByAppendingFormat:@".%@", extension]; + [panel beginSheetForDirectory:nil file:filename modalForWindow:mainWindow modalDelegate:self didEndSelector:@selector(exportPanelDidEnd:returnCode:contextInfo:) contextInfo:[exportData retain]]; +} + +- (void)exportPanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + NSData *data = (NSData *) contextInfo; + [data autorelease]; + + if(returnCode == NSOKButton) + [data writeToFile:[sheet filename] atomically:YES]; +} + +- (void)folderChoosePanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + if(returnCode == NSOKButton) + { + NSUInteger i = 1; + Resource *resource; + NSString *path, *filename, *extension; + NSDictionary *adjustments = [NSDictionary dictionaryWithObjectsAndKeys: @"ttf", @"sfnt", @"png", @"PNGf", nil]; + NSEnumerator *enumerator = [[outlineView selectedItems] objectEnumerator]; + while(resource = [enumerator nextObject]) + { + Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType:[resource type]]; + NSData *exportData = [resource data]; + extension = [[[resource type] lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + // basic overrides for file name extensions (assume no plug-ins installed) + if([adjustments objectForKey:[resource type]]) + extension = [adjustments objectForKey:[resource type]]; + + // ask for data + if([editorClass respondsToSelector:@selector(dataForFileExport:)]) + exportData = [editorClass dataForFileExport:resource]; + + // ask for file extension + if([editorClass respondsToSelector:@selector(filenameExtensionForFileExport:)]) + extension = [editorClass filenameExtensionForFileExport:resource]; + + filename = [resource name]; + if (!filename || [filename isEqualToString:@""]) + { + filename = [NSString stringWithFormat:NSLocalizedString(@"Untitled '%@' Resource %d",nil), [resource type], i++]; + filename = [filename stringByAppendingPathExtension:extension]; + } + else + { + NSUInteger j = 1; + NSString *tempname = [filename stringByAppendingPathExtension:extension]; + while ([[NSFileManager defaultManager] fileExistsAtPath:tempname]) + { + tempname = [filename stringByAppendingFormat:@" (%d)", j++]; + tempname = [tempname stringByAppendingPathExtension:extension]; + } + filename = tempname; + } + path = [[sheet filename] stringByAppendingPathComponent:filename]; + [exportData writeToFile:path atomically:YES]; + } + } +} + +#pragma mark - +#pragma mark Window Management - (NSString *)windowNibName { @@ -94,13 +631,15 @@ extern NSString *RKResourcePboardType; ResourceNameCell *resourceNameCell = [[[ResourceNameCell alloc] init] autorelease]; [resourceNameCell setEditable:YES]; [[outlineView tableColumnWithIdentifier:@"name"] setDataCell:resourceNameCell]; +// NSLog(@"Changed data cell"); } - // set outline view's inter-cell psacing to zero to avoid getting gaps between blue bits + // set outline view's inter-cell spacing to zero to avoid getting gaps between blue bits [outlineView setIntercellSpacing:NSMakeSize(0,0)]; - [outlineView swapForOutlineSortView]; [outlineView setTarget:self]; [outlineView setDoubleAction:@selector(openResources:)]; + [outlineView setVerticalMotionCanBeginDrag:YES]; + [outlineView registerForDraggedTypes:[NSArray arrayWithObjects:RKResourcePboardType, NSStringPboardType, NSFilenamesPboardType, nil]]; // register for resource will change notifications (for undo management) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceNameWillChange:) name:ResourceNameWillChangeNotification object:nil]; @@ -120,7 +659,7 @@ extern NSString *RKResourcePboardType; - (void)printOperationDidRun:(NSPrintOperation *)printOperation success:(BOOL)success contextInfo:(void *)contextInfo { - if( !success ) NSLog( @"Printing Failed!" ); + if(!success) NSLog(@"Printing Failed!"); } - (BOOL)keepBackupFile @@ -134,35 +673,31 @@ extern NSString *RKResourcePboardType; Resource *resource = (Resource *) [outlineView selectedItem]; // file menu - if( [item action] == @selector(saveDocument:) ) return [self isDocumentEdited]; + if([item action] == @selector(saveDocument:)) return [self isDocumentEdited]; // edit menu - else if( [item action] == @selector(clear:) ) return selectedRows > 0; - else if( [item action] == @selector(selectAll:) ) return [outlineView numberOfRows] > 0; - else if( [item action] == @selector(deselectAll:) ) return selectedRows > 0; + else if([item action] == @selector(clear:)) return selectedRows > 0; + else if([item action] == @selector(selectAll:)) return [outlineView numberOfRows] > 0; + else if([item action] == @selector(deselectAll:)) return selectedRows > 0; // resource menu - else if( [item action] == @selector(openResources:) ) return selectedRows > 0; - else if( [item action] == @selector(openResourcesInTemplate:) ) return selectedRows > 0; - else if( [item action] == @selector(openResourcesWithOtherTemplate:) ) return selectedRows > 0; - else if( [item action] == @selector(openResourcesAsHex:) ) return selectedRows > 0; - else if( [item action] == @selector(exportResourceToImageFile:) ) + else if([item action] == @selector(openResources:)) return selectedRows > 0; + else if([item action] == @selector(openResourcesInTemplate:)) return selectedRows > 0; + else if([item action] == @selector(openResourcesWithOtherTemplate:)) return selectedRows > 0; + else if([item action] == @selector(openResourcesAsHex:)) return selectedRows > 0; + else if([item action] == @selector(exportResourceToImageFile:)) { - Class edClass; - - if( selectedRows < 1 ) - return NO; - - edClass = [[RKEditorRegistry mainRegistry] editorForType: [resource type]]; - return [edClass respondsToSelector:@selector(imageForImageFileExport:)]; + if(selectedRows < 1) return NO; + Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType:[resource type]]; + return [editorClass respondsToSelector:@selector(imageForImageFileExport:)]; } - else if( [item action] == @selector(playSound:) ) return selectedRows == 1 && [[resource type] isEqualToString:@"snd "]; - else if( [item action] == @selector(revertResourceToSaved:) ) return selectedRows == 1 && [resource isDirty]; + else if([item action] == @selector(playSound:)) return selectedRows == 1 && [[resource type] isEqualToString:@"snd "]; + else if([item action] == @selector(revertResourceToSaved:)) return selectedRows == 1 && [resource isDirty]; else return [super validateMenuItem:item]; } -/* TOOLBAR MANAGMENT */ #pragma mark - +#pragma mark Toolbar Management static NSString *RKToolbarIdentifier = @"com.nickshanks.resknife.toolbar"; static NSString *RKCreateItemIdentifier = @"com.nickshanks.resknife.toolbar.create"; @@ -171,7 +706,7 @@ static NSString *RKEditItemIdentifier = @"com.nickshanks.resknife.toolbar.edit" static NSString *RKEditHexItemIdentifier = @"com.nickshanks.resknife.toolbar.edithex"; static NSString *RKSaveItemIdentifier = @"com.nickshanks.resknife.toolbar.save"; static NSString *RKShowInfoItemIdentifier = @"com.nickshanks.resknife.toolbar.showinfo"; -static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.export"; +static NSString *RKExportItemIdentifier = @"com.nickshanks.resknife.toolbar.export"; - (void)setupToolbar:(NSWindowController *)windowController { @@ -200,12 +735,15 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex [item setAction:@selector(clear:)]; [toolbarItems setObject:item forKey:RKDeleteItemIdentifier]; + NSImage *image; item = [[NSToolbarItem alloc] initWithItemIdentifier:RKEditItemIdentifier]; [item autorelease]; [item setLabel:NSLocalizedString(@"Edit", nil)]; [item setPaletteLabel:NSLocalizedString(@"Edit", nil)]; [item setToolTip:NSLocalizedString(@"Edit Resource In Default Editor", nil)]; - [item setImage:[NSImage imageNamed:@"Edit"]]; + if(image = [[NSWorkspace sharedWorkspace] iconForFileType:@"rtf"]) + [item setImage:image]; + else [item setImage:[NSImage imageNamed:@"Edit"]]; [item setTarget:self]; [item setAction:@selector(openResources:)]; [toolbarItems setObject:item forKey:RKEditItemIdentifier]; @@ -215,7 +753,9 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex [item setLabel:NSLocalizedString(@"Edit Hex", nil)]; [item setPaletteLabel:NSLocalizedString(@"Edit Hex", nil)]; [item setToolTip:NSLocalizedString(@"Edit Resource As Hexadecimal", nil)]; - [item setImage:[NSImage imageNamed:@"Edit Hex"]]; + if(image = [[NSWorkspace sharedWorkspace] iconForFileType:@"txt"]) + [item setImage:image]; + else [item setImage:[NSImage imageNamed:@"Edit Hex"]]; [item setTarget:self]; [item setAction:@selector(openResourcesAsHex:)]; [toolbarItems setObject:item forKey:RKEditHexItemIdentifier]; @@ -235,7 +775,9 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex [item setLabel:NSLocalizedString(@"Show Info", nil)]; [item setPaletteLabel:NSLocalizedString(@"Show Info", nil)]; [item setToolTip:NSLocalizedString(@"Show Resource Information Window", nil)]; - [item setImage:[NSImage imageNamed:@"Show Info"]]; + if(image = [NSImage imageNamed:@"NSGetInfoToolbar"]) + [item setImage:image]; + else [item setImage:[NSImage imageNamed:@"Show Info"]]; [item setTarget:[NSApp delegate]]; [item setAction:@selector(showInfo:)]; [toolbarItems setObject:item forKey:RKShowInfoItemIdentifier]; @@ -247,10 +789,10 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex [item setToolTip:NSLocalizedString(@"Export the resource's data to a file", nil)]; [item setImage:[NSImage imageNamed:@"Export"]]; [item setTarget:self]; - [item setAction:@selector(exportResourceToFile:)]; + [item setAction:@selector(exportResources:)]; [toolbarItems setObject:item forKey:RKExportItemIdentifier]; - if( [windowController window] == mainWindow ) + if([windowController window] == mainWindow) { NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:RKToolbarIdentifier] autorelease]; @@ -263,7 +805,7 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex // attach toolbar to window [toolbar setDelegate:self]; [mainWindow setToolbar:toolbar]; - } + } } - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag @@ -287,19 +829,19 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex int selectedRows = [outlineView numberOfSelectedRows]; NSString *identifier = [item itemIdentifier]; - if( [identifier isEqualToString:RKCreateItemIdentifier] ) valid = YES; - else if( [identifier isEqualToString:RKDeleteItemIdentifier] ) valid = selectedRows > 0; - else if( [identifier isEqualToString:RKEditItemIdentifier] ) valid = selectedRows > 0; - else if( [identifier isEqualToString:RKEditHexItemIdentifier] ) valid = selectedRows > 0; - else if( [identifier isEqualToString:RKExportItemIdentifier] ) valid = selectedRows > 0; - else if( [identifier isEqualToString:RKSaveItemIdentifier] ) valid = [self isDocumentEdited]; - else if( [identifier isEqualToString:NSToolbarPrintItemIdentifier] ) valid = YES; + if([identifier isEqualToString:RKCreateItemIdentifier]) valid = YES; + else if([identifier isEqualToString:RKDeleteItemIdentifier]) valid = selectedRows > 0; + else if([identifier isEqualToString:RKEditItemIdentifier]) valid = selectedRows > 0; + else if([identifier isEqualToString:RKEditHexItemIdentifier]) valid = selectedRows > 0; + else if([identifier isEqualToString:RKExportItemIdentifier]) valid = selectedRows > 0; + else if([identifier isEqualToString:RKSaveItemIdentifier]) valid = [self isDocumentEdited]; + else if([identifier isEqualToString:NSToolbarPrintItemIdentifier]) valid = YES; return valid; } -/* DOCUMENT MANAGEMENT */ #pragma mark - +#pragma mark Document Management - (IBAction)showCreateResourceSheet:(id)sender { @@ -308,19 +850,23 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex [sheetController showCreateResourceSheet:self]; } -- (IBAction)showSelectTemplateSheet:(id)sender +/*- (IBAction)showSelectTemplateSheet:(id)sender { // bug: ResourceDocument allocs a sheet controller, but it's never disposed of // SelectTemplateSheetController *sheetController = [[CreateResourceSheetController alloc] initWithWindowNibName:@"SelectTemplateSheet"]; // [sheetController showSelectTemplateSheet:self]; -} +}*/ - (IBAction)openResources:(id)sender { + // ignore double-clicks in table header + if(sender == outlineView && [outlineView clickedRow] == -1) + return; + Resource *resource; NSArray *selected = [outlineView selectedItems]; NSEnumerator *enumerator = [selected objectEnumerator]; - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) [self openResourceUsingEditor:resource]; } @@ -330,7 +876,7 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex Resource *resource; NSArray *selected = [outlineView selectedItems]; NSEnumerator *enumerator = [selected objectEnumerator]; - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) [self openResource:resource usingTemplate:[resource type]]; } @@ -339,7 +885,7 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex Resource *resource; NSArray *selected = [outlineView selectedItems]; NSEnumerator *enumerator = [selected objectEnumerator]; - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) [self openResourceAsHex:resource]; } @@ -356,17 +902,20 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex 2003-07-31 UK Changed to use plugin registry instead of file name. -------------------------------------------------------------------------- */ --(void) openResourceUsingEditor: (Resource*)resource +/* Method name should be changed to: -(void)openResource:(Resource *)resource usingEditor:(Class)overrideEditor */ + +- (void)openResourceUsingEditor:(Resource *)resource { - Class editorClass = [[RKEditorRegistry mainRegistry] editorForType: [resource type]]; + Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType:[resource type]]; // open the resources, passing in the template to use - if( editorClass ) + if(editorClass) { // bug: I alloc a plug instance here, but have no idea where I should dealloc it, perhaps the plug ought to call [self autorelease] when it's last window is closed? - // update: doug says window controllers automatically release themselves when their window is closed. + // update: doug says window controllers automatically release themselves when their window is closed. All default plugs have a window controller as their principal class, but 3rd party ones might not + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceDataDidChange:) name:ResourceDataDidChangeNotification object:resource]; id plug = [(id )[editorClass alloc] initWithResource:resource]; - if( plug ) return; + if(plug) return; } // if no editor exists, or the editor is broken, open using template @@ -386,69 +935,105 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex 2003-07-31 UK Changed to use plugin registry instead of file name. -------------------------------------------------------------------------- */ --(void) openResource: (Resource*)resource usingTemplate: (NSString*)templateName +- (void)openResource:(Resource *)resource usingTemplate:(NSString *)templateName { // opens resource in template using TMPL resource with name templateName - Class editorClass = [[RKEditorRegistry mainRegistry] editorForType: @"Template Editor"]; + Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType:@"Template Editor"]; // TODO: this checks EVERY DOCUMENT for template resources (might not be desired) // TODO: it doesn't, however, check the application's resource map for a matching template! Resource *tmpl = [Resource resourceOfType:@"TMPL" withName:[resource type] inDocument:nil]; // open the resources, passing in the template to use - if( tmpl && editorClass ) + if(tmpl && editorClass) { - // bug: I alloc a plug instance here, but have no idea where I should dealloc it, perhaps the plug ought to call [self autorelease] when it's last window is closed? - // update: doug says window controllers automatically release themselves when their window is closed. - NSWindowController *plugController = [(id )[editorClass alloc] initWithResources:resource, tmpl, nil]; - if( plugController ) return; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceDataDidChange:) name:ResourceDataDidChangeNotification object:resource]; + id plug = [(id )[editorClass alloc] initWithResources:resource, tmpl, nil]; + if(plug) return; } // if no template exists, or template editor is broken, open as hex [self openResourceAsHex:resource]; } +/*! +@method openResourceAsHex: +@author Nicholas Shanks +@created 2001 +@updated 2003-07-31 UK: Changed to use plugin registry instead of file name. +@description Open a hex editor for the specified Resource instance. This looks up the hexadecimal editor in the plugin registry and then instantiates an editor object, handing it the resource. +@param resource Resource to edit +*/ -/* ----------------------------------------------------------------------------- - openResourceAsHex: - Open a hex editor for the specified Resource instance. This looks - up the hexadecimal editor in the plugin registry and then instantiates an - editor object, handing it the resource. - - REVISIONS: - 2003-07-31 UK Changed to use plugin registry instead of file name. - -------------------------------------------------------------------------- */ - --(void) openResourceAsHex: (Resource*)resource +- (void)openResourceAsHex:(Resource *)resource { - Class editorClass = [[RKEditorRegistry mainRegistry] editorForType: @"Hexadecimal Editor"]; + Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType: @"Hexadecimal Editor"]; // bug: I alloc a plug instance here, but have no idea where I should dealloc it, perhaps the plug ought to call [self autorelease] when it's last window is closed? // update: doug says window controllers automatically release themselves when their window is closed. + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceDataDidChange:) name:ResourceDataDidChangeNotification object:resource]; NSWindowController *plugController = [(id )[editorClass alloc] initWithResource:resource]; +#pragma unused(plugController) } +/*! +@method playSound: +@abstract Plays the selected carbon 'snd ' resource. +@author Nicholas Shanks +@created 2001 +@updated 2003-10-22 NGS: Moved playing into seperate thread to avoid locking up main thread. +@pending should really be moved to a 'snd ' editor, but first we'd need to extend the plugin protocol to call the class so it can add such menu items. Of course, we could just make the 'snd ' editor have a button in its window that plays the sound. +@description This method is called from a menu item which is validated against there being only one selected resource (of type 'snd '), so shouldn't have to deal with playing multiple sounds, though this may of course change in future. +@param sender ignored +*/ -// TODO: These two should really be moved to a 'snd ' editor, but first we'd -// need to extend the plugin protocol to call the class so it can add -// such menu items. Of course, we could just make the 'snd ' editor -// have a button in its window that plays the sound. - (IBAction)playSound:(id)sender { // bug: can only cope with one selected item NSData *data = [(Resource *)[outlineView itemAtRow:[outlineView selectedRow]] data]; - if( data && [data length] != 0 ) + if(data && [data length] != 0) { - // bug: plays sound synchronously in main thread! - SndListPtr sndPtr = (SndListPtr) [data bytes]; - SndPlay( nil, &sndPtr, false ); + [NSThread detachNewThreadSelector:@selector(playSoundThreadController:) toTarget:self withObject:data]; } else NSBeep(); } +/*! +@method playSoundThreadController: +@abstract Plays a carbon 'snd ' resource. +@author Nicholas Shanks +@created 2003-10-22 +@pending should really be moved to a 'snd ' editor, but first we'd need to extend the plugin protocol to call the class so it can add such menu items. Of course, we could just make the 'snd ' editor have a button in its window that plays the sound. +@description This method was added to prevent having to use AsynchSoundHelper to play them asynchronously in the main thread and all the associated idle checking, which since we have no event loop, would have to have been called from a timer. I'm not sure if the autorelease pool is necessary, as no cocoa objects are created, but an NSData is passed in and messages sent to it, and NSBeep() might need one. +@param data An NSData object containing the snd resource data to be played. +*/ + +- (void)playSoundThreadController:(NSData *)data +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + if(data && [data length] != 0) + { + // plays sound synchronously, thread exits when sound is done playing + SndListPtr sndPtr = (SndListPtr) [data bytes]; + SndPlay(nil, &sndPtr, false); + } + else NSBeep(); + [pool release]; +} + +/*! +@method sound:didFinishPlaying: +@abstract Called frequently when playing a sound via NSSound. Unused, here for reference and possible future use. +@author Nicholas Shanks +@pending should really be moved to a 'snd ' editor, but first we'd need to extend the plugin protocol to call the class so it can add such menu items. Of course, we could just make the 'snd ' editor have a button in its window that plays the sound. +@param sound The NSSound that is playing. +@param finished Flag to indicate if it has just finished and that we should clean up. +*/ + - (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finished { - if( finished ) [sound release]; - NSLog( @"sound released" ); + // unused because I can't get NSSound to play snd resources, so I use Carbon's SndPlay(), above + if(finished) [sound release]; + NSLog(@"sound released"); } - (void)resourceNameWillChange:(NSNotification *)notification @@ -464,9 +1049,9 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex // this saves the current resource's ID number so we can undo the change Resource *resource = (Resource *) [notification object]; [[self undoManager] registerUndoWithTarget:resource selector:@selector(setResID:) object:[[[resource resID] copy] autorelease]]; - if( [[resource name] length] == 0 ) + if([[resource name] length] == 0) [[self undoManager] setActionName:NSLocalizedString(@"ID Change", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"ID Change for Ò%@Ó", nil), [resource name]]]; + else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"ID Change for '%@'", nil), [resource name]]]; } - (void)resourceTypeWillChange:(NSNotification *)notification @@ -474,9 +1059,9 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex // this saves the current resource's type so we can undo the change Resource *resource = (Resource *) [notification object]; [[self undoManager] registerUndoWithTarget:resource selector:@selector(setType:) object:[[[resource type] copy] autorelease]]; - if( [[resource name] length] == 0 ) + if([[resource name] length] == 0) [[self undoManager] setActionName:NSLocalizedString(@"Type Change", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Type Change for Ò%@Ó", nil), [resource name]]]; + else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Type Change for '%@'", nil), [resource name]]]; } - (void)resourceAttributesWillChange:(NSNotification *)notification @@ -484,13 +1069,18 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex // this saves the current state of the resource's attributes so we can undo the change Resource *resource = (Resource *) [notification object]; [[self undoManager] registerUndoWithTarget:resource selector:@selector(setAttributes:) object:[[[resource attributes] copy] autorelease]]; - if( [[resource name] length] == 0 ) + if([[resource name] length] == 0) [[self undoManager] setActionName:NSLocalizedString(@"Attributes Change", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Attributes Change for Ò%@Ó", nil), [resource name]]]; + else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Attributes Change for '%@'", nil), [resource name]]]; +} + +- (void)resourceDataDidChange:(NSNotification *)notification +{ + [self updateChangeCount:NSChangeDone]; } -/* EDIT OPERATIONS */ #pragma mark - +#pragma mark Edit Operations - (IBAction)cut:(id)sender { @@ -500,7 +1090,7 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex - (IBAction)copy:(id)sender { - #pragma unused( sender ) + #pragma unused(sender) NSArray *selectedItems = [outlineView selectedItems]; NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; [pb declareTypes:[NSArray arrayWithObject:RKResourcePboardType] owner:self]; @@ -509,9 +1099,9 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex - (IBAction)paste:(id)sender { - #pragma unused( sender ) + #pragma unused(sender) NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - if( [pb availableTypeFromArray:[NSArray arrayWithObject:RKResourcePboardType]] ) + if([pb availableTypeFromArray:[NSArray arrayWithObject:RKResourcePboardType]]) [self pasteResources:[NSUnarchiver unarchiveObjectWithData:[pb dataForType:RKResourcePboardType]]]; } @@ -519,10 +1109,10 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex { Resource *resource; NSEnumerator *enumerator = [pastedResources objectEnumerator]; - while( resource = (Resource *) [enumerator nextObject] ) + while(resource = (Resource *) [enumerator nextObject]) { // check resource type/ID is available - if( [dataSource resourceOfType:[resource type] andID:[resource resID]] == nil ) + if([dataSource resourceOfType:[resource type] andID:[resource resID]] == nil) { // resource slot is available, paste this one in [dataSource addResource:resource]; @@ -533,7 +1123,7 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex NSMutableArray *remainingResources = [[NSMutableArray alloc] initWithCapacity:1]; [remainingResources addObject:resource]; [remainingResources addObjectsFromArray:[enumerator allObjects]]; - NSBeginAlertSheet( @"Paste Error", @"Unique ID", @"Skip", @"Overwrite", mainWindow, self, NULL, @selector(overwritePasteSheetDidDismiss:returnCode:contextInfo:), remainingResources, @"There already exists a resource of type %@ with ID %@. Do you wish to assign the pasted resource a unique ID, overwrite the existing resource, or skip pasting of this resource?", [resource type], [resource resID] ); + NSBeginAlertSheet(@"Paste Error", @"Unique ID", @"Skip", @"Overwrite", mainWindow, self, NULL, @selector(overwritePasteSheetDidDismiss:returnCode:contextInfo:), remainingResources, @"There already exists a resource of type %@ with ID %@. Do you wish to assign the pasted resource a unique ID, overwrite the existing resource, or skip pasting of this resource?", [resource type], [resource resID]); } } } @@ -542,17 +1132,17 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex { NSMutableArray *remainingResources = [NSMutableArray arrayWithArray:[(NSArray *)contextInfo autorelease]]; Resource *resource = [remainingResources objectAtIndex:0]; - if( returnCode == NSAlertDefaultReturn ) // unique ID + if(returnCode == NSAlertDefaultReturn) // unique ID { Resource *newResource = [Resource resourceOfType:[resource type] andID:[dataSource uniqueIDForType:[resource type]] withName:[resource name] andAttributes:[resource attributes] data:[resource data]]; [dataSource addResource:newResource]; } - else if( NSAlertOtherReturn ) // overwrite + else if(NSAlertOtherReturn) // overwrite { [dataSource removeResource:[dataSource resourceOfType:[resource type] andID:[resource resID]]]; [dataSource addResource:resource]; } -// else if( NSAlertAlternateReturn ) // skip +// else if(NSAlertAlternateReturn) // skip // remove top resource and continue paste [remainingResources removeObjectAtIndex:0]; @@ -561,18 +1151,18 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex - (IBAction)clear:(id)sender { - #pragma unused( sender ) - if( [prefs boolForKey:@"DeleteResourceWarning"] ) + #pragma unused(sender) + if([prefs boolForKey:@"DeleteResourceWarning"]) { - NSBeginCriticalAlertSheet( @"Delete Resource", @"Delete", @"Cancel", nil, [self mainWindow], self, @selector(deleteResourcesSheetDidEnd:returnCode:contextInfo:), NULL, nil, @"Please confirm you wish to delete the selected resources." ); + NSBeginCriticalAlertSheet(@"Delete Resource", @"Delete", @"Cancel", nil, [self mainWindow], self, @selector(deleteResourcesSheetDidEnd:returnCode:contextInfo:), NULL, nil, @"Please confirm you wish to delete the selected resources."); } else [self deleteSelectedResources]; } - (void)deleteResourcesSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { - #pragma unused( contextInfo ) - if( returnCode == NSOKButton ) + #pragma unused(contextInfo) + if(returnCode == NSOKButton) [self deleteSelectedResources]; } @@ -585,325 +1175,25 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex // enumerate through array and delete resources [[self undoManager] beginUndoGrouping]; enumerator = [selectedItems reverseObjectEnumerator]; // reverse so an undo will replace items in original order - while( resource = [enumerator nextObject] ) + while(resource = [enumerator nextObject]) { [dataSource removeResource:resource]; - if( [[resource name] length] == 0 ) + if([[resource name] length] == 0) [[self undoManager] setActionName:NSLocalizedString(@"Delete Resource", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Delete Resource Ò%@Ó", nil), [resource name]]]; + else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Delete Resource '%@'", nil), [resource name]]]; } [[self undoManager] endUndoGrouping]; // generalise undo name if more than one was deleted - if( [outlineView numberOfSelectedRows] > 1 ) + if([outlineView numberOfSelectedRows] > 1) [[self undoManager] setActionName:NSLocalizedString(@"Delete Resources", nil)]; // deselect resources (otherwise other resources move into selected rows!) [outlineView deselectAll:self]; } -/* FILE HANDLING */ -#pragma mark - - -/*- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel -{ - [savePanel setTreatsFilePackagesAsDirectories:YES]; - return YES; -}*/ - - -/* ----------------------------------------------------------------------------- - readFromFile:ofType: - Open the specified file and read its resources. This first tries to - load the resources from the res fork, and failing that tries the data - fork. - - REVISIONS: - 2003-08-01 UK Commented. - -------------------------------------------------------------------------- */ - --(BOOL) readFromFile: (NSString*)fileName ofType: (NSString*)fileKind -{ - BOOL succeeded = NO; - OSStatus error = noErr; - HFSUniStr255 *resourceForkName = (HFSUniStr255 *) NewPtrClear( sizeof(HFSUniStr255) ); // This may be saved away in the instance variable "fork" to keep track of which fork our resources are in. - FSRef *fileRef = (FSRef *) NewPtrClear( sizeof(FSRef) ); - SInt16 fileRefNum = 0; - FSCatalogInfo info = { 0 }; - - // open fork with resources in it - error = FSPathMakeRef( [fileName cString], fileRef, nil ); - error = FSGetResourceForkName( resourceForkName ); - SetResLoad( false ); // don't load "preload" resources - - [type release]; - [creator release]; - - error = FSGetCatalogInfo( fileRef, kFSCatInfoFinderInfo, &info, nil, nil, nil ); - type = [[NSString stringWithCString: &((FileInfo*)info.finderInfo)->fileType length:4] retain]; - creator = [[NSString stringWithCString: &((FileInfo*)info.finderInfo)->fileCreator length:4] retain]; - - // Try res fork first: - error = FSOpenResourceFile( fileRef, resourceForkName->length, (UniChar *) &resourceForkName->unicode, fsRdPerm, &fileRefNum); - if( error ) // try to open data fork instead - { - NSLog( @"Opening Resource fork failed, trying data fork..." ); - error = FSOpenResourceFile( fileRef, 0, nil, fsRdPerm, &fileRefNum); - } - else - { - fork = resourceForkName; - [self readFork:@"" asStreamFromFile:fileName]; // bug: only reads data fork for now, need to scan file for other forks too - } - SetResLoad( true ); // restore resource loading as soon as is possible - - // read the resources (without spawning thousands of undos for resource creation) - [[self undoManager] disableUndoRegistration]; - if( fileRefNum && error == noErr ) - succeeded = [self readResourceMap:fileRefNum]; - else if( !fileRefNum ) - { - // supposed to read data fork as byte stream here - NSLog( @"Opening data fork failed too! (fileRef)" ); - } - else NSLog( @"Opening data fork failed too! (error)" ); - [[self undoManager] enableUndoRegistration]; - - // tidy up loose ends - if( !fork ) DisposePtr( (Ptr) resourceForkName ); // only delete if we're not saving it to "fork" instance var. - if( fileRefNum ) FSClose( fileRefNum ); - DisposePtr( (Ptr) fileRef ); - - return succeeded; -} - -- (BOOL)readFork:(NSString *)forkName asStreamFromFile:(NSString *)fileName -{ - NSData *data = [NSData dataWithContentsOfFile:fileName]; - Resource *resource = [Resource resourceOfType:@"" andID:0 withName:NSLocalizedString(@"Data Fork", nil) andAttributes:0 data:data]; - if( data && resource ) - { - /* NTFS Note: When running SFM (Services for Macintosh) a Windows NT-based system (including 2000 & XP) serving NTFS-formatted drives stores Mac resource forks in a stream named "AFP_Resource". The finder info/attributes are stored in a stream called "Afp_AfpInfo". The default data fork stream is called "$DATA" and any of these can be accessed thus: "c:\filename.txt:forkname". - As a result, ResKnife prohibits creation of forks with the following names: "" (empty string, Mac data fork name), - "$DATA" (NTFS data fork name), - "AFP_Resource" and "Afp_AfpInfo". - It is perfectly legal in ResKnife to read in forks of these names when accessing a shared NTFS drive from a server running SFM. */ - - [resource setRepresentedFork:forkName]; - [resource setDocument:self]; - [resources insertObject:resource atIndex:0]; - return YES; - } - else return NO; -} - --(BOOL) readResourceMap: (SInt16)fileRefNum -{ - OSStatus error = noErr; - unsigned short n; - unsigned short i; - SInt16 oldResFile = CurResFile(); - UseResFile( fileRefNum ); - - for( i = 1; i <= Count1Types(); i++ ) - { - ResType resType; - unsigned short j; - - Get1IndType( &resType, i ); - n = Count1Resources( resType ); - for( j = 1; j <= n; j++ ) - { - Str255 nameStr; - long sizeLong; - short resIDShort; - short attrsShort; - Handle resourceHandle; - NSString *name; - NSString *type; - NSNumber *resID; - NSNumber *attributes; - NSData *data; - Resource *resource; - - resourceHandle = Get1IndResource( resType, j ); - error = ResError(); - if( error != noErr ) - { - NSLog( @"Error reading resource map..." ); - UseResFile( oldResFile ); - return NO; - } - - GetResInfo( resourceHandle, &resIDShort, &resType, nameStr ); - sizeLong = GetResourceSizeOnDisk( resourceHandle ); - attrsShort = GetResAttrs( resourceHandle ); - HLockHi( resourceHandle ); - - // create the resource & add it to the array - name = [NSString stringWithCString:&nameStr[1] length:nameStr[0]]; - type = [NSString stringWithCString:(char *) &resType length:4]; - resID = [NSNumber numberWithShort:resIDShort]; - attributes = [NSNumber numberWithShort:attrsShort]; - data = [NSData dataWithBytes:*resourceHandle length:sizeLong]; - resource = [Resource resourceOfType:type andID:resID withName:name andAttributes:attributes data:data]; - [resource setDocument:self]; - [resources addObject:resource]; // array retains resource - - HUnlock( resourceHandle ); - ReleaseResource( resourceHandle ); - } - } - - // save resource map and clean up - UseResFile( oldResFile ); - return YES; -} - -- (BOOL)writeToFile:(NSString *)fileName ofType:(NSString *)type -{ - BOOL succeeded = NO; - OSStatus error = noErr; - FSRef *parentRef = (FSRef *) NewPtrClear( sizeof(FSRef) ); - FSRef *fileRef = (FSRef *) NewPtrClear( sizeof(FSRef) ); - FSSpec *fileSpec = (FSSpec *) NewPtrClear( sizeof(FSSpec) ); - SInt16 fileRefNum = 0; - - // create and open file for writing - error = FSPathMakeRef( [[fileName stringByDeletingLastPathComponent] cString], parentRef, nil ); - if( fork && ![type isEqualToString: @"Resource File (Data Fork)"] ) - { - unichar *uniname = (unichar *) NewPtrClear( sizeof(unichar) *256 ); - [[fileName lastPathComponent] getCharacters:uniname]; - error = FSCreateResourceFile( parentRef, [[fileName lastPathComponent] length], (UniChar *) uniname, kFSCatInfoNone, nil, fork->length, (UniChar *) &fork->unicode, fileRef, fileSpec ); - if( !error ) - { - // Set type & creator code: - FInfo macMetadata; - error = FSpGetFInfo( fileSpec, &macMetadata ); - macMetadata.fdType = 'rsrc'; - macMetadata.fdCreator = 'ResK'; - if( !error ) - FSpSetFInfo( fileSpec, &macMetadata ); - - // Open fork for fetching resources: - error = FSOpenResourceFile( fileRef, fork->length, (UniChar *) &fork->unicode, fsWrPerm, &fileRefNum); - - /* at some point make use of: - - FSCreateResourceFork( const FSRef * ref, - UniCharCount forkNameLength, - const UniChar * forkName, // can be NULL - UInt32 flags); - - Creates the named fork and initalises as a resource fork - - Mac OS 10.2 or later */ - } - } - else - { - unichar *uniname = (unichar *) NewPtrClear( sizeof(unichar) *256 ); - [[fileName lastPathComponent] getCharacters:uniname]; - error = FSCreateResourceFile( parentRef, [[fileName lastPathComponent] length], (UniChar *) uniname, kFSCatInfoNone, nil, 0, nil, fileRef, fileSpec ); - if( !error ) - { - // Set type & creator: - FInfo macMetadata; - error = FSpGetFInfo( fileSpec, &macMetadata ); - macMetadata.fdType = 'rsrc'; - macMetadata.fdCreator = 'ResK'; - if( !error ) - error = FSpSetFInfo( fileSpec, &macMetadata ); - - // Open resource map for fetching resources: - error = FSOpenResourceFile( fileRef, 0, nil, fsWrPerm, &fileRefNum); - } - } - - // write resource array to file - if( fileRefNum && !error ) - succeeded = [self writeResourceMap:fileRefNum]; - - // tidy up loose ends - if( fileRefNum ) FSClose( fileRefNum ); - DisposePtr( (Ptr) fileRef ); - return succeeded; -} - - -/* ----------------------------------------------------------------------------- - writeResourceMap: - Writes all resources (except the ones representing other forks of the - file) to the specified resource file. - - REVISIONS: - 2003-08-01 UK Swiss national holiday, and I'm stuck in Germany... - Commented, changed to use enumerator instead of - objectAtIndex. - -------------------------------------------------------------------------- */ - --(BOOL) writeResourceMap: (SInt16)fileRefNum -{ - OSStatus error = noErr; - NSEnumerator* enny; - Resource *resource; - - // Make the resource file current: - SInt16 oldResFile = CurResFile(); - UseResFile( fileRefNum ); - - // Loop over all our resources: - for( enny = [resources objectEnumerator]; resource = [enny nextObject]; ) - { - Str255 nameStr; - ResType resType; - short resIDShort; - short attrsShort; - Handle resourceHandle; - - // Resource represents another fork in the file? Skip it. - if( [resource representedFork] != nil ) continue; - - resIDShort = [[resource resID] shortValue]; - attrsShort = [[resource attributes] shortValue]; - resourceHandle = NewHandleClear( [[resource data] length] ); - - // Unicode name -> P-String: - nameStr[0] = [[resource name] cStringLength]; - BlockMoveData( [[resource name] cString], &nameStr[1], nameStr[0] ); - - // Type string to ResType: - [[resource type] getCString:(char *) &resType maxLength:4]; - - // NSData to resource data Handle: - HLockHi( resourceHandle ); - [[resource data] getBytes:*resourceHandle]; - HUnlock( resourceHandle ); - - // Now that everything's converted, write it to our file: - AddResource( resourceHandle, resType, resIDShort, nameStr ); - if( ResError() == addResFailed ) - { - NSLog( @"*Saving failed*; could not add resource ID %@ of type %@ to file.", [resource resID], [resource type] ); - error = addResFailed; - } - else - { - NSLog( @"Added resource %@, \"%@\", of type %@ to file.", [resource resID], [resource name], [resource type] ); - SetResAttrs( resourceHandle, attrsShort ); - ChangedResource( resourceHandle ); - UpdateResFile( fileRefNum ); - } - } - - // Save resource map and clean up: - UseResFile( oldResFile ); - return error? NO:YES; -} - -/* ACCESSORS */ #pragma mark - +#pragma mark Accessors - (NSWindow *)mainWindow { @@ -925,132 +1215,86 @@ static NSString *RKExportItemIdentifier = @"com.ulikusterer.resknife.toolbar.ex return resources; } -- (NSString *)creator +- (NSData *)creator { return creator; } -- (NSString *)type +- (NSData *)type { return type; } - (IBAction)creatorChanged:(id)sender { - [self setCreator:[sender stringValue]]; + unsigned long newCreator = 0x00; // creator is nil by default + NSData *creatorData = [[sender stringValue] dataUsingEncoding:NSMacOSRomanStringEncoding]; +// NSLog(@"creatorChanged: [sender stringValue] = '%@'; creatorData = '%@'", [sender stringValue], creatorData); + if(creatorData && [creatorData length] > 0) + { + newCreator = ' '; // pad with spaces if not nil + [creatorData getBytes:&newCreator length:([creatorData length] < 4? [creatorData length]:4)]; + } + [self setCreator:[NSData dataWithBytes:&newCreator length:4]]; +// NSLog(@"Creator changed to '%@'", [[[NSString alloc] initWithBytes:&newCreator length:4 encoding:NSMacOSRomanStringEncoding] autorelease]); } - (IBAction)typeChanged:(id)sender { - [self setType:[sender stringValue]]; + unsigned long newType = 0x00; + NSData *typeData = [[sender stringValue] dataUsingEncoding:NSMacOSRomanStringEncoding]; +// NSLog(@"typeChanged: [sender stringValue] = '%@'; typeData = '%@'", [sender stringValue], typeData); + if(typeData && [typeData length] > 0) + { + newType = ' '; + [typeData getBytes:&newType length:([typeData length] < 4? [typeData length]:4)]; + } + [self setType:[NSData dataWithBytes:&newType length:4]]; +// NSLog(@"Type changed to '%@'", [[[NSString alloc] initWithBytes:&newType length:4 encoding:NSMacOSRomanStringEncoding] autorelease]); } -- (void)setCreator:(NSString *)newCreator +- (BOOL)setCreator:(NSData *)newCreator { - if( ![newCreator isEqualToString:creator] ) + if(![newCreator isEqualToData:creator]) { id old = creator; - [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoWillChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", newCreator, @"NSString creator", nil]]; + [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoWillChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", newCreator, @"creator", nil]]; [[self undoManager] registerUndoWithTarget:self selector:@selector(setCreator:) object:creator]; - [[self undoManager] setActionName:NSLocalizedString( @"Change Creator Code", nil)]; + [[self undoManager] setActionName:NSLocalizedString(@"Change Creator Code", nil)]; creator = [newCreator copy]; [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoDidChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", newCreator, @"NSString creator", nil]]; + [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoDidChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", creator, @"creator", nil]]; + return YES; } + else return NO; } -- (void)setType:(NSString *)newType +- (BOOL)setType:(NSData *)newType { - if( ![newType isEqualToString:type] ) + if(![newType isEqualToData:type]) { id old = type; - [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoWillChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", newType, @"NSString type", nil]]; + [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoWillChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", newType, @"type", nil]]; [[self undoManager] registerUndoWithTarget:self selector:@selector(setType:) object:type]; - [[self undoManager] setActionName:NSLocalizedString( @"Change File Type", nil)]; + [[self undoManager] setActionName:NSLocalizedString(@"Change File Type", nil)]; type = [newType copy]; [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoDidChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", newType, @"NSString type", nil]]; + [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoDidChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", type, @"type", nil]]; + return YES; } + else return NO; } -- (void)setCreator:(NSString *)newCreator andType:(NSString *)newType +- (BOOL)setCreator:(NSData *)newCreator andType:(NSData *)newType { - BOOL changeAction = ![newCreator isEqualToString:creator] && ![newType isEqualToString:type]; + BOOL creatorChanged, typeChanged; [[self undoManager] beginUndoGrouping]; - [self setCreator:newCreator]; - [self setType:newType]; + creatorChanged = [self setCreator:newCreator]; + typeChanged = [self setType:newType]; [[self undoManager] endUndoGrouping]; - if( changeAction ) - [[self undoManager] setActionName:NSLocalizedString( @"Change Creator & Type", nil)]; -} - - --(void) exportDataPanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - NSData* data = contextInfo; - [data autorelease]; - - if( returnCode == NSOKButton ) - [data writeToFile:[sheet filename] atomically: YES]; -} - - --(void) exportImagePanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - NSImage* img = contextInfo; - [img autorelease]; - - if( returnCode == NSOKButton ) - { - NSData* data = [img TIFFRepresentation]; - [data writeToFile:[sheet filename] atomically: YES]; - } -} - - --(IBAction) exportResourceToFile: (id)sender -{ - Resource* resource = (Resource*) [outlineView selectedItem]; - NSData* theData; - Class edClass = [[RKEditorRegistry mainRegistry] editorForType: [resource type]]; - NSString* extension = [resource type]; - NSSavePanel* panel; - NSString* fName; - - if( [edClass respondsToSelector:@selector(dataForFileExport:)] ) - theData = [edClass dataForFileExport: resource]; - else - theData = [resource data]; - - if( [edClass respondsToSelector:@selector(extensionForFileExport:)] ) - extension = [edClass extensionForFileExport]; - - panel = [NSSavePanel savePanel]; - fName = [[resource name] stringByAppendingFormat: @".%@", extension]; - - [panel beginSheetForDirectory:nil file:fName modalForWindow:mainWindow modalDelegate:self - didEndSelector:@selector(exportDataPanelDidEnd:returnCode:contextInfo:) contextInfo:[theData retain]]; -} - - --(IBAction) exportResourceToImageFile: (id)sender -{ - Resource* resource = (Resource*) [outlineView selectedItem]; - NSImage* theData; - Class edClass = [[RKEditorRegistry mainRegistry] editorForType: [resource type]]; - NSString* extension = @"tiff"; - NSSavePanel* panel; - NSString* fName; - - if( ![edClass respondsToSelector:@selector(imageForImageFileExport:)] ) - return; - - theData = [edClass imageForImageFileExport: resource]; - panel = [NSSavePanel savePanel]; - fName = [[resource name] stringByAppendingFormat: @".%@", extension]; - - [panel beginSheetForDirectory:nil file:fName modalForWindow:mainWindow modalDelegate:self - didEndSelector:@selector(exportImagePanelDidEnd:returnCode:contextInfo:) contextInfo:[theData retain]]; + if(creatorChanged && typeChanged) + [[self undoManager] setActionName:NSLocalizedString(@"Change Creator & Type", nil)]; + return (creatorChanged || typeChanged); } @end diff --git a/Cocoa/Classes/ResourceNameCell.m b/Cocoa/Classes/ResourceNameCell.m index 375fd3a..44a58bf 100644 --- a/Cocoa/Classes/ResourceNameCell.m +++ b/Cocoa/Classes/ResourceNameCell.m @@ -5,10 +5,9 @@ - (id)init { self = [super init]; - if( self ) - { - drawImage = YES; - } + if(!self) return nil; + [self setWraps:NO]; + drawImage = YES; return self; } @@ -42,7 +41,7 @@ - (void)setImage:(NSImage *)newImage { - if( image != newImage ) + if(image != newImage) { // save image and set to 16x16 pixels id old = image; @@ -55,7 +54,7 @@ - (NSRect)imageFrameForCellFrame:(NSRect)cellFrame { - if( image != nil && drawImage == YES ) + if(image != nil && drawImage == YES) { // center image vertically in frame, offset right by three NSRect imageFrame; @@ -70,11 +69,11 @@ - (void)editWithFrame:(NSRect)cellFrame inView:(NSView *)controlView editor:(NSText *)textObject delegate:(id)delegateObject event:(NSEvent *)theEvent { - if( drawImage == YES ) + if(drawImage == YES) { // split cell frame into two, pass the text part to the superclass NSRect textFrame, imageFrame; - NSDivideRect( cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge ); + NSDivideRect(cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); [super editWithFrame:textFrame inView:controlView editor:textObject delegate:delegateObject event:theEvent]; } else @@ -85,11 +84,11 @@ - (void)selectWithFrame:(NSRect)cellFrame inView:(NSView *)controlView editor:(NSText *)textObject delegate:(id)delegateObject start:(int)selStart length:(int)selLength { - if( drawImage == YES ) + if(drawImage == YES) { // split cell frame into two, pass the text part to the superclass NSRect textFrame, imageFrame; - NSDivideRect( cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); + NSDivideRect(cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); [super selectWithFrame:textFrame inView:controlView editor:textObject delegate:delegateObject start:selStart length:selLength]; } else @@ -100,15 +99,14 @@ - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { - if( image != nil && drawImage == YES ) + if(image != nil && drawImage == YES) { NSRect imageFrame; NSSize imageSize = [image size]; // get image frame - NSDivideRect( cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge ); -// NSLog( "drawing name cell with bg: %@ colour: %@", [self drawsBackground]? @"YES":@"NO", [self backgroundColor] ); - if( [self drawsBackground] && ![self isHighlighted] /* ![self cellAttribute:NSCellHighlighted] */ ) + NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge); + if([self drawsBackground] && ![self isHighlighted] /* ![self cellAttribute:NSCellHighlighted] */) { [[self backgroundColor] set]; NSRectFill(imageFrame); @@ -117,7 +115,7 @@ imageFrame.size = imageSize; // center vertically - if( [controlView isFlipped] ) + if([controlView isFlipped]) imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2); else imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); @@ -132,7 +130,7 @@ - (NSSize)cellSize { NSSize cellSize = [super cellSize]; - if( drawImage == YES ) + if(drawImage == YES) cellSize.width += (image? [image size].width:0) + 3; return cellSize; } diff --git a/Cocoa/Classes/SizeFormatter.m b/Cocoa/Classes/SizeFormatter.m index 2cddebe..e71eb61 100644 --- a/Cocoa/Classes/SizeFormatter.m +++ b/Cocoa/Classes/SizeFormatter.m @@ -15,7 +15,7 @@ float value = [obj floatValue]; int power = 0; - while( value >= 1024 && power <= 30 ) + while( value >= 1024 /*&& power <= 30*/ ) { power += 10; // 10 == KB, 20 == MB, 30+ == GB value /= 1024; diff --git a/Cocoa/English.lproj/AboutPanel.nib/info.nib b/Cocoa/English.lproj/AboutPanel.nib/info.nib index 57f78f4..cd6112a 100644 --- a/Cocoa/English.lproj/AboutPanel.nib/info.nib +++ b/Cocoa/English.lproj/AboutPanel.nib/info.nib @@ -1,20 +1,20 @@ - - + + IBDocumentLocation - 109 310 356 240 0 0 1280 1002 + 147 310 356 240 0 0 1600 1002 IBFramework Version - 248.0 + 446.1 IBLockedObjects 25 IBOpenObjects - 23 + 21 IBSystem Version - 5P48 + 8L127 diff --git a/Cocoa/English.lproj/AboutPanel.nib/objects.nib b/Cocoa/English.lproj/AboutPanel.nib/objects.nib index 05ca5a12e8557894664b330d5956ec314ea486c9..f6d72e60c4fa03ac73a1f27468e8ce86d2eb610b 100644 GIT binary patch literal 4905 zcmb_gU2Gf25#ALkT0e9wDVAfoj!Pr~Y%7gQDXx(UK}A`q93?Srm`YsK2!hk`WM6aQ zvB#4o0e$e%%X{hDfg;FQB^n_$YFf5Zp*7IHxadPlAOQQ&_Mt`LqOAZLp8Bf&3jtUWqC*Dz&1#pl$t7Ou8DybMO?}!yAS7IU@ zLz}HP&z@8BrZl4|wowAdo zp9re59Ag}l#hxbHCKOHkmJne8%BHHP=(*Q5k+^XzT~)I|exGGoj4=@;(?qe@3A5i! zsk2I#4L~et5>7ajFTEhz&%b=>fW5`$naos{WD+~c4E(3SD*)rO`vsR- zg;!XG*|{8ajUoa$XH^8`Sd2`?LML=hhjS_+5%6?}5=$9VnX_R=SoVDH%GlyYB_P^n zXRnM6R&H>coxnu1{Q zPuwGlr2Vm>73b4BChc#^$h5^){oeW1+u;;cY(zps204x7?=%}(|1(7Xdg&nc=*TPH z9^H$@V2{3z{iv}^_&2drWhOOpli4LkSb=rU?R8Hxy65Uk?V!A$}Bw@<7MAP}e{l@$Okc{Q7$O%z44SUS)IQUyUvds`({*r_tYsi$XI6w*6ueB#wUNQ zRXyPbK<%I)h|-Y8TG4#$?gwazMB+Vwc7jM>D|8UXF3zgY*a zC<#2%*+TpLajk(*c@N=6juP+h2YT1s@U9m`X9>-JRC@@YFxS@B{y;q@K3G~>`drub z8{p4_UI%?0^fZXhs~zF{_5$zb;^N|GnBQ0f_*X$kKm(v|(00xb-~Pk?`Z4djpttF{ zX$^mZ&L3jDAGDM6kMK$UIl@Cv>wkqPolgGD_Qw+JVT>k9$AdU+F4}3%HZB=@w`M z7lZC?&%1{!hQ)q=)xBq5_U_qKTIMWn@ICHrl>XhjC@Relp(N*2MPPPz6qQ~0y`=7= zjJoiS`0OF5m6dbYYUldC1o8>LGG^?X_$^&g-3#y=0~XI(>?69UQ}322bXmXa{MEa( zi*_pV)h@KGfGLf8^It3uA6T4vOmKg8Df=9)h-!d0LKeS*y-xpMsC>R$n~qNC=_NzG zaM6tX=6Yl#8XbP=_}3zFRlcZeQYMnPD5c)d3`NE@EpnEmG7;27ig8Iv4(*_j?RKx` ztP*Y%vZc*Jwp^%H>5B;N=-&4dzpkRLh0( zy;4V^gt`2fU06mRrh4>nCUSZqg%3A{8ofGh7w$n{*Z7P+Z+hAat9Zfe!Unw`whOnZ zAF&Hn>c4^1`{mD(jDD@RH=c;AGpFZGO~HqTR0wBUY1 z!e<;_+aFIyeNf5TTCrIUHi{hYO6i9 z>b}}Cul@5tt=wC?y|=c}SG(6=`|rV8ZBOZ0D&+1Id!|lI=&~+N8mPq=bmM*7{vSU@ BpMC%U literal 2228 zcmb7F|7#pY6rZ_on&jGEVq4pya7aO-HC)qLBp|)?BsFclmTqZ(5RuK^T)TF2d+u$T z1_Zm8+4)siE=#ipE@;yl>-9?%BNjxoHa!jsK?D&ir35Pe1^(3f-tOI{jlbv~J2SWQ z=Dqj%ye|{!GAD{GS27JIk6PhBIZboU*Jq{SeTPThV~Y8PY|0k7$NAG)DfmKcClJYu zl}vp!_}E+Fp)?-dkd@vVGvyJDNv5F|PE!A5b6w%|<+dJS3r^K87Y-$|(h0SY)5njo z(V`}s%%Xo+_&Qb1!=tA0QNkgMerVB)7X96#k@B^(gz)pzM8NP=RyraVn1<`fag~h= z&>720xa{S;D=QskrJ`QQF@sbb+ao-VDp5H;0h*@QgN7kb5Y9nou&j7d#0yG}v9soo z%Cy{8&O5SFMlYC#uJz73Rj=Gh2&vle9JI)97X9FPLU44dj*UMaQ57XkC@4mT+L|&< z(_ZI14#pHy)eHE)+xHz;gFvdPmLv2bDU&qdjiB3ndb$Jf94x4L*4acl1ioylc-wjO z?Ol76cVghpHh3RCB8SKrQHV-%L?-)*0b>Ey43yFQ7ETpXqcu{C3EKu+0}xx=nd4z4 zokmxIgp97~z*;TF!-4IXG*L3yr~o(ON}X#1c(0 zM7=7yKtM(SHFUrh4!^jT#oNGN!e=qjV(|hJIRDuyA@iVp-En4=fVyO=Z+C8&;8(ou zm;Vd?FV+EW#2x|cSA5`$SIO0{z@;zIAwT59qw-0HX|(MU`WJ6T88#tgtvqKYa23r; z5-cFYhp7X3xG5_QsTwQDqpWmfM3;@+F(@=4;ug7`N)eJuJ%MV~8V0`iasZOdgC!`A zpwb}d`k0}x-iiyjAvV5u7>I7jpJGu{6&aIg82A?ATZm{_RaJ0V)M$(07n%s{12KzE zu19_+*FWLOT7CyIdU3)~Po6T9Kg=ilQ>mS=^zTS!Rppef$)%)pN-mr(^(6;2EqN5B zN=fjO8E06o?|%fNs~L=VI~Yq(1_St(6eu?hqhXQze%1AygR0}7dSMJ#C-9`HMcf~l zbsAood>`yWJp7i1`M26&Zu#F(y7jGZ*16-Ads+-3H${tl(wdz+K`lE#I5Zd32D#$2 z)4aoM=l9n@_Z9CssK)-+f@<6dTA>=>gv!&%85m8dNrlMmETqCCs4KicsaOas!}NZc zoOjPTwx6k(ub8o|mk40XrWC}Qe&Xyjz^i3^c@+AlqWlW*q3dSGjFN72R~G0ahu?I6 z!rJkhoIW0G2?4r^AW)c1J_E*?VUeFN`HVLCCTQ292HoJ>#nHD4-QxlPwVehJ=ko(l zt?_qrdP~cIuioK*{7co$%n6|VM9&%}Khnv)#^%gT1nfgSu+^evi-3(__7fMwa@V;R zgoj75qpO|plsUN4W(Y40JcctI@PERlJc9DD5hYgmuNno)KeEVOAUw1Hr>ESxs$2Ek z#j4w=x=U4ex#8ZZ;*|yYc(}+4`ww9Tg=QT-ix&$fBX#aK!x92}z?kLFZKKT;14*C8 z)_!YtRsu zk4rA$_HN-Wi#YFuRQhg_z=&{xqBsww)hSwUY_5Bo>ML97%Ny!T&(!A<^&1=O li#_#fcm2V$_4`}BZCDTIrxU~bGP IBDocumentLocation - 264 129 383 248 0 0 1024 746 + 75 727 356 240 0 0 1600 1002 IBEditorPositions 246 - 344 386 340 222 0 0 1024 746 + 569 580 520 175 0 0 1600 1002 29 - 22 682 347 44 0 0 1024 746 + 66 658 366 44 0 0 1600 1002 IBFramework Version - 326.0 + 446.1 + IBLockedObjects + + IBOldestOS + 1 IBOpenObjects - 246 29 IBSystem Version - 7A202 + 8L127 diff --git a/Cocoa/English.lproj/Application.nib/keyedobjects.nib b/Cocoa/English.lproj/Application.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..97761a838ef0aab813739fcbddc4c9a149664a5a GIT binary patch literal 26686 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 YYrwvM!wg^moHhpo?qv`fMh0900J)DCegFUf literal 0 HcmV?d00001 diff --git a/Cocoa/English.lproj/Application.nib/objects.nib b/Cocoa/English.lproj/Application.nib/objects.nib index 5cd86bad5ef9e2f758d93cd86d77fe1539f2641d..5525d74e278b6566986ef90ebbf42e27890dcee1 100644 GIT binary patch literal 11162 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 Lw%u5%ZTtTL9l?N= literal 9377 zcmb7K3vg7|c|I3C(CUehksl>w?LdTS?EzyPthz=*pdcQLq6O??d*apZm9%EHSGl{( z!>S2KzI!LrHseMk&RB{ZQ|denL1BVDaUGnXme#bVLrd$rrln;QS{j#z6f(4=G|=xq zckkU@2}wj6?YaBEU+48-6;~wp^y!gA($qt}yyz#E)?`^$bs*TbdUNLsdN{czlnil} zv8=K{(1Eb@phMDBP2D!?x4bH^euA0W)DX zMR)6wU^0}{fkMpiYb$#WkQ3GIrrxESdOWNr9)9>?`;7rMhq)GfJ^f}O$G{23*c;Q+ zsL%v;b7vGHC&{y_6RFN#nAIGnus14$tk+&+)~my19+!1sgem7f9|*cY^2N5Zrr)U{ zRqLV=y&%3?k3Fr6WPXL>+MMjs&B-1VM#S;9$Jpg>j>RT<>(P$nB3|{mRJ1VV+83rW ziDFQR7*L_=P5=%}@A{}fsi}B61*)pXMm#IYf^n7e`W8&Gr0x&syC^h@thPp>>r#o7p*jK=+I^sZ1Umh{ti!&EBt=~Ylf?^Eo%qRAdlz!tr?FGfX7R<4~{ z#DbiNV4oh2c16Q}SBC2>iMeO0YIkB)r^JL3{&o89Py}*%Lov^b+w-2tg`sxs?mojz z`jdvgH5$`N?{t&LQF(WcNzL**WWCeWl()x1d;CEo6^|%K`VfS>rVqm04t=K%HzpQK z$5d&+YC1!mj_1{BF~x>zw2C5^Q8ikG;#B6vr_zz5oxQnFkJI8srD4oWUqSS6CalMk zlk#yee?=;wgn=3Ms>M?yCRcnlJ3M*eSk++g%4h%HSw4^!# zDQSrr38(sZ&Fo@vFtpPlPRvYPPQ?CZwf<8GgEO;~Iu)TJZca}=gM;UtJkCJn)kRf1 z_C0@4Pp10ZjJHp(U#-yXI07VH2CDemZgNz%L|z%B1-&iaWwPbC(izY6~rMyO_Y$q4XP$)6PsI%T~oT~(ff!VyY+4-m)$dSR4EP|?RG|uR6->+ zGBa2G)&xy0$^edL{w~AB)^i&N^Yi9-R2K}JMl44AoX4-UzA%+mOf_|sbLzAVTXZaj zQ~ET)d>lb6q98V^AXd06ZXg?{QkCPWR;OgY%c(5<&6(NmD`dk;>Hlpb<==t}%Orc< z*pPqTa4fN(Xl^c z53bEh_>)N#MMN>~O2FJJeF~{Jc1?2dU@=kB33C%nQqwTtBxJi`^!lgZa-Ago4tdR{ zXgt~*eNlH=XukJOmyEy+M~a+mXZ_w{7_rWfImv^`w%p}hvdEY$(@ZC|U%{451~ykr zjMbs=jyter?rOTN(h8_fjizy%Gm7g06>v4q7f#Ug&lRWw;ELDjvA#(<50A*#MXQ33UvLeY5ka>B|dRn{!h=CfNxQAV5`7o%--$HwJ* z3*F6Ij998Sj!S!4Q&(44Q&Tt$nI(N86GxrJix-2kHcPoq$MM^2!7?#lUGBGFIc$yU zu?T^lw5&?plGM6I-)q&Cot~P}4~Rwwiup}8P==G1RosLhQqr!JKm#uKt%&lxp^=4F z$ur9z3qMy1!u#-d^A_94QY_4(EW$$Uv&_V29M3ugX*Xg89eQ1}t>jp#Rpgja8r*}8w3mWi)1zD@#}pUQ6@8a! zSV*kiHwW%ocC$&ja42n=BMZNMCq^Erf^lSEF%0~UbF#Ipifl-?MfF|3Wm!Hn8Q?z_ z@CQ{e2#hCCp&t5-IKs|U7X*zF+Cd55xR=@@h`F=y6Ns}PyFh0;DLH!w(<1|ODe#pP zcqCc+um?oH2)Ya9|kovL7q|;g2I8~uPBp8oLs9g71EMk z{JzIDG}bCqC88P|8>0vm>8GHlPZ0bB~sojWrxx)x|sf>Oig3Wnf59LbFwMO⋙2t+By=ggj?J0^5fWXOc#AmQ@0d+Duk77-_>oV{k}%yQU&g~g*XyLgm(i%0)a4WZ`jYmT{g(JZL& zbo;u^Xkj(MUQ|Jg?NM=RT-5kPM?l=`6LMUv^oi#J z;-hi#P=g3;6h}tIda}&gFP?7|?~IDA0WsGn=KDnBN^y2v+{lQHt)e|3PLGSRQE??B zZe>L0^Wup{v9v)%Iz?u^*cK2Aed66w(YjwO@QE|yqS7bMjf<-paWf-WMqJ2Tg(Nlz-Z(PAiN*QJ4V2i3nb%lTdbZ)PyJ2xns=kQQ6X&JBfJpuR}plM|&Ekt}#|Zy`OR zytEL4;#yP)LFP{vLXd*>qy>{22&6f8fPewxfO*+jRmcgi&J{u+{TkT@y_JO+RM8D! zW-UWTTk%ll9Z^LMDD!g;t(2UiWsl&g-w~r~%8A)=K#G^)#}@B9NN;x8!Uu?F?)~_Z zFZdC)ff6M98cI(h871^WBZ&=1YhxfdF!CANX6FThfoNy;6ow&=E4X2D_Sfnan1ga) zwL`}`((tIRPdBkm_0laWluVh}5E|)5&DrH+&k;dQ2rr-F-FjQRmF^H865HRa!_{Ug zPK~sUp*?v2frzD(eGVd{5I=wx~%$7$}DCv~$o8po>Y!Qa`BsMPo1 zC5(ETlD7aSJes$Ori5rb(7TE)6(=BWLbqkBBddzTdFJ0skkUTtOnH)O2v%aEujYXk z5UAX_kwdr#uT-Qs5ameg6)23xm`63AK&2`e9_$H%)ll3%o6-}B_E22UiCsm=>M*^Z za~lsHN(&h=+Ry!+Nx~YRWsN_T_99tT;Jukm_5uz z#bjW&oP@fjPzkhtC!wwrswN-RoJ-dYLe`_Tgf{{%=N5xn$PrKNS)wV&`Z*@9XFg@k#qL5WBaii9iK`c#(>-_@!7C%#c2a)vE+LGH6SeF- zhKCfm3m|GAdf=r5t|GA8BlJ+q2{o5cPvP~O*Uj_rD-=GV`h7^d+b#6)=LnxI57)bi z<#C#5RF)im_q|+UmZYL8h*DeJCH3?b5mj{`_4nOs^l+yXu0Vo=(-t1XNt4$7@<{Fk zNhO!V6qX|3YWt+^w1Olyr*^9yBFhA6w0Ts~)giZic*rADAhB9M;8ea^K2%p-b*Mcb zJ|G|F>FPaVE}nGC@<=`;lKUo-sCS21Ivcley5-DjiZ*ig$C7I}$A3p&ZIjpA<&8dk z|25A348umwu1U^ra5gAA?gn5RNHHwt?4K}z`4WaToc)*FugQz+K#Rlq4Zw;xJBn{V ze@dR^>~CdJKt93Q_a#85p#Q z*)K6X&9!0-OE^0xZ*le!o?*{_!ixX-B0gT_?7DoKvwxA9&jHoS*%gTh?U!YoeJl@i z#wElbk!R4=kn=fv14NH}`2%gIvkkJM!jw`FuAlfv*3<@JrYvH`d8>oSgw_EoVQFAODVg zi?ctF?{g;QBF?@A#5&Hdg8Zk8BwQPjY?HjuA&(*pz}?N+p91#_G%4gN&fb%k_sX@L z{gM2TYqKTd{3eJxIJ+fBAD7RS;LBs2{RG3OIQs`#k6Rg@(TTY%uWXiZ?nm-8jv$bD zr2&X%kt(?qw`x2;%-IEboU<><6`Xw)6gXIZ2>2&B`*VClz=ts$K(OUUoc)dLd_kT- zj6gA)vttr@9g|>r1%P`wJBa~@!k=TtFBfq3ZCQycBTxw5 zf5`PgJXLY_Jq)OTpULx_ot1Mr858 46 387 357 0 0 832 602 IBFramework Version 326.0 + IBOldestOS + 3 + IBOpenObjects + + 20 + IBSystem Version - 7A202 + 7A179 diff --git a/Cocoa/English.lproj/CreateResourceSheet.nib/keyedobjects.nib b/Cocoa/English.lproj/CreateResourceSheet.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..630827ce5299405a7a5cb1b777a26fdc1076c970 GIT binary patch literal 9039 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 literal 236 zcmaKl%?g4*6h`+x#l@wNT0{iVMxh@H7Y?*)bJeReIL^q-7}y*2mL);7h}Pfv&WQpz z>k_57Qw29NR%m5G*Kky|4tpuAgO)}MLF9SqE*VrMDZ`Fn3w}=aq(n{r<})#_jk~-( z%o(AY35>%P6yy+=U+A9P6!}G6%>x#3JfE#06D8LYEijI%wc$&UvBS`z$_XnhB&E6^ LjcB-=O8 IBDocumentLocation - 142 473 384 240 0 0 1024 746 + 267 434 384 240 0 0 1600 1002 IBFramework Version - 326.0 - IBOpenObjects - - 35 - 5 - 50 - + 439.0 + IBOldestOS + 0 IBSystem Version - 7A202 + 8I127 diff --git a/Cocoa/English.lproj/InfoWindow.nib/keyedobjects.nib b/Cocoa/English.lproj/InfoWindow.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..d3496eab163fbae3f6c2e183c18eae3aa55830d5 GIT binary patch literal 10492 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 ViZu6hcIk>PcN+k82>N-)`7hbedN%+7 diff --git a/Cocoa/English.lproj/Localizable.strings b/Cocoa/English.lproj/Localizable.strings index b844bf166db7603d8315d9b3a5b2b0147ee8852b..167aaf797025ffea833fc36616a04827383c36cf 100644 GIT binary patch literal 4484 zcmbtYU2hXH5ZqVz4Io*SN}*D}5b!{SL`e!%(1K`z=WCLdh%~9Lfl_`vFyoE8ced}6 z7Dc(c*t5H{_SoLbpTDvptK#InOr$4;jASUkWgvaD{lvYL3$#pRjJw1A1lK~&@gb5H z(^>x-ewBFUZ}sG0Gxcp_Ira9dh;|nrjrj@wFW~bBFg-jwcpt(qpQdt!7R0 z!LsnaI0u1$7j08~IT91te6O&~^^sqWe`=lPXc+a<0dvkRN6_LsS&?OViK~rQ1Jd0i z(%lDAJ%0A%MD=j~slJ$n`CJ5>O%wuJ8pVM7a_a^Q)%$e(h3a~Z1j6G%(Syy9)7F8?}TR=E@C$A!0 zwLM1fH=wmWM!#u5YkM`Jpygk+yML6tCW?HLl7jzUHIenj#&}5Vh-h%l2KV>TNMgjkt?3q}Gj>wbT*m zcyOKaER5Gu@Id{gesAk1X7d)K^DFB=^u!kNd^*|jdQp7g_naO^gQxB&>-nZ0ltHKk zY%Hv$j&MT7hrPwly>R{qyC$4^3+J!Jvld0fc^ES72@JIY(m6i?OS3tgRY%pn*edpG z*wT+TS1(UFCtvXtYL#4!+j>$)yU@%zB9+iQm8(^Z#cAr#S*J|q`D?StMc`S_^R~pb zS{bf*-S%hfbq{2%YBg+AM*riH48tkJIid>U+A@D~rWGl7j=GB4FgiBr=%rrTFjfAn z;#d!F_+6e)&eynO)RsI)xmUBg%;!_z|Kpf8_VaL>S34?S*HRJGF4YmocS*fbKOJJc z@tucLzU`ua*&YT{0j%P948jZU&T zx_+C?b86~WUiseZXqmU3ITi`O9q35kl#ii)YKm23p6eo50GC7xQdJi0bjKKyVz`B`4446`0J< zw-6z?fo}?ed&QW+G$WFA8)kd?_$0u;#w zvho-b!Q#b0b_qiUkXHg^r81;|)#Ni2F@R)pf#Q`wx*SO7fmM_MO;un>0-Ku%q;tS5 yh-eXz4Kr6k1*|0ns2C(%4AcxV6y%&7uw|)0p4H@aJd%_31%0^~^uSPw!5RQy6h0pS diff --git a/Cocoa/English.lproj/ResourceDocument.nib/classes.nib b/Cocoa/English.lproj/ResourceDocument.nib/classes.nib index 25bf16d..6252961 100644 --- a/Cocoa/English.lproj/ResourceDocument.nib/classes.nib +++ b/Cocoa/English.lproj/ResourceDocument.nib/classes.nib @@ -2,23 +2,17 @@ IBClasses = ( {CLASS = AttributesFormatter; LANGUAGE = ObjC; SUPERCLASS = NSFormatter; }, {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - { - CLASS = NameFormatter; - LANGUAGE = ObjC; - OUTLETS = {outlineView = NSOutlineView; }; - SUPERCLASS = NSFormatter; - }, { CLASS = OutlineViewDelegate; LANGUAGE = ObjC; OUTLETS = { attributesFormatter = NSFormatter; - nameFormatter = NSFormatter; sizeFormatter = NSNumberFormatter; window = NSWindow; }; SUPERCLASS = NSObject; }, + {CLASS = RKOutlineView; LANGUAGE = ObjC; SUPERCLASS = NSOutlineView; }, { CLASS = ResourceDataSource; LANGUAGE = ObjC; diff --git a/Cocoa/English.lproj/ResourceDocument.nib/info.nib b/Cocoa/English.lproj/ResourceDocument.nib/info.nib index bccdc20..aacca19 100644 --- a/Cocoa/English.lproj/ResourceDocument.nib/info.nib +++ b/Cocoa/English.lproj/ResourceDocument.nib/info.nib @@ -3,11 +3,15 @@ IBDocumentLocation - 71 141 530 549 0 0 1600 1002 + 579 557 418 241 0 0 1600 1002 IBFramework Version - 286.0 + 349.0 + IBLockedObjects + + 146 + IBSystem Version - 6F21 + 7H63 IBUserGuides CreateResourceSheet diff --git a/Cocoa/English.lproj/ResourceDocument.nib/objects.nib b/Cocoa/English.lproj/ResourceDocument.nib/objects.nib index b543e90eb6b6e0fd48086a275e0653adbe8d93b0..20d7ac0a89475b6dc72e39e4b3baf9aceb8fd22c 100644 GIT binary patch delta 1472 zcmZuxO>7%Q6rNfC#re0Alr*hKA(RS`5P@8XD%Bz=qC%voM(q){_NH2}y=Cp-QVBWZ z?9LUsQx9=V+i-B(L}G=6DT@_}5JlDWkV903Lk?7MNmaQfr1yrI-MCF?cQv!}d*A!s z_ukC&%$}<~-+Tev&gWKOD>(`$p-KLLZw~pfX!%gJZXDEg}x z3@JKbOi#BRfB)D-HmRnS6RMKKq)R%vw;}>s$6~R#t|gPgj=X zBe@e-jMk46nwM13hs&T0uw^Xl;)4hlkkr9g+(PxVv+m450uI- zk-TWo$&sCrhCY{IYYR!wBWMYB@wKWv{w80)S-sSN2%G zO=kQ(y&|tI*8D9K04NZhqSs`_-#skI`0D@&Ors?ljgF7=H9V{?-FA=5xOj;lxj!wZ z6pR4tM812*<(YyXJt7AKFZ5l7corL1W(wVdkD}mv^M}U$vB{@_m!M6)4h$V!c>*c; zxyGHa>)^&641r~ndx3Ymcf?-@x3(S8;2tS`n0yj^TYi=wW1n=xD3^n?*SON~X zXh}`S+~%8`I>Hk|j3cI5SX-C`Ub*-&JGSYXO>Kv++VrkX$%Ei4{&pk{lD^R4*QzEo z{Gz|S|G_Bo-7mwrsgVym_95`6WtOG6seFE`?r!Ag(2GsWHm$Bxr%JvG^^=F8{=7k{ z7?_xPP8rqol$^~fIyP~!)Ix3UXxYA7?i|ro0o}In3MNu%OxL+Bcv4L#v>c|j2XvYL z=5y)ZNDniJX;py6Vjhd*vA8oa;7;OOnAZQH8~@TGceReHN##)Hz_DDKOQD+&$zM$a zzWGu+355sqZn~V8jt>%;T^BJ;2_>nVma__WZMCORwM~&Uv#UxMT7Me4!J%Ee5xRP6 zBCBMcw1o%c!ECY4{mltEE6216J-(f??#a;N6DcK~^<)$UcXLWs)7$-VGuqFLw`&~x zzcT9X31~b1$#AhrmU)7lBL67iL`uOtY3jRzJY{5crO5H8BSPiv{}GDgqZ+_;qF@ uaGrI1$<_mG4S^!tc!OuST!Pg8(K33br#p|nGor;cc~s{^nA7ynF#Zoulz7Sj delta 1615 zcmZuyZ)jUp6u&or+q7xZzpk^ab*-%xk+s$jR*RvPvLSYZOeZ2pmb{e5k~~ZkGv|l& zCGXu2qNwkY$D*j65VtzEhbwE01D(`yp`SKXO271jMX?H9jJ1LvR?mH}X^UAN_rBzu z-}#;2IrqGmPuphO-+u!)e2~0@k$MczxTW*wYo6!B!c@#3A?gwys&f!o{v64QtVrq+ z%c+ieMUtfYNuMte6T;z_crGcTpTRh<&RT|XLH)_nle#9|$k~dD|8$r;%K3v_ zj8)hbCU-e!fa56puUr_B2&A8YJ7> zqUDf?6_$bBl_GFlhxLu}9o!d{CCMIw5ASj{H>bacvIwZ#EkRemw6&#JZk?^KDG0`Z zXa?YJ-wpLf-$5|zJmZIJ0bwLdbzZMG6oNG}!rxjlPE-2uBNz@_)F0tUW_;q;n;y~n zoAmK)+9uvZX%BE;VE#$w|4f$Er|r$Xmob?m(kHX&*1>z;U5w?-6uDX%DqWqj_hMar z$3FbYneFKTra!JbP?Pga)nbG%N9mtIKEW23WJhGhr*E@sE_K=Ia>2ysmXluGw zRPQF4m-S}_4hpfA~SxX5s7G3kzwSt+q$-*t5=*|9fhJM zX&SW6&Du60#3G=aixFAPI1fLts#m-|{@k8drOw{edN$Xn6(Q0w>0=X0v^DtAurs;i zLO2nL4iil`xP8YH@h~6dOkl1G_ylM&fyUgM(L~FFt$u{{7R{B$0tzsV{T7fZDUIeC!t$(z2usTlh(V&nd>bo^P)*CsGI$txG zG8{?M0S~xyZk${**5VbjaiwsKXZz5ys#&>#2vghVW`6IfXgSvYpsrfl{wUq(rmX|Cp^I)Eq0RlYzJoeysOKS? m#q@R^-Rz?W9?Oa7?Hp1dyXV;0xDXKh6Yx*LC56}-LjD8s7qg=P diff --git a/Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.h b/Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.h new file mode 100644 index 0000000..5c39092 --- /dev/null +++ b/Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.h @@ -0,0 +1,11 @@ +#import + +@interface NSData (RKHexRepresentationExtensions) +- (NSString *)hexRepresentation; +- (NSString *)asciiRepresentation; +- (NSString *)nonLossyAsciiRepresentation; +@end + +@interface NSString (RKHexConversionExtensions) +- (NSData *)dataFromHex; +@end \ No newline at end of file diff --git a/Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.m b/Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.m new file mode 100644 index 0000000..449b87f --- /dev/null +++ b/Cocoa/Plug-Ins/Hex Editor/Categories/NSData-HexRepresentation.m @@ -0,0 +1,95 @@ +#import "NSData-HexRepresentation.h" + +@implementation NSData (RKHexRepresentationExtensions) + +- (NSString *)hexRepresentation +{ + int currentByte = 0, dataLength = [self length]; + char buffer[dataLength*3 -1], hex1, hex2; + char *bytes = (char *) [self bytes]; + + // return empty string if no data + if(dataLength == 0) return [NSString string]; + + // calculate bytes + for(currentByte = 0; currentByte < dataLength; currentByte++) + { + hex1 = bytes[currentByte]; + hex2 = bytes[currentByte]; + hex1 >>= 4; + hex1 &= 0x0F; + hex2 &= 0x0F; + hex1 += (hex1 < 10)? 0x30 : 0x37; + hex2 += (hex2 < 10)? 0x30 : 0x37; + + buffer[currentByte*3] = hex1; + buffer[currentByte*3 +1] = hex2; + buffer[currentByte*3 +2] = 0x20; + } + + return [NSString stringWithCString:buffer length:(dataLength*3 -1)]; +} + +- (NSString *)asciiRepresentation +{ + int currentByte = 0, dataLength = [self length]; + char buffer[dataLength]; + char *bytes = (char *) [self bytes]; + + // calculate bytes + for(currentByte = 0; currentByte < dataLength; currentByte++) + { + if(bytes[currentByte] >= 0x20 && bytes[currentByte] < 0x7F) + buffer[currentByte] = bytes[currentByte]; + else buffer[currentByte] = 0x2E; // full stop + } + + return [NSString stringWithCString:buffer length:dataLength]; +} + +- (NSString *)nonLossyAsciiRepresentation +{ + int currentByte = 0, dataLength = [self length]; + char buffer[dataLength]; + char *bytes = (char *) [self bytes]; + + // calculate bytes + for(currentByte = 0; currentByte < dataLength; currentByte++) + { + if(bytes[currentByte] > 0x20) // doesn't check for < 0x7F + buffer[currentByte] = bytes[currentByte]; +// else if(bytes[currentByte] == 0x20) +// buffer[currentByte] = 0xCA; // nbsp to stop maligned wraps - doesn't work :( + else buffer[currentByte] = 0x2E; // full stop + } + + return [NSString stringWithCString:buffer length:dataLength]; +} + +@end + +@implementation NSString (RKHexConversionExtensions) + +- (NSData *)dataFromHex +{ + unsigned long actualBytesEncoded = 0; + unsigned long maxBytesEncoded = floor([self cStringLength] / 2.0); + const char *bytes = [self cString]; + char *buffer = (char *) malloc(maxBytesEncoded); + signed char hex1, hex2; + int i; + + for(i = 0; i < maxBytesEncoded * 2;) + { + hex1 = bytes[i]; + hex2 = bytes[i+1]; + hex1 -= (hex1 < 'A')? 0x30 : ((hex1 < 'a')? 0x37 : 0x57); // 0-9 < A-Z < a-z + hex2 -= (hex2 < 'A')? 0x30 : ((hex2 < 'a')? 0x37 : 0x57); + if(hex1 & 0xF0 || hex2 & 0xF0) { i++; continue; } // invalid character found, move forward one byte and try again + buffer[actualBytesEncoded++] = (hex1 << 4) + hex2; + i += 2; + } + return [NSData dataWithBytesNoCopy:buffer length:actualBytesEncoded freeWhenDone:YES]; +} + +@end \ No newline at end of file diff --git a/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/classes.nib b/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/classes.nib index e40a0f2..9c91d31 100644 --- a/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/classes.nib +++ b/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/classes.nib @@ -1,6 +1,19 @@ { IBClasses = ( - {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = AsciiTextView; LANGUAGE = ObjC; SUPERCLASS = HexEditorTextView; }, + { + ACTIONS = { + copyASCII = id; + copyHex = id; + pasteAsASCII = id; + pasteAsHex = id; + pasteAsUnicode = id; + pasteFromHex = id; + }; + CLASS = FirstResponder; + LANGUAGE = ObjC; + SUPERCLASS = NSObject; + }, { CLASS = HexEditorDelegate; LANGUAGE = ObjC; @@ -13,18 +26,20 @@ }; SUPERCLASS = NSObject; }, + {CLASS = HexEditorTextView; LANGUAGE = ObjC; SUPERCLASS = NSTextView; }, + {CLASS = HexTextView; LANGUAGE = ObjC; SUPERCLASS = HexEditorTextView; }, { ACTIONS = {showFind = id; }; CLASS = HexWindowController; LANGUAGE = ObjC; OUTLETS = { ascii = NSTextView; - asciiScroll = NSScrollView; + copySubmenu = NSMenu; hex = NSTextView; hexDelegate = HexEditorDelegate; - hexScroll = NSScrollView; message = NSTextField; offset = NSTextView; + pasteSubmenu = NSMenu; }; SUPERCLASS = NSWindowController; } diff --git a/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/info.nib b/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/info.nib index b13ed8d..65439ea 100644 --- a/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/info.nib +++ b/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/info.nib @@ -3,14 +3,34 @@ IBDocumentLocation - 137 230 413 304 0 0 1024 746 + 76 233 356 240 0 0 1600 1002 + IBEditorPositions + + 24 + 239 475 202 137 0 0 1600 1002 + 8 + 30 493 203 99 0 0 1600 1002 + IBFramework Version - 286.0 + 446.1 + IBLockedObjects + + 45 + 47 + 48 + 42 + 44 + 46 + 43 + + IBOldestOS + 2 IBOpenObjects - 6 + 24 + 36 IBSystem Version - 6F21 + 8L127 diff --git a/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/keyedobjects.nib b/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..343ebbf871ce0139c4f61e51551a9d7d14daaf99 GIT binary patch literal 12717 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 literal 0 HcmV?d00001 diff --git a/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/objects.nib b/Cocoa/Plug-Ins/Hex Editor/English.lproj/HexWindow.nib/objects.nib deleted file mode 100644 index ef83cd0d578463d2589306a99a4a9626e3acf966..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5909 zcmb7I-EZ606~DA)r~XJ{r%u~sZK|XlGN+yAB%L?tVU{ghj?!4xETswdO;eQ0R1#T= zj%{oYk$c6bJrNcm4MwL4i(EKpo2Jc%4eJo(fv-kk?0x9du)koyfOhBHOZihHUCA=3 zqjS&4@BZ$+JSWg+tY~t&Xy~$-FLnNl3Smm=iFh(LIk#{}mW(OU5KH8rls*$ratSG0 zTqUwtG}Js74zJOUFb)N^q@gQ?tguFf*Pgv5FW*uMX>}>077Sg@U2ujNETE(s3v{gxsxwPYidcE^(_8K$%^o}8D9np#N9I$6UodgIARPSNo9&^ikG z!M}u#P*fscf^gj`*9h$o!z<&yxbN9TLtMzo6S^+05K525ll*qA7O?0atVV5h;2t4$ z`o~(QMSpKKYpdi5|1Mbcch(2B)l&q%m*GW7Nl2E2ORcN*fmLR2TCGC-n5Bu~os1`4 zuP#c}>i0%RgWu$j*@0LiYEA_ds33LIPRI>CC0B}uoHyaN#{id1#iSqK@1z}>3=vE= z7UGG*Y@A-Jy+FHudgTr2=iQLT0DQjsnnZ|77Ku(2A`_hong09az5pL$)`*3cHUz=k z;K{-zyGp9|J*x~l_y#>!AMe2*KqCkTplJdyoA{w!;jko0j{z5;O=M9os`}vCM&Q4Q z)BsA5U@+tAqAtn9Yc}KsiO2F{R>mBUBTa#~e57fjbCW=tE;Be0WW7YTDeXbT7zc;f z*;L-+Q%Nw!_4Si%^6)d0UpoWEI5IDu#v5?1Mj*J=Q)m{uKg zgLQz6iYjt0edg~-)C=$Ea3AausPoly}vm-`W0EfbQVs0I8! z$d(%3O~7hal+}Rn6R#R-=f{4xo!niR;m7H7<^Kvn< zpo)4LWuc3yL@aUF!-a$#8csd${{?Di&q7f*wk#iTRlc zrga)Nfy24^2AmfqS4X~`3WCdM@a`KUqd`rCjfX)L!~=!tctwjNnbPGr8k#OhqE=kQ zLm(YYs6_)7nW7oNyO&3^?tREd6Gy;1noyQG-d<<3A?of9e`Z3{ za&iz3m$s*t*Om=9vY5TFhW*cfuhk^~Bk^i|iSo{qu$E_F8K8#y58hE7x`F869qOJi1e@!glv0@kLrwj(}oD<4eeE%J31; zpVs(L#e;p`Ef3q`;^hc9pY=`ajwW*@Pw1u-NjDl#HQf4m&>ly2i)rUPPxXum)!%hi zP~m^;3oPT{4QqI}2LG_yGwQxVruC8aDb%%(H&B10MC!ZcEH7pEmb1KQ+vi~mtZ(Dz z!DIU84dH8x{>A<)xP!_RS_#ngU^VT&%Jg#!E0cTwulPiZ@a84s)+Yjav{Pmt9_N;s z2ge*JGs(~%Ot8d6Tt=)>j?br9T=LX}o>E7sB#dMAh*utpRW|oFLf*%Uw|*dn-w1o^ z=QgDt;o!LSbvK2BV-BQH59eZ1QhHnIB!9S+_bYxTNH!hhE2aRs(#sQIzt4ofFGUMvYKd^%P~m!TA| zRtIku48_PnrPOMTU^4_dDBPM!Kdc6@`(-xD0u7)sn9%NUsq^3W1&Hp;5&;rG3!-9g zZ`sX;z16UvHf(BRdu0$BcGGFaQ1vM}CugA^gLYlTZiMW5qtGR>r249+bTpu1<+K?DuN-7egfE2iB%B)n|eTOfpn*dEQRAbpA^xewOhfYIY&dmE%~ z+XFp=UI--JZpwBIzU&RmqW^dT-4bZsJ%yQ>vFdzVUUt8t zg)XruDGC=<4vnbnA5l3pf@QqK+Ns>e_BcL%&NesQYt6k@#=%)1_}-aBrdB~{k3ln| zhz&FzcN-Dr-|Kc;uwTnvU^IONnD{s46*l)wT-(gCYqR~&^-Zj7W}6k9{~id4&$WvH zGNq3}(h@^Mr*IFxB#refc&acinPcJy)%Z_y3`Pqxk{PWIum(w`r6u;}_hn>= 4; - hex1 &= 0x0F; - hex2 &= 0x0F; - hex1 += (hex1 < 10)? 0x30 : 0x37; - hex2 += (hex2 < 10)? 0x30 : 0x37; - - buffer[addr*3] = hex1; - buffer[addr*3 +1] = hex2; - buffer[addr*3 +2] = 0x20; - - // advance current byte - currentByte++; - } - else - { - buffer[addr*3] = 0x00; - break; - } - } - - // clear last byte on line - buffer[bytesPerRow*3] = 0x00; - - // append buffer to representation - [representation appendString:[NSString stringWithCString:buffer]]; - } - - return representation; -} - -- (NSString *)asciiRepresentation:(NSData *)data; -{ - int currentByte = 0, dataLength = [data length], bytesPerRow = [controller bytesPerRow]; - int rows = (dataLength / bytesPerRow) + ((dataLength % bytesPerRow)? 1:0); - char buffer[bytesPerRow +1]; - char *bytes = (char *) [data bytes]; - NSMutableString *representation = [NSMutableString string]; - int row; - - // calculate bytes - for( row = 0; row < rows; row++ ) - { - int addr; - - for( addr = 0; addr < bytesPerRow; addr++ ) - { - if( currentByte < dataLength ) - { - if( bytes[currentByte] > 0x20 && bytes[currentByte] < 0x7F ) - buffer[addr] = bytes[currentByte]; - else if( bytes[currentByte] == 0x20 ) - buffer[addr] = 0xCA; // nbsp to stop maligned wraps - else buffer[addr] = 0x2E; // full stop - - // advance current byte - currentByte++; - } - else - { - buffer[addr] = 0x00; - break; - } - } - - // clear last byte on line - buffer[bytesPerRow] = 0x00; - - // append buffer to representation - [representation appendString:[NSString stringWithCString:buffer]]; - } - - return representation; -} - -- (NSString *)hexToAscii:(NSData *)data -{ - NSString *result; - unsigned long bytesEncoded = ([data length] + 1) / 3; - char *buffer = (char *) malloc( bytesEncoded ), hex1, hex2; - int i; - - for( i = 0; i < bytesEncoded; i++ ) - { - hex1 = ((char *)[data bytes])[3*i]; - hex2 = ((char *)[data bytes])[3*i+1]; - hex1 -= (hex1 < 'A')? 0x30 : 0x37; - hex2 -= (hex2 < 'A')? 0x30 : 0x37; - buffer[i] = (hex1 << 4) + hex2; - } - result = [NSString stringWithCString:buffer length:bytesEncoded]; - free( buffer ); - return result; -} - /* delegation methods */ +- (void)viewDidScroll:(NSNotification *)notification +{ + // get object refs for increased speed + NSClipView *object = (NSClipView *) [notification object]; + NSClipView *offsetClip = [[offset enclosingScrollView] contentView]; + NSClipView *hexClip = [[hex enclosingScrollView] contentView]; + NSClipView *asciiClip = [[ascii enclosingScrollView] contentView]; + + // remove observer to stop myself from receiving bounds changed notifications (n.b. -setPostsBoundsChangedNotifications: only suspends them temporarilly - you get a unified bounds changed notification upon enabling it again and is designed for live resizing and such, so of no use here) + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewBoundsDidChangeNotification object:nil]; + + // when a view scrolls, update the other two + if( object != offsetClip ) [offsetClip setBoundsOrigin:[object bounds].origin]; + if( object != hexClip ) [hexClip setBoundsOrigin:[object bounds].origin]; + if( object != asciiClip ) [asciiClip setBoundsOrigin:[object bounds].origin]; + + // restore notifications + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:offsetClip]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:hexClip]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:asciiClip]; +} + - (NSRange)textView:(NSTextView *)textView willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange toCharacterRange:(NSRange)newSelectedCharRange { NSRange hexRange, asciiRange, byteRange = NSMakeRange(0,0); @@ -156,16 +85,14 @@ if( textView == hex ) // we're selecting hexadecimal { - byteRange = [self byteRangeFromHexRange:newSelectedCharRange]; - asciiRange = [self asciiRangeFromByteRange:byteRange]; + byteRange = [HexWindowController byteRangeFromHexRange:newSelectedCharRange]; + asciiRange = [HexWindowController asciiRangeFromByteRange:byteRange]; [ascii setSelectedRange:asciiRange]; } else if( textView == ascii ) // we're selecting ASCII { - byteRange = [self byteRangeFromAsciiRange:newSelectedCharRange]; - hexRange = [self hexRangeFromByteRange:byteRange]; - if( hexRange.length > 0 ) - hexRange.length -= 1; + byteRange = [HexWindowController byteRangeFromAsciiRange:newSelectedCharRange]; + hexRange = [HexWindowController hexRangeFromByteRange:byteRange]; [hex setSelectedRange:hexRange]; } @@ -178,36 +105,9 @@ return newSelectedCharRange; } -/* range conversion methods */ - -- (NSRange)byteRangeFromHexRange:(NSRange)hexRange; +- (HexWindowController *)controller { - // valid for all window widths - NSRange byteRange = NSMakeRange(0,0); - byteRange.location = (hexRange.location / 3); - byteRange.length = (hexRange.length / 3) + ((hexRange.length % 3)? 1:0); - return byteRange; -} - -- (NSRange)hexRangeFromByteRange:(NSRange)byteRange; -{ - // valid for all window widths - NSRange hexRange = NSMakeRange(0,0); - hexRange.location = (byteRange.location * 3); - hexRange.length = (byteRange.length * 3); - return hexRange; -} - -- (NSRange)byteRangeFromAsciiRange:(NSRange)asciiRange; -{ - // one-to-one mapping - return asciiRange; -} - -- (NSRange)asciiRangeFromByteRange:(NSRange)byteRange; -{ - // one-to-one mapping - return byteRange; + return controller; } - (NSTextView *)hex @@ -230,4 +130,17 @@ editedLow = flag; } +- (NSRange)rangeForUserTextChange +{ + // if editing hex, convert hex selection to byte selection + if( [[controller window] firstResponder] == hex ) + rangeForUserTextChange = [HexWindowController byteRangeFromHexRange:[hex rangeForUserTextChange]]; + + // if editing ascii, convert ascii selection to byte selection + else if( [[controller window] firstResponder] == ascii ) + rangeForUserTextChange = [HexWindowController byteRangeFromAsciiRange:[ascii rangeForUserTextChange]]; + + return rangeForUserTextChange; +} + @end \ No newline at end of file diff --git a/Cocoa/Plug-Ins/Hex Editor/HexTextView.h b/Cocoa/Plug-Ins/Hex Editor/HexTextView.h index 4542d95..d0196e9 100644 --- a/Cocoa/Plug-Ins/Hex Editor/HexTextView.h +++ b/Cocoa/Plug-Ins/Hex Editor/HexTextView.h @@ -2,16 +2,18 @@ #import "HexEditorDelegate.h" #import "HexWindowController.h" -@interface HexTextView : NSTextView -{ -} -- (IBAction)clear:(id)sender; +@interface HexEditorTextView : NSTextView +- (IBAction)copyASCII:(id)sender; +- (IBAction)copyHex:(id)sender; - (IBAction)pasteAsASCII:(id)sender; - (IBAction)pasteAsHex:(id)sender; - (IBAction)pasteAsUnicode:(id)sender; +- (IBAction)clear:(id)sender; - (void)editData:(NSData *)data replaceBytesInRange:(NSRange)range withData:(NSData *)newData; @end -@interface NSTextView (HexTextView) -- (void)swapForHexTextView; -@end \ No newline at end of file +@interface HexTextView : HexEditorTextView +@end + +@interface AsciiTextView : HexEditorTextView +@end diff --git a/Cocoa/Plug-Ins/Hex Editor/HexTextView.m b/Cocoa/Plug-Ins/Hex Editor/HexTextView.m index b9fa792..42c5078 100644 --- a/Cocoa/Plug-Ins/Hex Editor/HexTextView.m +++ b/Cocoa/Plug-Ins/Hex Editor/HexTextView.m @@ -1,88 +1,10 @@ #import "HexTextView.h" +#import "NSData-HexRepresentation.h" -@implementation HexTextView - -- (void)drawRect:(NSRect)rect -{ - [super drawRect:rect]; -/* if( [[self window] isKeyWindow] && [[self window] firstResponder] == self ) - { - NSSetFocusRingStyle( NSFocusRingOnly ); - [self setKeyboardFocusRingNeedsDisplayInRect:rect]; - }*/ - -/* [super drawRect:rect]; - if( [[self window] isKeyWindow] ) - { - NSResponder *responder = [[self window] firstResponder]; - if( [responder isKindOfClass:[NSView class]] && [(NSView *)responder isDescendantOf:self]) - { - NSSetFocusRingStyle( NSFocusRingOnly ); - NSRectFill( rect ); - } - } - [self setKeyboardFocusRingNeedsDisplayInRect:rect];*/ -} - -- (void)setSelectedRange:(NSRange)charRange affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)flag -{ - NSRange newRange = charRange; - - // select whole bytes at a time (only if selecting in hex!) - if( self == (id) [[self delegate] hex] ) - { - // move selection offset to beginning of byte - newRange.location -= (charRange.location % 3); - newRange.length += (charRange.location % 3); - - // set selection length to whole number of bytes - if( charRange.length != 0 ) - newRange.length -= (newRange.length % 3) -2; - else newRange.length = 0; - - // move insertion point to next byte if needs be - if( newRange.location == charRange.location -1 && newRange.length == 0 ) - newRange.location += 3; - } - - // select return character if selecting ascii -#if( 0 ) // no longer necessary as there's a one-to-one for ascii, and the thing wraps properly instead :-) - else if( self == (id) [[self delegate] ascii] ) - { - // if ascii selection goes up to sixteenth byte on last line, select return character too - if( (charRange.length + charRange.location) % 17 == 16) - { - // if selection is zero bytes long, move insertion point to character after return - if( charRange.length == 0 ) - { - // if moving back from first byte of line to previous line, skip return char - NSRange selected = [self selectedRange]; - if( (selected.length + selected.location) % 17 == 0 ) - newRange.location -= 1; - else newRange.location += 1; - } - else newRange.length += 1; - } - } -#endif - - // call the superclass to update the selection - [super setSelectedRange:newRange affinity:affinity stillSelecting:NO]; -} +@implementation HexEditorTextView /* NSText overrides */ -- (BOOL)validateMenuItem:(NSMenuItem *)item -{ - // paste submenu - if( [item action] == @selector(paste:) ) - { - NSMenu *editMenu = [[item menu] supermenu]; - [[editMenu itemAtIndex:[editMenu indexOfItemWithSubmenu:[item menu]]] setEnabled:[super validateMenuItem:item]]; - } - return [super validateMenuItem:item]; -} - - (IBAction)cut:(id)sender { [self copy:sender]; @@ -91,117 +13,91 @@ - (IBAction)copy:(id)sender { - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else - { - NSLog( @"Pasting text into illegal object: %@", self ); - return; - } - [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self]; - [pb setData:[[[[self window] windowController] data] subdataWithRange:byteSelection] forType:NSStringPboardType]; + [pb setData:[[(HexWindowController *)[[self window] windowController] data] subdataWithRange:selection] forType:NSStringPboardType]; +} + +- (IBAction)copyASCII:(id)sender +{ + +} + +- (IBAction)copyHex:(id)sender +{ + } - (IBAction)paste:(id)sender { - // be 'smart' - determine if the pasted text is in hex format, such as "5F 3E 04 8E" or ascii. - // what about unicode? should I paste "00 63 00 64" as "63 64" ("Paste As ASCII" submenu item)? - - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else - { - NSLog( @"Pasting text into illegal object: %@", self ); - return; - } - - if( [pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] ) - [self editData:[[[self window] windowController] data] replaceBytesInRange:byteSelection withData:[pb dataForType:NSStringPboardType]]; + // pastes data as it is on the clipboard + if([pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]) + [self editData:[[[self window] windowController] data] replaceBytesInRange:selection withData:[pb dataForType:NSStringPboardType]]; } - (IBAction)pasteAsASCII:(id)sender { - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else + // converts whatever string encoding is on the clipboard to the default C string encoding, then pastes + if([pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]) { - NSLog( @"Pasting text into illegal object: %@", self ); - return; - } - - if( [pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] ) - [self editData:[[[self window] windowController] data] replaceBytesInRange:byteSelection withData:[pb dataForType:NSStringPboardType]]; -} - -- (IBAction)pasteAsHex:(id)sender -{ - NSRange selection = [self rangeForUserTextChange], byteSelection; - NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else - { - NSLog( @"Pasting text into illegal object: %@", self ); - return; - } - - if( [pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] ) - { - NSString *hexString = [[self delegate] hexRepresentation:[pb dataForType:NSStringPboardType]]; - [self editData:[[[self window] windowController] data] replaceBytesInRange:byteSelection withData:[NSData dataWithBytes:[hexString cString] length:[hexString cStringLength]]]; + NSData *asciiData = [[pb stringForType:NSStringPboardType] dataUsingEncoding:[NSString defaultCStringEncoding] allowLossyConversion:YES]; + [self editData:[[[self window] windowController] data] replaceBytesInRange:selection withData:asciiData]; } } - (IBAction)pasteAsUnicode:(id)sender { - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else + // converts whatever string encoding is on the clipboard to Unicode, strips off the byte order mark, then pastes + if([pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]) { - NSLog( @"Pasting text into illegal object: %@", self ); - return; + NSMutableData *unicodeData = [[[pb stringForType:NSStringPboardType] dataUsingEncoding:NSUnicodeStringEncoding] mutableCopy]; + if(*((unsigned short *)[unicodeData mutableBytes]) == 0xFEFF || *((unsigned short *)[unicodeData mutableBytes]) == 0xFFFE) + [unicodeData replaceBytesInRange:NSMakeRange(0,2) withBytes:NULL length:0]; + [self editData:[[[self window] windowController] data] replaceBytesInRange:selection withData:unicodeData]; } +} + +- (IBAction)pasteAsHex:(id)sender +{ + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; + NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - if( [pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] ) + // converts whatever data is on the clipboard to a hex representation of that data, then pastes + if([pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]) { - NSData *unicodeData = [[NSString stringWithUTF8String:[[pb dataForType:NSStringPboardType] bytes]] dataUsingEncoding:NSUnicodeStringEncoding]; - [self editData:[[[self window] windowController] data] replaceBytesInRange:byteSelection withData:unicodeData]; + NSData *hexData = [[[pb dataForType:NSStringPboardType] hexRepresentation] dataUsingEncoding:[NSString defaultCStringEncoding] allowLossyConversion:YES]; + [self editData:[[[self window] windowController] data] replaceBytesInRange:selection withData:hexData]; + } +} + +- (IBAction)pasteFromHex:(id)sender +{ + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; + NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; + + // converts hex data present on the clipboard to the bytes they represent, then pastes + if([pb availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]]) + { + NSData *binaryData = [[pb stringForType:NSStringPboardType] dataFromHex]; + [self editData:[[[self window] windowController] data] replaceBytesInRange:selection withData:binaryData]; } } - (IBAction)clear:(id)sender { NSRange selection = [self rangeForUserTextChange]; - if( selection.length > 0 ) + if(selection.length > 0) [self delete:sender]; } @@ -212,20 +108,13 @@ /* Dragging routines */ -- (unsigned int)_insertionGlyphIndexForDrag:(id )sender -{ - unsigned int charIndex = [super _insertionGlyphIndexForDrag:sender]; - if( self == [[self delegate] hex] ) - charIndex -= charIndex % 3; - return charIndex; -} - - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { -/* if( isLocal ) return NSDragOperationEvery; + return NSDragOperationNone; +/* if(isLocal) return NSDragOperationEvery; else return NSDragOperationCopy; -*/ return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; -} + return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; +*/} static NSRange draggedRange; @@ -236,7 +125,7 @@ static NSRange draggedRange; - (void)draggedImage:(NSImage *)image endedAt:(NSPoint)point operation:(NSDragOperation)operation { -/* if( operation == NSDragOperationMove ) + if(operation == NSDragOperationMove) { NSRange selection = [self rangeForUserTextChange]; [self editData:[[[self window] windowController] data] replaceBytesInRange:draggedRange withData:[NSData data]]; @@ -244,16 +133,16 @@ static NSRange draggedRange; // set the new selection/insertion point selection.location -= draggedRange.length; selection.length = draggedRange.length; - if( selection.location > draggedRange.location ) + if(selection.location > draggedRange.location) selection.location -= draggedRange.length; [self setSelectedRange:selection]; - }*/ + } } - (NSDragOperation)draggingUpdated:(id )sender { [super draggingUpdated:sender]; // ignore return value - if( [sender draggingSource] == [[self delegate] hex] || [sender draggingSource] == [[self delegate] ascii] ) + if([sender draggingSource] == [[self delegate] hex] || [sender draggingSource] == [[self delegate] ascii]) return NSDragOperationMove; else return NSDragOperationCopy; } @@ -263,18 +152,18 @@ static NSRange draggedRange; // get the insertion point location NSPasteboard *pb = [sender draggingPasteboard]; NSData *pastedData = [pb dataForType:NSStringPboardType]; - int charIndex = [self _insertionGlyphIndexForDrag:sender]; + unsigned int charIndex = (unsigned int) [self _insertionGlyphIndexForDrag:sender]; NSRange selection; // convert hex string to data - if( [sender draggingSource] == [[self delegate] hex] ) - pastedData = [[[self delegate] hexToAscii:pastedData] dataUsingEncoding:NSASCIIStringEncoding]; + if([sender draggingSource] == [[self delegate] hex]) + pastedData = [[[[NSString alloc] initWithData:pastedData encoding:[NSString defaultCStringEncoding]] autorelease] dataFromHex]; - if( [sender draggingSource] == [[self delegate] hex] || [sender draggingSource] == [[self delegate] ascii] ) -// if( operation == NSDragOperationMove ) + if([sender draggingSource] == [[self delegate] hex] || [sender draggingSource] == [[self delegate] ascii]) +// if(operation == NSDragOperationMove) { NSRange deleteRange = draggedRange; - if( self == [[self delegate] hex] ) + if(self == (id) [[self delegate] hex]) { deleteRange.location /= 3; deleteRange.length += 1; @@ -285,12 +174,12 @@ static NSRange draggedRange; [self editData:[[[self window] windowController] data] replaceBytesInRange:deleteRange withData:[NSData data]]; // compensate for already removing the dragged data - if( charIndex > draggedRange.location ) + if(charIndex > draggedRange.location) charIndex -= draggedRange.length; } // insert data at insertion point - if( self == [[self delegate] hex] ) charIndex /= 3; + if(self == (id) [[self delegate] hex]) charIndex /= 3; [self editData:[[[self window] windowController] data] replaceBytesInRange:NSMakeRange(charIndex,0) withData:pastedData]; // set the new selection/insertion point @@ -311,39 +200,35 @@ static NSRange draggedRange; - (void)insertText:(NSString *)string { - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSMutableData *data = [[[[self window] windowController] data] mutableCopy]; NSData *replaceData = [NSData dataWithBytes:[string cString] length:[string cStringLength]]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else - { - NSLog( @"Inserting text into illegal object: %@", self ); - return; - } - - if( self == (id) [[self delegate] hex] ) + if(self == (id) [[self delegate] hex]) { int i; // bug: iteration through each character in string is broken, paste not yet mapped to this function - for( i = 0; i < [string cStringLength]; i++ ) + for(i = 0; i < [string cStringLength]; i++) { char typedChar = [string characterAtIndex:i]; - if( typedChar >= 0x30 && typedChar <= 0x39 ) typedChar -= 0x30; // 0 to 9 - else if( typedChar >= 0x41 && typedChar <= 0x46 ) typedChar -= 0x37; // A to F - else if( typedChar >= 0x61 && typedChar <= 0x66 ) typedChar -= 0x57; // a to f + if(typedChar >= 0x30 && typedChar <= 0x39) typedChar -= 0x30; // 0 to 9 + else if(typedChar >= 0x41 && typedChar <= 0x46) typedChar -= 0x37; // A to F + else if(typedChar >= 0x61 && typedChar <= 0x66) typedChar -= 0x57; // a to f else return; - if( [[self delegate] editedLow] ) // edited low bits already + if(![[self delegate] editedLow]) // editing low bits + { + // put typed char into low bits + typedChar &= 0x0F; + replaceData = [NSData dataWithBytes:&typedChar length:1]; + [[self delegate] setEditedLow:YES]; + } + else // edited low bits already { // select & retrieve old byte so it gets replaced char prevByte; - byteSelection = NSMakeRange(byteSelection.location -1, 1); - [data getBytes:&prevByte range:byteSelection]; + selection = NSMakeRange(selection.location -1, 1); + [data getBytes:&prevByte range:selection]; // shift typed char into high bits and add new low char prevByte <<= 4; // store high bit @@ -351,89 +236,61 @@ static NSRange draggedRange; replaceData = [NSData dataWithBytes:&prevByte length:1]; [[self delegate] setEditedLow:NO]; } - else // editing low bits - { - // put typed char into low bits - typedChar &= 0x0F; - replaceData = [NSData dataWithBytes:&typedChar length:1]; - [[self delegate] setEditedLow:YES]; - } } } // replace bytes (updates views implicitly, records an undo) - [self editData:data replaceBytesInRange:byteSelection withData:replaceData]; + [self editData:data replaceBytesInRange:selection withData:replaceData]; [data release]; - // set the new selection/insertion point - byteSelection.location++; - byteSelection.length = 0; - if( self == (id) [[self delegate] hex] ) - selection = [[self delegate] hexRangeFromByteRange:byteSelection]; - else if( self == (id) [[self delegate] ascii] ) - selection = [[self delegate] asciiRangeFromByteRange:byteSelection]; + // set the new selection (insertion point) + selection.location++; + selection.length = 0; + if(self == (id) [[self delegate] hex]) selection = [HexWindowController hexRangeFromByteRange:selection]; + if(self == (id) [[self delegate] ascii]) selection = [HexWindowController asciiRangeFromByteRange:selection]; [self setSelectedRange:selection]; } - (IBAction)deleteBackward:(id)sender { - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSMutableData *data = [[[[self window] windowController] data] mutableCopy]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else - { - NSLog( @"Inserting text into illegal object: %@", self ); - return; - } - // adjust selection if is insertion point - if( byteSelection.length == 0 && selection.location > 0 ) + if(selection.length == 0 && selection.location > 0) { - byteSelection.location -= 1; - byteSelection.length = 1; + selection.location -= 1; + selection.length = 1; } // replace bytes (updates views implicitly) - [self editData:data replaceBytesInRange:byteSelection withData:[NSData data]]; + [self editData:data replaceBytesInRange:selection withData:[NSData data]]; [data release]; - // set the new selection/insertion point - if( selection.length == 0 ) + // set the new selection (insertion point) + if(selection.length == 0 && selection.location > 0) selection.location -= 1; else selection.length = 0; + if(self == (id) [[self delegate] hex]) selection = [HexWindowController hexRangeFromByteRange:selection]; + if(self == (id) [[self delegate] ascii]) selection = [HexWindowController asciiRangeFromByteRange:selection]; [self setSelectedRange:selection]; } - (IBAction)deleteForward:(id)sender { - NSRange selection = [self rangeForUserTextChange], byteSelection; + NSRange selection = [(HexEditorDelegate *)[self delegate] rangeForUserTextChange]; NSMutableData *data = [[[[self window] windowController] data] mutableCopy]; - // get selection range - if( self == (id) [[self delegate] hex] ) - byteSelection = [[self delegate] byteRangeFromHexRange:selection]; - else if( self == (id) [[self delegate] ascii] ) - byteSelection = [[self delegate] byteRangeFromAsciiRange:selection]; - else - { - NSLog( @"Inserting text into illegal object: %@", self ); - return; - } - // adjust selection if is insertion point - if( byteSelection.length == 0 && selection.location < [[self string] length] -1 ) - byteSelection.length = 1; + if(selection.length == 0 && [self rangeForUserTextChange].location < [[self string] length] -1) + selection.length = 1; // replace bytes (updates views implicitly) - [self editData:data replaceBytesInRange:byteSelection withData:[NSData data]]; + [self editData:data replaceBytesInRange:selection withData:[NSData data]]; [data release]; // set the new selection/insertion point + selection = [self rangeForUserTextChange]; selection.length = 0; [self setSelectedRange:selection]; } @@ -458,20 +315,25 @@ static NSRange draggedRange; [self transpose:sender]; } +- (void)setSelectedRange:(NSRange)charRange affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag +{ + [super setSelectedRange:charRange affinity:affinity stillSelecting:NO]; +} + - (void)editData:(NSData *)data replaceBytesInRange:(NSRange)range withData:(NSData *)newBytes { // save data we're about to replace so we can restore it in an undo - NSRange newRange = NSMakeRange( range.location, [newBytes length] ); + NSRange newRange = NSMakeRange(range.location, [newBytes length]); NSMutableData *newData = [NSMutableData dataWithData:data]; NSMutableData *oldBytes = [[data subdataWithRange:range] retain]; // bug: memory leak, need to release somewhere (call -[NSInvocation retainArguments] instead?) // manipulate undo stack to concatenate multiple undos BOOL closeUndoGroup = NO; id undoStack = nil; // object of class _NSUndoStack - if( ![[[self window] undoManager] isUndoing] ) - undoStack = [[[self window] undoManager] _undoStack]; + if(![[[self window] undoManager] isUndoing]) + undoStack = (id) [[[self window] undoManager] _undoStack]; - if( undoStack && (int)[undoStack count] > 0 && [[[self window] undoManager] groupingLevel] == 0 ) + if(undoStack && (int)[undoStack count] > 0 && [[[self window] undoManager] groupingLevel] == 0) { [undoStack popUndoObject]; // pop endUndoGrouping item closeUndoGroup = YES; @@ -481,23 +343,162 @@ static NSRange draggedRange; [newData replaceBytesInRange:range withBytes:[newBytes bytes] length:[newBytes length]]; [[(HexWindowController *)[[self window] windowController] resource] setData:newData]; [self setSelectedRange:NSMakeRange(range.location + [newBytes length], 0)]; -// [[self window] setDocumentEdited:YES]; // moved to window controller's -resourceDataDidChange: notification method // record undo with new data object [[[[self window] undoManager] prepareWithInvocationTarget:self] editData:newData replaceBytesInRange:newRange withData:oldBytes]; [[[self window] undoManager] setActionName:NSLocalizedString(@"Typing", nil)]; - if( closeUndoGroup ) + if(closeUndoGroup) [[[self window] undoManager] endUndoGrouping]; -// NSLog( @"%@", undoStack ); +} + +@end + +@implementation HexTextView + +/*! +@method selectionRangeForProposedRange:granularity: +@abstract Adjusts the selection for insertion point and byte-selection +@author Nicholas Shanks +@created 2003-11-10 +*/ + +- (NSRange)selectionRangeForProposedRange:(NSRange)proposedCharRange granularity:(NSSelectionGranularity)granularity +{ + NSRange newRange = proposedCharRange; + + if(newRange.length == 0) + { + // set insertion point location + if(newRange.location % 3 == 1) newRange.location--; + if(newRange.location % 3 == 2) newRange.location++; + } + else + { + // select whole bytes at a time - bug: this doesn't quite work when selecting forwards one byte with the mouse + granularity = NSSelectByWord; + newRange.location -= (proposedCharRange.location % 3); + newRange.length += (proposedCharRange.location % 3); + + // set selection length to whole number of bytes + if(newRange.length > 0) + { + if(newRange.length % 3 == 0) newRange.length--; + if(newRange.length % 3 == 1) newRange.length++; + } + } + + return [super selectionRangeForProposedRange:newRange granularity:granularity]; +} +// also, lots of subclasser pasteboard support better to use than overriding copy: and paste:? see NSTextView.h + +- (void)setSelectedRange:(NSRange)newRange affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag +{ + if(newRange.length == 0 && stillSelectingFlag == NO) + { + // moving insertion point + if(newRange.location % 3 == 1) newRange.location += 2; + if(newRange.location % 3 == 2) newRange.location -= 2; + } + else if(stillSelectingFlag == NO && [[self window] firstResponder] == self) + { + NSRange oldRange = [self rangeForUserTextChange]; + + // selecting forwards + if(oldRange.location == newRange.location && oldRange.length != newRange.length) +// if(affinity == NSSelectionAffinityDownstream) + { + // selecting first byte + if(newRange.location % 3 == 0 && newRange.length == 1 && oldRange.length < newRange.length) + newRange.length += 1; + // deselecting first byte + if(newRange.location % 3 == 0 && newRange.length == 1 && oldRange.length > newRange.length) + newRange.length = 0; + // extending selection + else if(newRange.location % 3 == 0 && newRange.length % 3 == 0) newRange.length += 2; + + // reducing selection + else if(newRange.location % 3 == 0 && newRange.length % 3 == 1) newRange.length -= 2; + } + + // reducing forwards selection spanning multiple rows past start point + else if(newRange.location + newRange.length == oldRange.location && newRange.length % 3 == 1 && oldRange.length > 0) + { + // example: 00 00 00 00 00 00 FF FF => 00 00 00|FF FF FF 00 00 + // FF FF FF|00 00 00 00 00 => 00 00 00 00 00 00 00 00 + + newRange.location += 1; + newRange.length -= 2; + } + + // inverse of above + else if(oldRange.location + oldRange.length == newRange.location && newRange.length % 3 == 0 && oldRange.length > 0) + { + // example: 00 00 00|FF FF FF 00 00 => 00 00 00 00 00 00 FF FF + // 00 00 00 00 00 00 00 00 => FF FF FF|00 00 00 00 00 + + newRange.location += 1; + newRange.length -= 1; + } + + // reducing backwards selection spanning multiple rows past start point + else if(oldRange.location + oldRange.length == newRange.location && newRange.length % 3 == 1 && oldRange.length > 0) + { + // example: 00 00 00 00 00 00|FF FF => 00 00 00 00 00 00 00 00 + // FF FF FF 00 00 00 00 00 => 00 00 00 FF FF FF|00 00 + + newRange.location += 1; + newRange.length -= 2; + } + + // inverse of above + else if(newRange.location + newRange.length == oldRange.location && newRange.length % 3 == 0 && oldRange.length > 0) + { + // example: 00 00 00 00 00 00 00 00 => 00 00 00 00 00 00|FF FF + // 00 00 00 FF FF FF|00 00 => FF FF FF 00 00 00 00 00 + + newRange.location += 1; + newRange.length -= 2; + } + + // selecting backwards + else if(oldRange.location != newRange.location && oldRange.length != newRange.length) +// else if(affinity == NSSelectionAffinityDownstream) + { + // selecting first byte + if(newRange.location % 3 == 2 && newRange.length == 1) { newRange.location -= 2; + newRange.length += 1; } + // deselecting first byte + else if(newRange.location % 3 == 1 && newRange.length == 1) { newRange.location += 2; + newRange.length = 0; } + // extending selection + else if(newRange.location % 3 == 2 && newRange.length % 3 == 0) { newRange.location -= 2; + newRange.length += 2; } + // reducing selection + else if(newRange.location % 3 == 1 && newRange.length % 3 == 1) { newRange.location += 2; + newRange.length -= 2; } + } + } + + [super setSelectedRange:newRange affinity:affinity stillSelecting:stillSelectingFlag]; +} + +/*! +@method selectionRangeForProposedRange:granularity: +@abstract Puts insertion pointer between bytes during drag operation +@author Nicholas Shanks +@updated 2003-11-10 NGS: Changed algorithm. +*/ + +- (unsigned int)_insertionGlyphIndexForDrag:(id )sender +{ + unsigned int glyphIndex = (unsigned int) [super _insertionGlyphIndexForDrag:sender]; + if(glyphIndex % 3 == 1) glyphIndex--; + if(glyphIndex % 3 == 2) glyphIndex++; + return glyphIndex; } @end -@implementation NSTextView (HexTextView) +@implementation AsciiTextView -- (void)swapForHexTextView -{ - isa = [HexTextView class]; -} - -@end \ No newline at end of file +@end diff --git a/Cocoa/Plug-Ins/Hex Editor/HexWindowController.h b/Cocoa/Plug-Ins/Hex Editor/HexWindowController.h index 7097100..215bea9 100644 --- a/Cocoa/Plug-Ins/Hex Editor/HexWindowController.h +++ b/Cocoa/Plug-Ins/Hex Editor/HexWindowController.h @@ -8,22 +8,31 @@ #define kWindowStepWidthPerChar 28 #define kWindowStepCharsPerStep 1 +/*! +@class HexWindowController +@author Nicholas Shanks +@pending Add a category to NSString to convert from hex-formatted strings to NSData objects. +*/ + +/* Based on HexEdit by Bill Bumgardner, Lane Roath & myself: http://hexedit.sourceforge.net/ */ +/* Some ideas, method names, and occasionally code stolen from HexEditor by Raphael Sebbe: http://raphaelsebbe.multimania.com/ */ + @interface HexWindowController : NSWindowController { IBOutlet HexEditorDelegate *hexDelegate; - IBOutlet NSScrollView *asciiScroll; - IBOutlet NSScrollView *hexScroll; - IBOutlet NSTextView *ascii; - IBOutlet NSTextView *hex; - IBOutlet NSTextView *offset; - IBOutlet NSTextField *message; + IBOutlet NSTextView *offset; // these four should be phased out whenever possible + IBOutlet HexTextView *hex; // these four should be phased out whenever possible + IBOutlet AsciiTextView *ascii; // these four should be phased out whenever possible + IBOutlet NSTextField *message; // these four should be phased out whenever possible + IBOutlet NSMenu *copySubmenu; IBOutlet NSMenu *pasteSubmenu; - NSUndoManager *undoManager; id resource; id backup; - BOOL liveEdit; - int bytesPerRow; + + BOOL liveEdit; + int bytesPerRow; + NSUndoManager *undoManager; } // conform to the ResKnifePluginProtocol with the inclusion of these methods @@ -34,11 +43,10 @@ // save sheet methods - (void)saveSheetDidClose:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; -- (void)saveResource; -- (void)revertResource; +- (IBAction)saveResource:(id)sender; +- (IBAction)revertResource:(id)sender; // normal methods -- (void)viewDidScroll:(NSNotification *)notification; - (void)resourceNameDidChange:(NSNotification *)notification; - (void)resourceDataDidChange:(NSNotification *)notification; - (void)resourceWasSaved:(NSNotification *)notification; @@ -48,5 +56,13 @@ - (id)resource; - (NSData *)data; - (int)bytesPerRow; +- (NSMenu *)copySubmenu; +- (NSMenu *)pasteSubmenu; + +// bug: these should be functions not class member methods ++ (NSRange)byteRangeFromHexRange:(NSRange)hexRange; ++ (NSRange)hexRangeFromByteRange:(NSRange)byteRange; ++ (NSRange)byteRangeFromAsciiRange:(NSRange)asciiRange; ++ (NSRange)asciiRangeFromByteRange:(NSRange)byteRange; @end diff --git a/Cocoa/Plug-Ins/Hex Editor/HexWindowController.m b/Cocoa/Plug-Ins/Hex Editor/HexWindowController.m index e25ce7c..7c950cb 100644 --- a/Cocoa/Plug-Ins/Hex Editor/HexWindowController.m +++ b/Cocoa/Plug-Ins/Hex Editor/HexWindowController.m @@ -1,17 +1,18 @@ #import "HexWindowController.h" #import "HexTextView.h" #import "FindSheetController.h" +#import "NSData-HexRepresentation.h" /* -OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) +OSStatus Plug_InitInstance(Plug_PlugInRef plug, Plug_ResourceRef resource) { // init function called by carbon apps - if( NSApplicationLoad() ) + if(NSApplicationLoad()) { id newResource = [NSClassFromString(@"Resource") resourceOfType:[NSString stringWithCString:length:4] andID:[NSNumber numberWithInt:] withName:[NSString stringWithCString:length:] andAttributes:[NSNumber numberWithUnsignedShort:] data:[NSData dataWithBytes:length:]]; - if( !newResource ) return paramErr; + if(!newResource) return paramErr; id windowController = [[HexWindowController alloc] initWithResource:newResource]; - if( !windowController ) return paramErr; + if(!windowController) return paramErr; else return noErr; } else return paramErr; @@ -23,35 +24,33 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) - (id)initWithResource:(id)newResource { self = [self initWithWindowNibName:@"HexWindow"]; - if( !self ) return self; + if(!self) return nil; // one instance of your principal class will be created for every resource the user wants to edit (similar to Windows apps) undoManager = [[NSUndoManager alloc] init]; liveEdit = NO; - if( liveEdit ) + if(liveEdit) { - resource = [newResource retain]; - backup = [newResource copy]; + resource = [newResource retain]; // resource to work on and monitor for external changes + backup = [newResource copy]; // for reverting only } else { - resource = [newResource copy]; - backup = [newResource retain]; + resource = [newResource copy]; // resource to work on + backup = [newResource retain]; // actual resource to change when saving data and monitor for external changes } bytesPerRow = 16; - // load the window from the nib file and set it's title - [self window]; // implicitly loads nib - [[self window] setTitle:[resource nameForEditorWindow]]; - + // load the window from the nib file + [self window]; return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [(id)resource autorelease]; [undoManager release]; + [(id)resource release]; [super dealloc]; } @@ -59,68 +58,86 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) { [super windowDidLoad]; - // swap text views to instances of my class instead - [offset swapForHexTextView]; - [hex swapForHexTextView]; - [ascii swapForHexTextView]; - - // turn off the background for the offset column (IB is broken when it comes to this) - [offset setDrawsBackground:NO]; - [[offset enclosingScrollView] setDrawsBackground:NO]; - - // set up tab, shift-tab and enter behaviour - [hex setFieldEditor:YES]; - [ascii setFieldEditor:YES]; + { + // set up tab, shift-tab and enter behaviour (cannot set these in IB at the moment) + [hex setFieldEditor:YES]; + [ascii setFieldEditor:YES]; + [offset setDrawsBackground:NO]; + [[offset enclosingScrollView] setDrawsBackground:NO]; + + // IB fonts get ignored for some reason + NSFont *courier = [[NSFontManager sharedFontManager] fontWithFamily:@"Courier" traits:0 weight:5 size:12.0]; + [hex setFont:courier]; + [ascii setFont:courier]; + [offset setFont:courier]; + + // from HexEditorDelegate, here until bug is fixed + [[NSNotificationCenter defaultCenter] addObserver:hexDelegate selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[offset enclosingScrollView] contentView]]; + [[NSNotificationCenter defaultCenter] addObserver:hexDelegate selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[hex enclosingScrollView] contentView]]; + [[NSNotificationCenter defaultCenter] addObserver:hexDelegate selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[ascii enclosingScrollView] contentView]]; + } // insert the resources' data into the text fields [self refreshData:[resource data]]; - [[self window] setResizeIncrements:NSMakeSize(kWindowStepWidthPerChar * kWindowStepCharsPerStep, 1)]; + [[self window] setResizeIncrements:NSMakeSize(kWindowStepWidthPerChar * kWindowStepCharsPerStep * [[self window] userSpaceScaleFactor], 1)]; // min 346, step 224, norm 570, step 224, max 794 - // we don't want this notification until we have a window! (Only register for notifications on the resource we're editing) + // here because we don't want these notifications until we have a window! (Only register for notifications on the resource we're editing) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceNameDidChange:) name:ResourceNameDidChangeNotification object:resource]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceDataDidChange:) name:ResourceDataDidChangeNotification object:resource]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceWasSaved:) name:ResourceWasSavedNotification object:resource]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceWasSaved:) name:ResourceWasSavedNotification object:backup]; + if(liveEdit) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceWasSaved:) name:ResourceDataDidChangeNotification object:resource]; + else [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceWasSaved:) name:ResourceDataDidChangeNotification object:backup]; - // put other notifications here too, just for togetherness - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[offset enclosingScrollView] contentView]]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[hex enclosingScrollView] contentView]]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[ascii enclosingScrollView] contentView]]; - - // finally, show the window + // finally, set the window title & show the window + [[self window] setTitle:[resource defaultWindowTitle]]; [self showWindow:self]; } - (void)windowDidResize:(NSNotification *)notification { - int width = [[notification object] frame].size.width; + float width = [[(NSWindow *)[notification object] contentView] frame].size.width; int oldBytesPerRow = bytesPerRow; bytesPerRow = (((width - (kWindowStepWidthPerChar * kWindowStepCharsPerStep) - 122) / (kWindowStepWidthPerChar * kWindowStepCharsPerStep)) + 1) * kWindowStepCharsPerStep; - if( bytesPerRow != oldBytesPerRow ) + if(bytesPerRow != oldBytesPerRow) [offset setString:[hexDelegate offsetRepresentation:[resource data]]]; - [hexScroll setFrameSize:NSMakeSize( (bytesPerRow * 21) + 5, [hexScroll frame].size.height)]; - [asciiScroll setFrameOrigin:NSMakePoint( (bytesPerRow * 21) + 95, 20)]; - [asciiScroll setFrameSize:NSMakeSize( (bytesPerRow * 7) + 28, [asciiScroll frame].size.height)]; + [[hex enclosingScrollView] setFrameSize:NSMakeSize((bytesPerRow * 21) + 5, [[hex enclosingScrollView] frame].size.height)]; + [[ascii enclosingScrollView] setFrameOrigin:NSMakePoint((bytesPerRow * 21) + 95, 20)]; + [[ascii enclosingScrollView] setFrameSize:NSMakeSize((bytesPerRow * 7) + 28, [[ascii enclosingScrollView] frame].size.height)]; } - (void)windowDidBecomeKey:(NSNotification *)notification { - // swap paste: menu item for my own paste submenu NSMenu *editMenu = [[[NSApp mainMenu] itemAtIndex:2] submenu]; + NSMenuItem *copyItem = [editMenu itemAtIndex:[editMenu indexOfItemWithTarget:nil andAction:@selector(copy:)]]; NSMenuItem *pasteItem = [editMenu itemAtIndex:[editMenu indexOfItemWithTarget:nil andAction:@selector(paste:)]]; - [NSBundle loadNibNamed:@"PasteMenu" owner:self]; + + // swap copy: menu item for my own copy submenu + [copyItem setEnabled:YES]; + [copyItem setKeyEquivalent:@"\0"]; // clear key equiv. + [copyItem setKeyEquivalentModifierMask:0]; + [editMenu setSubmenu:copySubmenu forItem:copyItem]; + + // swap paste: menu item for my own paste submenu [pasteItem setEnabled:YES]; - [pasteItem setKeyEquivalent:@"\0"]; // clear key equiv. (yes, really!) + [pasteItem setKeyEquivalent:@"\0"]; [pasteItem setKeyEquivalentModifierMask:0]; [editMenu setSubmenu:pasteSubmenu forItem:pasteItem]; } - (void)windowDidResignKey:(NSNotification *)notification { - // swap my submenu for plain paste menu item NSMenu *editMenu = [[[NSApp mainMenu] itemAtIndex:2] submenu]; + NSMenuItem *copyItem = [editMenu itemAtIndex:[editMenu indexOfItemWithSubmenu:copySubmenu]]; NSMenuItem *pasteItem = [editMenu itemAtIndex:[editMenu indexOfItemWithSubmenu:pasteSubmenu]]; + + // swap my submenu for plain copy menu item + [editMenu setSubmenu:nil forItem:copyItem]; + [copyItem setTarget:nil]; + [copyItem setAction:@selector(copy:)]; + [copyItem setKeyEquivalent:@"c"]; + [copyItem setKeyEquivalentModifierMask:NSCommandKeyMask]; + + // swap my submenu for plain paste menu item [editMenu setSubmenu:nil forItem:pasteItem]; [pasteItem setTarget:nil]; [pasteItem setAction:@selector(paste:)]; @@ -130,9 +147,9 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) - (BOOL)windowShouldClose:(id)sender { - if( [[self window] isDocumentEdited] ) + if([[self window] isDocumentEdited]) { - NSBeginAlertSheet( @"Do you want to save the changes you made to this resource?", @"Save", @"DonÕt Save", @"Cancel", sender, self, @selector(saveSheetDidClose:returnCode:contextInfo:), nil, nil, @"Your changes will be lost if you don't save them." ); + NSBeginAlertSheet(@"Do you want to keep the changes you made to this resource?", @"Keep", @"DonÕt Keep", @"Cancel", sender, self, @selector(saveSheetDidClose:returnCode:contextInfo:), nil, nil, @"Your changes cannot be saved later if you don't keep them."); return NO; } else return YES; @@ -140,15 +157,14 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) - (void)saveSheetDidClose:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { - switch( returnCode ) + switch(returnCode) { - case NSAlertDefaultReturn: // save - [self saveResource]; + case NSAlertDefaultReturn: // keep + [self saveResource:nil]; [[self window] close]; break; - case NSAlertAlternateReturn: // don't save - [self revertResource]; + case NSAlertAlternateReturn: // don't keep [[self window] close]; break; @@ -157,83 +173,33 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) } } -- (void)saveResource +- (void)saveResource:(id)sender { - if( liveEdit ) - { - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillBeSavedNotification object:resource]; - [backup setData:[resource data]]; - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWasSavedNotification object:resource]; - } - else - { - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWillBeSavedNotification object:backup]; - [backup setData:[resource data]]; - [[NSNotificationCenter defaultCenter] postNotificationName:ResourceWasSavedNotification object:backup]; - } + [backup setData:[[resource data] copy]]; } -- (void)revertResource +- (void)revertResource:(id)sender { - [resource setData:[backup data]]; + [resource setData:[[backup data] copy]]; } -- (IBAction)showFind:(id)sender +- (void)showFind:(id)sender { // bug: HexWindowController allocs a sheet controller, but it's never disposed of FindSheetController *sheetController = [[FindSheetController alloc] initWithWindowNibName:@"FindSheet"]; [sheetController showFindSheet:self]; } -- (void)viewDidScroll:(NSNotification *)notification -{ - // get object refs for increased speed - NSClipView *object = (NSClipView *) [notification object]; - NSClipView *offsetClip = [[offset enclosingScrollView] contentView]; - NSClipView *hexClip = [[hex enclosingScrollView] contentView]; - NSClipView *asciiClip = [[ascii enclosingScrollView] contentView]; - - // due to a bug in -[NSView setPostsBoundsChangedNotifications:] (it basically doesn't work), I am having to work around it by removing myself from the notification center and restoring things later on! - // update, Apple say this isn't their bug. Yeah, right! - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewBoundsDidChangeNotification object:nil]; - - // when a view scrolls, update the other two - if( object != offsetClip ) - { -// [offsetClip setPostsBoundsChangedNotifications:NO]; - [offsetClip setBoundsOrigin:[object bounds].origin]; -// [offsetClip setPostsBoundsChangedNotifications:YES]; - } - - if( object != hexClip ) - { -// [hexClip setPostsBoundsChangedNotifications:NO]; - [hexClip setBoundsOrigin:[object bounds].origin]; -// [hexClip setPostsBoundsChangedNotifications:YES]; - } - - if( object != asciiClip ) - { -// [asciiClip setPostsBoundsChangedNotifications:NO]; - [asciiClip setBoundsOrigin:[object bounds].origin]; -// [asciiClip setPostsBoundsChangedNotifications:YES]; - } - - // restore notifications - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:offsetClip]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:hexClip]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:asciiClip]; -} - - (void)resourceNameDidChange:(NSNotification *)notification { - [[self window] setTitle:[(id )[notification object] nameForEditorWindow]]; + [[self window] setTitle:[(id )[notification object] defaultWindowTitle]]; } - (void)resourceDataDidChange:(NSNotification *)notification { // ensure it's our resource which got changed (should always be true, we don't register for other resource notifications) - if( [notification object] == (id)resource ) + // bug: if liveEdit is false and another editor changes backup, if we are dirty we need to ask the user whether to accept the changes from the other editor and discard our changes, or vice versa. + if([notification object] == (id)resource) { [self refreshData:[resource data]]; [self setDocumentEdited:YES]; @@ -242,35 +208,21 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) - (void)resourceWasSaved:(NSNotification *)notification { - NSLog( @"%@; %@; %@", [notification object], resource, backup ); - if( [notification object] == (id)resource ) + id object = [notification object]; + if(liveEdit) { - // if resource gets saved, liveEdit is true and this resource is saving - [backup setData:[resource data]]; - [self setDocumentEdited:NO]; + // haven't worked out what to do here yet } - else if( [notification object] == (id)backup && !liveEdit ) + else { - // backup will get saved by this resource if liveEdit is false, rather than the 'resource' variable - // but really the data to preserve is in the resource variable - [backup setData:[resource data]]; -// [self refreshData:[resource data]]; - [self setDocumentEdited:NO]; - } - else if( [notification object] == (id)backup ) - { - // backup will get saved by another editor too if liveEdit is false - [resource setData:[backup data]]; -// [self refreshData:[resource data]]; + // this should refresh the view automatically + [resource setData:[[object data] copy]]; [self setDocumentEdited:NO]; } } - (void)refreshData:(NSData *)data; { - NSDictionary *dictionary; - NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - // save selections NSRange hexSelection = [hex selectedRange]; NSRange asciiSelection = [ascii selectedRange]; @@ -281,13 +233,16 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) [ascii setDelegate:nil]; // prepare attributes dictionary + NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; [paragraph setLineBreakMode:NSLineBreakByCharWrapping]; - dictionary = [NSDictionary dictionaryWithObject:paragraph forKey:NSParagraphStyleAttributeName]; + NSDictionary *dictionary = [NSDictionary dictionaryWithObject:paragraph forKey:NSParagraphStyleAttributeName]; // do stuff with data - [offset setString:[hexDelegate offsetRepresentation:data]]; - [hex setString:[hexDelegate hexRepresentation:data]]; - [ascii setString:[hexDelegate asciiRepresentation:data]]; + [offset setString:[hexDelegate offsetRepresentation:data]]; + if([data length] > 0) + [hex setString:[[data hexRepresentation] stringByAppendingString:@" "]]; + else [hex setString:[data hexRepresentation]]; + [ascii setString:[data asciiRepresentation]]; // apply attributes [[offset textStorage] addAttributes:dictionary range:NSMakeRange(0, [[offset textStorage] length])]; @@ -318,6 +273,11 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) return bytesPerRow; } +- (NSMenu *)copySubmenu +{ + return copySubmenu; +} + - (NSMenu *)pasteSubmenu { return pasteSubmenu; @@ -328,4 +288,36 @@ OSStatus Plug_InitInstance( Plug_PlugInRef plug, Plug_ResourceRef resource ) return undoManager; } +/* range conversion methods */ + ++ (NSRange)byteRangeFromHexRange:(NSRange)hexRange +{ + // valid for all window widths + NSRange byteRange = NSMakeRange(0,0); + byteRange.location = (hexRange.location / 3); + byteRange.length = (hexRange.length / 3) + ((hexRange.length % 3)? 1:0); + return byteRange; +} + ++ (NSRange)hexRangeFromByteRange:(NSRange)byteRange +{ + // valid for all window widths + NSRange hexRange = NSMakeRange(0,0); + hexRange.location = (byteRange.location * 3); + hexRange.length = (byteRange.length * 3) - ((byteRange.length > 0)? 1:0); + return hexRange; +} + ++ (NSRange)byteRangeFromAsciiRange:(NSRange)asciiRange +{ + // one-to-one mapping + return asciiRange; +} + ++ (NSRange)asciiRangeFromByteRange:(NSRange)byteRange +{ + // one-to-one mapping + return byteRange; +} + @end \ No newline at end of file diff --git a/Cocoa/Plug-Ins/Hex Editor/Info.plist b/Cocoa/Plug-Ins/Hex Editor/Info.plist index ee1d95f..bb083d9 100644 --- a/Cocoa/Plug-Ins/Hex Editor/Info.plist +++ b/Cocoa/Plug-Ins/Hex Editor/Info.plist @@ -1,34 +1,33 @@ - + CFBundleDevelopmentRegion English CFBundleExecutable Hexadecimal Editor - CFBundleGetInfoString - - CFBundleIconFile - CFBundleIdentifier com.nickshanks.resknife.hexadecimal CFBundleInfoDictionaryVersion 6.0 - CFBundleName - CFBundlePackageType BNDL - CFBundleShortVersionString - CFBundleSignature ResK CFBundleVersion - 0.0.1d1 - NSMainNibFile - HexWindow + 3 NSPrincipalClass HexWindowController - RKEditedType - Hexadecimal Editor + RKSupportedTypes + + + IsResKnifeDefaultForType + YES + RKTypeName + Hexadecimal Editor + RKTypeRole + Editor + + diff --git a/Cocoa/Resources/Apply3.png b/Cocoa/Resources/Apply3.png new file mode 100644 index 0000000000000000000000000000000000000000..91c45035e1ebf5ee89d8c82f528a4ea7c1fec051 GIT binary patch literal 3341 zcmV+o4f67dP)GRmVU3ob!9%_j4W$GYo?;4h&#vfuX2SBnGk4T3Q98 zsWC=d+i0|D)Wjw>(#Dh;(n_1EP2(S=Xsj9<+JGsosSq)gmZ#8}ftg`u?%bLCzQ4yg zXRo#VW1rve-pkxOGaV?=#GUM%GiUZ*`}f zmJ25@h=@mB6xRSSL)9bdm&E*u`I*H-2cMb$`pJc(`)k$cKR^3NUqAJh6Byji(64{w zruXi>=CWTMAKP-n@W5Ctrb<#ukX$h{6bVli)TH;s3As#*>j*ll?Cq{_5BM`sqJ;`N@S>&IMO|4r7wvy!Vn% zz2~l5@85mljhjmh;C)ssTxhYU+2AU%D^afu(N`X)uQEy{X#kM>Cb{H@=12ivG{ zh)2a38n0cxd*9&u<7#LBf$uH9bT)8jw!kohAO7T?uiSLgZFh`RFG4i90~G1Q0B4|v zIZzdzeC}V#(v+dbRvP7DlDJGKUuLm&0*x{*-T4j-E5Q2@;O3E4#FU)O=6LME10Q?% z3$K0V{0Iy(^x?m_;-B7i)9p7m%9{|$*G#e^1DbVR!veWh4fR%x2=3*G!mLQPC1*0H$7GvArI=Yc;z_@_TAfzogP)n)&3%PqffTRoXTHD7nA_0qVZ zCO90oUi$mgl7V%FHnUm2_JdE5YX&9(e79SUN`{vlZ#kkFq8Tm{zWa~IKKjU)kAH4G znaO$|-}|x6_w2jzowrq@LDIa5a}Ku=0V8CbB6!>B;)VoL-y+uxk*t?i#X>BJWQcma zWq1iOW-1_X-5rykT{@XP|HMNx-#ROSD{rdbdc!SO|6!vvK__bxH1BXd{M{GBtV_cH zMMO~5b-{-zhDeH+tjJOx)f_K@gtq`(Bo7(Qf{Qxml56i6`{MIY&s?|o8ndfKMz33< z{?qTf=ra>z7rD&0@si>-MKmq6k|AsU9o|J!a^Jz>C?(Z1;5Tx~$Teu$OG+*&UNdqH z?;=?N-Y`{644)hQqm@f;zH`gR&uD>t?;pHt*Y1n2P%*r=aW2C3w7=Sgg3irCumY%g zq9h@X*7eF_7I@7N-|1~?Vp#}Y%`sI9uMGQ!8m3?>c!7(q?EBERU6n5#*`FR*&jOXp z-!cAs_1YkrZwD)2R6k35a^;myQv+n32ZCj5fB>C=cN^XQ4I4^wI(5+DE{QB(9)p zMKKtxp-$Phr||)p`82S+hQP&FG;XUm>ZHC63eE!fpd-ir$f;6F}FN{nK8Sx$N~3aSi`_j)JmA`z-z`(*BXn zt~u~j`t8*OqS39j>xm)H+c+cme?h=&%Dzk9&ij7qlU-j34^~A+k*3y5x7{}0zn%N; zewg0mB9>NWIB;;})U$m4(GOq>&Z5GV6jO*COk7a9b`61gor$4|$__6nMusECu@bnYwDDQXI}hHtK4oEsH3!7SSqA=DtH;X?$Ja-KM52wobC# zo+ffh0NgFwY*qbZiX&OIktr$$2zfh0#d;b_07Pl~l-BaXQlnC@giPdI*k)EK(`|Hw zHgFbm)+4ro(+Fn?uB$s!u&AiuisG=aNQg&WLo82IR7fG5Z3BT0^FC)`d3LceI64R} z{O{T#biEQmd%#3AlptrOfOdlt4ad-~ZySXriUhJ6xN4|m(;S~==phkPqFrLi-nW(p^Oy^$3(GJ^?A2iHElADv}Qbqgx%UcWeUNjWut5LI7fo0WY))Z>V0RK}>42g&j_vkOOPHF@;CdR z;-f%kBLZ$@k`G>UJ74M>Aod*0SPl5J zw9#(z3b1)}D_12Y@IC~PVbrSq^i{`bR7NPr4a^jucgTH;6nQ%$1`;9?9C7dIEWw#W zBo9|Ik`cQKLyZgAGP;L};awzgg;R5fnVNoyG;Q_3FU^rX`z=1+UgQy8_p8o&d9O1! z#fzmXdj}`jk;EWsv|BCO?L}PVXw-%nXl!D*v6cSX1hw)|ueK2%E~Z3$k->a%v!Fzj zsaJ*>>EF%;qkGvtc{P*6mryJBGru&=p`+ht`qX|zeGh!Q1<(FF_f8+?i$MB%up8|< z4!CB|joi2MDy~lwiUS4^L8CFi*w_xnhj%d8H%YZr#}S2Va-WCGDxdYlM=qw6R4JG0 zp;V5`p8{Wq7z*YwO#;BJ2DVHiFu1pliICI6lsVC1fn(cY!7N4sQhVY^6&K?746^e{k{JxO-@f5-wN+ zKnpTBND`=&`>9ojs8t3jB^8pmjG7^mlVxq1omo1ac{*7r2_i?(I4fHB9;T0Q{G}(j zZ|($N0ZyC=;JI8ZIACl47{9#hYJPXqPA;u>&n&i5Q5SbmYm3U&i?|gHN2@Db2Si{3 zOLOSq7kKpGGu$s3-vJiR1>Cu|eqisWo&3typWqkAx3Rri52o*>{B!x$*R2q81dTW6 z(c`c3)X^7saAAgrfLDR+3{uXE0EC@;6u5kN3%6|A!Of#v_{qLu21->(VsH^X)vvJt z-Amg5I&H$@DUP2y%F|Pac%(VYw}Ar`SBB@>&i9Az2p9mil}haCALpupQTFtWvaMQU zvQnoJmq_B6GN9g*`;wJK`8GmX}0vf;&Fb0f7 zC5B2R>QR|K6!D&B-eM7$2WE=C2(&rlLF4T0&G}o2(`Cj4D|K^>5`exTu>arwH@5!) XkSS5Ytd2Aq00000NkvXXu0mjfn#^_( literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/Button_certified.png b/Cocoa/Resources/Button_certified.png new file mode 100644 index 0000000000000000000000000000000000000000..db18b52d7616241cf1fd71c28d52b5b8b2640371 GIT binary patch literal 1653 zcmV-*28#KKP)Dy`V<#X}bY*F7WpXSa3TSk6a5^t9YH4k4VPh_Bb#rNBXklz@E@OHM3S)9* zVRU6=Aa`kWXdrZGWgtgMO;9WfXmoUNIxjDGcXuvlX>D*WZ*pg>nlirt00n7DL_t(Y z$CZ|Aj9pa~$A9}g?%dbhxifcOopz?JmNKQJwO~^ywqr{hNuv?tCy4P=2`C>Zj~Gg# zB0`9!CgLM#h%rhaAt64Z2}rP1DKc11OIx0$L#NDiUcHaG?{m)HYx7}_W&nd_f7sc{ z$^Ngk{%5WKf4f}z@`29)0nonGOYX;f+YSr?^MC+b20is;UFZOg0}(I)i~uFT@=4ZE zPxtpnM}|+OQmLDO4Di5xJGTYEX<#SN@51kV_yaHss83YE)xG(B`?r7g#t?O5SF84^ zJ)5rB_l2y$5+h;-EJ!o4|1nXDo|ZS1(f z%fJ+%m-FU~bY>3UHPSscwr+$(t_xc&V@q?`poO&{VlmpH#bUG&X~85?I9)x=w<3Oi zer|ER*8EWzhQ9%(0kgaUnGK>}P2g?4ZgwiIrqALg61YmhbFczN3D$yxMI3Mxm{xL4x=mO0k z2u@Cv7MmLr>|9^SJD7+-gbSe%i6x~JB9>|>$hPa*eBZ+)`v!RDfp1a%=RXJ+D;Oip z2AZcTjaTQw=rQ2$z*#3A@j5W)Cex^F4r>+lTrZn`{98s2e2)d|QxO+^?Ot~L>~UPB zc>Cb(lwLYQb7~Ta3^uMX9=0>UYe3Zl`uh9(@7~gty=63?afA7JR2b5g%hNl&hSaVb z2+BoTQ|~c)&;3Lf=Q;oAA#}=--R_vDAEVkLg6iXOmdFKb;CB61C77jm0 zZ>Dk#-$j zt^U_dthI=Mh|n~aCmT`iFM*lMDiRsU%vg>Id>tqPvRsSKmm__!9BBniJMcBF<)-Pt zP;YBe3JS>%YC*ucXi1aSC~z!A4L_||rYcKv-3N37Swr6rYG z_;SHf>-P@~^&KuvMn?iUX<)^etA@lPG1&7lPBNxPKGrhRiiZlxj&r{6KLYFnesSB{ zRiT2jz&C(h4jl29wEwHI>0G*HMxa{SoD`84n zWUcAGM@-?rV?$9uDsJ`G{{nd*X(_;X{yz+F00000NkvXXu0mjf3&Z`_ literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/Button_reload.png b/Cocoa/Resources/Button_reload.png new file mode 100644 index 0000000000000000000000000000000000000000..3fa8db76996a956cd7980768a44c18c43b8bf895 GIT binary patch literal 1420 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 cxdQxu06THiH4&OV literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/Delete.png b/Cocoa/Resources/Delete.png new file mode 100644 index 0000000000000000000000000000000000000000..ba6ca80b9e478d39793c666d84ee25f9c7117ccb GIT binary patch literal 2367 zcmV-F3BdM=P)7^Nfz2_i_si^SvRBRMw4 zjk9L~lYjx}W_2&H_fCl176B_%-UBvE7Vz?#8mgaphPpLtsCf9{k_`TSsst4%0ozN8Jd9_%JG&4s7Wkr= zZqarv@W*{XAQ)uno;`$`np}$cjLc@(>xHaL|MCmx_Us{;mWi!f z$DC-CnZZE>N1gM&P?^7cIpNk;5|=MysH&?@uBgCQQ9$UIT&Q-=b!C*ij+t^PUz7`k;=;{d*A^Q z0|OX}V%KMMo$|Um5|=NNxp9Luw06MhlcqOZA{KDKZogF-TeXUeqJW~1Q4|D0AlBK5 zKN__^4mCFujmPb8vft+`k$9X?bF;1Mk4CBO>_ijY z84!%c2sSj>hBJynWchODR8{2|3bnKlUAfW*n#oflD_0U~Y01&`S5*;v`DGW0jG_>1 zXrMe6BM1l(w^jf}J@8t^0onY|i)=wpj^SBhThJRz+6wj5!gH{0U#~|KC42MBv(j`9XY~(`}&HLXlo<7e!bcA>(>)%Yb&br zdtVu#peRX*7A7C|#A=J|vD2CbF97~|^GtVgYfK+MbO;QCxlcYhJBek>2sAYz z&!1l${P*88dH8VNI{&g=jT{pB_NYd=QTQh@F3_qbDw%@R$!%o zpZ@MUCO`Saes<&v02t}C-Jtkwc)YXD09mL>0f^(5R2t)c;e%a5e$Qhr=Kng zvLN_xzh$zgCvRPrh&ncggqb_|ER4?YatLI{e-Y59rob`Ydu8Io55X{~c=p-b2mkfg zT>I!FJ2aiWE;yd`sVO^z0woZz!Ha-$^(y7{^|LO_Cf|P_!7vCt_gu-~6KBqF{eur& zKnsa>^=iS{7K#v1hlj~L{x}(*ui!#W04DeCBhcK8TwPrhyf!hx^?mztz&q{R`Ln8` z4iC>tAg3;ykc$ASN^)SJ;Icrlu2oyNmINL^uC6Asbt{6UFF5RYZKnqY5LDIvC-X&u z*8@WuGzJ_B%HSYnH8qHVfQw{Ssd`;Ik53u>y3R8{OTm_pZ?=l|mUDM6}+E zz>I~_spIv)kd8ZyP*sxW&gJz$bypXm)vIp{yiH>DYUX!!xq9E}jnuhw2&!sFLzYM} z0;f~B!$<^-sVP$Z{jRX7-oBksd;1-Mw@I|OGk^Q`oKRBw`^i|Nk8|6`^1$iY2%Jqi zz&lCk6B8(xE`g#@vuhU>Yu6S9sE>{oC$V-dkzKoN@Y3Mh5_IMZ*wiKy!+UwwsGSBJcK@vJ)j=4Rvt z3rJXmom-Ir6Tmd|cvH)KL+rsDIM_=Pf-ED-GG!&KDpSXfF}-64VmAHMb!K+#Abspu zQQbgW8=}>gD9iRrRImsD2faEu1hzo04!sju5`usn3L%9;40m>tK7YP2_|HBw!2_Z! zBRNWH=T4N*KQE}OoA^LpC;V=NB zn>L~J_veB?dX(wy+YvR*oP3f=cTrVR+qR(`J({Dd_4jjQ(7yuH`vjzT<4{Od^$RS-*5Fdxe z1-gzlJdFQ|Cy-=Qa>qAQ> z838Wd&DNrW#0$XjML-OYd_Dp#Ed&-XE(yHT3t7Nk;2A)q8wK#Q+Aed;Z>RuRBPz0>`VM zu>~{1mH=N>75DR08kG zu(=UfgnPD@Dl3s|YLH{Gydh+aj-ro`qfbrQ=VLn14_pD%Kk|slLnIFD_CdS}co4|9 z^zbGk&ba>_Gh8m4zK4*9&|JZ238RX{aR0nEoe3XKB_FowA-_>cLzhyTYhYd*1l l^pX#{OZh?X%YFG1 + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Delete + 2007-02-20 + + + Andreas Nilsson + Nicholas Shanks + + + http://tango-project.org/ + + + delete + remove + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Cocoa/Resources/Delete3.png b/Cocoa/Resources/Delete3.png new file mode 100644 index 0000000000000000000000000000000000000000..4e5e7903717ad0f8bc942125f9da52635cab6163 GIT binary patch literal 3590 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 M07*qoM6N<$f*+~Yd;kCd literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/Go3.png b/Cocoa/Resources/Go3.png new file mode 100644 index 0000000000000000000000000000000000000000..c7827e4f467cfb842dc18d777e26d27922dc70ee GIT binary patch literal 3276 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 KMNUMnLSTaT4nTDP literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/Help.png b/Cocoa/Resources/Help.png new file mode 100644 index 0000000000000000000000000000000000000000..07abdcdd0e95349aca8c5d590d9598402e591918 GIT binary patch literal 2622 zcmV-E3c>Y>P)1n%J=%Cqb>)GA+xNWJ@ANi4wWw?(|`n6eUX*eQEmQ0}Mz?J7@m? zbDJ}>@I;=-BZ)i?B}2n!+kg>Z2p9%3(P)%xG{%7mU~FRiWd2dtek1}z!)Hf;H-J&g zOX8+GvAiUf>tT7xP0t3UB7t8bC>8Mwiv*=2z!~73iSd(T4~yZU2t>e7iDi#?oqfdG zyXopoaH!v`7A81QO?a%TD*-8s$;<04@2aE2t=WBS}c3i z>+GXrAj5YK#Q4!rlD<9m11)^}Zk3NGihO;&%+k$ljmR0`tp^FMrU?uUpB)0ux#`YK zvi}G#ok;WYb1A&oqoq-)ta|vo<@G2i}|*Kl!KK=Iu%#0)H;KZ;)r69pKd; zr}5m!QoQbwlCSymM+LsPbd%!DBp6TJm&ARML}Bw`a^GOv@#6#h>Zj@E(KKq-%})dP z!v_T}U%p9kW-<@_GLPf^az4fX7Qb$sr|x$IUQY6sn?yv{zvvN?7rMi4?( zL!hB0sd(vlf`qrz)CZUS-3})PJ%SJdt<72?92syC%f{>M130za+(OT9pM}-1PP#Vcmcw1=0`>T> zM){CVDU>BR@i=xO1*UDU%hobFiS~9 zhOJGmbR>nR`*v?V{Hi9hwK9kxVz7yb!6?w;2`!$*dSwGR0^jYo`QCm9w~55Ra=S_pMx|5(8rDkM;1P(m zwzD=jGu$|5D}juYh@&jyfugU8#Uh~EctPseWW&Z9mP@c)3Jfs}q2Z%0y{$X%%#E_J z67tzKpMYpzjz|>C8f6P%73@SDww(0tA>gJX4=ABf(zLdKXzIX3NAQI@sRn}s!qIMv z7Y{kank=`sashw4RHj_jXaudzf?8_|H4gx>bjz*;qVQ3Og84#7Z`THJ0TV(sBGTvu zL*(T_m#2H0vpT@1*DHK-&97U$_E{Tqg%D+#QofzsL!bs;S&Fp^tXClBM&W~5z=VFy zx*Oky4>?VPpUH=ef8%p^B?K|n))=?eyil&ddPO73cwjpc_j(`#FP0z{%;W4jKsSpUnnlS$PTOqTnVWdau-ED|$(pw3Io4Ifk z4y6Pg1iKO#_g7Y;@QH>Jvaq79RjrHn#k*iQ{!P9}*zZAkra`9@7K)Ax!53 zLXpilEU9^5yiw;?yG<15=IJ^WkdNDDPTUdVw$$~+qeIftx+$p( zUtXh-oy`Jo?WD7*tHq~Yey*+SScbT(IM}JMt*D()=CgLNX*}TEBMrr0YaR7K+JuY- zLUVIBwHUDOYZkuBa^t=84}Z1TK;kvvT;^v#V9&7w#9ZM(yCUs1fUo5P+;=aiHEuN$ zL_~B5g_7oaE~M;--2F03_8*@?6PLTY_P%pB&i$t+^ZKRywc9_pJ;#gpc9AQaiqhsO zJR59f;@h^su}rAgs+l1Kp)g(0Ocz3e5ausTa^wBa^T2N&%k_FqYA-n2kMw5_{o)0j zcnqt)rkpu-bdW6BEVug_DQ&B6ccHS2Z~RjY6P gMfVeVB9AEl1wJBl?5!IaZU6uP07*qoM6N<$g61#@mH+?% literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/Help3.png b/Cocoa/Resources/Help3.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7bb00dafc8536cb577ae238c7430de60f42ea0 GIT binary patch literal 3870 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 literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/ResKnife-old.icns b/Cocoa/Resources/ResKnife-old.icns new file mode 100644 index 0000000000000000000000000000000000000000..da57f858def67075d006c2955e282a401e652856 GIT binary patch literal 61179 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 Z8HTax8z4q2-s*S)1ycVY#5*qhlCnc;v?7K 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 literal 58820 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 Z8HTax8z4q2-s*S)1ycVY#5*P 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 Ef;CHv-2eap literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/add.png b/Cocoa/Resources/add.png new file mode 100644 index 0000000000000000000000000000000000000000..8bd5f6e3346c03d7d840dd4361900b01db09388f GIT binary patch literal 3579 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 Bxt9O{ literal 0 HcmV?d00001 diff --git a/Cocoa/Resources/defaults.plist b/Cocoa/Resources/defaults.plist index 23c3a91..dd1da53 100644 --- a/Cocoa/Resources/defaults.plist +++ b/Cocoa/Resources/defaults.plist @@ -1,6 +1,6 @@ { PreserveBackups = YES; - Autosave = YES; + Autosave = NO; AutosaveInterval = 5; DeleteResourceWarning = YES; diff --git a/Cocoa/Resources/delete-1.png b/Cocoa/Resources/delete-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6602a507d9352a89d9268fc2c22c1752868dcd9c GIT binary patch literal 3788 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 + + + + IBDocumentLocation + 75 727 356 240 0 0 1600 1002 + IBEditorPositions + + 246 + 569 580 520 175 0 0 1600 1002 + 29 + 66 658 413 44 0 0 1600 1002 + + IBFramework Version + 446.1 + IBLockedObjects + + IBOldestOS + 1 + IBOpenObjects + + 29 + + IBSystem Version + 8P135 + + diff --git a/Cocoa/cy.lproj/Application.nib/keyedobjects.nib b/Cocoa/cy.lproj/Application.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..54c9612ac9902ac5f834cfd2e49082b907dcafc8 GIT binary patch literal 26672 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 literal 0 HcmV?d00001 diff --git a/Cocoa/cy.lproj/Application.nib/objects.nib b/Cocoa/cy.lproj/Application.nib/objects.nib new file mode 100644 index 0000000000000000000000000000000000000000..82a0594c9eacb7dc9496595de1c7763540bb5b2f GIT binary patch literal 11347 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 literal 0 HcmV?d00001 diff --git a/Cocoa/cy.lproj/InfoPlist.strings b/Cocoa/cy.lproj/InfoPlist.strings new file mode 100644 index 0000000..2b3f34c --- /dev/null +++ b/Cocoa/cy.lproj/InfoPlist.strings @@ -0,0 +1,6 @@ +/* Localized versions of Info.plist keys */ + +CFBundleName = "ResKnife"; +CFBundleShortVersionString = "0.6 beta 4"; +CFBundleGetInfoString = "ResKnife 0.6 b4, Hawlfraint © Nicolas Siancs, 2001-7."; +NSHumanReadableCopyright = "© Nicolas Siancs, 2001-7."; diff --git a/Cocoa/cy.lproj/Localizable.strings b/Cocoa/cy.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..0f2d44c0df534f9463318202fb36108c11e18af5 GIT binary patch literal 4416 zcmb_gZBG+H5T3948#LK8L6n3yqkbVKRtiWIG>ZE9`a)?eS8{E|`s3B-*>Rb@yS)~S zX-coV^YYB>volkE{g!Rn5GU_sB0b4uEF<|T1L;K@i&tzyeLVH z+28$5d@JzG?`p|GXXe*(8G8Km%6Z(@Yld!Kch?PUQlU z*TCT*!@r0Avk#fVOXVK(d#{zl!zXAm0*Cbxp2yH1;+tYd5@%61Z;NN3__q;ZOFCGe;mvGJp!Y38n%W~q)vV{fZef{>S=vVwJZEOp za5(os*5s9Y7$I6MX;we`ypc`h1KC(bV`p+3S+iV5aqM}JH=?xtJ-O#!%pW;O{^+gX z+0MXEC&xGuC!4Y>FXWj#$1CKUY*l7|K|FS=EQ)3c^{jrwopkUKY<~a)dN}(GEF#~V zJgkzVpQ@LqH(vH(zmTqvnvs&jCv0BiwlO1?tRIEtV^JX>C+N2eL zx0;${9`jkg8Ed%BJ3wZbY{j_1wOvR#c`L6gvhjLKf;tCNT;F&ko5FPmp zE^u!QQ;@3Xf~;rfA?mn#2MzKtZM%x`1QxWH83N59yA6_sdad>o<0pmT_F;T#CdmO1J0nR-OBJvO3XNzv2{EofcVV%G?U4$n0~D<=n}sCCy=DltpS5>b%xT!hs8%#dV6{ zyh|PSX4as26dxxp&a&ISU+~HK`80_Yfs#7oA%9u&Z}wd z)ZQ{p-Y(XO7;A{DZYw2i*3WK!{iU%r?XR+s@)|IvZKgELOB)Q=U$|ZHimd0oPGi1} z>|HFUkcC)Q`$}okdrQJJv+QQt)Ka}of%|5~|IZ-tYp`r%QQ{4egj!m?fB#--nr7TB X{0i7Y + + + + IBDocumentLocation + 75 727 356 240 0 0 1600 1002 + IBEditorPositions + + 246 + 567 580 520 175 0 0 1600 1002 + 29 + 408 624 463 44 0 0 1600 1002 + + IBFramework Version + 446.1 + IBLockedObjects + + IBOldestOS + 1 + IBOpenObjects + + 29 + + IBSystem Version + 8L127 + + diff --git a/Cocoa/gd.lproj/Application.nib/keyedobjects.nib b/Cocoa/gd.lproj/Application.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..11183386e01f239c9a6cbb6af681dd789be42bb1 GIT binary patch literal 26900 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 Ol>eDM#e6yI+_Wc)AX8od literal 0 HcmV?d00001 diff --git a/Cocoa/gd.lproj/Application.nib/objects.nib b/Cocoa/gd.lproj/Application.nib/objects.nib new file mode 100644 index 0000000000000000000000000000000000000000..c42d2e28a56dcba7f468af7bc99131b80eb7fa58 GIT binary patch literal 11342 zcmb_i4RBo5b-vH~vHs^`w1xwNKq2 z8+(+%mEXQ(noL79@-5y_P+Urh1CB8i#{(f?*Hxfyp`?Lu1BIj@prvJKX<>#LyWhF* z?b}`bcc$`q@7wct&pG#;d(S;@ORH1+2aKL%Dq-mTyySgb3)!|^*B)-&vc3CGBa+&x zr*zKVw(W}cunS?CVV9&SolIH%E^zgTJugJ8_3h!dbV~1z8R1mIjQ44Z(|aDVwJU1d z!;J$2F*Bm4Oe^kW99uK@2ym8z(}<@zJ2zsNnxRmL*@q9$zs-!t4ZY8Cr}RWOCKCF7 zX4~^2OFfQcYe=aoS43;d=;!ku92w5qwGhvx9O z0>*~!zHs3J%RtnE_ONT;4kKx$6A@$eh#-C7nSQ;`aPUl~LgA*U5!utPC-yi_#{Nt3 zFfd>yOq+R^(GyPTDFZ0D4gZ{B`-j8XQ8KOOYnIhtq{IOzagndYLzzb=Gc9Y{ABh>k z&S=6)_eFEudYtsp?kF;168}($F`Ae;j~5y{iH>M0Z#9#t;2)XBzBv#tYBW>PzNn#N zEqbDJ;ZmwRKD!!$b}JI?2{tA4czkUuMM4a=&dztSyLPn7#k{|}=iyn{=c-ywo3+;n zrmWx=J+fyOndH$$TPPiZjjqSaKW$j{SrCNmO-V z0@)8_%PFW%tDvetxZV;sdyPr5?Yd;TyC0GoBb0azDjq$7c`it+B57kv+NEuvT-zKq ztz<%vL}_vR)4}`{xqO)rLN0UN4y!M!tMrYpTenU{=$e@#bZm6!IYj7;Vd09d2^(gj zJ8GCoV~TJ%QfOK+Da>P}NIjezHWGWyh~arxCFa~UsBJRLSl$y5sYPeDjTWv-aW$P8 zjYO3@h-KP@_q^z4fF6vlz0HhGUe>}b;{Tw2^O@1UV)g%cI`v7@8u*KX&TvCfIm->W z`OUi76P-e_BN}aZUV!;jSb#c;uW=P$C1(yNlq2HPO`fN%YPOPnx*4MkCU;x2v($Pl z!S*ylcTz?a#mNL(=&8}%A1giU!hLDIJ9uU^8B`9KZUZ94mcms#jEE6WZM7n4BwVU6 z!p28u-(Otclx;n8%5?YjeKVUngoBHst4?tQ{ZJt<5$m)O=1x=*J~P^lM2#u8CTE_D z=Bdvy1aa!+mLohnUrl2wx;AF$N!|3~KQS}YTwPV`=14QPshm3I|BvL03ihzz*0dRm z8D^i6o1|mrNz|G&#m<~q+Z|08MDD1&Q%k`?Z~`>)XI|~X6q?t11e@K z+w=rtVM|n3>q@mnzQCEVVY?iqJB%Jn5r1uF;@Q{56N~mBrwsylpsX5Cm zbM>VcEFpikD1TPx*mEvzm~PrUPo27W1aq89+v{g%TVBi- zY)l4kx6;8*TmvWRo=b>gTgx$}fgOC(wp3Vm<%nSCJkq&S*;$9%P$ES->wBhhR&K&P zM{PJ|4b09!8s@b03X^c^%!!1aoUCR^Zuk5;l&hwxx|DJkH6_w19E6c*(BloFKFMwN zduDQN*BnyLon(1#R}Y%;;8vqoPsdWhZ9Qhna`#DN=4oi3T;Yq@hkKVVq|@jhh|yh> z5^US-V!l``25S;Ad(B8NCnsk(iJG>AaE)5#i_(+9n~b~k9?0s~-HL)Nnt^}z4bYuq zfnRmx7MAR!a%BeLjP6= z=~b{kPr>JgYh_E!v?8dDCSPxll;r{z))dg?w&Xz-y^DMS#dZCS&|unwe{c?Q>x#d4 z2QGlYzI1SVFM`C>W5Jz9chXF$Vrb${P?*Lp`z1N{uxh42#Q_W4R$@P`#O(Zww)LZe zLagsKV%C76vT`~uwHLru)u_bVZ~=AiEXqlKJ82^Cky7$;))9|o#pmN`>L!n3nlULyI*^@*A z!r|e-snVm@62j$uJB0Xw7IYtQg6zw99r~eNCjR9K_4<|NI4ZD@(Ho zGg%MQSqn?xGmd8i!nEFMTZ^z`+A(&l#>r$bm)j%A*d>ur2;DYnx4~8`!A6di*zHa@{q<-G!B8?!@wt>GCzyuK8eI4OXehA$dXNRpN{YYPD|+_o2C0a9pRcBfO+z@x?u8yN;|*|z?H)P4uPY1L2;sioR# zsD_fS?2QPE00z0I~=NoyHTq3BtyLWaP2g4@vE8L;9?0k5ap6f*}1-@w@up3!c( zL_p4dmj}CTHzkXJne5Oa3e+017`dVTux*u+6inp@{_k;i0?s*=9jdv9v9S#P<|nvz zs*W-GBouW|hcoC5Mq~sSctKsFnp<7x#7}7xkp_#>=f|^_+=#H`GK=% zjuR{5^$E@ngQ+IsdZ8#l58n9Yqd!KF7EvznDD&aW*$;4G%h*~2`nsH*B&*OS-;z$H ztT^*cs?3?hwb#uhOBh?SByZ3QWQ&R;myHtrM$W$P*;WDfk!{*qQfAKiQRU?aLn6Bo zz}Z>5GMO}0D?G%tdvBq(LHUs5gf2YpPLSd3MRfz^>~G!0DA4@u)S7eli;0?E0f)bs zpZ46}PchjQjyD&$Xs{QogBv3V|;{*f+lS`pej-f+$ThneuY3z28Ih@ArV70-6-3&tKyI zue@&=yNuGrtg2ePc*ur&FqJ*$nyP{3ILXp9uKfn4&?jJI3^4AeT}DSxq$qZmda+Br z>OQ_anZSPRxf7z*GW-VfLN?3kG@PM0&Dhl{kCDp_4JK`rwK!s%tVG;M z&?+J1Rn8Z9d>yM<$nYPksecX@4EF)fzWWfCR2`CWy`K)rk2xEqW0JG)A)@Gv%f-HX zytTVzekx~+D0_fcYaCkdx>gtI@-N8fQT-AhhjGvw@yqq#nWVc&5|=5h90aOZb} z%D#l@xkkZDP8_@uuE18XFq0XY_uM_qGlM4oZGk*^Uwk+&=8ub;Tg38!*mYV|jEi*v zaeiEUIxdz4#H9i8+L%}s5Dgol^+^PPIF%Jw2E?ml;@p^sb%}v4ar%(3y2LxD#g>ht zdR)jcaalmD4v5VgMduE2GAo|UiuD2Tzd;j1#vxHZF3z47kuI^bQzW~@N8w3zfzx7N7rvaOFE5RW zx5h+ZkubZ&i(}c4_z)WebHsTJ+SQJjPvZuMjDprEqWt4!y(2CKsNnUWBenp5Erp6h zdS3{VjevMBAsw-*7`@RE-Ng_vR7`@L1EggA2H?zM+*cftEQV}y#Ij-tRNn+hk(O9X zm&iZ69ifVtyyjrLo3jr@41_Q`XVBG9Vps75fRw^V^VVPGh|4CS5Ho<`)o=c6Uk{E& z08UWp6wx(C@a`mu0^WV!2d}>e@DyPnwgFzC*m^7#XYT?yWnhWVXc;l_>IrO6`YE!L zs_TM8>V*sB~dPJ%i>S!CI#G&9zvdLp8sSSEs@ ztr&7Gne+x=#diWn++0itZMp#Qm0ekkzRnRJkPa9Fg=D7ztnjZgVvuNH_uHT;U5`IU z>?;-oeKr(BVAcU*1MNFx{EA{U)})5eh|_u+p=fV01&m$}NZ~?4)^31`e5et(a>sXo zLNpazkwCw>SSY4lH$mtI9JZ<+%KePMNTEO~qxW?wHu5Y3`hn~gqFI8v-|Y6PSPXHr z{j3CMFR33exF{F4aO8>63=~_8nER1fML8nmxw$RMbcmY`;mL<~5=zBN`v{reaIS35eIsQ?jiftx6*W>aQe7 z`GAf~n=ffO!O9YN9pHmj6R0YwdaDrb!VL4ea-+RuQONIm3tDOt5g%JscO1=@w3SXOGS%C}ZOy0sjA(1U zWp9dE$-I#t5UM6_?908U^O-(WOmumeggUQKNqw&|38fLLz7W-zU#?O@E={0)k?`LO zc3NS`>G7xCM>JLF;q6D0B<{j(JD{R`dpZ>}aEs0dIoGau;*h(KR`ldfWiOU1NRkT4 z)_8AzVRjSvBJy|>e(sYpazAYeM-3w%&$x-hFP_WjH!8k@CkeCIb$q8~#k%!G7{YMH z^5#871Yba!c-Y*pFw{?dI&@f25M(hWjl7)GBiWcl^U#;}3=vdW30y^~ZuQ}72wu}; zOb*6Pgi&@=+uvtsP~cvG+R=*e!J7$OOW+PHjENZXQ6WMtBGgW_Sp7EwK7NbBC)GOx zEMxACgO5jX?0MS7<$9{cp6*ptMILC4=SY27^+Z)SfF^_=IX*6;a77Y)+?8%{s0{0% z^zOFwM9wL9;QITncVrWLapmSMrz*neRIku`deBYDFM+Da2veOf`tduM0whU(51c^O zdTj2^)(sL5eHQ2idEO}~sP3tyi+sNFQEHI@)VDNwRS$lg<~9`b!adxiocNqvHPuew zX+%ZMQr{JRb)#;do<9bZ2+HtW#QM%o5~|+K?@34$yWUzD)W!6hm_9e^beCY^UK3qW z*Cg29m*1_>baY8-6^Yk;^(CC3`D@ZigMPO~I{TO>bC}kM6)(cjN9?Vge7k7PMJX3q76V!m zYvoZ~P4RpWXa6PFpw`2)!?l3?U%C-QcTc)piwU&OGTv*%># zfP9*>xA1i*_CL9Zv%ip!A!sBb;gnp5D3>eH#E{P~mY;L&4Y=L;2K5jw-B5d;I`GEYK7GjY%kz>m}{2< zgDw13xf+dMfNn?I4nr?z|AIkqZ54(_w83POvwxH?!*+>$`URjvoc*`F42=>zALH6q zc{68EOK|=J0N0_XBHu!@5%SM+?P3gA-AZ5{;@Y)Yq+gZ|qdHsAx~0jASbB2;otb^u Is2%5j0h=w&o&W#< literal 0 HcmV?d00001 diff --git a/Cocoa/gd.lproj/InfoPlist.strings b/Cocoa/gd.lproj/InfoPlist.strings new file mode 100644 index 0000000..6873859 --- /dev/null +++ b/Cocoa/gd.lproj/InfoPlist.strings @@ -0,0 +1,6 @@ +/* Localized versions of Info.plist keys */ + +CFBundleName = "ResKnife"; +CFBundleShortVersionString = "0.6 beta 4"; +CFBundleGetInfoString = "ResKnife 0.6 b4, Dlighe-sgrìobhaidh © Nicolas Sauncs, 2001-7."; +NSHumanReadableCopyright = "© Nicolas Sauncs, 2001-7."; diff --git a/Cocoa/gd.lproj/Localizable.strings b/Cocoa/gd.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..c0d52fc5bd510a0f9f58efebff4099610cdfda57 GIT binary patch literal 5126 zcmb7I-EJFI5T09j29S@B`)xxtf_RQL|~ zzQF%duJIuyIhxJ+1a~#Ad2dJoJdHl9WTE^IA?-_iOy+OEzX9eNG&5WWpf7>Tt47{K z2Cquxyph+SyoDYCH2i;{-{+vIm8w#mUn*Ax2`AvB1p&{OxV{Ac0(YiE0f{TQk{z6w zHFI3opiecLfP&`*_yGpT2=vcbna=~}#$qXhjq za7tKbNQLa{9es0|P@TYzHPGt~o%?f7EjhwT16|v`Kg2V}rIH7m^Eq&@@RVBdY^^-> z$`V)foNM_Cvgq|D(PAGueUyou!TPoOfjZIyh1{3lL46L~=(!i5u}B4Z3Z8O9y^C0p zgV~UCxIYW|1=1PmAg91wLGqcRMf81~GIs)e#^_Y|Oyp3%=eW=Pda}u;VZ38VnSqLR zFpg+8>}MWi6-E8b7Na|WHgkCgeb4kNAgivSBjeo9F@8Q*1X|8$GBZ45-HV-tX+$DQ2w%xP`8j-@Xf#e~na#Xrhif!)%#OAu(ert) zV9l~`v13&5Seg;J^h0C<`$R+5 z%w3BQCkbtewtNb0l*Ud;8o|D6E&pU5k_w2W<1=`K-%nG@NZ@eRLlGTU@ zJ(Ko0KIL5GG_ZWNs>tbs9D|F!sqO#hog9gsn_V@X)qiU?(4qnr!HGI=X=8J>)Tn=e z_GyKt97Hz$nIepJ0akuQZR>T4vjy~Z%b&rM^hLCdvbk^2N3<-}%c;A*VLh-a$es3c z=g6l-TSi;UPr)+ZI)1>^=9C+@BT~f7jNI*52ien%GSpIQeFl$kLrb@#F-x|im<_%= zM%_;^vAF3l2EOOmv~pV8B?2c4yxyI8Il>UN=O-(L8x%AvNjehR77sv5(-P=*gWwWnw_SN{G?lTWGkI!ML z?Lh3B+zaCS&yY2acmqy<3vo2xs8TfdC3~HDz`Hp;%jmVYzqs3^-MhOpcJs*N$j-ry z@gJaj#ds9sn@!jA+YzI^xgGwVv3vLa5Of=@&~rJHIdAM8hu8E&YF9dyx;Y-BFg9I0 zySC%?@15xc?3r81uIjxZ&aQ1bx2IX&(OqM9OP_>Yv_6fu_fALCc(6#JhwJE8WciV2av$yZh?@>dW@DAP@c9MBJ*0F+M9}f3z GD*O*!VIIK% literal 0 HcmV?d00001 diff --git a/Cocoa/ja.lproj/Application.nib/classes.nib b/Cocoa/ja.lproj/Application.nib/classes.nib new file mode 100644 index 0000000..1c978c4 --- /dev/null +++ b/Cocoa/ja.lproj/Application.nib/classes.nib @@ -0,0 +1,50 @@ +{ + IBClasses = ( + { + ACTIONS = { + emailDeveloper = id; + showAbout = id; + showInfo = id; + showPasteboard = id; + showPrefs = id; + visitSourceforge = id; + visitWebsite = id; + }; + CLASS = ApplicationDelegate; + LANGUAGE = ObjC; + OUTLETS = {openPanelDelegate = OpenPanelDelegate; }; + SUPERCLASS = NSObject; + }, + { + ACTIONS = { + deselectAll = id; + openResources = id; + openResourcesAsHex = id; + openResourcesInTemplate = id; + playSound = id; + revertResource = id; + saveResource = id; + showCreateResourceSheet = id; + showSelectTemplateSheet = id; + useIconView = id; + useListView = id; + }; + CLASS = FirstResponder; + LANGUAGE = ObjC; + SUPERCLASS = NSObject; + }, + { + ACTIONS = {addFork = id; removeFork = id; }; + CLASS = OpenPanelDelegate; + LANGUAGE = ObjC; + OUTLETS = { + addForkButton = NSButton; + forkTableView = NSTableView; + openPanelAccessoryView = NSView; + removeForkButton = NSButton; + }; + SUPERCLASS = NSObject; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/Cocoa/ja.lproj/Application.nib/info.nib b/Cocoa/ja.lproj/Application.nib/info.nib new file mode 100644 index 0000000..844d92b --- /dev/null +++ b/Cocoa/ja.lproj/Application.nib/info.nib @@ -0,0 +1,23 @@ + + + + + IBDocumentLocation + 454 731 356 240 0 0 1600 1002 + IBEditorPositions + + 252 + 580 400 520 175 0 0 1600 1002 + 29 + 465 651 429 44 0 0 1600 1002 + + IBFramework Version + 446.1 + IBOpenObjects + + 29 + + IBSystem Version + 8L127 + + diff --git a/Cocoa/ja.lproj/Application.nib/keyedobjects.nib b/Cocoa/ja.lproj/Application.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..23840a976c07c9d0a397f0dbf680f1fe6a4ac280 GIT binary patch literal 25589 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

{K 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 q( +/*! +@function main +*/ + int main(int argc, const char *argv[]) { return NSApplicationMain(argc, argv); diff --git a/ICONEditor/ICONWindowController.m b/ICONEditor/ICONWindowController.m index 39c2adc..f099bf0 100644 --- a/ICONEditor/ICONWindowController.m +++ b/ICONEditor/ICONWindowController.m @@ -82,7 +82,7 @@ resImage = [[NSImage alloc] init]; resData = [[resource data] retain]; - planes[0] = (char*) [resData bytes]; + planes[0] = (unsigned char*) [resData bytes]; if( [resType isEqualToString: @"ICN#"] ) { diff --git a/NuTemplateEditor/TEMPLATE EDITOR.txt b/NuTemplateEditor/Read Me.txt similarity index 75% rename from NuTemplateEditor/TEMPLATE EDITOR.txt rename to NuTemplateEditor/Read Me.txt index a7ea2a4..baf5537 100644 --- a/NuTemplateEditor/TEMPLATE EDITOR.txt +++ b/NuTemplateEditor/Read Me.txt @@ -1,40 +1,37 @@ ABOUT THE CODE -------------- - WHAT HAPPENS WHEN A TEMPLATE EDITOR IS OPENED FOR A RESOURCE The template editor uses a dedicated class for each field type (or family of field types). -These classes are all subclasses of the common base class NuTemplateElement. For things like -lists, there is a subclass NuTemplateGroupElement from which you can instead subclass to +These classes are all subclasses of the common base class Element. For things like +lists, there is a subclass GroupElement from which you can instead subclass to have some of the work done for you. -When opening a resource, the template editor first creates a NuTemplateStream for the template -resource and calls readOneObject: on it until it runs out of data, instantiating a hierarchy -of NuTemplateElement subclasses for based on the template. +When opening a resource, the template editor first creates a TemplateStream for the template +resource and calls readOneObject:on it until it runs out of data, instantiating a hierarchy +of Element subclasses for based on the template. -After that, it creates a NuTemplateStream for the resource and loops over the template object -hierarchy, creating a copy of each item, and then calling readDataFrom:containingArray: on -the copy, which in turn reads data from the NuTemplateStream and stores it in its instance -variables. For this to work, subclasses of NuTemplateElement *must* implement the NSCopying +After that, it creates a TemplateStream for the resource and loops over the template object +hierarchy, creating a copy of each item, and then calling readDataFrom:containingArray:on +the copy, which in turn reads data from the TemplateStream and stores it in its instance +variables. For this to work, subclasses of Element *must* implement the NSCopying protocol. This results in an object hierarchy that describes the entire resource using template fields containing the data, which can now be edited, displayed in lists, etc. - WHAT HAPPENS WHEN THE TEMPLATE EDITOR IS CLOSED -As soon as the template editor is closed, another NuTemplateStream is created for the +As soon as the template editor is closed, another TemplateStream is created for the resource and passed to all template fields (the copies with the resource data, not the pre-parsed template hierarchy), via writeDataTo:, which is where they should write their -data to the stream. Before that, sizeOnDisk is called on each NuTemplateElement to +data to the stream. Before that, sizeOnDisk is called on each Element to calculate the new size of the resource before the actual process of writing them out. -This size must include the size of all of their sub-items, and writeDataTo: must call +This size must include the size of all of their sub-items, and writeDataTo:must call these sub items if they are to be written to disk. - -SPECIAL CASE: LISTS +SPECIAL CASE:LISTS When the editor encounters an LSTB element, the LSTB element is called upon to parse its "sub-elements" (the items that make up one list item). The LSTB element reads all elements @@ -65,8 +62,7 @@ Analogous behaviour is employed for other kinds of lists, except that additional features in LSTEs are activated to allow writing terminating zeroes to the file, and that the equivalent to the "LSTB" item may also update a counter field. - - REVISIONS: + 2006-02-05 NS Rewrote plugin. 2003-08-13 UK Finished chapter on lists, added revision history. 2003-08-08 UK Created. diff --git a/NuTemplateEditor/Resources/DisplayTMPL.png b/NuTemplateEditor/Resources/DisplayTMPL.png new file mode 100644 index 0000000000000000000000000000000000000000..695d4c0a0d8493995b4ccf5e3081ead2de603905 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0j8=#Da{> zWas?6vecrI)FRVZk9R;tTRdGHLn`LHnRb!)fC7h$WQU@)v-n%CzbiVgHAHB|`TS8Z z)VzAUa)nDtfM~er@(IdMYkN)3vsJLI(J@jiGL7ls&Dze?H0%9I2~LJkhIfr&skhG8 z?^e*<#F$Wh|9xX%>;k4Ko)e!pT*|Dx_@dZ>RpGDlG3KzTm)^d3*}%Ji$>&>hjBkj0 z3A4*w&TI{a?+&XsUDQwc#^AxVmY-oix6bqa8|A_auKo^YSip6_rhu7&;s1YTh8^q& VobIkrR0F!7!PC{xWt~$(6958zXEgu- literal 0 HcmV?d00001 diff --git a/NuTemplateEditor/TMPLs.rsrc b/NuTemplateEditor/TMPLs.rsrc new file mode 100644 index 0000000000000000000000000000000000000000..0454a6350db9dac20a98548102e34294ba0a8d89 GIT binary patch literal 15074 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 literal 0 HcmV?d00001 diff --git a/NuTemplateEditor/Templates.rsrc b/NuTemplateEditor/Templates.rsrc new file mode 100644 index 0000000000000000000000000000000000000000..5b696e319dfc53caf3ad63ab8c6c885713527aed GIT binary patch literal 22260 zcmd^n3y@@Ib>82rJ3ZY!J+re9tt5otmlm-rB&}v3u1xM60nI;f}CK$M%ctCL{7;-Y$~Q=Tp=kElSD~G zB4ZNredoXT_Cvd9jZsCZOx5YGKj-}Coc}77QcA64lv>8W^ml;#|Ms_k^t7|P z?%94-FWF6JWv#rb)D<@j&w8y;&zDN)R!dod*W5Qd#KzVtzT>p?T-Dce8=)kXy|!++ zEl02Wj=jmGeFZNJz2-pb_=@kgLbtV{>!@8fwGSkTHO~v3Bz@$Z+p2oodey0ft24!N zet|s%ZM%X7*hj8xuj?R0-;@35R6lyWA3f2J-rkSi(U0Cq^kC6zbeb)FPbUc7np?3$ z*K5rc?ki_joxt(8oGOt6^A!)v;`#2IkM$07zoega{ID;1yeGL`w*y(+y=%>5x~CoX zK9;0O8%)ZVoSNNfgnG+$woB+cU2_`^$Dai_R(5twhOXM7GshOr1de{Qhwb2628F_W z`M}zy+t#6P2X(z|`znm-tgV3uKKn~&75g<0;j4^uxgAP??tA1k;z_U zg2*W6bZf|wZP;y&IJf5cpb-C_4LA|uFbSm!U&fd1}=tXYtMPy{7 zoaag%!)JHQ9x1zF!_mctTiGO@FM91=J>RN3z8f-Oe976?vtFaxn>d2~_WWpY80+|= zy`v9nuco(!Bm?e&QmOwoj2#I;3$jg1o#r~I7o~h}TZ-)KCRK!jB=um?X*6`*aX0Fr zKH7G7oJMdHTR0#Y+io?i_oXLPCKHZH?#F^$HD?EU3#196Zs?%mdl=ff?Xz)3YI*_t zzJ`6*d0fD1F5dh8BMYUO*&`Z6;dT6qqunYO>IEFs7zee14U`k?^er;U7UJP}PDr8Y z;7lwRm&!x0;@`qrxj3?jG!8amoJr0Ms=al@5I1RUl1=sCQv>+%0sO=Oe)|A^#{hok z0Dh7<#_%UE?NX$naT)PUEA(AwU^2s!Wh6jmK6ILT$vei?A6f+`m?U2rJ|&Vs;B=wU zaZIulnCdAYuqhy*6gb{fKwwiqKq+vdr+~nwfPe`FuuR`Fe<;myn_&-~<5`+Tk@TD# zHvw0CuVV7kvxaM;KyIdGuQ#08#zrs)?lUBOgTgRr{QitIjD?V7a+t$h)-2?wcHY!+ zw~BMqtJy`{-_*sr?Gqak{zl=DG(%FD%wZdrYr>5CDJaV{yS349DDnC#O z_4+fpb9EPtIYgJ`rRl{SSuB{D=ieOx^c=!7hiIe|zZerqOz5vBW+n`P-2v{k*3f8*58)DzMKm|9%DD^tFs~V8x z$5z~(MWjF`C4zOuu540gta*OZmR;RXY9LLU;m6Y&ojWF?qR|lr4c(2NH7U@QsInm? zhYp-ZvSND=>vcB_wA(Umaoesu4Ekxdakg3mIpb03Hb}naIt`IV2fORrqJqv ze0?`VPE16bJ!>S2PC}HZ@)9#TPDo>e%tG}89xTQ%>PTXMFz!TA_Ji&?U#Bw=nK!CwIhk^<6zu)YLyZGSCn9NX?TM$~1= zvr%J7!Wv8LCaBmgVpwR5Wc@t1<2)14&pqDyF?TiyxquvfoV3tQLf29XdU8Y?drivvJteOK zvJ>S!s#u%#z2=#~XY*09HYtP>mS-(agP3(FyqFgE$+WXxgTsh>kR+UYHiw1eIM(qa zqffVab38vcF?9zx-(6!}J*E)03}pe(liCP+*&CA}IsoxJ@u|TAQ@X#v@xcPe2MU}R zEO26=!0m$tZXYOc$6$dwx&?A((6Oi&bSk--3wpdCJ<*Te-jCjqphnOetzaZ=M9n$5 z?W+&;-ea;y-c)sJMT{9R&{TST6tKW2|?2caLg zlgP7~G%Dci_v<~P(onzH6KQU-2&Qb@%Fo(Ox3O!adVj@{C@WqtHO(=J!9sKZDSa#d zsG#RoJWx@hh#2*Zvlxnt%yb8eo_B^Ii^?7cmY=D*A@mEc)z}r)$6`fnhIG#^s($( z-P@iHLvz4zioTFXtH*TJ*>Wp`87Mh-q9>8KebA9ygo2VyTf<)h!kO{b^bsF{w zvQLX!AWZryDLVzH^Xc5J5=Dtaa9LV}KZC?h^Hy zs4^3hsmPs!DZ^+>gPaKC;9Qg8t!UfxtCCq*DlJ6h3A+2}p*4F81Y+!nN0-+FsLr8t z6PNbN=?V{%4mv^Gfdb@gQ3+$tH6=F?-QF{2t-sz_(Qd(TQQ5@Z9l9hdyrkseCN3mK z9URl1J*9(f7j`CQ?_I`89;h;Y3d(cMr|GjolaX|MLo_72-PTnXIadGj2zxm+2Q!aupi0Bk(>Ba)l6Av^N23eXJl|=;@~P_sWu^P^ zwNUJh;J4knhjRh?*^xVXH zWyn;|jisL_OC|9B==#>j)ix4x1$~dxfa^j*;TZv~3lH24Jxr*hl<-Vy|AHl zG33>%U&>_32f*D7NBJRl;$&^Ols}Oxm|I=M{?c8$3#%C&Xc*JRMLE zqN_H{j1;Pgg@C8%GLfs6Jgk&l*!3n@VAHF@W8jEE6>bD000uJ-L?(~H^!;mfw-!F9 zoh#*B(B#6qX2q$)q-bpaS4mD?xOiV44#;uw3pg$8BQMiOE70P=Tgir9Fx*?GZqdPR zKs#TYGAVNBAa=z;Nf3&AkDl27Z;WgJXWGvD=36yJd$RAC)%*HB~Ml|Hem3ju|jEIy!Ip;rSBy zu%TB_%1nBCp1Vy7hZf|vMU|4v=8YO;xlYhJx`L(ATg3kqaZL$7*}N7_N0ztN%`5k-mpbYx@Of0;gk#YcHL=> zq8V5%0)5xi?KiR-Bs(lE8s-~_P8nt7|LLaW&O0ryUH8`A3JY8Z4H9K(Fu{J_ItpEe zGSQHZOv{>XG~{Y9G}CgL0%eLm>42D<^ZvKhhdHOmG=Rs}YoSkW6P`Ci+r)nYsYYeFj~ z>D(-aKVM@K+exq3yJulF0#}gZV9Z7AfQMrZTtIpwQtCu{B#~1dDxsKEDmZm}i&&0X zynh)fn4<#Jvp7VPaS&N`K+m!^GOTXVEU4Y7kxfan_jWKrNg|qG@a!t*ALr*e;obxq zO51U6hBJ6sU@p35+%fI665iL z!6Y2dTs+XdG^Ac>ornBlKh}K_FmygPY7gBPL*Q1Yhq?O=TLzIuo0K7D&uKmeAO1Zy zlPQ5kQXEQ~v%d2t0=Y#upvc2Ch@!dAk3>n-2c;}-Vlt3i*@0zWbW^5hKst$CbeIS& zi^#YF=0a(V=fBHs{_+qR9-OmK!Rvb0>#(_WnPN!v)a)!QvsJy(5x!*=VR(qt&?hr+ z{cpz0oG|Jhu0A}yu>loPrj;&wF@Xs^$DBWN&cS6KVu0K}OGI{-SY{fFOadb^T=c0_ z2l4R$!^C260R|RV_U7IWG?=oi#!^F<1j$sP`u^loQ zlEwmWEz)tk7r7E7NxkGWY~kD^X7la?18<86jmOk;hXrefvmJ`Y^t@@xN5ldqGq9HV zxLC|8K)K*Eu=>H$Y8cBfEeH`jv=bkgq1_lt@04LvG^@IsfM{nQG<7(bqsG`dc=`!z zCq9q6F%VOVHR~DCn%0_PfrOgTdJ$yNX%ZRIu)uER= zbb6t))A4sNukg^KgK1t~+3XBFmhC3?zz0@ zauFU0IH`R6uTmLi(I36%$se)u#VkgtdasQrG3fAIbrIOy5=7Q2CX*kI>=%P<-D!%I zgl2w`Yx_zNSKfwp;k@v+Xuf7MSF$iEo!$U&H8GaRp*h%Xrr(&|V;lQXhIg5D#$fKn z45BEOh+uQ6BDx+O*cl@*C*szph9iKcShS#w&c``dB3=_JE2H63uQu8-7t;ZM1>#LVJ+L0JtX`~Oy zFFF#KYP1-1k#0%?9HNCR!hAMbR0F4xk)Ni~F2w$Hd|Ai*nKnXE9Bpm_ECGABSPkPL z<(I)!pdxk0h%JT3045@Ca89t!I(D7QHgrbx6r8c4bG#MMRh5on8aS}X^#!nR27L&E zEM+>e+8^Vj6B_pWr_`M*Ny?^uJFhS-Ab8?Z@tnQ7NZ8swG|u*|6A;&DHyVauT4WKCW_RKu``P``hc4h)o{U zErdY2&Wj#S+~cKCYMcHrU6Gioe*X!%RRs~DqL5`4!0kfl_i~^Yyw*k+JGEHWCAU^P z#-nqEyC%7;>p9|jA4TgMdtY!!5vJlM zD&>C?Gx)^9+Zb$;Likz{FoY{2?<#2O6S8IRzNI0JfmH5=)z~ zGlIjo+4Jp>6goo>M~tQCVU93f1B)u4l%P#k7Mzo~tM5e(R|cU+eAsde?nje|5~f~E z7;EM8y@bG1uvykZS(8Jv1Dm3c!gwd~C09Q;3noIRC7D+}H*+0qUh)nVk}v|Z(LHTG zH>;=3=Vm5tn!OXXiE2))kn~3z)%Jo>L{CT{g_{GxKKT_o`|x5yynWyhbezBexJ&PO z$eT}=O23KOfnYTl-RsMPs?}$Dk8*P0xFcQUMXCrx4!v=Jh5w~I%kq>Vd7zPm`Cr=2 z{Pt|g-|`c8kYHi~6%QfvW@wlsmLbMh0tvF*cEnvRwP3tQ3?#}8vm9ck2sG1WF0Pg}TpH>3A3IT&tx(CnH-07RJz6)3&$%^uc; z4j$zVy2C9xjprs#P9z}_gKBvOp`RTpiObF<0GL>&X*`Z zlXOmSariJ^av@r%KN`hIDs!@A!G#x_hZ$J^?&C&g_BD7W!3t=Er%uk6Tt=w>!t^4+ z@kVPk(K`%nmp2bl1s?gqEW%4*et`b*wv+#a{&;Lx6xn#bqn`z?vn}~ht zFA_-?ju4Lt@Qx6dM!s8vkdzxcGY$=A7rPipg`2L#x3SRSDk&*drPNTWvQ;arxQhrBeJlfi?HZRa0mRo53*H ze&w%AU)(eknJUCb6uM->iV{s*!lw}51YbsU@IRSh`?Pn-ScO1H5yG%ZA2HIi_rs^L ztq~n$mU?Ib#z>3} z&r4ncQyL6-i*E4Dj<0MuyeEFR?CX7woSaG?`Y*j0mnIouVT3yalQv)F@Uoi|T#gFS zq#&k}nj2w&E_@&7@E(_oIzs6&9YQ!5Uv-uqe{7ry4i*1@ck^;2k08k%5wx2<0^O8* zz;Iyp4Cf5`qAm#}zv4T!AYy6KGoM~_7;u^s&m+&R?Jl=CA|_-Qkd;)I>pr4BSWDVl z@{qI%pAOz+#R=>W+6rFxqQ{XX?|#oi95|jM6OY)*^MmL+E_+E3Wbsq^Ij7MUqXdpF zM~vrUJjLSG9hvrhs7+!J=@%9~2a=kQ(687rAW~rki34-^_DvrX9buY4$VL2D(NZ@U9lR{QgMW&?1Jf0qdqKZdP@l1IB)5g#vYWRx_+*d*9 z86p!A)aWu&tRc?G@op;PTur=pR<7L|CK67`T*3|O*z@p3<~%0)mriV4sI$MTEHBzH zTfwo{znA$a*=!z1|J*v3@-~Ha(P)TgUH6cm{G)eG7)m|ktD@XY+w1A zy-AZMuvNsRoH2ABN8?>hi?36*8=LSzP`8aKo3p$MBR;0f2=YPPD!Ge33YXAn2}8UJ zvg}fM<6v&Sp6#@f=yo(_5_^IJd8B%XhOY_{Mk^D~B@>sK=c2qQWW7I^ta|1mBsyNj zIftzj#NQ?Jeci;K6Jb^G6@nM?{2m0yL4-YQ^@zBH>$K%;n-J8|O~+|#XU9drW#ozP z7!xnwwQxwIpeys%9{P`j1ZFALsSOFXH`*S`Z@S~TZ+qeD1!|qdeUxcpq!dJc>kgO`0mM8HiS)s7lo%G_J;ILb1#$S=aV`VvTaGZ+sMcenMZCd=C9{JfBX2l zglD$xBe1Lzh1QI<;I%-&EuP}>?2_nnxUN+3lp5E3qI+8)qXEjl+_O5G@b!3kv(br; z_%cRd|=zt^UeIDa`NMz`dHFY()SQ&ZB{%sR~C^rxZ>$Gtc|%$rpp^)1R~(O za@&?47}XnlhnR&)8cT)^JoP*~AuAs5L>AYREnUHAL|2SQGcyz~M~@k`_uCgYTt|aE z*e8SR;l@PlngcP0B+-4?7#PO)#_)-t35>hP?KO&|$-Wd8n(8l0`QEuk_PW+%|yk)GuzSBMigEQi-p}dW8z+fG{NvDf*tNk5}t<4vg z`jhrY-M}V{%el}tneD;IunyCE%hO`SFsB(Biush3Wbi2PZ0>90M(DuRTkS22x7%@Q zTyWI5EqWTvMUIT9r7^SEz0Hh7NpTwoU|ou%0D8-fF&%-6JB*pa z{v@%lY#vt(?4j{d$y+LL69h1J6R`X5*dJ-F<_(Eie{^&p*3R)-vw}Bp@mQ~=C5Fle z)SaWRn0Vdt?CdT26|=LiTVA?}eO!x(JC6BM`Qk6%j5L2%xGH*ZK`GCdKI_$E+Qmhk zJpBgJZ?yvzzJfP{(yeYvkaX4ckIDN#78^E~Bl#Xy1fS?hKi&h&XS$*?@|CU#mXCDB zq{HrGn+2BQ#)zUMIdJi`mlHSc7@4|wV>p-niQP=f()A$8(GtUbMoliJdtR{3$I~XJ zrf}DNvw4?wkz0A@G?pd43JoLT0P)xXTP7?w3&04K4mRTqLE@ZYeB&$5ARMQ6IXnmf z1L%GSaLD@bW9kHwUTXbkrOJyd3(8SB^$(TONK|u6?^nOBh5#QLvVP?g>XRy`)fIOE zepEfG_G&dW1^99GkJLfHF5oBBKUUWO{!f6PRG(5W(<=QG;BTnM)M2fLL%`oszoCu- z{y5-otACRIpAm2r`4T+KMMH!>NnM0fS(w$K4PiQsA;XT?*N=v zpH;JfKMVMv`kXqg)ySiOU#fmft!R~hJz%YVTb^A^UsL!kWwc7h#z$ew?>ThT@ zZUMeaeL+W%awN1^AZ$pI2X00pNcFxUT-0+5!9*fE()f)K6-4 z;Bmlh^(FPwS{*zKI8;xlcK{9m@2G#S-lNqaw)qzIW%U5yR|9^l`WNaK0DFMnsh(6H z0Q|23e^C9t`VioM3;1K|U#bgQT{Q;y6Y44TtANh~epLN|`Xt~g;K$Tg)MJ4EJK#^N zud3hF>gxLde@=Z({Wjpw0DfHkEA_j8xrSd%J)@q`>LncW6RGd2-v|6Pz)zUg_vw*+9=Ze&rRyR%zS&yhaR_cIOudD&KQvWk`wN^(z3^=3Snz|0~p8?LR zx20~->ZW^#tP5rJ)2SnXzXbTa`kB-%TD|H!fd88M+0>*~w_pt~{7v<9sXG8a1h}f+ zo_eiTw_XdluHKP)1K_s-Zm4&rX0$p6dcM$Be=Bv5R=2GJ4%NF-%YZSS3p?uFsj^lR zHv@i)dQa*;z)u5ytNQuWU)O4K9`Mhqzn!W8{vzOas=t$}Yc=&M!0%D-O*OT;{oR1y zs~$-CfI*)Z-ml)5+SclhPXYc#^>cQ080sjZUkEmZr zy<4l3p!o|QQ-3e@UcgxM3!hNGn0gTKmjOSjekt{kR9_CjI(y(i|UtCp91`Oz)z@$Q=iuAb?*ZFr20_mx3qfw z9|C?#eK_?yTHVdH{hIof)RzGNGT^VPkEEW|>J6Zc3*S(Wr2asw;_ZOHsV=1cP^;2U z0sfZyXzGu(n)!La-&X%1^-Zm2!8a~^M|~{y@3fk00e)J2JoO*7y62ApKcjv%^abOwIbXKOaIG?4 z1X~@yp)FX60&AN?J2$^nviMmMYp2=jSk(v6Q8jpQ!>T@9b*zntwnFQT54Se0=7T}Y zYCW*tu^#f;f#p3M)~xmeXeFpW*tUZ9gBV8p!4N+Wty{s@gV5T3z;0W$#si^+@alE^ zbbM=iVYO`84S&a)UcrD0_=tg3VJ?I6tO~v|Wfd1or>zRdQe4EU!GgG870dS>wyG>w zt>LFMkF;uIW5+5jEaTg3t7lg&XjXwWTPQDCHI|z#&9CBXX{{PYP(5r>wc$_Mnq8fl z#n0MVYxdlH$vU;Px?t52ooVr2ZMm)Wb^KJD_^H|a3Gmb2#E(xDi-W!=Ehwfa7d9&V G+5A6~GYi)M literal 0 HcmV?d00001 diff --git a/ResKnife.xcodeproj/project.pbxproj b/ResKnife.xcodeproj/project.pbxproj index b00074e..2306ed6 100644 --- a/ResKnife.xcodeproj/project.pbxproj +++ b/ResKnife.xcodeproj/project.pbxproj @@ -7,6 +7,17 @@ objects = { /* Begin PBXBuildFile section */ + E17752350E424BAB00F737F8 /* NSData-HexRepresentation.m in Sources */ = {isa = PBXBuildFile; fileRef = E17752330E424BAB00F737F8 /* NSData-HexRepresentation.m */; }; + E177526F0E424DCB00F737F8 /* OpenPanelDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E177526D0E424DCB00F737F8 /* OpenPanelDelegate.m */; }; + E17752700E424DCB00F737F8 /* OpenPanelDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E177526E0E424DCB00F737F8 /* OpenPanelDelegate.h */; }; + E17752760E424ED400F737F8 /* Notifications.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C9ECCE027F474A01A8010C /* Notifications.m */; }; + E17753350E424F0C00F737F8 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884A0156D40B01000001 /* Carbon.framework */; }; + E177538B0E4251C600F737F8 /* DisplayTMPL.png in Resources */ = {isa = PBXBuildFile; fileRef = E17753880E4251C600F737F8 /* DisplayTMPL.png */; }; + E177538E0E4251D000F737F8 /* Templates.rsrc in Copy Support Resources */ = {isa = PBXBuildFile; fileRef = E17753890E4251C600F737F8 /* Templates.rsrc */; }; + E177539D0E42521800F737F8 /* Font Templates.rsrc in Copy Support Resources */ = {isa = PBXBuildFile; fileRef = E1B2A73B0E41218F00A72928 /* Font Templates.rsrc */; }; + E17753B90E42528100F737F8 /* NovaTools.plugin in CopyFiles */ = {isa = PBXBuildFile; fileRef = E1B2A4940E41103800A72928 /* NovaTools.plugin */; }; + E17753CD0E42528400F737F8 /* Font Editor.plugin in CopyFiles */ = {isa = PBXBuildFile; fileRef = E1B2A7220E41213300A72928 /* Font Editor.plugin */; }; + E17753E40E42534300F737F8 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884B0156D40B01000001 /* Cocoa.framework */; }; E1B2A3EA0E41103700A72928 /* ResKnifeResourceProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */; }; E1B2A3EB0E41103700A72928 /* ResKnifePluginProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5502C4001C579FF01C57124 /* ResKnifePluginProtocol.h */; }; E1B2A3EC0E41103700A72928 /* ApplicationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = F5B5881D0156D40B01000001 /* ApplicationDelegate.h */; }; @@ -27,7 +38,6 @@ E1B2A3FB0E41103700A72928 /* PasteboardDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = F5F1071603CCC61E01A8010A /* PasteboardDocument.h */; }; E1B2A3FC0E41103700A72928 /* PasteboardWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F5F1071A03CCFAAC01A8010A /* PasteboardWindowController.h */; }; E1B2A3FD0E41103700A72928 /* RKDocumentController.h in Headers */ = {isa = PBXBuildFile; fileRef = F59481AD03D0776C01A8010A /* RKDocumentController.h */; }; - E1B2A3FE0E41103700A72928 /* OpenFileDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = F59481B103D077DC01A8010A /* OpenFileDataSource.h */; }; E1B2A3FF0E41103700A72928 /* RKEditorRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D35755C04DAEB6200B8225B /* RKEditorRegistry.h */; }; E1B2A4000E41103700A72928 /* RKSupportResourceRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D53A9FD04F171DC006651FA /* RKSupportResourceRegistry.h */; }; E1B2A4020E41103700A72928 /* AboutPanel.nib in Resources */ = {isa = PBXBuildFile; fileRef = F5B588360156D40B01000001 /* AboutPanel.nib */; }; @@ -70,18 +80,11 @@ E1B2A42D0E41103700A72928 /* PasteboardDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F1071703CCC61E01A8010A /* PasteboardDocument.m */; }; E1B2A42E0E41103700A72928 /* PasteboardWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F1071B03CCFAAC01A8010A /* PasteboardWindowController.m */; }; E1B2A42F0E41103700A72928 /* RKDocumentController.m in Sources */ = {isa = PBXBuildFile; fileRef = F59481AE03D0776C01A8010A /* RKDocumentController.m */; }; - E1B2A4300E41103700A72928 /* OpenFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = F59481B203D077DC01A8010A /* OpenFileDataSource.m */; }; E1B2A4310E41103700A72928 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D35755A04DAEB4300B8225B /* main.m */; }; E1B2A4320E41103700A72928 /* RKEditorRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D35755D04DAEB6200B8225B /* RKEditorRegistry.m */; }; E1B2A4330E41103700A72928 /* RKSupportResourceRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.m */; }; E1B2A4350E41103700A72928 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884B0156D40B01000001 /* Cocoa.framework */; }; E1B2A4360E41103700A72928 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884A0156D40B01000001 /* Carbon.framework */; }; - E1B2A4400E41103800A72928 /* ResKnifeResourceProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */; }; - E1B2A4410E41103800A72928 /* ResKnifePluginProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5502C4001C579FF01C57124 /* ResKnifePluginProtocol.h */; }; - E1B2A4420E41103800A72928 /* HexEditorDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = F5EF83A0020C08E601A80001 /* HexEditorDelegate.h */; }; - E1B2A4430E41103800A72928 /* HexTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = F5EF83A2020C08E601A80001 /* HexTextView.h */; }; - E1B2A4440E41103800A72928 /* HexWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F5EF83A7020C08E601A80001 /* HexWindowController.h */; }; - E1B2A4450E41103800A72928 /* FindSheetController.h in Headers */ = {isa = PBXBuildFile; fileRef = F54E6220021B6A0801A80001 /* FindSheetController.h */; }; E1B2A4470E41103800A72928 /* HexWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = F5EF83C7020C20D701A80001 /* HexWindow.nib */; }; E1B2A4480E41103800A72928 /* FindSheet.nib in Resources */ = {isa = PBXBuildFile; fileRef = F54E6222021B6A0801A80001 /* FindSheet.nib */; }; E1B2A4490E41103800A72928 /* PasteMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = F5606FDD02ACF2F701A8010C /* PasteMenu.nib */; }; @@ -98,19 +101,6 @@ E1B2A4600E41103800A72928 /* Element.m in Sources */ = {isa = PBXBuildFile; fileRef = F535444E0226B5F501A80001 /* Element.m */; }; E1B2A4610E41103800A72928 /* Notifications.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C9ECCE027F474A01A8010C /* Notifications.m */; }; E1B2A4630E41103800A72928 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884B0156D40B01000001 /* Cocoa.framework */; }; - E1B2A46C0E41103800A72928 /* HostCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = F5B588920156D6D901000001 /* HostCallbacks.h */; }; - E1B2A46D0E41103800A72928 /* BoomWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F58F6B7E025BC3A501A8010C /* BoomWindowController.h */; }; - E1B2A46E0E41103800A72928 /* NovaWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F58F6B82025BC73001A8010C /* NovaWindowController.h */; }; - E1B2A46F0E41103800A72928 /* CharWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F58F6B86025BC76D01A8010C /* CharWindowController.h */; }; - E1B2A4700E41103800A72928 /* ColrWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F58F6B8A025BC7C001A8010C /* ColrWindowController.h */; }; - E1B2A4710E41103800A72928 /* CronWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F58F6B8E025BCF5901A8010C /* CronWindowController.h */; }; - E1B2A4720E41103800A72928 /* DescWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = F58F6B93025BD97701A8010C /* DescWindowController.h */; }; - E1B2A4730E41103800A72928 /* ResKnifeResourceProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */; }; - E1B2A4740E41103800A72928 /* ResKnifePluginProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5502C4001C579FF01C57124 /* ResKnifePluginProtocol.h */; }; - E1B2A4750E41103800A72928 /* DescSplitViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = F58A18410278355D01A8010C /* DescSplitViewDelegate.h */; }; - E1B2A4760E41103800A72928 /* DataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = F543AFDB027B2A5001A8010C /* DataSource.h */; }; - E1B2A4770E41103800A72928 /* Structs.h in Headers */ = {isa = PBXBuildFile; fileRef = F5C9ECD8027F562201A8010C /* Structs.h */; }; - E1B2A4780E41103800A72928 /* NSNumber-Range.h in Headers */ = {isa = PBXBuildFile; fileRef = F59D5DE8032106D201A8010C /* NSNumber-Range.h */; }; E1B2A47A0E41103800A72928 /* NovaTools.nib in Resources */ = {isa = PBXBuildFile; fileRef = F58F6BA9025BDBA701A8010C /* NovaTools.nib */; }; E1B2A47B0E41103800A72928 /* boom.nib in Resources */ = {isa = PBXBuildFile; fileRef = F5EDC612025BFB7301A8010C /* boom.nib */; }; E1B2A47C0E41103800A72928 /* char.nib in Resources */ = {isa = PBXBuildFile; fileRef = F5EDC615025BFB7C01A8010C /* char.nib */; }; @@ -244,28 +234,10 @@ E1B2A53F0E41103900A72928 /* Templar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F50DFE67036C258301A8010A /* Templar.cpp */; }; E1B2A5400E41103900A72928 /* TemplateWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F50DFE6D036C258301A8010A /* TemplateWindow.cpp */; }; E1B2A5430E41103900A72928 /* Templar.rsrc in Rez */ = {isa = PBXBuildFile; fileRef = F50DFE6C036C258301A8010A /* Templar.rsrc */; }; - E1B2A54B0E41103A00A72928 /* ResKnifePluginProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5502C4001C579FF01C57124 /* ResKnifePluginProtocol.h */; }; - E1B2A54C0E41103A00A72928 /* ResKnifeResourceProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */; }; - E1B2A54D0E41103A00A72928 /* ICONWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D3B99B904DC16A30056861E /* ICONWindowController.h */; }; E1B2A54F0E41103A00A72928 /* ICONWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 3D3B99BC04DC16FC0056861E /* ICONWindow.nib */; }; E1B2A5510E41103A00A72928 /* Notifications.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C9ECCE027F474A01A8010C /* Notifications.m */; }; E1B2A5520E41103A00A72928 /* ICONWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D3B99B804DC16A30056861E /* ICONWindowController.m */; }; E1B2A5540E41103A00A72928 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884B0156D40B01000001 /* Cocoa.framework */; }; - E1B2A55D0E41103A00A72928 /* NuTemplateWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0B38B204DEF41E005AED5E /* NuTemplateWindowController.h */; }; - E1B2A55E0E41103A00A72928 /* ResKnifePluginProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5502C4001C579FF01C57124 /* ResKnifePluginProtocol.h */; }; - E1B2A55F0E41103A00A72928 /* ResKnifeResourceProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */; }; - E1B2A5600E41103A00A72928 /* NuTemplateElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933A604DEFEE600DD74B1 /* NuTemplateElement.h */; }; - E1B2A5610E41103A00A72928 /* NuTemplateGroupElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933BA04DF10D700DD74B1 /* NuTemplateGroupElement.h */; }; - E1B2A5620E41103A00A72928 /* NuTemplateStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933BE04DF151C00DD74B1 /* NuTemplateStream.h */; }; - E1B2A5630E41103A00A72928 /* NuTemplateLSTBElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933C404DF1C0800DD74B1 /* NuTemplateLSTBElement.h */; }; - E1B2A5640E41103A00A72928 /* NuTemplateTNAMElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933E304DF2FF700DD74B1 /* NuTemplateTNAMElement.h */; }; - E1B2A5650E41103A00A72928 /* NuTemplatePSTRElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933E704DF317D00DD74B1 /* NuTemplatePSTRElement.h */; }; - E1B2A5660E41103A00A72928 /* NuTemplateDWRDElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933EF04DF381900DD74B1 /* NuTemplateDWRDElement.h */; }; - E1B2A5670E41103A00A72928 /* NuTemplateLSTEElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D0933F604DFE80500DD74B1 /* NuTemplateLSTEElement.h */; }; - E1B2A5680E41103A00A72928 /* NuTemplateDLNGElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D4737B404E872DB00AF65FE /* NuTemplateDLNGElement.h */; }; - E1B2A5690E41103A00A72928 /* NuTemplateDBYTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D4737B804E873F300AF65FE /* NuTemplateDBYTElement.h */; }; - E1B2A56A0E41103A00A72928 /* NuTemplateOCNTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D50046F04EF040900F3B64D /* NuTemplateOCNTElement.h */; }; - E1B2A56B0E41103A00A72928 /* NuTemplateLSTCElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D50047404EF122000F3B64D /* NuTemplateLSTCElement.h */; }; E1B2A56D0E41103A00A72928 /* NuTemplateWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 3D0B38B504DEF465005AED5E /* NuTemplateWindow.nib */; }; E1B2A56F0E41103A00A72928 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3D2EE5E204E5C56F00515930 /* Localizable.strings */; }; E1B2A5710E41103A00A72928 /* NuTemplateWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D0B38B304DEF41E005AED5E /* NuTemplateWindowController.m */; }; @@ -289,18 +261,13 @@ E1B2A73F0E41218F00A72928 /* FontDocument.nib in Resources */ = {isa = PBXBuildFile; fileRef = E1B2A7350E41218F00A72928 /* FontDocument.nib */; }; E1B2A7400E41218F00A72928 /* FontWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = E1B2A7370E41218F00A72928 /* FontWindow.nib */; }; E1B2A7410E41219000A72928 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E1B2A7390E41218F00A72928 /* Localizable.strings */; }; - E1B2A7420E41219000A72928 /* Font Templates.rsrc in Resources */ = {isa = PBXBuildFile; fileRef = E1B2A73B0E41218F00A72928 /* Font Templates.rsrc */; }; E1B2A7430E41219000A72928 /* FontWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A73D0E41218F00A72928 /* FontWindowController.m */; }; E1B2A7760E41230E00A72928 /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A7750E41230E00A72928 /* NGSCategories.m */; }; E1B2A7770E41230E00A72928 /* NGSCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B2A7740E41230E00A72928 /* NGSCategories.h */; }; E1B2A7780E41230E00A72928 /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A7750E41230E00A72928 /* NGSCategories.m */; }; - E1B2A7790E41230E00A72928 /* NGSCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B2A7740E41230E00A72928 /* NGSCategories.h */; }; E1B2A77A0E41230E00A72928 /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A7750E41230E00A72928 /* NGSCategories.m */; }; - E1B2A77B0E41230E00A72928 /* NGSCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B2A7740E41230E00A72928 /* NGSCategories.h */; }; E1B2A77C0E41230E00A72928 /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A7750E41230E00A72928 /* NGSCategories.m */; }; - E1B2A77D0E41230E00A72928 /* NGSCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B2A7740E41230E00A72928 /* NGSCategories.h */; }; E1B2A77E0E41230E00A72928 /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A7750E41230E00A72928 /* NGSCategories.m */; }; - E1B2A77F0E41230E00A72928 /* NGSCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B2A7740E41230E00A72928 /* NGSCategories.h */; }; E1B2A7800E41230E00A72928 /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B2A7750E41230E00A72928 /* NGSCategories.m */; }; /* End PBXBuildFile section */ @@ -324,6 +291,20 @@ /* End PBXBuildRule section */ /* Begin PBXContainerItemProxy section */ + E17753B10E42526500F737F8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F5B5880F0156D2A601000001 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E1B2A7210E41213300A72928 /* Font Editor Cocoa */; + remoteInfo = "Font Editor Cocoa"; + }; + E17753B30E42526F00F737F8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F5B5880F0156D2A601000001 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E1B2A46A0E41103800A72928 /* NovaTools */; + remoteInfo = NovaTools; + }; E1B2A5870E41103A00A72928 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F5B5880F0156D2A601000001 /* Project object */; @@ -341,6 +322,28 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + E17753850E4250CA00F737F8 /* Copy Support Resources */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "Support Resources"; + dstSubfolderSpec = 7; + files = ( + E177538E0E4251D000F737F8 /* Templates.rsrc in Copy Support Resources */, + ); + name = "Copy Support Resources"; + runOnlyForDeploymentPostprocessing = 0; + }; + E177539C0E42520800F737F8 /* Copy Support Resources */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "Support Resources"; + dstSubfolderSpec = 7; + files = ( + E177539D0E42521800F737F8 /* Font Templates.rsrc in Copy Support Resources */, + ); + name = "Copy Support Resources"; + runOnlyForDeploymentPostprocessing = 0; + }; E1B2A4170E41103700A72928 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -349,6 +352,8 @@ files = ( E1B2A5930E41103A00A72928 /* Hexadecimal Editor.plugin in CopyFiles */, E1B2A5920E41103A00A72928 /* Template Editor.plugin in CopyFiles */, + E17753CD0E42528400F737F8 /* Font Editor.plugin in CopyFiles */, + E17753B90E42528100F737F8 /* NovaTools.plugin in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -372,12 +377,12 @@ 3D0933F404DFD7CF00DD74B1 /* TODO.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO.txt; sourceTree = SOURCE_ROOT; }; 3D0933F604DFE80500DD74B1 /* NuTemplateLSTEElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NuTemplateLSTEElement.h; sourceTree = ""; }; 3D0933F704DFE80500DD74B1 /* NuTemplateLSTEElement.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NuTemplateLSTEElement.m; sourceTree = ""; }; - 3D0ABFB904E152CA00C85300 /* TEMPLATE EDITOR.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "TEMPLATE EDITOR.txt"; path = "NuTemplateEditor/TEMPLATE EDITOR.txt"; sourceTree = SOURCE_ROOT; }; + 3D0ABFB904E152CA00C85300 /* Read Me.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Read Me.txt"; sourceTree = ""; }; 3D0ABFBC04E172F700C85300 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = SOURCE_ROOT; }; 3D0B38B204DEF41E005AED5E /* NuTemplateWindowController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NuTemplateWindowController.h; sourceTree = ""; }; 3D0B38B304DEF41E005AED5E /* NuTemplateWindowController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NuTemplateWindowController.m; sourceTree = ""; }; 3D0B38B604DEF465005AED5E /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/NuTemplateWindow.nib; sourceTree = ""; }; - 3D2EE5E204E5C56F00515930 /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; + 3D2EE5E204E5C56F00515930 /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = Localizable.strings; path = ../Localizable.strings; sourceTree = ""; }; 3D35755A04DAEB4300B8225B /* main.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 3D35755C04DAEB6200B8225B /* RKEditorRegistry.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RKEditorRegistry.h; sourceTree = ""; }; 3D35755D04DAEB6200B8225B /* RKEditorRegistry.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = RKEditorRegistry.m; sourceTree = ""; }; @@ -395,6 +400,13 @@ 3D50047404EF122000F3B64D /* NuTemplateLSTCElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NuTemplateLSTCElement.h; sourceTree = ""; }; 3D53A9FD04F171DC006651FA /* RKSupportResourceRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKSupportResourceRegistry.h; sourceTree = ""; }; 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKSupportResourceRegistry.m; sourceTree = ""; }; + E17752320E424BAB00F737F8 /* NSData-HexRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData-HexRepresentation.h"; sourceTree = ""; }; + E17752330E424BAB00F737F8 /* NSData-HexRepresentation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData-HexRepresentation.m"; sourceTree = ""; }; + E177526D0E424DCB00F737F8 /* OpenPanelDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenPanelDelegate.m; sourceTree = ""; }; + E177526E0E424DCB00F737F8 /* OpenPanelDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenPanelDelegate.h; sourceTree = ""; }; + E17753880E4251C600F737F8 /* DisplayTMPL.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DisplayTMPL.png; sourceTree = ""; }; + E17753890E4251C600F737F8 /* Templates.rsrc */ = {isa = PBXFileReference; lastKnownFileType = archive.rsrc; name = Templates.rsrc; path = ../Templates.rsrc; sourceTree = ""; }; + E177538A0E4251C600F737F8 /* TMPLs.rsrc */ = {isa = PBXFileReference; lastKnownFileType = archive.rsrc; name = TMPLs.rsrc; path = ../TMPLs.rsrc; sourceTree = ""; }; E1B2A43B0E41103700A72928 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../Plug-Ins/Hex Editor/Info.plist"; sourceTree = ""; }; E1B2A43C0E41103800A72928 /* ResKnife Cocoa.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ResKnife Cocoa.app"; sourceTree = BUILT_PRODUCTS_DIR; }; E1B2A4560E41103800A72928 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -415,7 +427,7 @@ E1B2A5470E41103900A72928 /* Info-Uli_s_Template_Editor__Upgraded_.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Uli_s_Template_Editor__Upgraded_.plist"; sourceTree = ""; }; E1B2A5480E41103A00A72928 /* Ulis Template Editor.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Ulis Template Editor.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; E1B2A55A0E41103A00A72928 /* Bitmap Editor.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Bitmap Editor.plugin"; sourceTree = BUILT_PRODUCTS_DIR; }; - E1B2A5850E41103A00A72928 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E1B2A5850E41103A00A72928 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Info.plist; sourceTree = ""; }; E1B2A5860E41103A00A72928 /* Template Editor.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Template Editor.plugin"; sourceTree = BUILT_PRODUCTS_DIR; }; E1B2A7220E41213300A72928 /* Font Editor.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Font Editor.plugin"; sourceTree = BUILT_PRODUCTS_DIR; }; E1B2A7360E41218F00A72928 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/FontDocument.nib; sourceTree = ""; }; @@ -460,8 +472,6 @@ F543AFDB027B2A5001A8010C /* DataSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DataSource.h; sourceTree = ""; }; F543AFDC027B2A5001A8010C /* DataSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DataSource.m; sourceTree = ""; }; F543AFF0027C716E01A8010C /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = "English.lproj/Resource Types.strings"; sourceTree = ""; }; - F54625C6029174F601A8010C /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; - F54626490291750201A8010C /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; F54E6220021B6A0801A80001 /* FindSheetController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FindSheetController.h; sourceTree = ""; }; F54E6221021B6A0801A80001 /* FindSheetController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = FindSheetController.m; sourceTree = ""; }; F54E6223021B6A0801A80001 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/FindSheet.nib; sourceTree = ""; }; @@ -494,8 +504,6 @@ F58F6BAA025BDBA701A8010C /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/NovaTools.nib; sourceTree = ""; }; F59481AD03D0776C01A8010A /* RKDocumentController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RKDocumentController.h; sourceTree = ""; }; F59481AE03D0776C01A8010A /* RKDocumentController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = RKDocumentController.m; sourceTree = ""; }; - F59481B103D077DC01A8010A /* OpenFileDataSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = OpenFileDataSource.h; sourceTree = ""; }; - F59481B203D077DC01A8010A /* OpenFileDataSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = OpenFileDataSource.m; sourceTree = ""; }; F59D5DE40320DFF601A8010C /* NSString-FSSpec.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "NSString-FSSpec.h"; sourceTree = ""; }; F59D5DE50320DFF601A8010C /* NSString-FSSpec.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = "NSString-FSSpec.m"; sourceTree = ""; }; F59D5DE8032106D201A8010C /* NSNumber-Range.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "NSNumber-Range.h"; sourceTree = ""; }; @@ -527,15 +535,13 @@ F5B5883B0156D40B01000001 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/InfoWindow.nib; sourceTree = ""; }; F5B5883F0156D40B01000001 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/PrefsWindow.nib; sourceTree = ""; }; F5B588410156D40B01000001 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/ResourceDocument.nib; sourceTree = ""; }; - F5B588430156D40B01000001 /* English */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + F5B588430156D40B01000001 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; lineEnding = 0; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; F5B588450156D40B01000001 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; lineEnding = 0; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; F5B588460156D40B01000001 /* ResKnife.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = ResKnife.icns; sourceTree = ""; }; F5B588470156D40B01000001 /* Resource file.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "Resource file.icns"; sourceTree = ""; }; F5B588480156D40B01000001 /* Icon file.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "Icon file.icns"; sourceTree = ""; }; F5B5884A0156D40B01000001 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; F5B5884B0156D40B01000001 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - F5B5884C0156D40B01000001 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - F5B5884D0156D40B01000001 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; F5B5887D0156D6D901000001 /* Carbon Prefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "Carbon Prefix.h"; sourceTree = ""; }; F5B5887E0156D6D901000001 /* Classic Prefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "Classic Prefix.h"; sourceTree = ""; }; F5B588800156D6D901000001 /* Transfer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Transfer.h; sourceTree = ""; }; @@ -744,6 +750,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E17753350E424F0C00F737F8 /* Carbon.framework in Frameworks */, + E17753E40E42534300F737F8 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -778,7 +786,7 @@ 3D0B38A504DEF41E005AED5E /* Template Editor */ = { isa = PBXGroup; children = ( - 3D0ABFB904E152CA00C85300 /* TEMPLATE EDITOR.txt */, + 3D0ABFB904E152CA00C85300 /* Read Me.txt */, 3D0B38B204DEF41E005AED5E /* NuTemplateWindowController.h */, 3D0B38B304DEF41E005AED5E /* NuTemplateWindowController.m */, 3D0933A604DEFEE600DD74B1 /* NuTemplateElement.h */, @@ -788,9 +796,7 @@ 3D0933BE04DF151C00DD74B1 /* NuTemplateStream.h */, 3D0933BF04DF151C00DD74B1 /* NuTemplateStream.m */, 3D0933EB04DF319F00DD74B1 /* Field Types */, - E1B2A5850E41103A00A72928 /* Info.plist */, - 3D2EE5E204E5C56F00515930 /* Localizable.strings */, - 3D0B38B504DEF465005AED5E /* NuTemplateWindow.nib */, + E17753870E4251C600F737F8 /* Resources */, ); name = "Template Editor"; path = NuTemplateEditor; @@ -808,14 +814,36 @@ path = "Template Editor"; sourceTree = ""; }; + E17752310E424BAB00F737F8 /* Categories */ = { + isa = PBXGroup; + children = ( + E17752320E424BAB00F737F8 /* NSData-HexRepresentation.h */, + E17752330E424BAB00F737F8 /* NSData-HexRepresentation.m */, + ); + path = Categories; + sourceTree = ""; + }; + E17753870E4251C600F737F8 /* Resources */ = { + isa = PBXGroup; + children = ( + E1B2A5850E41103A00A72928 /* Info.plist */, + 3D2EE5E204E5C56F00515930 /* Localizable.strings */, + E17753880E4251C600F737F8 /* DisplayTMPL.png */, + E17753890E4251C600F737F8 /* Templates.rsrc */, + E177538A0E4251C600F737F8 /* TMPLs.rsrc */, + 3D0B38B504DEF465005AED5E /* NuTemplateWindow.nib */, + ); + path = Resources; + sourceTree = ""; + }; E1B2A7340E41218F00A72928 /* Font Editor */ = { isa = PBXGroup; children = ( E1B2A73C0E41218F00A72928 /* FontWindowController.h */, E1B2A73D0E41218F00A72928 /* FontWindowController.m */, - E1B2A73B0E41218F00A72928 /* Font Templates.rsrc */, E1B2A73E0E41218F00A72928 /* Info.plist */, E1B2A7390E41218F00A72928 /* Localizable.strings */, + E1B2A73B0E41218F00A72928 /* Font Templates.rsrc */, E1B2A7350E41218F00A72928 /* FontDocument.nib */, E1B2A7370E41218F00A72928 /* FontWindow.nib */, ); @@ -902,9 +930,10 @@ F5502C4001C579FF01C57124 /* ResKnifePluginProtocol.h */, F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */, F5EF839F020C08E601A80001 /* Hex Editor */, - E1B2A7340E41218F00A72928 /* Font Editor */, - 3D3B99B704DC167D0056861E /* Bitmap Editor */, 3D0B38A504DEF41E005AED5E /* Template Editor */, + 3D3B99B704DC167D0056861E /* Bitmap Editor */, + E1B2A7340E41218F00A72928 /* Font Editor */, + F5DF1C0F0254C78801A80001 /* NovaTools */, F5354435022673C101A80001 /* Template Editor (Abandoned) */, ); path = "Plug-Ins"; @@ -929,7 +958,6 @@ F5B5881A0156D40B01000001 /* Cocoa */, F5B5887F0156D6D901000001 /* Carbon */, F5EA10690254A7B401A80001 /* External */, - F5DF1C0F0254C78801A80001 /* NovaTools */, F5B588490156D40B01000001 /* Frameworks */, F5B588110156D30301000001 /* Products */, E1B2A4C30E41103800A72928 /* Info-ResKnife_Carbon__Upgraded_.plist */, @@ -987,8 +1015,8 @@ F5B588260156D40B01000001 /* InfoWindowController.m */, F5B588270156D40B01000001 /* NameFormatter.h */, F5B588280156D40B01000001 /* NameFormatter.m */, - F59481B103D077DC01A8010A /* OpenFileDataSource.h */, - F59481B203D077DC01A8010A /* OpenFileDataSource.m */, + E177526E0E424DCB00F737F8 /* OpenPanelDelegate.h */, + E177526D0E424DCB00F737F8 /* OpenPanelDelegate.m */, F5B588290156D40B01000001 /* OutlineViewDelegate.h */, F5B5882A0156D40B01000001 /* OutlineViewDelegate.m */, F5F1071603CCC61E01A8010A /* PasteboardDocument.h */, @@ -1050,11 +1078,7 @@ isa = PBXGroup; children = ( F5B5884A0156D40B01000001 /* Carbon.framework */, - F54625C6029174F601A8010C /* CoreServices.framework */, - F54626490291750201A8010C /* ApplicationServices.framework */, F5B5884B0156D40B01000001 /* Cocoa.framework */, - F5B5884C0156D40B01000001 /* AppKit.framework */, - F5B5884D0156D40B01000001 /* Foundation.framework */, ); name = Frameworks; sourceTree = ""; @@ -1251,7 +1275,8 @@ F58A183F0278353501A8010C /* Aux Support */, F51FB38E0256057F01A80001 /* Resources */, ); - path = NovaTools; + name = NovaTools; + path = ../../NovaTools; sourceTree = ""; }; F5EA10690254A7B401A80001 /* External */ = { @@ -1276,6 +1301,7 @@ F5EF83A7020C08E601A80001 /* HexWindowController.h */, F5EF83A8020C08E601A80001 /* HexWindowController.m */, E1B2A4560E41103800A72928 /* Info.plist */, + E17752310E424BAB00F737F8 /* Categories */, F5EF83C7020C20D701A80001 /* HexWindow.nib */, F5606FDD02ACF2F701A8010C /* PasteMenu.nib */, F54E6222021B6A0801A80001 /* FindSheet.nib */, @@ -1310,24 +1336,10 @@ E1B2A3FB0E41103700A72928 /* PasteboardDocument.h in Headers */, E1B2A3FC0E41103700A72928 /* PasteboardWindowController.h in Headers */, E1B2A3FD0E41103700A72928 /* RKDocumentController.h in Headers */, - E1B2A3FE0E41103700A72928 /* OpenFileDataSource.h in Headers */, E1B2A3FF0E41103700A72928 /* RKEditorRegistry.h in Headers */, E1B2A4000E41103700A72928 /* RKSupportResourceRegistry.h in Headers */, E1B2A7770E41230E00A72928 /* NGSCategories.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E1B2A43F0E41103800A72928 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E1B2A4400E41103800A72928 /* ResKnifeResourceProtocol.h in Headers */, - E1B2A4410E41103800A72928 /* ResKnifePluginProtocol.h in Headers */, - E1B2A4420E41103800A72928 /* HexEditorDelegate.h in Headers */, - E1B2A4430E41103800A72928 /* HexTextView.h in Headers */, - E1B2A4440E41103800A72928 /* HexWindowController.h in Headers */, - E1B2A4450E41103800A72928 /* FindSheetController.h in Headers */, - E1B2A7790E41230E00A72928 /* NGSCategories.h in Headers */, + E17752700E424DCB00F737F8 /* OpenPanelDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1340,27 +1352,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E1B2A46B0E41103800A72928 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E1B2A46C0E41103800A72928 /* HostCallbacks.h in Headers */, - E1B2A46D0E41103800A72928 /* BoomWindowController.h in Headers */, - E1B2A46E0E41103800A72928 /* NovaWindowController.h in Headers */, - E1B2A46F0E41103800A72928 /* CharWindowController.h in Headers */, - E1B2A4700E41103800A72928 /* ColrWindowController.h in Headers */, - E1B2A4710E41103800A72928 /* CronWindowController.h in Headers */, - E1B2A4720E41103800A72928 /* DescWindowController.h in Headers */, - E1B2A4730E41103800A72928 /* ResKnifeResourceProtocol.h in Headers */, - E1B2A4740E41103800A72928 /* ResKnifePluginProtocol.h in Headers */, - E1B2A4750E41103800A72928 /* DescSplitViewDelegate.h in Headers */, - E1B2A4760E41103800A72928 /* DataSource.h in Headers */, - E1B2A4770E41103800A72928 /* Structs.h in Headers */, - E1B2A4780E41103800A72928 /* NSNumber-Range.h in Headers */, - E1B2A77F0E41230E00A72928 /* NGSCategories.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; E1B2A4960E41103800A72928 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -1460,40 +1451,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E1B2A54A0E41103A00A72928 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E1B2A54B0E41103A00A72928 /* ResKnifePluginProtocol.h in Headers */, - E1B2A54C0E41103A00A72928 /* ResKnifeResourceProtocol.h in Headers */, - E1B2A54D0E41103A00A72928 /* ICONWindowController.h in Headers */, - E1B2A77D0E41230E00A72928 /* NGSCategories.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E1B2A55C0E41103A00A72928 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E1B2A55D0E41103A00A72928 /* NuTemplateWindowController.h in Headers */, - E1B2A55E0E41103A00A72928 /* ResKnifePluginProtocol.h in Headers */, - E1B2A55F0E41103A00A72928 /* ResKnifeResourceProtocol.h in Headers */, - E1B2A5600E41103A00A72928 /* NuTemplateElement.h in Headers */, - E1B2A5610E41103A00A72928 /* NuTemplateGroupElement.h in Headers */, - E1B2A5620E41103A00A72928 /* NuTemplateStream.h in Headers */, - E1B2A5630E41103A00A72928 /* NuTemplateLSTBElement.h in Headers */, - E1B2A5640E41103A00A72928 /* NuTemplateTNAMElement.h in Headers */, - E1B2A5650E41103A00A72928 /* NuTemplatePSTRElement.h in Headers */, - E1B2A5660E41103A00A72928 /* NuTemplateDWRDElement.h in Headers */, - E1B2A5670E41103A00A72928 /* NuTemplateLSTEElement.h in Headers */, - E1B2A5680E41103A00A72928 /* NuTemplateDLNGElement.h in Headers */, - E1B2A5690E41103A00A72928 /* NuTemplateDBYTElement.h in Headers */, - E1B2A56A0E41103A00A72928 /* NuTemplateOCNTElement.h in Headers */, - E1B2A56B0E41103A00A72928 /* NuTemplateLSTCElement.h in Headers */, - E1B2A77B0E41230E00A72928 /* NGSCategories.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -1513,6 +1470,8 @@ dependencies = ( E1B2A5880E41103A00A72928 /* PBXTargetDependency */, E1B2A5900E41103A00A72928 /* PBXTargetDependency */, + E17753B20E42526500F737F8 /* PBXTargetDependency */, + E17753B40E42526F00F737F8 /* PBXTargetDependency */, ); name = "ResKnife Cocoa"; productInstallPath = "$(USER_APPS_DIR)"; @@ -1524,7 +1483,6 @@ isa = PBXNativeTarget; buildConfigurationList = E1B2A4530E41103800A72928 /* Build configuration list for PBXNativeTarget "Hex Editor Cocoa" */; buildPhases = ( - E1B2A43F0E41103800A72928 /* Headers */, E1B2A4460E41103800A72928 /* Resources */, E1B2A44A0E41103800A72928 /* Sources */, E1B2A4500E41103800A72928 /* Frameworks */, @@ -1563,11 +1521,9 @@ isa = PBXNativeTarget; buildConfigurationList = E1B2A4900E41103800A72928 /* Build configuration list for PBXNativeTarget "NovaTools" */; buildPhases = ( - E1B2A46B0E41103800A72928 /* Headers */, E1B2A4790E41103800A72928 /* Resources */, E1B2A4810E41103800A72928 /* Sources */, E1B2A48C0E41103800A72928 /* Frameworks */, - E1B2A48F0E41103800A72928 /* Rez */, ); buildRules = ( ); @@ -1701,11 +1657,9 @@ isa = PBXNativeTarget; buildConfigurationList = E1B2A5560E41103A00A72928 /* Build configuration list for PBXNativeTarget "Bitmap Editor Cocoa" */; buildPhases = ( - E1B2A54A0E41103A00A72928 /* Headers */, E1B2A54E0E41103A00A72928 /* Resources */, E1B2A5500E41103A00A72928 /* Sources */, E1B2A5530E41103A00A72928 /* Frameworks */, - E1B2A5550E41103A00A72928 /* Rez */, ); buildRules = ( ); @@ -1721,11 +1675,10 @@ isa = PBXNativeTarget; buildConfigurationList = E1B2A5820E41103A00A72928 /* Build configuration list for PBXNativeTarget "Template Editor Cocoa" */; buildPhases = ( - E1B2A55C0E41103A00A72928 /* Headers */, E1B2A56C0E41103A00A72928 /* Resources */, + E17753850E4250CA00F737F8 /* Copy Support Resources */, E1B2A5700E41103A00A72928 /* Sources */, E1B2A57F0E41103A00A72928 /* Frameworks */, - E1B2A5810E41103A00A72928 /* Rez */, ); buildRules = ( E1B2A5980E41103D00A72928 /* PBXBuildRule */, @@ -1744,6 +1697,7 @@ buildConfigurationList = E1B2A7260E41213400A72928 /* Build configuration list for PBXNativeTarget "Font Editor Cocoa" */; buildPhases = ( E1B2A71E0E41213300A72928 /* Resources */, + E177539C0E42520800F737F8 /* Copy Support Resources */, E1B2A71F0E41213300A72928 /* Sources */, E1B2A7200E41213300A72928 /* Frameworks */, ); @@ -1898,6 +1852,7 @@ files = ( E1B2A56D0E41103A00A72928 /* NuTemplateWindow.nib in Resources */, E1B2A56F0E41103A00A72928 /* Localizable.strings in Resources */, + E177538B0E4251C600F737F8 /* DisplayTMPL.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1908,7 +1863,6 @@ E1B2A73F0E41218F00A72928 /* FontDocument.nib in Resources */, E1B2A7400E41218F00A72928 /* FontWindow.nib in Resources */, E1B2A7410E41219000A72928 /* Localizable.strings in Resources */, - E1B2A7420E41219000A72928 /* Font Templates.rsrc in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1936,13 +1890,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E1B2A48F0E41103800A72928 /* Rez */ = { - isa = PBXRezBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; E1B2A4BD0E41103800A72928 /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; @@ -1989,20 +1936,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E1B2A5550E41103A00A72928 /* Rez */ = { - isa = PBXRezBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E1B2A5810E41103A00A72928 /* Rez */ = { - isa = PBXRezBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -2029,11 +1962,11 @@ E1B2A42D0E41103700A72928 /* PasteboardDocument.m in Sources */, E1B2A42E0E41103700A72928 /* PasteboardWindowController.m in Sources */, E1B2A42F0E41103700A72928 /* RKDocumentController.m in Sources */, - E1B2A4300E41103700A72928 /* OpenFileDataSource.m in Sources */, E1B2A4310E41103700A72928 /* main.m in Sources */, E1B2A4320E41103700A72928 /* RKEditorRegistry.m in Sources */, E1B2A4330E41103700A72928 /* RKSupportResourceRegistry.m in Sources */, E1B2A7780E41230E00A72928 /* NGSCategories.m in Sources */, + E177526F0E424DCB00F737F8 /* OpenPanelDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2047,6 +1980,7 @@ E1B2A44E0E41103800A72928 /* FindSheetController.m in Sources */, E1B2A44F0E41103800A72928 /* Notifications.m in Sources */, E1B2A77A0E41230E00A72928 /* NGSCategories.m in Sources */, + E17752350E424BAB00F737F8 /* NSData-HexRepresentation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2204,12 +2138,23 @@ files = ( E1B2A7430E41219000A72928 /* FontWindowController.m in Sources */, E1B2A7760E41230E00A72928 /* NGSCategories.m in Sources */, + E17752760E424ED400F737F8 /* Notifications.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + E17753B20E42526500F737F8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E1B2A7210E41213300A72928 /* Font Editor Cocoa */; + targetProxy = E17753B10E42526500F737F8 /* PBXContainerItemProxy */; + }; + E17753B40E42526F00F737F8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E1B2A46A0E41103800A72928 /* NovaTools */; + targetProxy = E17753B30E42526F00F737F8 /* PBXContainerItemProxy */; + }; E1B2A5880E41103A00A72928 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = E1B2A43E0E41103800A72928 /* Hex Editor Cocoa */; @@ -2229,6 +2174,7 @@ 3D0B38B604DEF465005AED5E /* English */, ); name = NuTemplateWindow.nib; + path = ..; sourceTree = ""; }; 3D3B99BC04DC16FC0056861E /* ICONWindow.nib */ = { @@ -2444,19 +2390,17 @@ 84A45AA60E410BAD008598FD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = com.apple.compilers.llvmgcc42; - MACOSX_DEPLOYMENT_TARGET = 10.1; }; name = Debug; }; 84A45AA70E410BAD008598FD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = c99; GCC_VERSION = com.apple.compilers.llvmgcc42; - MACOSX_DEPLOYMENT_TARGET = 10.1; }; name = Release; }; @@ -2470,7 +2414,6 @@ GCC_PREFIX_HEADER = "Prefix Files/C99 Prefix.h"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; INFOPLIST_FILE = Cocoa/Info.plist; - OTHER_LDFLAGS = ""; PREBINDING = NO; PRODUCT_NAME = "ResKnife Cocoa"; PROFILING_CODE = YES; @@ -2493,7 +2436,6 @@ GCC_PREFIX_HEADER = "Prefix Files/C99 Prefix.h"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; INFOPLIST_FILE = Cocoa/Info.plist; - OTHER_LDFLAGS = ""; PREBINDING = NO; PRODUCT_NAME = "ResKnife Cocoa"; PROFILING_CODE = YES;