/** GSNibCompatibility These are templates for use with OSX Nib files. These classes are the templates and other things which are needed for reading/writing nib files. Copyright (C) 1997, 1999 Free Software Foundation, Inc. Author: Gregory John Casamento Date: 2003, 2005 This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "AppKit/AppKit.h" #include #include #include #include static BOOL _isInInterfaceBuilder = NO; @interface NSView (NibCompatibility) - (void) _fixSubviews; @end @implementation NSView (NibCompatibility) - (void) _setWindow: (id) w { ASSIGN(_window,w); } - (void) _fixSubviews { NSEnumerator *en = [[self subviews] objectEnumerator]; id v = nil; while ((v = [en nextObject]) != nil) { if ([v window] != [self window] || [v superview] != self) { [v _setWindow: [self window]]; RETAIN(v); [_sub_views removeObject: v]; [self addSubview: v]; RELEASE(v); } [v _fixSubviews]; } } @end @implementation NSWindowTemplate + (void) initialize { if (self == [NSWindowTemplate class]) { [self setVersion: 0]; } } - (void) dealloc { RELEASE(_title); RELEASE(_viewClass); RELEASE(_windowClass); RELEASE(_view); RELEASE(_autosaveName); [super dealloc]; } - (id) initWithWindow: (NSWindow *)window className: (NSString *)windowClass isDeferred: (BOOL) deferred isOneShot: (BOOL) oneShot isVisible: (BOOL) visible wantsToBeColor: (BOOL) wantsToBeColor autoPositionMask: (int) autoPositionMask { if ((self = [super init]) != nil) { if (window != nil) { // object members ASSIGN(_title, [window title]); ASSIGN(_viewClass, NSStringFromClass([[window contentView] class])); ASSIGN(_windowClass, windowClass); ASSIGN(_view, [window contentView]); ASSIGN(_autosaveName, [window frameAutosaveName]); // style & size _windowStyle = [window styleMask]; _backingStoreType = [window backingType]; _maxSize = [window maxSize]; _minSize = [window minSize]; _windowRect = [window frame]; _screenRect = [[NSScreen mainScreen] frame]; // flags _flags.isHiddenOnDeactivate = [window hidesOnDeactivate]; _flags.isNotReleasedOnClose = (![window isReleasedWhenClosed]); _flags.isDeferred = deferred; _flags.isOneShot = oneShot; _flags.isVisible = visible; _flags.wantsToBeColor = wantsToBeColor; _flags.dynamicDepthLimit = [window hasDynamicDepthLimit]; _flags.autoPositionMask = autoPositionMask; _flags.savePosition = YES; // not yet implemented. } } return self; } - (id) initWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { if ([coder containsValueForKey: @"NSViewClass"]) { ASSIGN(_viewClass, [coder decodeObjectForKey: @"NSViewClass"]); } if ([coder containsValueForKey: @"NSWindowClass"]) { ASSIGN(_windowClass, [coder decodeObjectForKey: @"NSWindowClass"]); } if ([coder containsValueForKey: @"NSWindowStyleMask"]) { _windowStyle = [coder decodeIntForKey: @"NSWindowStyleMask"]; } if ([coder containsValueForKey: @"NSWindowBacking"]) { _backingStoreType = [coder decodeIntForKey: @"NSWindowBacking"]; } if ([coder containsValueForKey: @"NSWindowView"]) { ASSIGN(_view, [coder decodeObjectForKey: @"NSWindowView"]); } if ([coder containsValueForKey: @"NSWTFlags"]) { unsigned long flags = [coder decodeIntForKey: @"NSWTFlags"]; memcpy((void *)&_flags,(void *)&flags,sizeof(struct _GSWindowTemplateFlags)); } if ([coder containsValueForKey: @"NSMinSize"]) { _minSize = [coder decodeSizeForKey: @"NSMinSize"]; } if ([coder containsValueForKey: @"NSMaxSize"]) { _maxSize = [coder decodeSizeForKey: @"NSMaxSize"]; } if ([coder containsValueForKey: @"NSWindowRect"]) { _windowRect = [coder decodeRectForKey: @"NSWindowRect"]; } if ([coder containsValueForKey: @"NSFrameAutosaveName"]) { ASSIGN(_autosaveName, [coder decodeObjectForKey: @"NSFrameAutosaveName"]); } if ([coder containsValueForKey: @"NSWindowTitle"]) { ASSIGN(_title, [coder decodeObjectForKey: @"NSWindowTitle"]); _windowStyle |= NSTitledWindowMask; } _baseWindowClass = [NSWindow class]; } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } return self; } - (void) encodeWithCoder: (NSCoder *)aCoder { if ([aCoder allowsKeyedCoding]) { unsigned long flags = 0; NSRect rect = [NSWindow contentRectForFrameRect: _windowRect styleMask: _windowStyle]; memcpy((void *)&flags,(void *)&_flags,sizeof(unsigned long)); [aCoder encodeObject: _viewClass forKey: @"NSViewClass"]; [aCoder encodeObject: _windowClass forKey: @"NSWindowClass"]; [aCoder encodeInt: _windowStyle forKey: @"NSWindowStyleMask"]; [aCoder encodeInt: _backingStoreType forKey: @"NSWindowBacking"]; [aCoder encodeObject: _view forKey: @"NSWindowView"]; [aCoder encodeInt: flags forKey: @"NSWTFlags"]; [aCoder encodeSize: _minSize forKey: @"NSMinSize"]; [aCoder encodeSize: _maxSize forKey: @"NSMaxSize"]; [aCoder encodeRect: rect forKey: @"NSWindowRect"]; [aCoder encodeObject: _title forKey: @"NSWindowTitle"]; [aCoder encodeObject: _autosaveName forKey: @"NSFrameAutosaveName"]; } } - (id) nibInstantiate { if (_realObject == nil) { Class aClass; NSEnumerator *en; id v = nil; if ([NSClassSwapper isInInterfaceBuilder]) { aClass = [self baseWindowClass]; } else { aClass = NSClassFromString(_windowClass); } if (aClass == nil) { [NSException raise: NSInternalInconsistencyException format: @"Unable to find class '%@'", _windowClass]; } _realObject = [[aClass allocWithZone: NSDefaultMallocZone()] initWithContentRect: _windowRect styleMask: _windowStyle backing: _backingStoreType defer: _flags.isDeferred screen: nil]; // set flags... [_realObject setHidesOnDeactivate: _flags.isHiddenOnDeactivate]; [_realObject setReleasedWhenClosed: !(_flags.isNotReleasedOnClose)]; [_realObject setOneShot: _flags.isOneShot]; // [_realObject setVisible: _flags.isVisible]; // this is determined by whether it's in the visible windows array... // [_realObject setWantsToBeColor: _flags.wantsToBeColor]; // not applicable on GNUstep. [_realObject setAutodisplay: YES]; [_realObject setDynamicDepthLimit: _flags.dynamicDepthLimit]; // [_realObject setAutoPositionMask: _flags.autoPositionMask]; // currently not implemented for nibs // [_realObject setAutoPosition: _flags.autoPosition]; [_realObject setDynamicDepthLimit: _flags.dynamicDepthLimit]; [_realObject setFrameAutosaveName: _autosaveName]; // reset attributes... [_realObject setContentView: _view]; [_realObject setMinSize: _minSize]; [_realObject setMaxSize: _maxSize]; [_realObject setTitle: _title]; [_view _fixSubviews]; // resize the window... [_realObject setFrame: [NSWindow frameRectForContentRect: [self windowRect] styleMask: [self windowStyle]] display: NO]; // swap out any views which need to be swapped... en = [[[_realObject contentView] subviews] objectEnumerator]; while ((v = [en nextObject]) != nil) { if ([v respondsToSelector: @selector(nibInstantiate)]) { [v nibInstantiate]; } } } return _realObject; } // setters and getters - (void) setBackingStoreType: (NSBackingStoreType)type { _backingStoreType = type; } - (NSBackingStoreType) backingStoreType { return _backingStoreType; } - (void) setDeferred: (BOOL)flag { _flags.isDeferred = flag; } - (BOOL) isDeferred { return _flags.isDeferred; } - (void) setMaxSize: (NSSize)maxSize { _maxSize = maxSize; } - (NSSize) maxSize { return _maxSize; } - (void) setMinSize: (NSSize)minSize { _minSize = minSize; } - (NSSize) minSize { return _minSize; } - (void) setWindowStyle: (unsigned)style { _windowStyle = style; } - (unsigned) windowStyle { return _windowStyle; } - (void) setTitle: (NSString *) title { ASSIGN(_title, title); } - (NSString *)title; { return _title; } - (void) setViewClass: (NSString *)viewClass { ASSIGN(_viewClass,viewClass); } - (NSString *)viewClass { return _viewClass; } - (void) setWindowRect: (NSRect)rect { _windowRect = rect; } - (NSRect)windowRect { return _windowRect; } - (void) setScreenRect: (NSRect)rect { _screenRect = rect; } - (NSRect) screenRect { return _screenRect; } - (id) realObject { return _realObject; } - (void) setView: (id)view { ASSIGN(_view,view); } - (id) view { return _view; } - (void) setClassName: (NSString *)name { ASSIGN(_windowClass, name); } - (NSString *)className { return _windowClass; } - (Class) baseWindowClass { return _baseWindowClass; } @end // Template for any classes which derive from NSView @implementation NSViewTemplate + (void) initialize { if (self == [NSViewTemplate class]) { [self setVersion: 0]; } } - (id) initWithCoder: (NSCoder *)coder { self = [super initWithCoder: coder]; if (self != nil) { if ([coder allowsKeyedCoding]) { _className = [coder decodeObjectForKey: @"NSClassName"]; } } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } return self; } - (void) encodeWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { [coder encodeObject: (id)_className forKey: @"NSClassName"]; } } - (id) nibInstantiate { if (_realObject == nil) { Class aClass = NSClassFromString(_className); if (aClass == nil) { [NSException raise: NSInternalInconsistencyException format: @"Unable to find class '%@'", _className]; } else { _realObject = [[aClass allocWithZone: NSDefaultMallocZone()] initWithFrame: [self frame]]; [[self superview] replaceSubview: self with: _realObject]; // replace the old view... } } return _realObject; } // setters and getters - (void) setClassName: (NSString *)name { ASSIGN(_className, name); } - (NSString *)className { return _className; } - (id) realObject { return _realObject; } @end // Template for any classes which derive from NSText @implementation NSTextTemplate + (void) initialize { if (self == [NSTextTemplate class]) { [self setVersion: 0]; } } @end // Template for any classes which derive from NSTextView @implementation NSTextViewTemplate + (void) initialize { if (self == [NSTextViewTemplate class]) { [self setVersion: 0]; } } - (id)nibInstantiate { if (_realObject == nil) { Class aClass = NSClassFromString(_className); if (aClass == nil) { [NSException raise: NSInternalInconsistencyException format: @"Unable to find class '%@'", _className]; } else { _realObject = [[aClass allocWithZone: NSDefaultMallocZone()] initWithFrame: [self frame]]; [[self superview] replaceSubview: self with: _realObject]; // replace the old view... } } return _realObject; } @end // Template for any classes which derive from NSMenu. @implementation NSMenuTemplate + (void) initialize { if (self == [NSMenuTemplate class]) { [self setVersion: 0]; } } - (id) initWithCoder: (NSCoder *)aCoder { return nil; } - (void) encodeWithCoder: (NSCoder *)aCoder { } - (id) nibInstantiate { return nil; } - (void) setClassName: (NSString *)className { ASSIGN(_menuClass, className); } - (NSString *)className { return _menuClass; } - (id) realObject { return _realObject; } @end @implementation NSCustomObject - (void) setClassName: (NSString *)name { ASSIGNCOPY(_className, name); } - (NSString *)className { return _className; } - (void) setExtension: (NSString *)name { ASSIGNCOPY(_extension, name); } - (NSString *)extension { return _extension; } - (void) setObject: (id)obj { ASSIGN(_object, obj); } - (id) object { return _object; } - (id) initWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); ASSIGN(_extension, [coder decodeObjectForKey: @"NSExtension"]); } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } return self; } - (void) encodeWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { [coder encodeObject: (id)_className forKey: @"NSClassName"]; [coder encodeConditionalObject: (id)_extension forKey: @"NSExtension"]; } else { [NSException raise: NSInvalidArgumentException format: @"Keyed coding not implemented for %@.", NSStringFromClass([self class])]; } } - (id) nibInstantiate { if (_object == nil) { Class aClass; if ([NSClassSwapper isInInterfaceBuilder]) { aClass = [self class]; } else { aClass = NSClassFromString(_className); } if (aClass == nil) { [NSException raise: NSInternalInconsistencyException format: @"Unable to find class '%@'", _className]; } _object = [[aClass allocWithZone: NSDefaultMallocZone()] init]; } return _object; } - (void) dealloc { RELEASE(_className); RELEASE(_extension); [super dealloc]; } @end @implementation NSCustomView - (void) setClassName: (NSString *)name { ASSIGNCOPY(_className, name); } - (NSString *)className { return _className; } - (void) setExtension: (NSString *)ext; { ASSIGNCOPY(_extension, ext); } - (NSString *)extension { return _extension; } - (id) nibInstantiate { if (_view == nil) { Class aClass; if ([NSClassSwapper isInInterfaceBuilder]) { aClass = [self class]; } else { aClass = NSClassFromString(_className); } if (aClass == nil) { [NSException raise: NSInternalInconsistencyException format: @"Unable to find class '%@'", _className]; } else { _view = [[aClass allocWithZone: NSDefaultMallocZone()] initWithFrame: [self frame]]; [_view setAutoresizingMask: [self autoresizingMask]]; [_view setNextResponder: [self nextResponder]]; [[self superview] replaceSubview: self with: _view]; // replace the old view... } } return _view; } - (id) initWithCoder: (NSCoder *)coder { self = [super initWithCoder: coder]; if (self != nil) { if ([coder allowsKeyedCoding]) { ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); ASSIGN(_extension, [coder decodeObjectForKey: @"NSExtension"]); } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } } return self; } - (void) encodeWithCoder: (NSCoder *)coder { [super encodeWithCoder: coder]; if ([coder allowsKeyedCoding]) { [coder encodeObject: _className forKey: @"NSClassName"]; [coder encodeObject: _extension forKey: @"NSExtension"]; } else { [NSException raise: NSInvalidArgumentException format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } } @end @implementation NSCustomResource - (void) setClassName: (NSString *)className { ASSIGNCOPY(_className, className); } - (NSString *)className { return _className; } - (void) setResourceName: (NSString *)resourceName { ASSIGNCOPY(_resourceName, resourceName); } - (NSString *)resourceName { return _resourceName; } - (id)nibInstantiate { return self; } - (id) initWithCoder: (NSCoder *)coder { id realObject = nil; if ([coder allowsKeyedCoding]) { ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); ASSIGN(_resourceName, [coder decodeObjectForKey: @"NSResourceName"]); // this is a hack, but for now it should do. if ([_className isEqual: @"NSSound"]) { realObject = RETAIN([NSSound soundNamed: _resourceName]); } else if ([_className isEqual: @"NSImage"]) { realObject = RETAIN([NSImage imageNamed: _resourceName]); } // if an object has been substituted, then release the placeholder. if (realObject != nil) { RELEASE(self); } } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } return realObject; } - (void) encodeWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { [coder encodeObject: (id)_className forKey: @"NSClassName"]; [coder encodeObject: (id)_resourceName forKey: @"NSResourceName"]; } } @end @interface NSKeyedUnarchiver (NSClassSwapperPrivate) - (BOOL) replaceObject: (id)oldObj withObject: (id)newObj; - (NSDictionary *)keyMap; @end @implementation NSKeyedUnarchiver (NSClassSwapperPrivate) - (BOOL) replaceObject: (id)oldObj withObject: (id)newObj { unsigned int i = 0; unsigned int count = GSIArrayCount(_objMap); for (i = 0; i < count; i++) { id obj = GSIArrayItemAtIndex(_objMap, i).obj; if (obj == oldObj) break; } if (i < count) { GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)newObj, i); return YES; } return NO; } - (NSDictionary *)keyMap { return _keyMap; } @end @implementation NSClassSwapper - (id) initWithObject: (id)object withClassName: (NSString *)className originalClassName: (NSString *)origClassName { if ((self = [super init]) != nil) { [self setTemplate: object]; [self setClassName: className]; [self setOriginalClassName: origClassName]; } return self; } + (void) setIsInInterfaceBuilder: (BOOL)flag { _isInInterfaceBuilder = flag; } + (BOOL) isInInterfaceBuilder { return _isInInterfaceBuilder; } - (void) setTemplate: (id)temp { ASSIGN(_template, temp); } - (id) template { return _template; } - (void) setClassName: (NSString *)className { ASSIGNCOPY(_className, className); } - (NSString *)className { return _className; } - (void) setOriginalClassName: (NSString *)className { ASSIGNCOPY(_originalClassName, className); } - (NSString *)originalClassName { return _originalClassName; } - (void) instantiateRealObject: (NSCoder *)coder withClassName: (NSString *)className { Class aClass = nil; id object = nil; Class newCellClass = nil; NSString *origCellClassName = nil; Class origCellClass = nil; // if there is a replacement class, use it, otherwise, use the one specified. if ((aClass = [(NSKeyedUnarchiver *)coder classForClassName: className]) == nil) { aClass = NSClassFromString(className); } if (aClass == nil) { [NSException raise: NSInternalInconsistencyException format: @"NSClassSwapper unable to find class '%@'", className]; } // if this is a class which uses cells, override with the new cellClass, if the // subclass responds to cellClass. if ([aClass respondsToSelector: @selector(cellClass)] && [className isEqualToString: _originalClassName] == NO) { Class origClass = NSClassFromString(_originalClassName); origCellClass = [origClass cellClass]; newCellClass = [aClass cellClass]; origCellClassName = NSStringFromClass(origCellClass); [(NSKeyedUnarchiver *)coder setClass: newCellClass forClassName: origCellClassName]; } // swap the class... object = [aClass allocWithZone: NSDefaultMallocZone()]; [(NSKeyedUnarchiver *)coder replaceObject: self withObject: object]; [self setTemplate: [object initWithCoder: coder]]; if (object != _template) { [(NSKeyedUnarchiver *)coder replaceObject: object withObject: _template]; } if (newCellClass != nil && origCellClass != nil) { [(NSKeyedUnarchiver *)coder setClass: origCellClass forClassName: nil]; } } - (id) initWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { ASSIGN(_className, [coder decodeObjectForKey: @"NSClassName"]); ASSIGN(_originalClassName, [coder decodeObjectForKey: @"NSOriginalClassName"]); // build the real object... if ([NSClassSwapper isInInterfaceBuilder] == YES) { [self instantiateRealObject: coder withClassName: _originalClassName]; } else { [self instantiateRealObject: coder withClassName: _className]; } } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } return _template; } - (void) encodeWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { [coder encodeObject: _originalClassName forKey: @"NSOriginalClassName"]; [coder encodeObject: _className forKey: @"NSClassName"]; [_template encodeWithCoder: coder]; // encode the actual object; } else { [NSException raise: NSInvalidArgumentException format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } } - (void) dealloc { RELEASE(_className); RELEASE(_originalClassName); RELEASE(_template); [super dealloc]; } @end /* Correct some instances where the ":" is missing from the method name in the label */ @interface NSNibControlConnector (NibCompatibility) - (void) instantiateWithInstantiator: (id)instantiator; @end @implementation NSNibControlConnector (NibCompatibility) - (void) instantiateWithInstantiator: (id)instantiator { NSRange colonRange = [_tag rangeOfString: @":"]; unsigned int location = colonRange.location; if (location == NSNotFound) { NSString *newTag = [NSString stringWithFormat: @"%@:",_tag]; [self setLabel: (id)newTag]; } [super instantiateWithInstantiator: instantiator]; } @end @implementation NSIBObjectData - (id)instantiateObject: (id)obj { id newObject = obj; if ([obj respondsToSelector: @selector(nibInstantiate)]) { newObject = [obj nibInstantiate]; if ([newObject respondsToSelector: @selector(awakeFromNib)]) { // awaken the object. [newObject awakeFromNib]; } } return newObject; } - (void) nibInstantiateWithOwner: (id)owner { [self nibInstantiateWithOwner: owner topLevelObjects: nil]; } - (void) nibInstantiateWithOwner: (id)owner topLevelObjects: (NSMutableArray *)topLevelObjects { NSEnumerator *en = [_connections objectEnumerator]; NSArray *objs = NSAllMapTableKeys([self names]); id obj = nil; id menu = nil; // replace the owner with the actual instance provided. [_root setObject: owner]; // iterate over connections, instantiate, and then establish them. while ((obj = [en nextObject]) != nil) { if ([obj respondsToSelector: @selector(instantiateWithInstantiator:)]) { [obj instantiateWithInstantiator: self]; [obj establishConnection]; } } // instantiate all windows and fill in the top level array. en = [objs objectEnumerator]; while ((obj = [en nextObject]) != nil) { if ([obj isKindOfClass: [NSWindowTemplate class]]) { if ([obj realObject] == nil) { id o = [self instantiateObject: obj]; [topLevelObjects addObject: o]; } } else { id v = NSMapGet(_objects, obj); if (v == nil || v == owner) { [topLevelObjects addObject: obj]; } } } // bring visible windows to front... en = [_visibleWindows objectEnumerator]; while ((obj = [en nextObject]) != nil) { id w = [obj realObject]; [w orderFront: self]; } // add the menu... menu = [self objectForName: @"MainMenu"]; if (menu != nil) { menu = [self instantiateObject: menu]; [NSApp setMainMenu: menu]; } } - (void) awakeWithContext: (NSDictionary *)context { NSMutableArray *tlo = [context objectForKey: @"NSTopLevelObjects"]; id owner = [context objectForKey: @"NSOwner"]; [self nibInstantiateWithOwner: owner topLevelObjects: tlo]; } - (NSMutableArray *) connections { return _connections; } - (NSMutableSet *) topLevelObjects { return _topLevelObjects; } - (NSMutableDictionary *) nameTable { return nil; } - (NSMutableArray *) visibleWindows { return _visibleWindows; } - (NSMapTable *) objects { return _objects; } - (NSMapTable *) names { return _names; } - (NSMapTable *) classes { return _classes; } - (NSMapTable *) oids { return _oids; } - (id) objectForName: (NSString *)name { NSArray *nameKeys = (NSArray *)NSAllMapTableKeys(_names); NSArray *nameValues = (NSArray *)NSAllMapTableValues(_names); int i = [nameValues indexOfObject: name]; id result = nil; if (i != NSNotFound) { result = [nameKeys objectAtIndex: i]; } return result; } - (NSString *) nameForObject: (id)obj { NSArray *nameKeys = (NSArray *)NSAllMapTableKeys(_names); NSArray *nameValues = (NSArray *)NSAllMapTableValues(_names); int i = [nameKeys indexOfObject: obj]; NSString *result = [nameValues objectAtIndex: i]; return result; } /** * Get the values from the map in the same order as the keys. */ - (NSArray *) _valuesForKeys: (NSArray *)keys inMap: (NSMapTable *)map { NSMutableArray *result = [NSMutableArray array]; NSEnumerator *en = [keys objectEnumerator]; id key = nil; while ((key = [en nextObject]) != nil) { id value = (id)NSMapGet(map,key); [result addObject: value]; } return result; } - (void) encodeWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { NSArray *accessibilityOidsKeys = (NSArray *)NSAllMapTableKeys(_accessibilityOids); NSArray *accessibilityOidsValues = [self _valuesForKeys: accessibilityOidsKeys inMap: _accessibilityOids]; NSArray *classKeys = (NSArray *)NSAllMapTableKeys(_classes); NSArray *classValues = [self _valuesForKeys: classKeys inMap: _classes]; NSArray *nameKeys = (NSArray *)NSAllMapTableKeys(_names); NSArray *nameValues = [self _valuesForKeys: nameKeys inMap: _names]; NSArray *objectsKeys = (NSArray *)NSAllMapTableKeys(_objects); NSArray *objectsValues = [self _valuesForKeys: objectsKeys inMap: _objects]; NSArray *oidsKeys = (NSArray *)NSAllMapTableKeys(_oids); NSArray *oidsValues = [self _valuesForKeys: oidsKeys inMap: _oids]; [(NSKeyedArchiver *)coder setClassName: @"_NSCornerView" forClass: NSClassFromString(@"GSTableCornerView")]; [coder encodeObject: (id)_accessibilityConnectors forKey: @"NSAccessibilityConnectors"]; [coder encodeObject: (id) accessibilityOidsKeys forKey: @"NSAccessibilityOidsKeys"]; [coder encodeObject: (id) accessibilityOidsValues forKey: @"NSAccessibilityOidsValues"]; [coder encodeObject: (id) classKeys forKey: @"NSClassesKeys"]; [coder encodeObject: (id) classValues forKey: @"NSClassesValues"]; [coder encodeObject: (id) nameKeys forKey: @"NSNamesKeys"]; [coder encodeObject: (id) nameValues forKey: @"NSNamesValues"]; [coder encodeObject: (id) objectsKeys forKey: @"NSObjectsKeys"]; [coder encodeObject: (id) objectsValues forKey: @"NSObjectsValues"]; [coder encodeObject: (id) oidsKeys forKey: @"NSOidsKeys"]; [coder encodeObject: (id) oidsValues forKey: @"NSOidsValues"]; [coder encodeObject: (id) _connections forKey: @"NSConnections"]; [coder encodeObject: (id) _fontManager forKey: @"NSFontManager"]; [coder encodeObject: (id) _framework forKey: @"NSFramework"]; [coder encodeObject: (id) _visibleWindows forKey: @"NSVisibleWindows"]; [coder encodeInt: _nextOid forKey: @"NSNextOid"]; [coder encodeConditionalObject: (id) _root forKey: @"NSRoot"]; } else { [NSException raise: NSInvalidArgumentException format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } } - (void) _buildMap: (NSMapTable *)mapTable withKeys: (NSArray *)keys andValues: (NSArray *)values { NSEnumerator *ken = [keys objectEnumerator]; NSEnumerator *ven = [values objectEnumerator]; id key = nil; id value = nil; while ((key = [ken nextObject]) != nil && (value = [ven nextObject]) != nil) { NSMapInsert(mapTable, key, value); } } - (id) initWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { ASSIGN(_root, [coder decodeObjectForKey: @"NSRoot"]); ASSIGN(_visibleWindows, (NSMutableArray *)[coder decodeObjectForKey: @"NSVisibleWindows"]); ASSIGN(_accessibilityConnectors, (NSMutableArray *)[coder decodeObjectForKey: @"NSAccessibilityConnectors"]); ASSIGN(_fontManager, [coder decodeObjectForKey: @"NSFontManager"]); ASSIGN(_framework, [coder decodeObjectForKey: @"NSFramework"]); _nextOid = [coder decodeIntForKey: @"NSNextOid"]; { NSArray *objectsKeys = (NSArray *) [coder decodeObjectForKey: @"NSObjectsKeys"]; NSArray *objectsValues = (NSArray *) [coder decodeObjectForKey: @"NSObjectsValues"]; NSArray *nameKeys = (NSArray *) [coder decodeObjectForKey: @"NSNamesKeys"]; NSArray *nameValues = (NSArray *) [coder decodeObjectForKey: @"NSNamesValues"]; NSArray *oidsKeys = (NSArray *) [coder decodeObjectForKey: @"NSOidsKeys"]; NSArray *oidsValues = (NSArray *) [coder decodeObjectForKey: @"NSOidsValues"]; NSArray *classKeys = (NSArray *) [coder decodeObjectForKey: @"NSClassesKeys"]; NSArray *classValues = (NSArray *) [coder decodeObjectForKey: @"NSClassesValues"]; NSArray *accessibilityOidsKeys = (NSArray *) [coder decodeObjectForKey: @"NSAccessibilityOidsKeys"]; NSArray *accessibilityOidsValues = (NSArray *) [coder decodeObjectForKey: @"NSAccessibilityOidsValues"]; // instantiate the maps.. _objects = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _names = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _oids = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _classes = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _accessibilityOids = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); // fill in the maps... [self _buildMap: _accessibilityOids withKeys: accessibilityOidsKeys andValues: accessibilityOidsValues]; [self _buildMap: _classes withKeys: classKeys andValues: classValues]; [self _buildMap: _names withKeys: nameKeys andValues: nameValues]; [self _buildMap: _objects withKeys: objectsKeys andValues: objectsValues]; [self _buildMap: _oids withKeys: oidsKeys andValues: oidsValues]; ASSIGN(_connections, [[coder decodeObjectForKey: @"NSConnections"] mutableCopy]); // instantiate... _topLevelObjects = [[NSMutableSet alloc] init]; } } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } return self; } - (id) init { if ((self = [super init]) != nil) { // instantiate the maps.. _objects = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _names = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _oids = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _classes = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); _accessibilityOids = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2); // initialize the objects... _accessibilityConnectors = [[NSMutableArray alloc] init]; _connections = [[NSMutableArray alloc] init]; _visibleWindows = [[NSMutableArray alloc] init]; _framework = nil; _fontManager = nil; _root = nil; _nextOid = 0; } return self; } - (void) dealloc { // free the maps. NSFreeMapTable(_objects); NSFreeMapTable(_names); NSFreeMapTable(_oids); NSFreeMapTable(_classes); NSFreeMapTable(_accessibilityOids); // free other objects. RELEASE(_accessibilityConnectors); RELEASE(_connections); RELEASE(_fontManager); RELEASE(_framework); RELEASE(_visibleWindows); RELEASE(_root); RELEASE(_topLevelObjects); [super dealloc]; } - (void) setRoot: (id) root { ASSIGN(_root, root); } - (id) root { return _root; } - (void) setNextOid: (int)noid { _nextOid = noid; } - (int) nextOid { return _nextOid; } @end @implementation NSButtonImageSource - (id) initWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { ASSIGN(imageName, [coder decodeObjectForKey: @"NSImageName"]); } else { [NSException raise: NSInvalidArgumentException format: @"Can't decode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } RELEASE(self); return [NSImage imageNamed: imageName]; } - (void) encodeWithCoder: (NSCoder *)coder { if ([coder allowsKeyedCoding]) { [coder encodeObject: imageName forKey: @"NSImageName"]; } else { [NSException raise: NSInvalidArgumentException format: @"Can't encode %@ with %@.",NSStringFromClass([self class]), NSStringFromClass([coder class])]; } } - (id) initWithImageNamed: (NSString *)name { if ((self = [super init]) != nil) { ASSIGN(imageName,name); } return self; } - (NSString *)imageName { return imageName; } - (void) dealloc { RELEASE(imageName); [super dealloc]; } @end @implementation NSIBHelpConnector - (id) init { if ((self = [super init]) != nil) { _file = nil; _marker = @"NSToolTipHelpKey"; } return self; } - (id) initWithCoder: (NSCoder *)coder { if ((self = [super initWithCoder: coder]) != nil) { if ([coder allowsKeyedCoding]) { if ([coder containsValueForKey: @"NSFile"]) { _file = RETAIN([coder decodeObjectForKey: @"NSFile"]); } if ([coder containsValueForKey: @"NSMarker"]) { _marker = RETAIN([coder decodeObjectForKey: @"NSMarker"]); } } else { _file = RETAIN([coder decodeObject]); _marker = RETAIN([coder decodeObject]); } } return self; } - (void) encodeWithCoder: (NSCoder *)coder { [super encodeWithCoder: coder]; if ([coder allowsKeyedCoding]) { if (_file != nil) { [coder encodeObject: _file forKey: @"NSFile"]; } if (_marker != nil) { [coder encodeObject: _file forKey: @"NSMarker"]; } } else { [coder encodeObject: _file]; [coder encodeObject: _marker]; } } - (void) establishConnection { [_dst setToolTip: _marker]; } - (void) setFile: (id)file { ASSIGN(_file, file); } - (id) file { return _file; } - (void) setMarker: (id)marker { ASSIGN(_marker, marker); } - (id) marker { return _marker; } @end @interface NSDecimalNumberPlaceholder : NSObject @end @implementation NSDecimalNumberPlaceholder - (id) initWithCoder: (NSCoder *)coder { NSDecimalNumber *dn = nil; if ([coder allowsKeyedCoding]) { unsigned int len = 0; short exponent = (short)[coder decodeIntForKey: @"NS.exponent"]; NSByteOrder bo = [coder decodeIntForKey: @"NS.mantissa.bo"]; BOOL negative = [coder decodeBoolForKey: @"NS.negative"]; void *mantissaBytes = (void *)[coder decodeBytesForKey: @"NS.mantissa" returnedLength: &len]; unsigned long long unswapped = 0; unsigned long long mantissa = 0; // BOOL compact = [coder decodeBoolForKey: @"NS.compact"]; // int length = [coder decodeIntForKey: @"NS.length"]; memcpy((void *)&unswapped, (void *)mantissaBytes, sizeof(unsigned long long)); switch(bo) { case NS_BigEndian: mantissa = NSSwapBigLongLongToHost(unswapped); break; case NS_LittleEndian: mantissa = NSSwapLittleLongLongToHost(unswapped); break; default: break; } dn = [[NSDecimalNumber alloc] initWithMantissa: mantissa exponent: exponent isNegative: negative]; } return dn; } @end // ...dummy/placeholder classes... // overridden in NSTableView to be GSTableCornerView, // but the class needs to be present to be overridden. @interface _NSCornerView : NSView @end @implementation _NSCornerView @end // class needed for nib encoding/decoding by @implementation NSPSMatrix - (void) encodeWithCoder: (NSCoder *)coder { // do nothing... just encoding the presence of the class. } - (id) initWithCoder: (NSCoder *)coder { // what's NSPSMatix all about? // NSLog(@"NSPSMatrix = %@",[(NSKeyedUnarchiver *)coder keyMap]); return self; } @end