Fixed NSUndoManager bug #14448 by extending NSInvocation with the possibility to retain or not the target

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21721 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Quentin Mathe 2005-09-17 21:41:12 +00:00
parent 2bbc7e41a6
commit 3df62a4799
4 changed files with 79 additions and 32 deletions

View file

@ -1,3 +1,18 @@
2005-09-17 Saso Kiselkov <diablos@manga.sk>
* Headers/Foundation/NSInvocation.h:
* Source/NSInvocation.m:
(-targetRetained, -retainArgumentsIncludingTarget:):
Added new methods which allow target to be not retained when arguments
are and to check whether it is retained or not (-retainsArguments code
moved in -retainArgumentsIncludingTarged and simplified by removing a
redundant nested branch statement).
* Source/NSUndoManager.m (-forwardInvocation:,
-registerUndoWithTarget:selector:object:): Fixed bug #14488 by relying
on previous new methods to retain undo invocation (taking in account
the fact arguments may have been released before it is called).
Patch committed by Quentin Mathe.
2005-09-01 Adam Fedor <fedor@gnu.org>
* Source/NSSortDescriptor.m ([NSArray

View file

@ -42,6 +42,7 @@
void *_dummy;
#endif
BOOL _argsRetained;
BOOL _targetRetained;
BOOL _validReturn;
BOOL _sendToSuper;
}
@ -71,6 +72,11 @@
- (BOOL) argumentsRetained;
- (void) retainArguments;
#if OS_API_VERSION(GS_API_NONE,GS_API_NONE) && GS_API_VERSION(011201,GS_API_LATEST)
- (BOOL) targetRetained;
- (void) retainArgumentsIncludingTarget: (BOOL)retainTargetFlag;
#endif
/*
* Dispatching an Invocation.
*/

View file

@ -189,9 +189,13 @@ _arg_addr(NSInvocation *inv, int index)
- (void) dealloc
{
if (_targetRetained)
{
_targetRetained = NO;
RELEASE(_target);
}
if (_argsRetained)
{
RELEASE(_target);
_argsRetained = NO;
if (_cframe && _sig)
{
@ -437,11 +441,14 @@ _arg_addr(NSInvocation *inv, int index)
*/
- (void) setTarget: (id)anObject
{
if (_argsRetained)
if (_targetRetained)
{
ASSIGN(_target, anObject);
}
_target = anObject;
else
{
_target = anObject;
}
}
/**
@ -463,55 +470,73 @@ _arg_addr(NSInvocation *inv, int index)
/**
* Instructs the invocation to retain its object arguments (including the
* target). The default is not to retain them.
* target). The default is not to retain them.
*/
- (void) retainArguments
{
if (_argsRetained)
{
return;
}
else
[self retainArgumentsIncludingTarget: YES];
}
/**
* Returns YES if target has been retained yet, NO otherwise.
*/
- (BOOL) targetRetained
{
return _targetRetained;
}
/**
* Similar to -[NSInvocation retainArguments], but allows the sender to
* explicitly control whether the target is retained as well. Retaining
* the target is sometimes not desirable (such as in NSUndoManager), as
* retain loops could result.
*/
- (void) retainArgumentsIncludingTarget: (BOOL)retainTargetFlag
{
if (_argsRetained == NO)
{
unsigned int i;
_argsRetained = YES;
IF_NO_GC(RETAIN(_target));
if (_cframe == 0)
{
return;
}
for (i = 3; i <= _numArgs; i++)
{
if (*_info[i].type == _C_ID || *_info[i].type == _C_CHARPTR)
if (*_info[i].type == _C_ID)
{
if (*_info[i].type == _C_ID)
{
id old;
id old;
_get_arg(self, i-1, &old);
if (old != nil)
{
IF_NO_GC(RETAIN(old));
}
_get_arg(self, i-1, &old);
if (old != nil)
{
IF_NO_GC(RETAIN(old));
}
else
{
char *str;
}
else if (*_info[i].type == _C_CHARPTR)
{
char *str;
_get_arg(self, i-1, &str);
if (str != 0)
{
char *tmp;
_get_arg(self, i-1, &str);
if (str != 0)
{
char *tmp;
tmp = NSZoneMalloc(NSDefaultMallocZone(), strlen(str)+1);
strcpy(tmp, str);
_set_arg(self, i-1, &tmp);
}
tmp = NSZoneMalloc(NSDefaultMallocZone(), strlen(str)+1);
strcpy(tmp, str);
_set_arg(self, i-1, &tmp);
}
}
}
}
}
if (retainTargetFlag && _targetRetained == NO)
{
_targetRetained = YES;
IF_NO_GC(RETAIN(_target));
}
}
/**

View file

@ -425,6 +425,7 @@
format: @"forwardInvocation without beginUndoGrouping"];
}
}
[anInvocation retainArgumentsIncludingTarget: NO];
[anInvocation setTarget: _nextTarget];
_nextTarget = nil;
[_group addInvocation: anInvocation];
@ -726,7 +727,7 @@
g = _group;
sig = [target methodSignatureForSelector: aSelector];
inv = [NSInvocation invocationWithMethodSignature: sig];
[inv retainArguments];
[inv retainArgumentsIncludingTarget: NO];
[inv setTarget: target];
[inv setSelector: aSelector];
[inv setArgument: &anObject atIndex: 2];