mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 13:10:59 +00:00
Merge some of the changes from the testplant branch.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@40403 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
3d777c81fe
commit
db123bcd81
8 changed files with 1043 additions and 926 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2017-03-19 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/NSBrowser.m: Add encoding of NSColumnsAutosaveName.
|
||||
* Headers/Additions/GNUstepGUI/GSXibLoading.h,
|
||||
* Source/GSXibLoader.m,
|
||||
* Source/GSXibKeyedUnarchiver.h,
|
||||
* Source/GSXibKeyedUnarchiver.m,
|
||||
* Source/GNUmakefile: Split of GSXibKeyedUnarchiver in separate file.
|
||||
* Source/GSXibLoading.m: Add description method for IBUserDefinedRuntimeAttribute.
|
||||
Merge some of the changes from the testplant branch.
|
||||
|
||||
2017-03-05 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Headers/AppKit/NSImage.h
|
||||
|
|
|
@ -191,17 +191,4 @@
|
|||
|
||||
@end
|
||||
|
||||
|
||||
@interface GSXibKeyedUnarchiver: NSKeyedUnarchiver
|
||||
{
|
||||
NSMutableDictionary *objects;
|
||||
NSMutableArray *stack;
|
||||
GSXibElement *currentElement;
|
||||
NSMutableDictionary *decoded;
|
||||
}
|
||||
|
||||
- (id) _decodeArrayOfObjectsForElement: (GSXibElement*)element;
|
||||
- (id) _decodeDictionaryOfObjectsForElement: (GSXibElement*)element;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -254,6 +254,7 @@ GSNibLoader.m \
|
|||
GSXibElement.m \
|
||||
GSXibLoader.m \
|
||||
GSXibLoading.m \
|
||||
GSXibKeyedUnarchiver.m \
|
||||
GSXibObjectContainer.m \
|
||||
GSXibParser.m \
|
||||
GSHelpAttachment.m
|
||||
|
|
53
Source/GSXibKeyedUnarchiver.h
Normal file
53
Source/GSXibKeyedUnarchiver.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/** <title>GSXibKeyedUnarchiver.h</title>
|
||||
|
||||
<abstract>
|
||||
These are templates for use with OSX XIB 5 files. These classes are the
|
||||
templates and other things which are needed for reading XIB 5 files.
|
||||
</abstract>
|
||||
|
||||
Copyright (C) 2005,2017 Free Software Foundation, Inc.
|
||||
|
||||
File created by Marcian Lytwyn on 12/30/16 from original code by:
|
||||
|
||||
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 Lesser 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class GSXibElement;
|
||||
|
||||
@interface GSXibKeyedUnarchiver : NSKeyedUnarchiver
|
||||
{
|
||||
NSMutableDictionary *objects;
|
||||
NSMutableArray *stack;
|
||||
GSXibElement *currentElement;
|
||||
NSMutableDictionary *decoded;
|
||||
}
|
||||
|
||||
- (void) _initCommon;
|
||||
- (id) decodeObjectForXib: (GSXibElement*)element
|
||||
forClassName: (NSString*)classname
|
||||
withID: (NSString*)objID;
|
||||
- (id) _decodeArrayOfObjectsForElement: (GSXibElement*)element;
|
||||
- (id) _decodeDictionaryOfObjectsForElement: (GSXibElement*)element;
|
||||
- (id) objectForXib: (GSXibElement*)element;
|
||||
@end
|
955
Source/GSXibKeyedUnarchiver.m
Normal file
955
Source/GSXibKeyedUnarchiver.m
Normal file
|
@ -0,0 +1,955 @@
|
|||
/** <title>GSXibKeyedUnarchiver.m</title>
|
||||
|
||||
<abstract>
|
||||
These are templates for use with OSX XIB 5 files. These classes are the
|
||||
templates and other things which are needed for reading XIB 5 files.
|
||||
</abstract>
|
||||
|
||||
Copyright (C) 2005, 2017 Free Software Foundation, Inc.
|
||||
|
||||
File created by Marcian Lytwyn on 12/30/16 from original code by:
|
||||
|
||||
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 Lesser 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#import "GSXibKeyedUnarchiver.h"
|
||||
#import "GNUstepGUI/GSXibElement.h"
|
||||
#import "GNUstepGUI/GSNibLoading.h"
|
||||
|
||||
@implementation GSXibKeyedUnarchiver
|
||||
|
||||
- (NSData *) _preProcessXib: (NSData *)data
|
||||
{
|
||||
NSData *result = nil;
|
||||
|
||||
#if GNUSTEP_BASE_HAVE_LIBXML
|
||||
NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data
|
||||
options:0
|
||||
error:NULL];
|
||||
result = data;
|
||||
if (document == nil)
|
||||
{
|
||||
NSLog(@"%s:DOCUMENT IS NIL: %@\n", __PRETTY_FUNCTION__, document);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test to see if this is an Xcode 5 XIB...
|
||||
NSArray *documentNodes = [document nodesForXPath:@"/document"
|
||||
error:NULL];
|
||||
if ([documentNodes count] > 0)
|
||||
{
|
||||
NSLog(@"Unsupported... This is an XCode 5 XIB file.");
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *customClassNodes = [document nodesForXPath:@"//dictionary[@key=\"flattenedProperties\"]/"
|
||||
@"string[contains(@key,\"CustomClassName\")]"
|
||||
error:NULL];
|
||||
NSMutableDictionary *customClassDict = [NSMutableDictionary dictionary];
|
||||
if (customClassNodes)
|
||||
{
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassNodes: %@\n", __PRETTY_FUNCTION__, customClassNodes);
|
||||
|
||||
// Replace the NSXMLNodes with a dictionary...
|
||||
NSInteger index = 0;
|
||||
for (index = 0; index < [customClassNodes count]; ++index)
|
||||
{
|
||||
id node = [customClassNodes objectAtIndex:index];
|
||||
if ([node isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
NSString *key = [[node attributeForName:@"key"] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
[customClassDict setObject:[node stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *flatProps = [document nodesForXPath:@"//object[@key=\"flattenedProperties\"]" error:NULL];
|
||||
if ([flatProps count] == 1)
|
||||
{
|
||||
NSInteger index = 0;
|
||||
NSArray *xmlKeys = [[flatProps objectAtIndex:0] nodesForXPath:@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.sortedKeys\"]/*" error:NULL];
|
||||
NSArray *xmlObjs = [[flatProps objectAtIndex:0] nodesForXPath:@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.values\"]/*" error:NULL];
|
||||
if ([xmlKeys count] != [xmlObjs count])
|
||||
{
|
||||
NSLog(@"%s:keys to objs count mismatch - keys: %d objs: %d\n", __PRETTY_FUNCTION__,
|
||||
(int)[xmlKeys count], (int)[xmlObjs count]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < [xmlKeys count]; ++index)
|
||||
{
|
||||
id key = [[xmlKeys objectAtIndex:index] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
// NSString *obj = [[xmlObjs objectAtIndex:index] stringValue];
|
||||
[customClassDict setObject:[[xmlObjs objectAtIndex:index] stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassDict: %@\n", __PRETTY_FUNCTION__, customClassDict);
|
||||
|
||||
if ([customClassDict count] > 0)
|
||||
{
|
||||
NSArray *objectRecords = nil;
|
||||
NSEnumerator *en = [[customClassDict allKeys] objectEnumerator];
|
||||
NSString *key = nil;
|
||||
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
NSString *keyValue = [key stringByReplacingOccurrencesOfString:@".CustomClassName" withString:@""];
|
||||
NSString *className = [customClassDict objectForKey: key];
|
||||
NSString *objectRecordXpath = nil;
|
||||
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"int[@key=\"objectID\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
|
||||
if (objectRecords == nil)
|
||||
{
|
||||
// If that didn't work then it could be a 4.6+ XIB...
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"string[@key=\"id\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
}
|
||||
|
||||
NSString *refId = nil;
|
||||
if ([objectRecords count] > 0)
|
||||
{
|
||||
id record = nil;
|
||||
NSEnumerator *oen = [objectRecords objectEnumerator];
|
||||
while ((record = [oen nextObject]) != nil)
|
||||
{
|
||||
if ([record isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
if([[[record attributeForName:@"key"] stringValue] isEqualToString:@"object"])
|
||||
{
|
||||
NSArray *classNodes = nil;
|
||||
id classNode = nil;
|
||||
NSString *refXpath = nil;
|
||||
|
||||
refId = [[record attributeForName:@"ref"] stringValue];
|
||||
refXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]",refId];
|
||||
classNodes = [document nodesForXPath:refXpath
|
||||
error:NULL];
|
||||
if([classNodes count] > 0)
|
||||
{
|
||||
id classAttr = nil;
|
||||
Class cls = NSClassFromString(className);
|
||||
|
||||
classNode = [classNodes objectAtIndex:0];
|
||||
classAttr = [classNode attributeForName:@"class"];
|
||||
[classAttr setStringValue:className];
|
||||
|
||||
if (cls != nil)
|
||||
{
|
||||
if ([cls respondsToSelector:@selector(cellClass)])
|
||||
{
|
||||
NSArray *cellNodes = nil;
|
||||
id cellNode = nil;
|
||||
id cellClass = [cls cellClass];
|
||||
NSString *cellXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]/object[@key=\"NSCell\"]",refId];
|
||||
cellNodes = [document nodesForXPath:cellXpath
|
||||
error:NULL];
|
||||
if ([cellNodes count] > 0)
|
||||
{
|
||||
NSString *cellClassString = NSStringFromClass(cellClass);
|
||||
id cellAttr = nil;
|
||||
cellNode = [cellNodes objectAtIndex:0];
|
||||
cellAttr = [cellNode attributeForName:@"class"];
|
||||
[cellAttr setStringValue:cellClassString];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = [document XMLData];
|
||||
RELEASE(document);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) _initCommon
|
||||
{
|
||||
objects = [[NSMutableDictionary alloc] init];
|
||||
stack = [[NSMutableArray alloc] init];
|
||||
decoded = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
- (id) initForReadingWithData: (NSData*)data
|
||||
{
|
||||
#if GNUSTEP_BASE_HAVE_LIBXML
|
||||
NSXMLParser *theParser;
|
||||
NSData *theData = data;
|
||||
|
||||
// If we are in the interface builder app, do not replace
|
||||
// the existing classes with their custom subclasses.
|
||||
if ([NSClassSwapper isInInterfaceBuilder] == NO)
|
||||
{
|
||||
theData = [self _preProcessXib: data];
|
||||
}
|
||||
|
||||
if (theData == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Initialize...
|
||||
[self _initCommon];
|
||||
|
||||
theParser = [[NSXMLParser alloc] initWithData: theData];
|
||||
[theParser setDelegate: self];
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
// Parse the XML data
|
||||
[theParser parse];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Exception occurred while parsing Xib: %@",[localException reason]);
|
||||
DESTROY(self);
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
|
||||
DESTROY(theParser);
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(objects);
|
||||
DESTROY(stack);
|
||||
DESTROY(decoded);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
foundCharacters: (NSString*)string
|
||||
{
|
||||
[currentElement setValue: string];
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
didStartElement: (NSString*)elementName
|
||||
namespaceURI: (NSString*)namespaceURI
|
||||
qualifiedName: (NSString*)qualifiedName
|
||||
attributes: (NSDictionary*)attributeDict
|
||||
{
|
||||
GSXibElement *element = [[GSXibElement alloc] initWithType: elementName
|
||||
andAttributes: attributeDict];
|
||||
NSString *key = [attributeDict objectForKey: @"key"];
|
||||
NSString *ref = [attributeDict objectForKey: @"id"];
|
||||
|
||||
// FIXME: We should use proper memory management here
|
||||
AUTORELEASE(element);
|
||||
|
||||
if (key != nil)
|
||||
{
|
||||
[currentElement setElement: element forKey: key];
|
||||
}
|
||||
else
|
||||
{
|
||||
// For Arrays
|
||||
[currentElement addElement: element];
|
||||
}
|
||||
if (ref != nil)
|
||||
{
|
||||
[objects setObject: element forKey: ref];
|
||||
}
|
||||
|
||||
if (![@"archive" isEqualToString: elementName] &&
|
||||
![@"data" isEqualToString: elementName])
|
||||
{
|
||||
// only used for the root element
|
||||
// push
|
||||
[stack addObject: currentElement];
|
||||
}
|
||||
|
||||
if (![@"archive" isEqualToString: elementName])
|
||||
{
|
||||
currentElement = element;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
didEndElement: (NSString*)elementName
|
||||
namespaceURI: (NSString*)namespaceURI
|
||||
qualifiedName: (NSString*)qName
|
||||
{
|
||||
if (![@"archive" isEqualToString: elementName] &&
|
||||
![@"data" isEqualToString: elementName])
|
||||
{
|
||||
// pop
|
||||
currentElement = [stack lastObject];
|
||||
[stack removeLastObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) allocObjectForClassName: (NSString*)classname
|
||||
{
|
||||
Class c = nil;
|
||||
id delegate = [self delegate];
|
||||
|
||||
c = [self classForClassName: classname];
|
||||
|
||||
if (c == nil)
|
||||
{
|
||||
c = [[self class] classForClassName: classname];
|
||||
if (c == nil)
|
||||
{
|
||||
c = NSClassFromString(classname);
|
||||
if (c == nil)
|
||||
{
|
||||
c = [delegate unarchiver: self
|
||||
cannotDecodeObjectOfClassName: classname
|
||||
originalClasses: nil];
|
||||
if (c == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ -%@]: no class for name '%@'",
|
||||
NSStringFromClass([self class]),
|
||||
NSStringFromSelector(_cmd),
|
||||
classname];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create instance.
|
||||
return [c allocWithZone: [self zone]];
|
||||
}
|
||||
|
||||
- (BOOL) replaceObject: (id)oldObj withObject: (id)newObj
|
||||
{
|
||||
NSEnumerator *keyEnumerator = [decoded keyEnumerator];
|
||||
id key;
|
||||
BOOL found = NO;
|
||||
|
||||
while ((key = [keyEnumerator nextObject]) != nil)
|
||||
{
|
||||
id obj = [decoded objectForKey: key];
|
||||
if (obj == oldObj)
|
||||
{
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
[decoded setObject: newObj forKey: key];
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
- (id) decodeObjectForXib: (GSXibElement*)element
|
||||
forClassName: (NSString*)classname
|
||||
withID: (NSString*)objID
|
||||
{
|
||||
GSXibElement *last;
|
||||
id o, r;
|
||||
id delegate = [self delegate];
|
||||
|
||||
// Create instance.
|
||||
o = [self allocObjectForClassName: classname];
|
||||
// Make sure the object stays around, even when replaced.
|
||||
RETAIN(o);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
|
||||
// push
|
||||
last = currentElement;
|
||||
currentElement = element;
|
||||
|
||||
r = [o initWithCoder: self];
|
||||
|
||||
// pop
|
||||
currentElement = last;
|
||||
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
r = [o awakeAfterUsingCoder: self];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
if (delegate != nil)
|
||||
{
|
||||
r = [delegate unarchiver: self didDecodeObject: o];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
}
|
||||
|
||||
// Balance the retain above
|
||||
RELEASE(o);
|
||||
|
||||
if (objID != nil)
|
||||
{
|
||||
NSDebugLLog(@"XIB", @"decoded object %@ for id %@", o, objID);
|
||||
}
|
||||
|
||||
return AUTORELEASE(o);
|
||||
}
|
||||
|
||||
/*
|
||||
This method is a copy of decodeObjectForXib:forClassName:withKey:
|
||||
The only difference being in the way we decode the object and the
|
||||
missing context switch.
|
||||
*/
|
||||
- (id) decodeDictionaryForXib: (GSXibElement*)element
|
||||
forClassName: (NSString*)classname
|
||||
withID: (NSString*)objID
|
||||
{
|
||||
id o, r;
|
||||
id delegate = [self delegate];
|
||||
|
||||
// Create instance.
|
||||
o = [self allocObjectForClassName: classname];
|
||||
// Make sure the object stays around, even when replaced.
|
||||
RETAIN(o);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
|
||||
r = [o initWithDictionary: [self _decodeDictionaryOfObjectsForElement: element]];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
r = [o awakeAfterUsingCoder: self];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
if (delegate != nil)
|
||||
{
|
||||
r = [delegate unarchiver: self didDecodeObject: o];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
}
|
||||
// Balance the retain above
|
||||
RELEASE(o);
|
||||
|
||||
if (objID != nil)
|
||||
{
|
||||
NSDebugLLog(@"XIB", @"decoded object %@ for id %@", o, objID);
|
||||
}
|
||||
|
||||
return AUTORELEASE(o);
|
||||
}
|
||||
|
||||
- (id) objectForXib: (GSXibElement*)element
|
||||
{
|
||||
NSString *elementName;
|
||||
NSString *objID;
|
||||
|
||||
if (element == nil)
|
||||
return nil;
|
||||
|
||||
NSDebugLLog(@"XIB", @"decoding element %@", element);
|
||||
objID = [element attributeForKey: @"id"];
|
||||
if (objID)
|
||||
{
|
||||
id new = [decoded objectForKey: objID];
|
||||
if (new != nil)
|
||||
{
|
||||
// The object was already decoded as a reference
|
||||
return new;
|
||||
}
|
||||
}
|
||||
|
||||
elementName = [element type];
|
||||
if ([@"object" isEqualToString: elementName])
|
||||
{
|
||||
NSString *classname = [element attributeForKey: @"class"];
|
||||
return [self decodeObjectForXib: element
|
||||
forClassName: classname
|
||||
withID: objID];
|
||||
}
|
||||
else if ([@"string" isEqualToString: elementName])
|
||||
{
|
||||
NSString *type = [element attributeForKey: @"type"];
|
||||
id new = [element value];
|
||||
|
||||
if ([type isEqualToString: @"base64-UTF8"])
|
||||
{
|
||||
NSData *d = [[NSData alloc] initWithBase64EncodedString: new
|
||||
options: 0];
|
||||
new = AUTORELEASE([[NSString alloc] initWithData: d
|
||||
encoding: NSUTF8StringEncoding]);
|
||||
RELEASE(d);
|
||||
}
|
||||
|
||||
// empty strings are not nil!
|
||||
if (new == nil)
|
||||
new = @"";
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"int" isEqualToString: elementName])
|
||||
{
|
||||
id new = [NSNumber numberWithInt: [[element value] intValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"double" isEqualToString: elementName])
|
||||
{
|
||||
id new = [NSNumber numberWithDouble: [[element value] doubleValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"bool" isEqualToString: elementName])
|
||||
{
|
||||
id new = [NSNumber numberWithBool: [[element value] boolValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"integer" isEqualToString: elementName])
|
||||
{
|
||||
NSString *value = [element attributeForKey: @"value"];
|
||||
id new = [NSNumber numberWithInteger: [value integerValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"real" isEqualToString: elementName])
|
||||
{
|
||||
NSString *value = [element attributeForKey: @"value"];
|
||||
id new = [NSNumber numberWithFloat: [value floatValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"boolean" isEqualToString: elementName])
|
||||
{
|
||||
NSString *value = [element attributeForKey: @"value"];
|
||||
id new = [NSNumber numberWithBool: [value boolValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"reference" isEqualToString: elementName])
|
||||
{
|
||||
NSString *ref = [element attributeForKey: @"ref"];
|
||||
|
||||
if (ref == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
id new = [decoded objectForKey: ref];
|
||||
|
||||
// FIXME: We need a marker for nil
|
||||
if (new == nil)
|
||||
{
|
||||
//NSLog(@"Decoding reference %@", ref);
|
||||
element = [objects objectForKey: ref];
|
||||
if (element != nil)
|
||||
{
|
||||
// Decode the real object
|
||||
new = [self objectForXib: element];
|
||||
}
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
}
|
||||
else if ([@"nil" isEqualToString: elementName])
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else if ([@"characters" isEqualToString: elementName])
|
||||
{
|
||||
id new = [element value];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"bytes" isEqualToString: elementName])
|
||||
{
|
||||
id new = AUTORELEASE([[NSData alloc] initWithBase64EncodedString: [element value]
|
||||
options: 0]);
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"array" isEqualToString: elementName])
|
||||
{
|
||||
NSString *classname = [element attributeForKey: @"class"];
|
||||
|
||||
if (classname == nil)
|
||||
{
|
||||
classname = @"NSArray";
|
||||
}
|
||||
return [self decodeObjectForXib: element
|
||||
forClassName: classname
|
||||
withID: objID];
|
||||
}
|
||||
else if ([@"dictionary" isEqualToString: elementName])
|
||||
{
|
||||
NSString *classname = [element attributeForKey: @"class"];
|
||||
|
||||
if (classname == nil)
|
||||
{
|
||||
classname = @"NSDictionary";
|
||||
}
|
||||
|
||||
return [self decodeDictionaryForXib: element
|
||||
forClassName: classname
|
||||
withID: objID];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Unknown element type %@", elementName);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id) _decodeArrayOfObjectsForKey: (NSString*)aKey
|
||||
{
|
||||
// FIXME: This is wrong but the only way to keep the code for
|
||||
// [NSArray-initWithCoder:] working
|
||||
return [self _decodeArrayOfObjectsForElement: currentElement];
|
||||
}
|
||||
|
||||
- (id) _decodeArrayOfObjectsForElement: (GSXibElement*)element
|
||||
{
|
||||
NSArray *values = [element values];
|
||||
int max = [values count];
|
||||
id list[max];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
list[i] = [self objectForXib: [values objectAtIndex: i]];
|
||||
if (list[i] == nil)
|
||||
NSLog(@"No object for %@ at index %d", [values objectAtIndex: i], i);
|
||||
}
|
||||
|
||||
return [NSArray arrayWithObjects: list count: max];
|
||||
}
|
||||
|
||||
- (id) _decodeDictionaryOfObjectsForElement: (GSXibElement*)element
|
||||
{
|
||||
NSDictionary *elements = [element elements];
|
||||
NSEnumerator *en;
|
||||
NSString *key;
|
||||
NSMutableDictionary *dict;
|
||||
|
||||
dict = [[NSMutableDictionary alloc] init];
|
||||
en = [elements keyEnumerator];
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
id obj = [self objectForXib: [elements objectForKey: key]];
|
||||
if (obj == nil)
|
||||
NSLog(@"No object for %@ at key %@", [elements objectForKey: key], key);
|
||||
else
|
||||
[dict setObject: obj forKey: key];
|
||||
}
|
||||
|
||||
return AUTORELEASE(dict);
|
||||
}
|
||||
|
||||
/*
|
||||
Extension method to decode the object id of an object referenced by its key.
|
||||
*/
|
||||
- (NSString *) decodeReferenceForKey: (NSString*)aKey
|
||||
{
|
||||
GSXibElement *element = [currentElement elementForKey: aKey];
|
||||
NSString *objID;
|
||||
|
||||
if (element == nil)
|
||||
return nil;
|
||||
|
||||
objID = [element attributeForKey: @"id"];
|
||||
if (objID)
|
||||
{
|
||||
return objID;
|
||||
}
|
||||
|
||||
objID = [element attributeForKey: @"ref"];
|
||||
if (objID)
|
||||
{
|
||||
return objID;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL) containsValueForKey: (NSString*)aKey
|
||||
{
|
||||
GSXibElement *element = [currentElement elementForKey: aKey];
|
||||
|
||||
return (element != nil);
|
||||
}
|
||||
|
||||
- (id) decodeObjectForKey: (NSString*)aKey
|
||||
{
|
||||
GSXibElement *element = [currentElement elementForKey: aKey];
|
||||
|
||||
if (element == nil)
|
||||
return nil;
|
||||
|
||||
return [self objectForXib: element];
|
||||
}
|
||||
|
||||
- (BOOL) decodeBoolForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
return [o boolValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (const uint8_t*) decodeBytesForKey: (NSString*)aKey
|
||||
returnedLength: (NSUInteger*)length
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSData class]] == YES)
|
||||
{
|
||||
*length = [o length];
|
||||
return [o bytes];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
*length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (double) decodeDoubleForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
return [o doubleValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
- (float) decodeFloatForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
return [o floatValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
- (int) decodeIntForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
long long l = [o longLongValue];
|
||||
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int32_t) decodeInt32ForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
long long l = [o longLongValue];
|
||||
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int64_t) decodeInt64ForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
long long l = [o longLongValue];
|
||||
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
|
@ -48,6 +48,7 @@
|
|||
#import "GNUstepGUI/GSXibParser.h"
|
||||
#import "GNUstepGUI/GSXibObjectContainer.h"
|
||||
#import "GNUstepGUI/GSXibElement.h"
|
||||
#import "GSXibKeyedUnarchiver.h"
|
||||
|
||||
@interface NSApplication (NibCompatibility)
|
||||
- (void) _setMainMenu: (NSMenu*)aMenu;
|
||||
|
@ -1072,916 +1073,3 @@
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GSXibKeyedUnarchiver
|
||||
|
||||
- (NSData *) _preProcessXib: (NSData *)data
|
||||
{
|
||||
NSData *result = nil;
|
||||
|
||||
#if GNUSTEP_BASE_HAVE_LIBXML
|
||||
NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data
|
||||
options:0
|
||||
error:NULL];
|
||||
result = data;
|
||||
if (document == nil)
|
||||
{
|
||||
NSLog(@"%s:DOCUMENT IS NIL: %@\n", __PRETTY_FUNCTION__, document);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test to see if this is an Xcode 5 XIB...
|
||||
NSArray *documentNodes = [document nodesForXPath:@"/document"
|
||||
error:NULL];
|
||||
if ([documentNodes count] > 0)
|
||||
{
|
||||
NSLog(@"Unsupported... This is an XCode 5 XIB file.");
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *customClassNodes = [document nodesForXPath:@"//dictionary[@key=\"flattenedProperties\"]/"
|
||||
@"string[contains(@key,\"CustomClassName\")]"
|
||||
error:NULL];
|
||||
NSMutableDictionary *customClassDict = [NSMutableDictionary dictionary];
|
||||
if (customClassNodes)
|
||||
{
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassNodes: %@\n", __PRETTY_FUNCTION__, customClassNodes);
|
||||
|
||||
// Replace the NSXMLNodes with a dictionary...
|
||||
NSInteger index = 0;
|
||||
for (index = 0; index < [customClassNodes count]; ++index)
|
||||
{
|
||||
id node = [customClassNodes objectAtIndex:index];
|
||||
if ([node isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
NSString *key = [[node attributeForName:@"key"] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
[customClassDict setObject:[node stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *flatProps = [document nodesForXPath:@"//object[@key=\"flattenedProperties\"]" error:NULL];
|
||||
if ([flatProps count] == 1)
|
||||
{
|
||||
NSInteger index = 0;
|
||||
NSArray *xmlKeys = [[flatProps objectAtIndex:0] nodesForXPath:@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.sortedKeys\"]/*" error:NULL];
|
||||
NSArray *xmlObjs = [[flatProps objectAtIndex:0] nodesForXPath:@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.values\"]/*" error:NULL];
|
||||
if ([xmlKeys count] != [xmlObjs count])
|
||||
{
|
||||
NSLog(@"%s:keys to objs count mismatch - keys: %d objs: %d\n", __PRETTY_FUNCTION__,
|
||||
(int)[xmlKeys count], (int)[xmlObjs count]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < [xmlKeys count]; ++index)
|
||||
{
|
||||
id key = [[xmlKeys objectAtIndex:index] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
// NSString *obj = [[xmlObjs objectAtIndex:index] stringValue];
|
||||
[customClassDict setObject:[[xmlObjs objectAtIndex:index] stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassDict: %@\n", __PRETTY_FUNCTION__, customClassDict);
|
||||
|
||||
if ([customClassDict count] > 0)
|
||||
{
|
||||
NSArray *objectRecords = nil;
|
||||
NSEnumerator *en = [[customClassDict allKeys] objectEnumerator];
|
||||
NSString *key = nil;
|
||||
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
NSString *keyValue = [key stringByReplacingOccurrencesOfString:@".CustomClassName" withString:@""];
|
||||
NSString *className = [customClassDict objectForKey: key];
|
||||
NSString *objectRecordXpath = nil;
|
||||
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"int[@key=\"objectID\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
|
||||
if (objectRecords == nil)
|
||||
{
|
||||
// If that didn't work then it could be a 4.6+ XIB...
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"string[@key=\"id\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
}
|
||||
|
||||
NSString *refId = nil;
|
||||
if ([objectRecords count] > 0)
|
||||
{
|
||||
id record = nil;
|
||||
NSEnumerator *oen = [objectRecords objectEnumerator];
|
||||
while ((record = [oen nextObject]) != nil)
|
||||
{
|
||||
if ([record isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
if([[[record attributeForName:@"key"] stringValue] isEqualToString:@"object"])
|
||||
{
|
||||
NSArray *classNodes = nil;
|
||||
id classNode = nil;
|
||||
NSString *refXpath = nil;
|
||||
|
||||
refId = [[record attributeForName:@"ref"] stringValue];
|
||||
refXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]",refId];
|
||||
classNodes = [document nodesForXPath:refXpath
|
||||
error:NULL];
|
||||
if([classNodes count] > 0)
|
||||
{
|
||||
id classAttr = nil;
|
||||
Class cls = NSClassFromString(className);
|
||||
|
||||
classNode = [classNodes objectAtIndex:0];
|
||||
classAttr = [classNode attributeForName:@"class"];
|
||||
[classAttr setStringValue:className];
|
||||
|
||||
if (cls != nil)
|
||||
{
|
||||
if ([cls respondsToSelector:@selector(cellClass)])
|
||||
{
|
||||
NSArray *cellNodes = nil;
|
||||
id cellNode = nil;
|
||||
id cellClass = [cls cellClass];
|
||||
NSString *cellXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]/object[@key=\"NSCell\"]",refId];
|
||||
cellNodes = [document nodesForXPath:cellXpath
|
||||
error:NULL];
|
||||
if ([cellNodes count] > 0)
|
||||
{
|
||||
NSString *cellClassString = NSStringFromClass(cellClass);
|
||||
id cellAttr = nil;
|
||||
cellNode = [cellNodes objectAtIndex:0];
|
||||
cellAttr = [cellNode attributeForName:@"class"];
|
||||
[cellAttr setStringValue:cellClassString];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = [document XMLData];
|
||||
RELEASE(document);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id) initForReadingWithData: (NSData*)data
|
||||
{
|
||||
#if GNUSTEP_BASE_HAVE_LIBXML
|
||||
NSXMLParser *theParser;
|
||||
NSData *theData = data;
|
||||
|
||||
// If we are in the interface builder app, do not replace
|
||||
// the existing classes with their custom subclasses.
|
||||
if ([NSClassSwapper isInInterfaceBuilder] == NO)
|
||||
{
|
||||
theData = [self _preProcessXib: data];
|
||||
}
|
||||
|
||||
if (theData == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
objects = [[NSMutableDictionary alloc] init];
|
||||
stack = [[NSMutableArray alloc] init];
|
||||
decoded = [[NSMutableDictionary alloc] init];
|
||||
|
||||
theParser = [[NSXMLParser alloc] initWithData: theData];
|
||||
[theParser setDelegate: self];
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
// Parse the XML data
|
||||
[theParser parse];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Exception occurred while parsing Xib: %@",[localException reason]);
|
||||
DESTROY(self);
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
|
||||
DESTROY(theParser);
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(objects);
|
||||
DESTROY(stack);
|
||||
DESTROY(decoded);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
foundCharacters: (NSString*)string
|
||||
{
|
||||
[currentElement setValue: string];
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
didStartElement: (NSString*)elementName
|
||||
namespaceURI: (NSString*)namespaceURI
|
||||
qualifiedName: (NSString*)qualifiedName
|
||||
attributes: (NSDictionary*)attributeDict
|
||||
{
|
||||
GSXibElement *element = [[GSXibElement alloc] initWithType: elementName
|
||||
andAttributes: attributeDict];
|
||||
NSString *key = [attributeDict objectForKey: @"key"];
|
||||
NSString *ref = [attributeDict objectForKey: @"id"];
|
||||
|
||||
// FIXME: We should use proper memory management here
|
||||
AUTORELEASE(element);
|
||||
|
||||
if (key != nil)
|
||||
{
|
||||
[currentElement setElement: element forKey: key];
|
||||
}
|
||||
else
|
||||
{
|
||||
// For Arrays
|
||||
[currentElement addElement: element];
|
||||
}
|
||||
if (ref != nil)
|
||||
{
|
||||
[objects setObject: element forKey: ref];
|
||||
}
|
||||
|
||||
if (![@"archive" isEqualToString: elementName] &&
|
||||
![@"data" isEqualToString: elementName])
|
||||
{
|
||||
// only used for the root element
|
||||
// push
|
||||
[stack addObject: currentElement];
|
||||
}
|
||||
|
||||
if (![@"archive" isEqualToString: elementName])
|
||||
{
|
||||
currentElement = element;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
didEndElement: (NSString*)elementName
|
||||
namespaceURI: (NSString*)namespaceURI
|
||||
qualifiedName: (NSString*)qName
|
||||
{
|
||||
if (![@"archive" isEqualToString: elementName] &&
|
||||
![@"data" isEqualToString: elementName])
|
||||
{
|
||||
// pop
|
||||
currentElement = [stack lastObject];
|
||||
[stack removeLastObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) allocObjectForClassName: (NSString*)classname
|
||||
{
|
||||
Class c = nil;
|
||||
id delegate = [self delegate];
|
||||
|
||||
c = [self classForClassName: classname];
|
||||
|
||||
if (c == nil)
|
||||
{
|
||||
c = [[self class] classForClassName: classname];
|
||||
if (c == nil)
|
||||
{
|
||||
c = NSClassFromString(classname);
|
||||
if (c == nil)
|
||||
{
|
||||
c = [delegate unarchiver: self
|
||||
cannotDecodeObjectOfClassName: classname
|
||||
originalClasses: nil];
|
||||
if (c == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ -%@]: no class for name '%@'",
|
||||
NSStringFromClass([self class]),
|
||||
NSStringFromSelector(_cmd),
|
||||
classname];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create instance.
|
||||
return [c allocWithZone: [self zone]];
|
||||
}
|
||||
|
||||
- (BOOL) replaceObject: (id)oldObj withObject: (id)newObj
|
||||
{
|
||||
NSEnumerator *keyEnumerator = [decoded keyEnumerator];
|
||||
id key;
|
||||
BOOL found = NO;
|
||||
|
||||
while ((key = [keyEnumerator nextObject]) != nil)
|
||||
{
|
||||
id obj = [decoded objectForKey: key];
|
||||
if (obj == oldObj)
|
||||
{
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
[decoded setObject: newObj forKey: key];
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
- (id) decodeObjectForXib: (GSXibElement*)element
|
||||
forClassName: (NSString*)classname
|
||||
withID: (NSString*)objID
|
||||
{
|
||||
GSXibElement *last;
|
||||
id o, r;
|
||||
id delegate = [self delegate];
|
||||
|
||||
// Create instance.
|
||||
o = [self allocObjectForClassName: classname];
|
||||
// Make sure the object stays around, even when replaced.
|
||||
RETAIN(o);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
|
||||
// push
|
||||
last = currentElement;
|
||||
currentElement = element;
|
||||
|
||||
r = [o initWithCoder: self];
|
||||
|
||||
// pop
|
||||
currentElement = last;
|
||||
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
r = [o awakeAfterUsingCoder: self];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
if (delegate != nil)
|
||||
{
|
||||
r = [delegate unarchiver: self didDecodeObject: o];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
}
|
||||
|
||||
// Balance the retain above
|
||||
RELEASE(o);
|
||||
|
||||
if (objID != nil)
|
||||
{
|
||||
NSDebugLLog(@"XIB", @"decoded object %@ for id %@", o, objID);
|
||||
}
|
||||
|
||||
return AUTORELEASE(o);
|
||||
}
|
||||
|
||||
/*
|
||||
This method is a copy of decodeObjectForXib:forClassName:withKey:
|
||||
The only difference being in the way we decode the object and the
|
||||
missing context switch.
|
||||
*/
|
||||
- (id) decodeDictionaryForXib: (GSXibElement*)element
|
||||
forClassName: (NSString*)classname
|
||||
withID: (NSString*)objID
|
||||
{
|
||||
id o, r;
|
||||
id delegate = [self delegate];
|
||||
|
||||
// Create instance.
|
||||
o = [self allocObjectForClassName: classname];
|
||||
// Make sure the object stays around, even when replaced.
|
||||
RETAIN(o);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
|
||||
r = [o initWithDictionary: [self _decodeDictionaryOfObjectsForElement: element]];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
r = [o awakeAfterUsingCoder: self];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
|
||||
if (delegate != nil)
|
||||
{
|
||||
r = [delegate unarchiver: self didDecodeObject: o];
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
willReplaceObject: o
|
||||
withObject: r];
|
||||
ASSIGN(o, r);
|
||||
if (objID != nil)
|
||||
[decoded setObject: o forKey: objID];
|
||||
}
|
||||
}
|
||||
// Balance the retain above
|
||||
RELEASE(o);
|
||||
|
||||
if (objID != nil)
|
||||
{
|
||||
NSDebugLLog(@"XIB", @"decoded object %@ for id %@", o, objID);
|
||||
}
|
||||
|
||||
return AUTORELEASE(o);
|
||||
}
|
||||
|
||||
- (id) objectForXib: (GSXibElement*)element
|
||||
{
|
||||
NSString *elementName;
|
||||
NSString *objID;
|
||||
|
||||
if (element == nil)
|
||||
return nil;
|
||||
|
||||
NSDebugLLog(@"XIB", @"decoding element %@", element);
|
||||
objID = [element attributeForKey: @"id"];
|
||||
if (objID)
|
||||
{
|
||||
id new = [decoded objectForKey: objID];
|
||||
if (new != nil)
|
||||
{
|
||||
// The object was already decoded as a reference
|
||||
return new;
|
||||
}
|
||||
}
|
||||
|
||||
elementName = [element type];
|
||||
if ([@"object" isEqualToString: elementName])
|
||||
{
|
||||
NSString *classname = [element attributeForKey: @"class"];
|
||||
return [self decodeObjectForXib: element
|
||||
forClassName: classname
|
||||
withID: objID];
|
||||
}
|
||||
else if ([@"string" isEqualToString: elementName])
|
||||
{
|
||||
NSString *type = [element attributeForKey: @"type"];
|
||||
id new = [element value];
|
||||
|
||||
if ([type isEqualToString: @"base64-UTF8"])
|
||||
{
|
||||
NSData *d = [[NSData alloc] initWithBase64EncodedString: new
|
||||
options: 0];
|
||||
new = AUTORELEASE([[NSString alloc] initWithData: d
|
||||
encoding: NSUTF8StringEncoding]);
|
||||
RELEASE(d);
|
||||
}
|
||||
|
||||
// empty strings are not nil!
|
||||
if (new == nil)
|
||||
new = @"";
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"int" isEqualToString: elementName])
|
||||
{
|
||||
id new = [NSNumber numberWithInt: [[element value] intValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"double" isEqualToString: elementName])
|
||||
{
|
||||
id new = [NSNumber numberWithDouble: [[element value] doubleValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"bool" isEqualToString: elementName])
|
||||
{
|
||||
id new = [NSNumber numberWithBool: [[element value] boolValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"integer" isEqualToString: elementName])
|
||||
{
|
||||
NSString *value = [element attributeForKey: @"value"];
|
||||
id new = [NSNumber numberWithInteger: [value integerValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"real" isEqualToString: elementName])
|
||||
{
|
||||
NSString *value = [element attributeForKey: @"value"];
|
||||
id new = [NSNumber numberWithFloat: [value floatValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"boolean" isEqualToString: elementName])
|
||||
{
|
||||
NSString *value = [element attributeForKey: @"value"];
|
||||
id new = [NSNumber numberWithBool: [value boolValue]];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"reference" isEqualToString: elementName])
|
||||
{
|
||||
NSString *ref = [element attributeForKey: @"ref"];
|
||||
|
||||
if (ref == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
id new = [decoded objectForKey: ref];
|
||||
|
||||
// FIXME: We need a marker for nil
|
||||
if (new == nil)
|
||||
{
|
||||
//NSLog(@"Decoding reference %@", ref);
|
||||
element = [objects objectForKey: ref];
|
||||
if (element != nil)
|
||||
{
|
||||
// Decode the real object
|
||||
new = [self objectForXib: element];
|
||||
}
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
}
|
||||
else if ([@"nil" isEqualToString: elementName])
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else if ([@"characters" isEqualToString: elementName])
|
||||
{
|
||||
id new = [element value];
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"bytes" isEqualToString: elementName])
|
||||
{
|
||||
id new = AUTORELEASE([[NSData alloc] initWithBase64EncodedString: [element value]
|
||||
options: 0]);
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"array" isEqualToString: elementName])
|
||||
{
|
||||
NSString *classname = [element attributeForKey: @"class"];
|
||||
|
||||
if (classname == nil)
|
||||
{
|
||||
classname = @"NSArray";
|
||||
}
|
||||
return [self decodeObjectForXib: element
|
||||
forClassName: classname
|
||||
withID: objID];
|
||||
}
|
||||
else if ([@"dictionary" isEqualToString: elementName])
|
||||
{
|
||||
NSString *classname = [element attributeForKey: @"class"];
|
||||
|
||||
if (classname == nil)
|
||||
{
|
||||
classname = @"NSDictionary";
|
||||
}
|
||||
|
||||
return [self decodeDictionaryForXib: element
|
||||
forClassName: classname
|
||||
withID: objID];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Unknown element type %@", elementName);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id) _decodeArrayOfObjectsForKey: (NSString*)aKey
|
||||
{
|
||||
// FIXME: This is wrong but the only way to keep the code for
|
||||
// [NSArray-initWithCoder:] working
|
||||
return [self _decodeArrayOfObjectsForElement: currentElement];
|
||||
}
|
||||
|
||||
- (id) _decodeArrayOfObjectsForElement: (GSXibElement*)element
|
||||
{
|
||||
NSArray *values = [element values];
|
||||
int max = [values count];
|
||||
id list[max];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
list[i] = [self objectForXib: [values objectAtIndex: i]];
|
||||
if (list[i] == nil)
|
||||
NSLog(@"No object for %@ at index %d", [values objectAtIndex: i], i);
|
||||
}
|
||||
|
||||
return [NSArray arrayWithObjects: list count: max];
|
||||
}
|
||||
|
||||
- (id) _decodeDictionaryOfObjectsForElement: (GSXibElement*)element
|
||||
{
|
||||
NSDictionary *elements = [element elements];
|
||||
NSEnumerator *en;
|
||||
NSString *key;
|
||||
NSMutableDictionary *dict;
|
||||
|
||||
dict = [[NSMutableDictionary alloc] init];
|
||||
en = [elements keyEnumerator];
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
id obj = [self objectForXib: [elements objectForKey: key]];
|
||||
if (obj == nil)
|
||||
NSLog(@"No object for %@ at key %@", [elements objectForKey: key], key);
|
||||
else
|
||||
[dict setObject: obj forKey: key];
|
||||
}
|
||||
|
||||
return AUTORELEASE(dict);
|
||||
}
|
||||
|
||||
/*
|
||||
Extension method to decode the object id of an object referenced by its key.
|
||||
*/
|
||||
- (NSString *) decodeReferenceForKey: (NSString*)aKey
|
||||
{
|
||||
GSXibElement *element = [currentElement elementForKey: aKey];
|
||||
NSString *objID;
|
||||
|
||||
if (element == nil)
|
||||
return nil;
|
||||
|
||||
objID = [element attributeForKey: @"id"];
|
||||
if (objID)
|
||||
{
|
||||
return objID;
|
||||
}
|
||||
|
||||
objID = [element attributeForKey: @"ref"];
|
||||
if (objID)
|
||||
{
|
||||
return objID;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL) containsValueForKey: (NSString*)aKey
|
||||
{
|
||||
GSXibElement *element = [currentElement elementForKey: aKey];
|
||||
|
||||
return (element != nil);
|
||||
}
|
||||
|
||||
- (id) decodeObjectForKey: (NSString*)aKey
|
||||
{
|
||||
GSXibElement *element = [currentElement elementForKey: aKey];
|
||||
|
||||
if (element == nil)
|
||||
return nil;
|
||||
|
||||
return [self objectForXib: element];
|
||||
}
|
||||
|
||||
- (BOOL) decodeBoolForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
return [o boolValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (const uint8_t*) decodeBytesForKey: (NSString*)aKey
|
||||
returnedLength: (NSUInteger*)length
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSData class]] == YES)
|
||||
{
|
||||
*length = [o length];
|
||||
return [o bytes];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
*length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (double) decodeDoubleForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
return [o doubleValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
- (float) decodeFloatForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
return [o floatValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
- (int) decodeIntForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
long long l = [o longLongValue];
|
||||
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int32_t) decodeInt32ForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
long long l = [o longLongValue];
|
||||
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int64_t) decodeInt64ForKey: (NSString*)aKey
|
||||
{
|
||||
id o = [self decodeObjectForKey: aKey];
|
||||
|
||||
if (o != nil)
|
||||
{
|
||||
if ([o isKindOfClass: [NSNumber class]] == YES)
|
||||
{
|
||||
long long l = [o longLongValue];
|
||||
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidUnarchiveOperationException
|
||||
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
aKey, o];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -65,6 +65,18 @@
|
|||
return value;
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
NSMutableString *description = [[super description] mutableCopy];
|
||||
|
||||
[description appendString: @" <"];
|
||||
[description appendFormat: @" type: %@", typeIdentifier];
|
||||
[description appendFormat: @" keyPath: %@", keyPath];
|
||||
[description appendFormat: @" value: %@", value];
|
||||
[description appendString: @">"];
|
||||
return AUTORELEASE(description);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBUserDefinedRuntimeAttributesPlaceholder
|
||||
|
|
|
@ -2870,6 +2870,10 @@ static BOOL browserUseBezels;
|
|||
|
||||
[aCoder encodeInt: _columnResizing forKey: @"NSColumnResizingType"];
|
||||
//[aCoder encodeInt: prefWidth forKey: @"NSPreferedColumnWidth"];
|
||||
if (nil != [self columnsAutosaveName])
|
||||
{
|
||||
[aCoder encodeObject: [self columnsAutosaveName] forKey: @"NSColumnsAutosaveName"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3024,6 +3028,12 @@ static BOOL browserUseBezels;
|
|||
{
|
||||
//int prefWidth = [aDecoder decodeIntForKey: @"NSPreferedColumnWidth"];
|
||||
}
|
||||
|
||||
if ([aDecoder containsValueForKey: @"NSColumnsAutosaveName"])
|
||||
{
|
||||
[self setColumnsAutosaveName: [aDecoder decodeObjectForKey:
|
||||
@"NSColumnsAutosaveName"]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue