From 3f01db306e2bbde089e0b801faba71e647810328 Mon Sep 17 00:00:00 2001 From: uid65715 Date: Tue, 23 Dec 2003 18:45:18 +0000 Subject: [PATCH] Cleanup of memory management in loadNib code. Minor formatting changes in gopen and GSspell. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@18264 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 12 +++++++ Source/GSNibTemplates.m | 67 ++++++++++++++++++++++++++++++++++++-- Source/NSBundleAdditions.m | 9 ----- Tools/GSspell.m | 2 +- Tools/gopen.m | 4 +-- 5 files changed, 80 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 54f703dfe..d6ed44406 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2003-12-23 13:46 Gregory John Casamento + + * Source/GSNibTemplates.m: Added a loop which retains only the + top level objects in the nameTable. Also added some conditions + which prevent some of the special entries in the nametable from + having awakeFromNib called unnecessarily. Added code + which implements the NSTopLevelObjects undocumented feature which + allows users to get the top level objects in an array so that they + can be easily released. Tightened up memory management. + * Source/NSBundleAdditions.m: Removed extra retain which was + causing the container to leak. + 2003-12-23 18:13 Alexander Malmberg * Source/NSWindow.m (-_handleWindowNeedsDisplay:): Disable flushing diff --git a/Source/GSNibTemplates.m b/Source/GSNibTemplates.m index 09924e16a..9efd9e493 100644 --- a/Source/GSNibTemplates.m +++ b/Source/GSNibTemplates.m @@ -25,7 +25,6 @@ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// #include "gnustep/gui/config.h" #include #include #include @@ -96,6 +95,8 @@ static const int currentVersion = 1; // GSNibItem version number... NSString *key; NSArray *visible; NSMenu *menu; + NSMutableArray *topLevelObjects; + id obj; _isAwake = YES; /* @@ -162,7 +163,12 @@ static const int currentVersion = 1; // GSNibItem version number... while ((key = [enumerator nextObject]) != nil) { if ([context objectForKey: key] == nil || - [key isEqualToString: @"NSOwner"]) // we want to send the message to the owner + ([key isEqualToString: @"NSOwner"] && // we want to send the message to the owner + [key isEqualToString: @"NSWindowsMenu"] == NO && // we don't want to send a message to these menus twice, + [key isEqualToString: @"NSServicesMenu"] == NO && // if they're custom classes. + [key isEqualToString: @"NSVisible"] == NO && // also exclude any other special parts of the nameTable. + [key isEqualToString: @"NSDeferred"] == NO && + [key isEqualToString: @"NSTopLevelObjects"] == NO)) { id o; @@ -173,6 +179,63 @@ static const int currentVersion = 1; // GSNibItem version number... } } } + + + /* + * See if the user has passed in the NSTopLevelObjects key. + * This is an implementation of an undocumented, but commonly used feature + * of nib files to allow the release of the top level objects in the nib + * file. + */ + obj = [context objectForKey: @"NSTopLevelObjects"]; + if([obj isKindOfClass: [NSMutableArray class]]) + { + topLevelObjects = obj; + } + else + { + topLevelObjects = nil; + } + + /* + * Retain all "top level" items so that, when the container is released, they will remain. + */ + enumerator = [nameTable keyEnumerator]; + while ((key = [enumerator nextObject]) != nil) + { + if ([context objectForKey: key] == nil || + ([key isEqualToString: @"NSOwner"] == NO && // dont retain the owner. + [key isEqualToString: @"NSWindowsMenu"] == NO && // exclude special sections. + [key isEqualToString: @"NSServicesMenu"] == NO && + [key isEqualToString: @"NSVisible"] == NO && + [key isEqualToString: @"NSDeferred"] == NO && + [key isEqualToString: @"NSTopLevelObjects"] == NO)) + { + id o = [nameTable objectForKey: key]; + // RETAIN all top-level items... + if (([o isKindOfClass: [NSMenu class]] == YES && + [key isEqualToString: @"NSMenu"] == YES) || // the main menu... + ([o isKindOfClass: [NSWindow class]] == YES) || // any windows... + ([o isKindOfClass: [NSObject class]] == YES && + [o isKindOfClass: [NSView class]] == NO)) // any objects which are not views.. + { + if(topLevelObjects == nil) + { + // It is expected, if the NSTopLevelObjects key is not passed in, + // that the user has opted to either allow these objects to leak or + // to release them explicitly. + RETAIN(o); + } + else + { + // We don't want to do the extra retain if the items are added to the + // array, since the array will do the retain for us. When the array + // is released, the top level objects should be released as well. + [topLevelObjects addObject: o]; + } + } + } + } /* * See if there are objects that should be made visible. diff --git a/Source/NSBundleAdditions.m b/Source/NSBundleAdditions.m index 2f5a16bac..047dd4738 100644 --- a/Source/NSBundleAdditions.m +++ b/Source/NSBundleAdditions.m @@ -286,9 +286,6 @@ Class gmodel_class(void) { id obj; - // font fallback and automatic translation... - // [unarchiver decodeClassName: @"NSString" asClassName: @"GSStringProxy"]; - NSDebugLog(@"Invoking unarchiver"); [unarchiver setObjectZone: zone]; obj = [unarchiver decodeObject]; @@ -298,12 +295,6 @@ Class gmodel_class(void) { NSDebugLog(@"Calling awakeWithContext"); [obj awakeWithContext: context]; - /* - *Ok - it's all done now - just retain the nib container - *so that it will not be released when the unarchiver - *is released, and the nib contents will persist. - */ - RETAIN(obj); loaded = YES; } else diff --git a/Tools/GSspell.m b/Tools/GSspell.m index 7c9142c1d..94e8b6bfc 100644 --- a/Tools/GSspell.m +++ b/Tools/GSspell.m @@ -303,7 +303,7 @@ findMisspelledWordInString:(NSString *)stringToCheck else if(![outputScanner scanUpToCharactersFromSet: [NSCharacterSet whitespaceAndNewlineCharacterSet] - intoString: &guessWord]) + intoString: &guessWord]) { break; } diff --git a/Tools/gopen.m b/Tools/gopen.m index 920f6be7b..54f1784fb 100644 --- a/Tools/gopen.m +++ b/Tools/gopen.m @@ -84,8 +84,8 @@ main(int argc, char** argv, char **env_c) if (application) { -// Don't start the application itself but use it for file opening. -// [workspace launchApplication: application]; + // Don't start the application itself but use it for file opening. + // [workspace launchApplication: application]; } if (filetoopen)