From 972ca4dde46f578cc44dd863af3aa735ce426dd1 Mon Sep 17 00:00:00 2001 From: Nicholas Shanks Date: Tue, 31 Aug 2010 10:01:42 +0000 Subject: [PATCH] Removal of the ObjC++ files and merging their differences into the ObjC versions. --- Cocoa/Categories/NGSCategories.m | 12 +- Cocoa/Classes/ApplicationDelegate.m | 2 +- Cocoa/Classes/CreateResourceSheetController.m | 8 +- Cocoa/Classes/InfoWindowController.m | 2 - Cocoa/Classes/OutlineViewDelegate.m | 14 +- Cocoa/Classes/RKEditorRegistry.m | 4 +- Cocoa/Classes/RKSupportResourceRegistry.m | 6 +- Cocoa/Classes/RKSupportResourceRegistry.mm | 25 - Cocoa/Classes/Resource.h | 1 - Cocoa/Classes/Resource.m | 4 +- Cocoa/Classes/ResourceDataSource.mm | 247 ---- Cocoa/Classes/ResourceDocument.m | 75 +- Cocoa/Classes/ResourceDocument.mm | 1244 ----------------- Cocoa/English.lproj/InfoPlist.strings | Bin 594 -> 594 bytes .../Font Editor/FontWindowController.mm | 2 +- Cocoa/Plug-Ins/Hex Editor/HexTextView.m | 2 +- Cocoa/Plug-Ins/Notifications.m | 26 +- Cocoa/Plug-Ins/ResKnifeResourceProtocol.h | 2 + External/MoreFilesX/MoreFilesX.c | 1 + NovaTools/boom/BoomWindowController.h | 2 +- NovaTools/boom/BoomWindowController.m | 4 +- README.txt | 2 +- ResKnife.xcodeproj/project.pbxproj | 40 +- 23 files changed, 120 insertions(+), 1605 deletions(-) delete mode 100644 Cocoa/Classes/RKSupportResourceRegistry.mm delete mode 100644 Cocoa/Classes/ResourceDataSource.mm delete mode 100644 Cocoa/Classes/ResourceDocument.mm diff --git a/Cocoa/Categories/NGSCategories.m b/Cocoa/Categories/NGSCategories.m index a9b3f36..f123c26 100644 --- a/Cocoa/Categories/NGSCategories.m +++ b/Cocoa/Categories/NGSCategories.m @@ -208,11 +208,21 @@ } - (NSArray *)selectedItems; { - NSNumber *row; NSMutableArray *items = [NSMutableArray array]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 + NSIndexSet *indicies = [self selectedRowIndexes]; + unsigned int rowIndex = [indicies firstIndex]; + while (rowIndex != NSNotFound) + { + [items addObject:[self itemAtRow:rowIndex]]; + rowIndex = [indicies indexGreaterThanIndex:rowIndex]; + } +#else + NSNumber *row; NSEnumerator *enumerator = [self selectedRowEnumerator]; while(row = [enumerator nextObject]) [items addObject:[self itemAtRow:[row intValue]]]; +#endif return items; } @end diff --git a/Cocoa/Classes/ApplicationDelegate.m b/Cocoa/Classes/ApplicationDelegate.m index 3a938cc..f0cb209 100644 --- a/Cocoa/Classes/ApplicationDelegate.m +++ b/Cocoa/Classes/ApplicationDelegate.m @@ -31,7 +31,7 @@ /*! @method awakeFromNib -@change 2003-10-24 NGS: moved icon caching into method called by timer (to speed up app launch time) +@updated 2003-10-24 NGS: moved icon caching into method called by timer (to speed up app launch time) */ - (void)awakeFromNib diff --git a/Cocoa/Classes/CreateResourceSheetController.m b/Cocoa/Classes/CreateResourceSheetController.m index aeae93f..4787956 100644 --- a/Cocoa/Classes/CreateResourceSheetController.m +++ b/Cocoa/Classes/CreateResourceSheetController.m @@ -8,8 +8,8 @@ /*! @method controlTextDidChange: @abstract Handles updating of the 'Create' button when valid values are present in the sheet's fields. -@change 2003-08-01 UK: Changed to use data source's resourceOfType instead of directly messing with the resource list's enumerator. -@change 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 :) +@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. */ @@ -32,8 +32,8 @@ /*! @method showCreateResourceSheet: @abstract Shows the sheet allowing the user to define the properties of a new resource. -@change 2003-08-01 UK: Made it "fake" a popup selection so type field and popup match. -@change 2003-08-01 UK: Made it suggest an unused resource ID. +@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. */ - (void)showCreateResourceSheet:(ResourceDocument *)sheetDoc diff --git a/Cocoa/Classes/InfoWindowController.m b/Cocoa/Classes/InfoWindowController.m index 1e19602..5053476 100644 --- a/Cocoa/Classes/InfoWindowController.m +++ b/Cocoa/Classes/InfoWindowController.m @@ -48,8 +48,6 @@ if(selectedResource) { - NSLog(@"selected resource data: %@", [selectedResource data]); - // set UI values [[self window] setTitle:NSLocalizedString(@"Resource Info",nil)]; [nameView setStringValue:[selectedResource name]]; diff --git a/Cocoa/Classes/OutlineViewDelegate.m b/Cocoa/Classes/OutlineViewDelegate.m index be7fdd6..efae584 100644 --- a/Cocoa/Classes/OutlineViewDelegate.m +++ b/Cocoa/Classes/OutlineViewDelegate.m @@ -56,7 +56,7 @@ /*! @function compareResourcesAscending -@change 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare +@updated 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare */ int compareResourcesAscending(Resource *r1, Resource *r2, void *context) @@ -71,7 +71,7 @@ int compareResourcesAscending(Resource *r1, Resource *r2, void *context) /*! @function compareResourcesDescending -@change 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare +@updated 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare */ int compareResourcesDescending(Resource *r1, Resource *r2, void *context) @@ -93,13 +93,13 @@ int compareResourcesDescending(Resource *r1, Resource *r2, void *context) /*! @method outlineView:willDisplayCell:forTableColumn:item: -@change 2003-10-25 NGS: Moved functionality of NameFormatter into this method, removed NameFormatter class. -@change 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. -@change 2003-10-24 NGS: Added iconForResourceType method to app delegate instead of interrogating the cache here. +@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 *)olView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { Resource *resource = (Resource *)item; NSString *identifier = [tableColumn identifier]; @@ -161,7 +161,7 @@ int compareResourcesDescending(Resource *r1, Resource *r2, void *context) // draw alternating blue/white backgrounds (if pre-10.3) if(NSAppKitVersionNumber < 700.0) { - int row = [olView rowForItem:item]; + 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]; diff --git a/Cocoa/Classes/RKEditorRegistry.m b/Cocoa/Classes/RKEditorRegistry.m index cc2e0e3..f2573c9 100644 --- a/Cocoa/Classes/RKEditorRegistry.m +++ b/Cocoa/Classes/RKEditorRegistry.m @@ -44,7 +44,7 @@ @method +defaultRegistry @author Uli Kusterer @created 2003-07-31 -@change 2003-10-28 NS: Changed method name from +mainRegistry (so it more closly matchs +defaultCenter) and moved global var inside method, making it a static. +@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 @@ -74,7 +74,7 @@ @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 -@change 2003-10-28 NGS: Updated to look for more sophisticated RKSupportedTypes key in addition to (the now deprecated) RKEditedTypes. +@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 diff --git a/Cocoa/Classes/RKSupportResourceRegistry.m b/Cocoa/Classes/RKSupportResourceRegistry.m index a8b367a..61cb0e4 100644 --- a/Cocoa/Classes/RKSupportResourceRegistry.m +++ b/Cocoa/Classes/RKSupportResourceRegistry.m @@ -1,14 +1,14 @@ #import "RKSupportResourceRegistry.h" -#import "NGSCategories.h" +#import "../Categories/NGSCategories.h" @implementation RKSupportResourceRegistry + (void)scanForSupportResources { - // TODO: Instead of hard-coding sysPath we should use some FindFolder-like API! #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"]; + // FIXME: log content of dirsArray and merge with the following: #endif [RKSupportResourceRegistry scanForSupportResourcesInFolder:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Support Resources"]]; [RKSupportResourceRegistry scanForSupportResourcesInFolder:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/ResKnife/Support Resources"]]; @@ -25,7 +25,7 @@ { // 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; + // FIXME: this method was deprecated 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/RKSupportResourceRegistry.mm b/Cocoa/Classes/RKSupportResourceRegistry.mm deleted file mode 100644 index 855493d..0000000 --- a/Cocoa/Classes/RKSupportResourceRegistry.mm +++ /dev/null @@ -1,25 +0,0 @@ -#import "RKSupportResourceRegistry.h" - -@implementation RKSupportResourceRegistry - -+ (void)scanForSupportResources -{ - // TODO: Instead of hard-coding sysPath we should use some FindFolder-like API! - [RKSupportResourceRegistry scanForSupportResourcesInFolder:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Support Resources"]]; - [RKSupportResourceRegistry scanForSupportResourcesInFolder:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/ResKnife/Support Resources/"]]; - [RKSupportResourceRegistry scanForSupportResourcesInFolder:[@"/" stringByAppendingPathComponent:@"Library/Application Support/ResKnife/Support Resources/"]]; -} - -+ (void)scanForSupportResourcesInFolder:(NSString *)path -{ -// NSLog(@"Looking for resources in %@", path); - NSEnumerator *enumerator = [[[NSFileManager defaultManager] directoryContentsAtPath:path] objectEnumerator]; - while(NSString *name = [enumerator nextObject]) - { -// NSLog(@"Examining %@", name); - if([[name pathExtension] isEqualToString:@"rsrc"]) - [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:[path stringByAppendingPathComponent:name] display:YES]; - } -} - -@end diff --git a/Cocoa/Classes/Resource.h b/Cocoa/Classes/Resource.h index 6108f19..596e242 100644 --- a/Cocoa/Classes/Resource.h +++ b/Cocoa/Classes/Resource.h @@ -8,7 +8,6 @@ @description The Resource class fully complies with key-value coding, with the keys @"name", @"type", @"resID", @"attributes", @"data", @"dirty" and @"representedFork" available. */ -@class ResourceDocument; @interface Resource : NSObject { @private diff --git a/Cocoa/Classes/Resource.m b/Cocoa/Classes/Resource.m index 6bf78c7..7c41543 100644 --- a/Cocoa/Classes/Resource.m +++ b/Cocoa/Classes/Resource.m @@ -90,7 +90,7 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; return [NSArray arrayWithArray:array]; } -+ (id)resourceOfType:(NSString *)typeValue withName:(NSString *)nameValue inDocument:(NSDocument *)searchDoc ++ (Resource *)resourceOfType:(NSString *)typeValue withName:(NSString *)nameValue inDocument:(NSDocument *)searchDoc { NSDocument *doc; NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; @@ -106,7 +106,7 @@ NSString *RKResourcePboardType = @"RKResourcePboardType"; return nil; } -+ (id)resourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue inDocument:(NSDocument *)searchDoc ++ (Resource *)resourceOfType:(NSString *)typeValue andID:(NSNumber *)resIDValue inDocument:(NSDocument *)searchDoc { NSDocument *doc; NSEnumerator *enumerator = [[[NSDocumentController sharedDocumentController] documents] objectEnumerator]; diff --git a/Cocoa/Classes/ResourceDataSource.mm b/Cocoa/Classes/ResourceDataSource.mm deleted file mode 100644 index 64b5cc7..0000000 --- a/Cocoa/Classes/ResourceDataSource.mm +++ /dev/null @@ -1,247 +0,0 @@ -#import "ResourceDataSource.h" -#import "ResourceDocument.h" -#import "Resource.h" -#import - -NSString *DataSourceWillAddResourceNotification = @"DataSourceWillAddResource"; -NSString *DataSourceDidAddResourceNotification = @"DataSourceDidAddResource"; -NSString *DataSourceWillRemoveResourceNotification = @"DataSourceWillRemoveResource"; -NSString *DataSourceDidRemoveResourceNotification = @"DataSourceDidRemoveResource"; - -extern NSString *RKResourcePboardType; - -@implementation ResourceDataSource - -- (id)init -{ - self = [super init]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceDidChange:) name:ResourceDidChangeNotification object:nil]; - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; -} - -- (NSWindow *)window -{ - return window; -} - -- (NSArray *)resources -{ - return resources; -} - -- (void)setResources:(NSMutableArray *)newResources -{ - id old = resources; - resources = [newResources retain]; - [old release]; - [outlineView reloadData]; -} - -- (void)addResource:(Resource *)resource -{ - NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:self, @"DataSource", resource, @"Resource", nil]; - [[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 hundreds of times upon load - [resources addObject:resource]; - [outlineView reloadData]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DataSourceDidAddResourceNotification object:dictionary]; - [[document undoManager] registerUndoWithTarget:self selector:@selector(removeResource:) object:resource]; // undo action name set by calling function -} - -- (void)removeResource:(Resource *)resource -{ - NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:self, @"DataSource", resource, @"Resource", nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:DataSourceWillRemoveResourceNotification object:dictionary]; - - // see comments in addResource: about inefficiency of reloadData - [resources removeObjectIdenticalTo:resource]; - [outlineView reloadData]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DataSourceDidRemoveResourceNotification object:dictionary]; - [[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 -} - -- (void)resourceDidChange:(NSNotification *)notification -{ - // reload the data for the changed resource - [outlineView reloadItem:[notification object]]; -} - -/* Data source protocol implementation */ - -- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item -{ - #pragma unused(outlineView, item) - return [resources objectAtIndex:index]; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item -{ - #pragma unused(outlineView, item) - return NO; -} - -- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item -{ - #pragma unused(outlineView, item) - return [resources count]; -} - -- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item -{ - #pragma unused(outlineView) - return [item valueForKey:[tableColumn identifier]]; -} - -- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item -{ - #pragma unused(outlineView) - NSString *identifier = [tableColumn 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]) - { - if(resID && [[resource resID] isEqualToNumber:resID] && type && [[resource type] isEqualToString:type]) - return resource; - } - return nil; -} - -- (Resource *)resourceOfType:(NSString *)type withName:(NSString *)name -{ - Resource *resource; - NSEnumerator *enumerator = [resources objectEnumerator]; - while(resource = [enumerator nextObject]) - { - if([[resource name] isEqualToString:name] && [[resource type] isEqualToString:type]) - return resource; - } - return nil; -} - -- (NSArray *)allResourcesOfType:(NSString *)type -{ - Resource *resource; - NSMutableArray *array = [NSMutableArray array]; - NSEnumerator *enumerator = [resources objectEnumerator]; - while(resource = [enumerator nextObject]) - { - 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:. -@change 2003-08-01 UK Created based on allResourcesOfType: -*/ - -- (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]) - { - 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. -@change 2003-08-01 UK Created. -@change 2003-10-21 NS Changed to obtain initial ID from -[resource defaultIDForType:], so we can vary it on a pre-resource-type basis (like Resourcerer can) -*/ - -- (NSNumber *)uniqueIDForType:(NSString *)type -{ - short theID = [[self defaultIDForType:type] shortValue]; - NSArray *array = [self allResourceIDsOfType:type]; - - if([array count] <= USHRT_MAX) - { - 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 *)olView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)childIndex -{ - if([info draggingSource] != olView) - { - [olView 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.m b/Cocoa/Classes/ResourceDocument.m index c4d405d..45a43a7 100644 --- a/Cocoa/Classes/ResourceDocument.m +++ b/Cocoa/Classes/ResourceDocument.m @@ -8,7 +8,7 @@ #import "InfoWindowController.h" #import "PrefsWindowController.h" #import "CreateResourceSheetController.h" -#import "NGSCategories.h" +#import "../Categories/NGSCategories.h" #import "../Categories/NSString-FSSpec.h" #import "../Categories/NSOutlineView-SelectedItems.h" @@ -82,7 +82,7 @@ extern NSString *RKResourcePboardType; { // get selected fork from open panel, 10.3+ int row = [[openPanelDelegate forkTableView] selectedRow]; - NSString *selectedFork = [(NSDictionary *)[[openPanelDelegate forks] objectAtIndex:row] valueForKey:@"forkname"]; + NSString *selectedFork = [(NSDictionary *)[[openPanelDelegate forks] objectAtIndex:row] objectForKey:@"forkname"]; fork = (HFSUniStr255 *) NewPtrClear(sizeof(HFSUniStr255)); fork->length = ([selectedFork length] < 255)? [selectedFork length]:255; if(fork->length > 0) @@ -125,13 +125,13 @@ extern NSString *RKResourcePboardType; 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"]; + NSNumber *fAlloc = [[forks firstObjectReturningValue:[NSString stringWithCharacters:fork->unicode length:fork->length] forKey:@"forkname"] objectForKey:@"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"]; + fAlloc = [[forks firstObjectReturningValue:[NSString stringWithCharacters:fork->unicode length:fork->length] forKey:@"forkname"] objectForKey:@"forkallocation"]; if([fAlloc unsignedLongLongValue] > 0) { // resource fork is not empty either, give up (ask user for a fork?) @@ -173,7 +173,7 @@ extern NSString *RKResourcePboardType; NSString *forkName; NSEnumerator *forkEnumerator = [forks objectEnumerator]; NSString *selectedFork = [NSString stringWithCharacters:fork->unicode length:fork->length]; - while(forkName = [[forkEnumerator nextObject] valueForKey:@"forkname"]) + while(forkName = [[forkEnumerator nextObject] objectForKey:@"forkname"]) { // check current fork is not the fork we're going to parse if(![forkName isEqualToString:selectedFork]) @@ -181,7 +181,7 @@ extern NSString *RKResourcePboardType; } // tidy up loose ends - if(fileRefNum) FSClose(fileRefNum); + if(fileRefNum) FSCloseFork(fileRefNum); DisposePtr((Ptr) fileRef); return succeeded; } @@ -212,7 +212,7 @@ extern NSString *RKResourcePboardType; 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]; + ByteCount forkLength = (ByteCount) [[[[(ApplicationDelegate *)[NSApp delegate] forksForFile:fileRef] firstObjectReturningValue:forkName forKey:@"forkname"] objectForKey:@"forksize"] unsignedLongValue]; void *buffer = malloc(forkLength); if(!buffer) return NO; @@ -251,13 +251,12 @@ extern NSString *RKResourcePboardType; 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); + ResType resTypeCode; + Get1IndType(&resTypeCode, i); + unsigned short n = Count1Resources(resTypeCode); for(unsigned short j = 1; j <= n; j++) { - Handle resourceHandle = Get1IndResource(resType, j); + Handle resourceHandle = Get1IndResource(resTypeCode, j); error = ResError(); if(error != noErr) { @@ -268,22 +267,34 @@ extern NSString *RKResourcePboardType; Str255 nameStr; short resIDShort; - GetResInfo(resourceHandle, &resIDShort, &resType, nameStr); - long sizeLong = GetResourceSizeOnDisk(resourceHandle); + GetResInfo(resourceHandle, &resIDShort, &resTypeCode, nameStr); + long sizeLong = GetResourceSizeOnDisk(resourceHandle), badSize = 0; + if (sizeLong < 0 || sizeLong > 16777215) // the max size of resource manager file is ~12 MB; I am rounding up to three bytes + { + // this only happens when opening ResEdit using the x86 binary (not under Rosetta, for example) + badSize = sizeLong; + sizeLong = EndianS32_BtoL(sizeLong); + } short attrsShort = GetResAttrs(resourceHandle); HLockHi(resourceHandle); +#if __LITTLE_ENDIAN__ + CoreEndianFlipData(kCoreEndianResourceManagerDomain, resTypeCode, resIDShort, *resourceHandle, sizeLong, true); +#endif // 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 + ResType logicalType = EndianS32_NtoB(resTypeCode); // swapped type for use as string (types are treated as numbers by the resource manager and swapped on Intel). NSString *name = [[NSString alloc] initWithBytes:&nameStr[1] length:nameStr[0] encoding:NSMacOSRomanStringEncoding]; - NSString *resType = [[NSString alloc] initWithBytes:(char *) &swappedType length:4 encoding:NSMacOSRomanStringEncoding]; + NSString *resType = [[NSString alloc] initWithBytes:(char *) &logicalType 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 + if (badSize != 0) + NSLog(@"GetResourceSizeOnDisk() reported incorrect size for %@ resource %@ in %@: %li should be %li", resType, resID, [self displayName], badSize, sizeLong); [name release]; [resType release]; @@ -298,8 +309,8 @@ extern NSString *RKResourcePboardType; } /*! -@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! +@pending Uli has 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 @@ -348,7 +359,7 @@ extern NSString *RKResourcePboardType; succeeded = [self writeResourceMap:fileRefNum]; // tidy up loose ends - if(fileRefNum) FSClose(fileRefNum); + if(fileRefNum) FSCloseFork(fileRefNum); DisposePtr((Ptr) fileRef); // update info window @@ -386,7 +397,7 @@ extern NSString *RKResourcePboardType; 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); + if(forkRefNum) FSCloseFork(forkRefNum); } DisposePtr((Ptr) fileRef); return YES; @@ -410,32 +421,39 @@ extern NSString *RKResourcePboardType; while(resource = [enumerator nextObject]) { Str255 nameStr; - char resType[5]; // includes null char for getCString: + ResType resTypeCode; + char resTypeStr[5]; // includes null char for getCString: short resIDShort; short attrsShort; + long sizeLong; Handle resourceHandle; // if the resource represents another fork in the file, skip it if([resource representedFork] != nil) continue; + sizeLong = [[resource data] length]; resIDShort = [[resource resID] shortValue]; attrsShort = [[resource attributes] shortValue]; - resourceHandle = NewHandleClear([[resource data] length]); + resourceHandle = NewHandleClear(sizeLong); // 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]; + [[resource type] getCString:resTypeStr maxLength:4]; + resTypeCode = CFSwapInt32HostToBig(*(ResType *)resTypeStr); // convert NSData to resource handle HLockHi(resourceHandle); [[resource data] getBytes:*resourceHandle]; +#if __LITTLE_ENDIAN__ + CoreEndianFlipData(kCoreEndianResourceManagerDomain, resTypeCode, resIDShort, *resourceHandle, sizeLong, false); +#endif HUnlock(resourceHandle); // now that everything's converted, tell the resource manager we want to create this resource - AddResource(resourceHandle, *(ResType *)resType, resIDShort, nameStr); + AddResource(resourceHandle, resTypeCode, resIDShort, nameStr); if(ResError() == addResFailed) { NSLog(@"*Saving failed*; could not add resource ID %@ of type %@ to file.", [resource resID], [resource type]); @@ -494,7 +512,6 @@ extern NSString *RKResourcePboardType; @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 @@ -530,7 +547,7 @@ extern NSString *RKResourcePboardType; // 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]) + if(newExtension = [adjustments objectForKey:extension]) extension = newExtension; // ask for data @@ -560,7 +577,7 @@ extern NSString *RKResourcePboardType; { if(returnCode == NSOKButton) { - NSUInteger i = 1; + unsigned int i = 1; Resource *resource; NSString *path, *filename, *extension; NSDictionary *adjustments = [NSDictionary dictionaryWithObjectsAndKeys: @"ttf", @"sfnt", @"png", @"PNGf", nil]; @@ -591,7 +608,7 @@ extern NSString *RKResourcePboardType; } else { - NSUInteger j = 1; + unsigned int j = 1; NSString *tempname = [filename stringByAppendingPathExtension:extension]; while ([[NSFileManager defaultManager] fileExistsAtPath:tempname]) { @@ -850,12 +867,12 @@ static NSString *RKExportItemIdentifier = @"com.nickshanks.resknife.toolbar.exp [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 { diff --git a/Cocoa/Classes/ResourceDocument.mm b/Cocoa/Classes/ResourceDocument.mm deleted file mode 100644 index bf1ac94..0000000 --- a/Cocoa/Classes/ResourceDocument.mm +++ /dev/null @@ -1,1244 +0,0 @@ -#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 "Categories.h" -#import "../Categories/NSString-FSSpec.h" -#import "../Categories/NSOutlineView-SelectedItems.h" - -#import "../Plug-Ins/ResKnifePluginProtocol.h" -#import "RKEditorRegistry.h" - - -NSString *DocumentInfoWillChangeNotification = @"DocumentInfoWillChangeNotification"; -NSString *DocumentInfoDidChangeNotification = @"DocumentInfoDidChangeNotification"; -extern NSString *RKResourcePboardType; - -@implementation ResourceDocument - -- (id)init -{ - self = [super init]; - if(!self) return nil; - toolbarItems = [[NSMutableDictionary alloc] init]; - resources = [[NSMutableArray alloc] init]; - fork = nil; - 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); - [resources release]; - [toolbarItems release]; - [type release]; - [creator release]; - [super dealloc]; -} - -#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 -@change 2003-11-08 NS: 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 - NSEnumerator *forkEnumerator = [forks objectEnumerator]; - NSString *selectedFork = [NSString stringWithCharacters:fork->unicode length:fork->length]; - while(NSString *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) FSCloseFork(fileRefNum); - DisposePtr((Ptr) fileRef); - return succeeded; -} - -/*! -@method readFork:asStreamFromFile: -@author Nicholas Shanks -@change 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 resTypeCode; - Get1IndType(&resTypeCode, i); - unsigned short n = Count1Resources(resTypeCode); - for(unsigned short j = 1; j <= n; j++) - { - Handle resourceHandle = Get1IndResource(resTypeCode, j); - error = ResError(); - if(error != noErr) - { - NSLog(@"Error %d reading resource map...", error); - UseResFile(oldResFile); - return NO; - } - - Str255 nameStr; - short resIDShort; - GetResInfo(resourceHandle, &resIDShort, &resTypeCode, nameStr); - long sizeLong = GetResourceSizeOnDisk(resourceHandle), badSize = 0; - if (sizeLong < 0 || sizeLong > 16777215) // the max size of resource manager file is ~12 MB; I am rounding up to three bytes - { - // this only happens when opening ResEdit using the x86 binary (not under Rosetta, for example) - badSize = sizeLong; - sizeLong = EndianS32_BtoL(sizeLong); - } - short attrsShort = GetResAttrs(resourceHandle); - HLockHi(resourceHandle); -#if __LITTLE_ENDIAN__ - CoreEndianFlipData(kCoreEndianResourceManagerDomain, resTypeCode, resIDShort, *resourceHandle, sizeLong, true); -#endif - - // 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 - ResType logicalType = EndianS32_NtoB(resTypeCode); // swapped type for use as string (types are treated as numbers by the resource manager and swapped on Intel). - NSString *name = [[NSString alloc] initWithBytes:&nameStr[1] length:nameStr[0] encoding:NSMacOSRomanStringEncoding]; - NSString *resType = [[NSString alloc] initWithBytes:(char *) &logicalType 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]; - [resources addObject:resource]; // array retains resource - if (badSize != 0) - NSLog(@"GetResourceSizeOnDisk() reported incorrect size for %@ resource %@ in %@: %li should be %li", resType, resID, [self displayName], badSize, sizeLong); - [name release]; - [resType release]; - - HUnlock(resourceHandle); - ReleaseResource(resourceHandle); - } - } - - // save resource map and clean up - UseResFile(oldResFile); - return YES; -} - -/*! -@pending Uli has 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) FSCloseFork(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; - } - - NSEnumerator *enumerator = [resources objectEnumerator]; - while(Resource *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) FSCloseFork(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 - NSEnumerator *enumerator = [resources objectEnumerator]; - while(Resource *resource = [enumerator nextObject]) - { - Str255 nameStr; - ResType resTypeCode; - char resTypeStr[5]; // includes null char for getCString: - short resIDShort; - short attrsShort; - long sizeLong; - Handle resourceHandle; - - // if the resource represents another fork in the file, skip it - if([resource representedFork] != nil) continue; - - sizeLong = [[resource data] length]; - resIDShort = [[resource resID] shortValue]; - attrsShort = [[resource attributes] shortValue]; - resourceHandle = NewHandleClear(sizeLong); - - // 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:resTypeStr maxLength:4]; - resTypeCode = CFSwapInt32HostToBig(*(ResType *)resTypeStr); - - // convert NSData to resource handle - HLockHi(resourceHandle); - [[resource data] getBytes:*resourceHandle]; -#if __LITTLE_ENDIAN__ - CoreEndianFlipData(kCoreEndianResourceManagerDomain, resTypeCode, resIDShort, *resourceHandle, sizeLong, false); -#endif - HUnlock(resourceHandle); - - // now that everything's converted, tell the resource manager we want to create this resource - AddResource(resourceHandle, resTypeCode, 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 -{ - Resource *current; - NSEnumerator *enumerator = [[outlineView selectedItems] objectEnumerator]; - while(current = [enumerator nextObject]) - { - [self exportResource:current]; - } -} - -/*! -@method exportResource: -@author Uli Kusterer -@change 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]; - NSSavePanel *panel; - NSString *filename; - - if([editorClass respondsToSelector:@selector(dataForFileExport:)]) - exportData = [editorClass dataForFileExport:resource]; - - if([editorClass respondsToSelector:@selector(filenameExtensionForFileExport:)]) - extension = [editorClass filenameExtensionForFileExport:resource]; - - panel = [NSSavePanel savePanel]; - filename = [[resource name] 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]; -} - -#pragma mark - -#pragma mark Window Management - -- (NSString *)windowNibName -{ - return @"ResourceDocument"; -} - -/* This is not used, just here for reference in case I need it in the future - -- (void)makeWindowControllers -{ - ResourceWindowController *resourceController = [[ResourceWindowController allocWithZone:[self zone]] initWithWindowNibName:@"ResourceDocument"]; - [self addWindowController:resourceController]; -}*/ - -- (void)windowControllerDidLoadNib:(NSWindowController *)controller -{ - [super windowControllerDidLoadNib:controller]; - [self setupToolbar:controller]; - - { // set up first column in outline view to display images as well as text - ResourceNameCell *resourceNameCell = [[[ResourceNameCell alloc] init] autorelease]; - [resourceNameCell setEditable:YES]; - [[outlineView tableColumnWithIdentifier:@"name"] setDataCell:resourceNameCell]; -// NSLog(@"Changed data cell"); - } - - // set outline view's inter-cell spacing to zero to avoid getting gaps between blue bits - [outlineView setIntercellSpacing:NSMakeSize(0,0)]; - [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]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceIDWillChange:) name:ResourceIDWillChangeNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceTypeWillChange:) name:ResourceTypeWillChangeNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resourceAttributesWillChange:) name:ResourceAttributesWillChangeNotification object:nil]; - -// [[controller window] setResizeIncrements:NSMakeSize(1,18)]; - [dataSource setResources:resources]; -} - -- (void)printShowingPrintPanel:(BOOL)flag -{ - NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:[mainWindow contentView]]; - [printOperation runOperationModalForWindow:mainWindow delegate:self didRunSelector:@selector(printOperationDidRun:success:contextInfo:) contextInfo:nil]; -} - -- (void)printOperationDidRun:(NSPrintOperation *)printOperation success:(BOOL)success contextInfo:(void *)contextInfo -{ - if(!success) NSLog(@"Printing Failed!"); -} - -- (BOOL)keepBackupFile -{ - return [[NSUserDefaults standardUserDefaults] boolForKey:@"PreserveBackups"]; -} - -- (BOOL)validateMenuItem:(NSMenuItem *)item -{ - int selectedRows = [outlineView numberOfSelectedRows]; - Resource *resource = (Resource *) [outlineView selectedItem]; - - // file menu - 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; - - // 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:)) - { - 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 return [super validateMenuItem:item]; -} - -#pragma mark - -#pragma mark Toolbar Management - -static NSString *RKToolbarIdentifier = @"com.nickshanks.resknife.toolbar"; -static NSString *RKCreateItemIdentifier = @"com.nickshanks.resknife.toolbar.create"; -static NSString *RKDeleteItemIdentifier = @"com.nickshanks.resknife.toolbar.delete"; -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.nickshanks.resknife.toolbar.export"; - -- (void)setupToolbar:(NSWindowController *)windowController -{ - /* This routine should become invalid once toolbars are integrated into nib files */ - - NSToolbarItem *item; - [toolbarItems removeAllObjects]; // just in case this method is called more than once per document (which it shouldn't be!) - - item = [[NSToolbarItem alloc] initWithItemIdentifier:RKCreateItemIdentifier]; - [item autorelease]; - [item setLabel:NSLocalizedString(@"Create", nil)]; - [item setPaletteLabel:NSLocalizedString(@"Create", nil)]; - [item setToolTip:NSLocalizedString(@"Create New Resource", nil)]; - [item setImage:[NSImage imageNamed:@"Create"]]; - [item setTarget:self]; - [item setAction:@selector(showCreateResourceSheet:)]; - [toolbarItems setObject:item forKey:RKCreateItemIdentifier]; - - item = [[NSToolbarItem alloc] initWithItemIdentifier:RKDeleteItemIdentifier]; - [item autorelease]; - [item setLabel:NSLocalizedString(@"Delete", nil)]; - [item setPaletteLabel:NSLocalizedString(@"Delete", nil)]; - [item setToolTip:NSLocalizedString(@"Delete Selected Resource", nil)]; - [item setImage:[NSImage imageNamed:@"Delete"]]; - [item setTarget:self]; - [item setAction:@selector(clear:)]; - [toolbarItems setObject:item forKey:RKDeleteItemIdentifier]; - - 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"]]; - [item setTarget:self]; - [item setAction:@selector(openResources:)]; - [toolbarItems setObject:item forKey:RKEditItemIdentifier]; - - item = [[NSToolbarItem alloc] initWithItemIdentifier:RKEditHexItemIdentifier]; - [item autorelease]; - [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"]]; - [item setTarget:self]; - [item setAction:@selector(openResourcesAsHex:)]; - [toolbarItems setObject:item forKey:RKEditHexItemIdentifier]; - - item = [[NSToolbarItem alloc] initWithItemIdentifier:RKSaveItemIdentifier]; - [item autorelease]; - [item setLabel:NSLocalizedString(@"Save", nil)]; - [item setPaletteLabel:NSLocalizedString(@"Save", nil)]; - [item setToolTip:[NSString stringWithFormat:NSLocalizedString(@"Save To %@ Fork", nil), !fork? NSLocalizedString(@"Data", nil) : NSLocalizedString(@"Resource", nil)]]; - [item setImage:[NSImage imageNamed:@"Save"]]; - [item setTarget:self]; - [item setAction:@selector(saveDocument:)]; - [toolbarItems setObject:item forKey:RKSaveItemIdentifier]; - - item = [[NSToolbarItem alloc] initWithItemIdentifier:RKShowInfoItemIdentifier]; - [item autorelease]; - [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"]]; - [item setTarget:[NSApp delegate]]; - [item setAction:@selector(showInfo:)]; - [toolbarItems setObject:item forKey:RKShowInfoItemIdentifier]; - - item = [[NSToolbarItem alloc] initWithItemIdentifier:RKExportItemIdentifier]; - [item autorelease]; - [item setLabel:NSLocalizedString(@"Export Data", nil)]; - [item setPaletteLabel:NSLocalizedString(@"Export Resource Data", nil)]; - [item setToolTip:NSLocalizedString(@"Export the resource's data to a file", nil)]; - [item setImage:[NSImage imageNamed:@"Export"]]; - [item setTarget:self]; - [item setAction:@selector(exportResources:)]; - [toolbarItems setObject:item forKey:RKExportItemIdentifier]; - - if([windowController window] == mainWindow) - { - NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:RKToolbarIdentifier] autorelease]; - - // set toolbar properties - [toolbar setVisible:YES]; - [toolbar setAutosavesConfiguration:YES]; - [toolbar setAllowsUserCustomization:YES]; - [toolbar setDisplayMode:NSToolbarDisplayModeDefault]; - - // attach toolbar to window - [toolbar setDelegate:self]; - [mainWindow setToolbar:toolbar]; - } -} - -- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag -{ - return [toolbarItems objectForKey:itemIdentifier]; -} - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar -{ - return [NSArray arrayWithObjects:RKCreateItemIdentifier, RKShowInfoItemIdentifier, RKDeleteItemIdentifier, NSToolbarSeparatorItemIdentifier, RKEditItemIdentifier, RKEditHexItemIdentifier, NSToolbarSeparatorItemIdentifier, RKSaveItemIdentifier, NSToolbarPrintItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarCustomizeToolbarItemIdentifier, nil]; -} - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar -{ - return [NSArray arrayWithObjects:RKCreateItemIdentifier, RKDeleteItemIdentifier, RKEditItemIdentifier, RKEditHexItemIdentifier, RKSaveItemIdentifier, RKExportItemIdentifier, RKShowInfoItemIdentifier, NSToolbarPrintItemIdentifier, NSToolbarCustomizeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; -} - -- (BOOL)validateToolbarItem:(NSToolbarItem *)item -{ - BOOL valid = NO; - 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; - - return valid; -} - -#pragma mark - -#pragma mark Document Management - -- (IBAction)showCreateResourceSheet:(id)sender -{ - // bug: ResourceDocument allocs a sheet controller, but it's never disposed of - CreateResourceSheetController *sheetController = [[CreateResourceSheetController alloc] initWithWindowNibName:@"CreateResourceSheet"]; - [sheetController showCreateResourceSheet:self]; -} - -- (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]) - [self openResourceUsingEditor:resource]; -} - -- (IBAction)openResourcesInTemplate:(id)sender -{ - // opens the resource in its default template - Resource *resource; - NSArray *selected = [outlineView selectedItems]; - NSEnumerator *enumerator = [selected objectEnumerator]; - while(resource = [enumerator nextObject]) - [self openResource:resource usingTemplate:[resource type]]; -} - -- (IBAction)openResourcesAsHex:(id)sender -{ - Resource *resource; - NSArray *selected = [outlineView selectedItems]; - NSEnumerator *enumerator = [selected objectEnumerator]; - while(resource = [enumerator nextObject]) - [self openResourceAsHex:resource]; -} - - -/* ----------------------------------------------------------------------------- - openResourceUsingEditor: - Open an editor for the specified Resource instance. This looks up - the editor to use in the plugin registry and then instantiates an - editor object, handing it the resource. If there is no editor for this - type registered, it falls back to the template editor, which in turn - uses the hex editor as a fallback. - - REVISIONS: - 2003-07-31 UK Changed to use plugin registry instead of file name. - -------------------------------------------------------------------------- */ - -/* Method name should be changed to: -(void)openResource:(Resource *)resource usingEditor:(Class)overrideEditor */ - -- (void)openResourceUsingEditor:(Resource *)resource -{ - Class editorClass = [[RKEditorRegistry defaultRegistry] editorForType:[resource type]]; - - // open the resources, passing in the template to use - 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. 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 no editor exists, or the editor is broken, open using template - [self openResource:resource usingTemplate:[resource type]]; -} - - -/* ----------------------------------------------------------------------------- - openResource:usingTemplate: - Open a template editor for the specified Resource instance. This looks - up the template editor in the plugin registry and then instantiates an - editor object, handing it the resource and the template resource to use. - If there is no template editor registered, or there is no template for - this resource type, it falls back to the hex editor. - - REVISIONS: - 2003-07-31 UK Changed to use plugin registry instead of file name. - -------------------------------------------------------------------------- */ - -- (void)openResource:(Resource *)resource usingTemplate:(NSString *)templateName -{ - // opens resource in template using TMPL resource with name templateName - 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) - { - [[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 -@change 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 -*/ - -- (void)openResourceAsHex:(Resource *)resource -{ - 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 -@change 2003-10-22 NS: 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 -*/ - -- (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) - { - [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 -{ - // 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 -{ - // this saves the current resource's name so we can undo the change - Resource *resource = (Resource *) [notification object]; - [[self undoManager] registerUndoWithTarget:resource selector:@selector(setName:) object:[[[resource name] copy] autorelease]]; - [[self undoManager] setActionName:NSLocalizedString(@"Name Change", nil)]; -} - -- (void)resourceIDWillChange:(NSNotification *)notification -{ - // 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) - [[self undoManager] setActionName:NSLocalizedString(@"ID Change", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"ID Change for '%@'", nil), [resource name]]]; -} - -- (void)resourceTypeWillChange:(NSNotification *)notification -{ - // 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) - [[self undoManager] setActionName:NSLocalizedString(@"Type Change", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Type Change for '%@'", nil), [resource name]]]; -} - -- (void)resourceAttributesWillChange:(NSNotification *)notification -{ - // 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) - [[self undoManager] setActionName:NSLocalizedString(@"Attributes Change", nil)]; - else [[self undoManager] setActionName:[NSString stringWithFormat:NSLocalizedString(@"Attributes Change for '%@'", nil), [resource name]]]; -} - -- (void)resourceDataDidChange:(NSNotification *)notification -{ - [self updateChangeCount:NSChangeDone]; -} - -#pragma mark - -#pragma mark Edit Operations - -- (IBAction)cut:(id)sender -{ - [self copy:sender]; - [self clear:sender]; -} - -- (IBAction)copy:(id)sender -{ - #pragma unused(sender) - NSArray *selectedItems = [outlineView selectedItems]; - NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - [pb declareTypes:[NSArray arrayWithObject:RKResourcePboardType] owner:self]; - [pb setData:[NSArchiver archivedDataWithRootObject:selectedItems] forType:RKResourcePboardType]; -} - -- (IBAction)paste:(id)sender -{ - #pragma unused(sender) - NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSGeneralPboard]; - if([pb availableTypeFromArray:[NSArray arrayWithObject:RKResourcePboardType]]) - [self pasteResources:[NSUnarchiver unarchiveObjectWithData:[pb dataForType:RKResourcePboardType]]]; -} - -- (void)pasteResources:(NSArray *)pastedResources -{ - Resource *resource; - NSEnumerator *enumerator = [pastedResources objectEnumerator]; - while(resource = (Resource *) [enumerator nextObject]) - { - // check resource type/ID is available - if([dataSource resourceOfType:[resource type] andID:[resource resID]] == nil) - { - // resource slot is available, paste this one in - [dataSource addResource:resource]; - } - else - { - // resource slot is ocupied, ask user what to do - 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]); - } - } -} - -- (void)overwritePasteSheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - NSMutableArray *remainingResources = [NSMutableArray arrayWithArray:[(NSArray *)contextInfo autorelease]]; - Resource *resource = [remainingResources objectAtIndex:0]; - 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 - { - [dataSource removeResource:[dataSource resourceOfType:[resource type] andID:[resource resID]]]; - [dataSource addResource:resource]; - } -// else if(NSAlertAlternateReturn) // skip - - // remove top resource and continue paste - [remainingResources removeObjectAtIndex:0]; - [self pasteResources:remainingResources]; -} - -- (IBAction)clear:(id)sender -{ - #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."); - } - else [self deleteSelectedResources]; -} - -- (void)deleteResourcesSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo -{ - #pragma unused(contextInfo) - if(returnCode == NSOKButton) - [self deleteSelectedResources]; -} - -- (void)deleteSelectedResources -{ - Resource *resource; - NSEnumerator *enumerator; - NSArray *selectedItems = [outlineView selectedItems]; - - // 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]) - { - [dataSource removeResource:resource]; - if([[resource name] length] == 0) - [[self undoManager] setActionName:NSLocalizedString(@"Delete Resource", nil)]; - 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) - [[self undoManager] setActionName:NSLocalizedString(@"Delete Resources", nil)]; - - // deselect resources (otherwise other resources move into selected rows!) - [outlineView deselectAll:self]; -} - -#pragma mark - -#pragma mark Accessors - -- (NSWindow *)mainWindow -{ - return mainWindow; -} - -- (ResourceDataSource *)dataSource -{ - return dataSource; -} - -- (NSOutlineView *)outlineView -{ - return outlineView; -} - -- (NSArray *)resources -{ - return resources; -} - -- (NSData *)creator -{ - return creator; -} - -- (NSData *)type -{ - return type; -} - -- (IBAction)creatorChanged:(id)sender -{ - 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 -{ - 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]); -} - -- (BOOL)setCreator:(NSData *)newCreator -{ - if(![newCreator isEqualToData:creator]) - { - id old = creator; - [[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)]; - creator = [newCreator copy]; - [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoDidChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", creator, @"creator", nil]]; - return YES; - } - else return NO; -} - -- (BOOL)setType:(NSData *)newType -{ - if(![newType isEqualToData:type]) - { - id old = type; - [[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)]; - type = [newType copy]; - [old release]; - [[NSNotificationCenter defaultCenter] postNotificationName:DocumentInfoDidChangeNotification object:[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSDocument", type, @"type", nil]]; - return YES; - } - else return NO; -} - -- (BOOL)setCreator:(NSData *)newCreator andType:(NSData *)newType -{ - BOOL creatorChanged, typeChanged; - [[self undoManager] beginUndoGrouping]; - creatorChanged = [self setCreator:newCreator]; - typeChanged = [self setType:newType]; - [[self undoManager] endUndoGrouping]; - if(creatorChanged && typeChanged) - [[self undoManager] setActionName:NSLocalizedString(@"Change Creator & Type", nil)]; - return (creatorChanged || typeChanged); -} - -@end diff --git a/Cocoa/English.lproj/InfoPlist.strings b/Cocoa/English.lproj/InfoPlist.strings index 010ccd63681739d21875ebfe67f1b46bef5a1e61..8d8bbdeb7ca688678fbb4e77efaaa447195c2426 100644 GIT binary patch delta 14 Vcmcb_a*1VwIU{4 UInt32 TableChecksum(UInt32 *table, UInt32 length) diff --git a/Cocoa/Plug-Ins/Hex Editor/HexTextView.m b/Cocoa/Plug-Ins/Hex Editor/HexTextView.m index 7b84a4a..42c5078 100644 --- a/Cocoa/Plug-Ins/Hex Editor/HexTextView.m +++ b/Cocoa/Plug-Ins/Hex Editor/HexTextView.m @@ -486,7 +486,7 @@ static NSRange draggedRange; @method selectionRangeForProposedRange:granularity: @abstract Puts insertion pointer between bytes during drag operation @author Nicholas Shanks -@change 2003-11-10 NS: Changed algorithm. +@updated 2003-11-10 NGS: Changed algorithm. */ - (unsigned int)_insertionGlyphIndexForDrag:(id )sender diff --git a/Cocoa/Plug-Ins/Notifications.m b/Cocoa/Plug-Ins/Notifications.m index 68c1cb5..97b76e9 100644 --- a/Cocoa/Plug-Ins/Notifications.m +++ b/Cocoa/Plug-Ins/Notifications.m @@ -6,16 +6,18 @@ #import -NSString *ResourceWillChangeNotification = @"ResourceWillChange"; -NSString *ResourceNameWillChangeNotification = @"ResourceNameWillChange"; -NSString *ResourceTypeWillChangeNotification = @"ResourceTypeWillChange"; -NSString *ResourceIDWillChangeNotification = @"ResourceIDWillChange"; -NSString *ResourceAttributesWillChangeNotification = @"ResourceAttributesWillChange"; -NSString *ResourceDataWillChangeNotification = @"ResourceDataWillChange"; +NSString *ResourceWillChangeNotification = @"ResourceWillChangeNotification"; +NSString *ResourceNameWillChangeNotification = @"ResourceNameWillChangeNotification"; +NSString *ResourceTypeWillChangeNotification = @"ResourceTypeWillChangeNotification"; +NSString *ResourceIDWillChangeNotification = @"ResourceIDWillChangeNotification"; +NSString *ResourceAttributesWillChangeNotification = @"ResourceAttributesWillChangeNotification"; +NSString *ResourceDataWillChangeNotification = @"ResourceDataWillChangeNotification"; +NSString *ResourceWillBeSavedNotification = @"ResourceWillBeSavedNotification"; -NSString *ResourceNameDidChangeNotification = @"ResourceNameDidChange"; -NSString *ResourceTypeDidChangeNotification = @"ResourceTypeDidChange"; -NSString *ResourceIDDidChangeNotification = @"ResourceIDDidChange"; -NSString *ResourceAttributesDidChangeNotification = @"ResourceAttributesDidChange"; -NSString *ResourceDataDidChangeNotification = @"ResourceDataDidChange"; -NSString *ResourceDidChangeNotification = @"ResourceDidChange"; +NSString *ResourceNameDidChangeNotification = @"ResourceNameDidChangeNotification"; +NSString *ResourceTypeDidChangeNotification = @"ResourceTypeDidChangeNotification"; +NSString *ResourceIDDidChangeNotification = @"ResourceIDDidChangeNotification"; +NSString *ResourceAttributesDidChangeNotification = @"ResourceAttributesDidChangeNotification"; +NSString *ResourceDataDidChangeNotification = @"ResourceDataDidChangeNotification"; +NSString *ResourceDidChangeNotification = @"ResourceDidChangeNotification"; +NSString *ResourceWasSavedNotification = @"ResourceWasSavedNotification"; diff --git a/Cocoa/Plug-Ins/ResKnifeResourceProtocol.h b/Cocoa/Plug-Ins/ResKnifeResourceProtocol.h index 2f1983e..a133030 100644 --- a/Cocoa/Plug-Ins/ResKnifeResourceProtocol.h +++ b/Cocoa/Plug-Ins/ResKnifeResourceProtocol.h @@ -64,6 +64,7 @@ extern NSString *ResourceTypeWillChangeNotification; extern NSString *ResourceIDWillChangeNotification; extern NSString *ResourceAttributesWillChangeNotification; extern NSString *ResourceDataWillChangeNotification; +extern NSString *ResourceWillBeSavedNotification; extern NSString *ResourceNameDidChangeNotification; extern NSString *ResourceTypeDidChangeNotification; @@ -71,3 +72,4 @@ extern NSString *ResourceIDDidChangeNotification; extern NSString *ResourceAttributesDidChangeNotification; extern NSString *ResourceDataDidChangeNotification; extern NSString *ResourceDidChangeNotification; +extern NSString *ResourceWasSavedNotification; \ No newline at end of file diff --git a/External/MoreFilesX/MoreFilesX.c b/External/MoreFilesX/MoreFilesX.c index e614f2b..c28f4e8 100644 --- a/External/MoreFilesX/MoreFilesX.c +++ b/External/MoreFilesX/MoreFilesX.c @@ -2179,6 +2179,7 @@ PBUnlockRangeSync: return ( result ); } + #endif /*****************************************************************************/ diff --git a/NovaTools/boom/BoomWindowController.h b/NovaTools/boom/BoomWindowController.h index e784a97..6463047 100644 --- a/NovaTools/boom/BoomWindowController.h +++ b/NovaTools/boom/BoomWindowController.h @@ -35,7 +35,7 @@ enum // boom defaults - (void)update; - (void)controlTextDidChange:(NSNotification *)notification; -- (IBAction)setSilent:(id)sender; +- (IBAction)toggleSilence:(id)sender; - (IBAction)playSound:(id)sender; @end diff --git a/NovaTools/boom/BoomWindowController.m b/NovaTools/boom/BoomWindowController.m index 30af5e2..0076b62 100644 --- a/NovaTools/boom/BoomWindowController.m +++ b/NovaTools/boom/BoomWindowController.m @@ -111,9 +111,11 @@ [self setDocumentEdited:[resource isDirty]]; } -- (IBAction)setSilent:(id)sender +- (IBAction)toggleSilence:(id)sender { silent = ![soundButton state]; + [soundField setEnabled:!silent]; + [playButton setEnabled:!silent]; [resource touch]; [self setDocumentEdited:YES]; } diff --git a/README.txt b/README.txt index 2125bcf..9ab5937 100644 --- a/README.txt +++ b/README.txt @@ -82,6 +82,6 @@ ResKnife methods, functions, headers, classes, ivars and practically anything el 3) The pertinent keywords or their equivalents in the above item should retain the specified order wherever reasonably applicable (e.g. for @class and @protocol comments) 4) The value for the @created keyword should take the following form: YYYY-MM-DD - 5) The value for the @change keyword should take the following form: YYYY-MM-DD Author: Description + 5) The value for the @updated keyword should take the following form: YYYY-MM-DD Author: Description where Author is an identifier for the person who made the change, not necessarilly the value in @author. Convention is that it simply contains the initials of the person. */ diff --git a/ResKnife.xcodeproj/project.pbxproj b/ResKnife.xcodeproj/project.pbxproj index 1fc1d25..f71d7c6 100644 --- a/ResKnife.xcodeproj/project.pbxproj +++ b/ResKnife.xcodeproj/project.pbxproj @@ -7,10 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 0EBA8666122CF49800FEC1AC /* NGSCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EBA8664122CF49800FEC1AC /* NGSCategories.h */; }; + 0EBA8667122CF49800FEC1AC /* NGSCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EBA8665122CF49800FEC1AC /* NGSCategories.m */; }; 0EF71540122BD0D0005DF94E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0EF7153F122BD0D0005DF94E /* Localizable.strings */; }; E1193609099830D300A3A6EA /* FontDocument.nib in Resources */ = {isa = PBXBuildFile; fileRef = E1193607099830D200A3A6EA /* FontDocument.nib */; }; - E119363A099833AE00A3A6EA /* Categories.h in Headers */ = {isa = PBXBuildFile; fileRef = E1193638099833AE00A3A6EA /* Categories.h */; }; - E119363B099833AE00A3A6EA /* Categories.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1193639099833AE00A3A6EA /* Categories.mm */; }; E11936660998552900A3A6EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E11936650998552900A3A6EA /* Localizable.strings */; }; E1193683099864AD00A3A6EA /* ElementUBYT.h in Headers */ = {isa = PBXBuildFile; fileRef = E119367D099864AD00A3A6EA /* ElementUBYT.h */; }; E1193684099864AD00A3A6EA /* ElementUBYT.m in Sources */ = {isa = PBXBuildFile; fileRef = E119367E099864AD00A3A6EA /* ElementUBYT.m */; }; @@ -89,8 +89,8 @@ E18BF574069FEA1300F076B8 /* OutlineViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F5B5882A0156D40B01000001 /* OutlineViewDelegate.m */; }; E18BF575069FEA1300F076B8 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F5B5882C0156D40B01000001 /* PrefsWindowController.m */; }; E18BF576069FEA1300F076B8 /* Resource.m in Sources */ = {isa = PBXBuildFile; fileRef = F5B5882E0156D40B01000001 /* Resource.m */; }; - E18BF577069FEA1300F076B8 /* ResourceDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5B588300156D40B01000001 /* ResourceDataSource.mm */; }; - E18BF578069FEA1300F076B8 /* ResourceDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5B588320156D40B01000001 /* ResourceDocument.mm */; }; + E18BF577069FEA1300F076B8 /* ResourceDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = F5B588300156D40B01000001 /* ResourceDataSource.m */; }; + E18BF578069FEA1300F076B8 /* ResourceDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = F5B588320156D40B01000001 /* ResourceDocument.m */; }; E18BF579069FEA1300F076B8 /* ResourceNameCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F577A901021215C801A80001 /* ResourceNameCell.m */; }; E18BF57A069FEA1300F076B8 /* SizeFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F5B588340156D40B01000001 /* SizeFormatter.m */; }; E18BF57B069FEA1300F076B8 /* NSOutlineView-SelectedItems.m in Sources */ = {isa = PBXBuildFile; fileRef = F5D0CBD0022744C701A80001 /* NSOutlineView-SelectedItems.m */; }; @@ -103,7 +103,7 @@ E18BF582069FEA1300F076B8 /* OpenPanelDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F59481B203D077DC01A8010A /* OpenPanelDelegate.m */; }; E18BF583069FEA1300F076B8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D35755A04DAEB4300B8225B /* main.m */; }; E18BF584069FEA1300F076B8 /* RKEditorRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D35755D04DAEB6200B8225B /* RKEditorRegistry.m */; }; - E18BF585069FEA1300F076B8 /* RKSupportResourceRegistry.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.mm */; }; + E18BF585069FEA1300F076B8 /* RKSupportResourceRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.m */; }; E18BF587069FEA1300F076B8 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884B0156D40B01000001 /* Cocoa.framework */; }; E18BF588069FEA1300F076B8 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B5884A0156D40B01000001 /* Carbon.framework */; }; E18BF590069FEA1400F076B8 /* ResKnifeResourceProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CDEBAB01FC893201A80001 /* ResKnifeResourceProtocol.h */; }; @@ -414,6 +414,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0EBA8664122CF49800FEC1AC /* NGSCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NGSCategories.h; sourceTree = ""; }; + 0EBA8665122CF49800FEC1AC /* NGSCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NGSCategories.m; sourceTree = ""; }; 3D0933A604DEFEE600DD74B1 /* Element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Element.h; sourceTree = ""; }; 3D0933A704DEFEE600DD74B1 /* Element.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Element.m; sourceTree = ""; }; 3D0933BE04DF151C00DD74B1 /* TemplateStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateStream.h; sourceTree = ""; }; @@ -449,10 +451,8 @@ 3D50047304EF122000F3B64D /* ElementLSTC.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = ElementLSTC.mm; sourceTree = ""; }; 3D50047404EF122000F3B64D /* ElementLSTC.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ElementLSTC.h; sourceTree = ""; }; 3D53A9FD04F171DC006651FA /* RKSupportResourceRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKSupportResourceRegistry.h; sourceTree = ""; }; - 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RKSupportResourceRegistry.mm; sourceTree = ""; }; + 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKSupportResourceRegistry.m; sourceTree = ""; }; E1193608099830D300A3A6EA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/FontDocument.nib; sourceTree = ""; }; - E1193638099833AE00A3A6EA /* Categories.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Categories.h; path = ../Categories.h; sourceTree = SOURCE_ROOT; }; - E1193639099833AE00A3A6EA /* Categories.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = Categories.mm; path = ../Categories.mm; sourceTree = SOURCE_ROOT; }; E11936620998551200A3A6EA /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; E119367D099864AD00A3A6EA /* ElementUBYT.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ElementUBYT.h; sourceTree = ""; }; E119367E099864AD00A3A6EA /* ElementUBYT.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ElementUBYT.m; sourceTree = ""; }; @@ -597,9 +597,9 @@ F5B5882D0156D40B01000001 /* Resource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Resource.h; sourceTree = ""; }; F5B5882E0156D40B01000001 /* Resource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Resource.m; sourceTree = ""; }; F5B5882F0156D40B01000001 /* ResourceDataSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ResourceDataSource.h; sourceTree = ""; }; - F5B588300156D40B01000001 /* ResourceDataSource.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceDataSource.mm; sourceTree = ""; }; + F5B588300156D40B01000001 /* ResourceDataSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ResourceDataSource.m; sourceTree = ""; }; F5B588310156D40B01000001 /* ResourceDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ResourceDocument.h; sourceTree = ""; }; - F5B588320156D40B01000001 /* ResourceDocument.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceDocument.mm; sourceTree = ""; }; + F5B588320156D40B01000001 /* ResourceDocument.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ResourceDocument.m; sourceTree = ""; }; F5B588330156D40B01000001 /* SizeFormatter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SizeFormatter.h; sourceTree = ""; }; F5B588340156D40B01000001 /* SizeFormatter.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = SizeFormatter.m; sourceTree = ""; }; F5B588370156D40B01000001 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/AboutPanel.nib; sourceTree = ""; }; @@ -1007,8 +1007,8 @@ F5594EE9021F3E2301A80001 /* Categories */ = { isa = PBXGroup; children = ( - E1193638099833AE00A3A6EA /* Categories.h */, - E1193639099833AE00A3A6EA /* Categories.mm */, + 0EBA8664122CF49800FEC1AC /* NGSCategories.h */, + 0EBA8665122CF49800FEC1AC /* NGSCategories.m */, F5D0CBCF022744C701A80001 /* NSOutlineView-SelectedItems.h */, F5D0CBD0022744C701A80001 /* NSOutlineView-SelectedItems.m */, F59D5DE40320DFF601A8010C /* NSString-FSSpec.h */, @@ -1118,9 +1118,9 @@ F5B5882D0156D40B01000001 /* Resource.h */, F5B5882E0156D40B01000001 /* Resource.m */, F5B5882F0156D40B01000001 /* ResourceDataSource.h */, - F5B588300156D40B01000001 /* ResourceDataSource.mm */, + F5B588300156D40B01000001 /* ResourceDataSource.m */, F5B588310156D40B01000001 /* ResourceDocument.h */, - F5B588320156D40B01000001 /* ResourceDocument.mm */, + F5B588320156D40B01000001 /* ResourceDocument.m */, F577A900021215C801A80001 /* ResourceNameCell.h */, F577A901021215C801A80001 /* ResourceNameCell.m */, F59481AD03D0776C01A8010A /* RKDocumentController.h */, @@ -1128,7 +1128,7 @@ 3D35755C04DAEB6200B8225B /* RKEditorRegistry.h */, 3D35755D04DAEB6200B8225B /* RKEditorRegistry.m */, 3D53A9FD04F171DC006651FA /* RKSupportResourceRegistry.h */, - 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.mm */, + 3D53A9FE04F171DC006651FA /* RKSupportResourceRegistry.m */, F5B588330156D40B01000001 /* SizeFormatter.h */, F5B588340156D40B01000001 /* SizeFormatter.m */, ); @@ -1435,6 +1435,7 @@ E18BF550069FEA1300F076B8 /* OpenPanelDelegate.h in Headers */, E18BF551069FEA1300F076B8 /* RKEditorRegistry.h in Headers */, E18BF552069FEA1300F076B8 /* RKSupportResourceRegistry.h in Headers */, + 0EBA8666122CF49800FEC1AC /* NGSCategories.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1628,7 +1629,6 @@ buildActionMask = 2147483647; files = ( E18BF7D4069FFC7600F076B8 /* FontWindowController.h in Headers */, - E119363A099833AE00A3A6EA /* Categories.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2165,8 +2165,8 @@ E18BF574069FEA1300F076B8 /* OutlineViewDelegate.m in Sources */, E18BF575069FEA1300F076B8 /* PrefsWindowController.m in Sources */, E18BF576069FEA1300F076B8 /* Resource.m in Sources */, - E18BF577069FEA1300F076B8 /* ResourceDataSource.mm in Sources */, - E18BF578069FEA1300F076B8 /* ResourceDocument.mm in Sources */, + E18BF577069FEA1300F076B8 /* ResourceDataSource.m in Sources */, + E18BF578069FEA1300F076B8 /* ResourceDocument.m in Sources */, E18BF579069FEA1300F076B8 /* ResourceNameCell.m in Sources */, E18BF57A069FEA1300F076B8 /* SizeFormatter.m in Sources */, E18BF57B069FEA1300F076B8 /* NSOutlineView-SelectedItems.m in Sources */, @@ -2179,7 +2179,8 @@ E18BF582069FEA1300F076B8 /* OpenPanelDelegate.m in Sources */, E18BF583069FEA1300F076B8 /* main.m in Sources */, E18BF584069FEA1300F076B8 /* RKEditorRegistry.m in Sources */, - E18BF585069FEA1300F076B8 /* RKSupportResourceRegistry.mm in Sources */, + E18BF585069FEA1300F076B8 /* RKSupportResourceRegistry.m in Sources */, + 0EBA8667122CF49800FEC1AC /* NGSCategories.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2358,7 +2359,6 @@ files = ( E18BF7D5069FFC7600F076B8 /* FontWindowController.mm in Sources */, E18BF8EB06A0027700F076B8 /* Notifications.m in Sources */, - E119363B099833AE00A3A6EA /* Categories.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };