Attributed string fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6208 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 2000-03-08 08:38:42 +00:00
parent 433d24fdb6
commit 2086baecd1
2 changed files with 200 additions and 175 deletions

View file

@ -1,3 +1,8 @@
Wed Mar 08 07:40:00 2000 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/NSAttributedString.m: Bugfix by fred Kiefer for extending
attributes. Related bugfixes by me, plus tidying up.
2000-03-06 Adam Fedor <fedor@gnu.org> 2000-03-06 Adam Fedor <fedor@gnu.org>
* config.guess: Better guess of NetBSD systems. * config.guess: Better guess of NetBSD systems.

View file

@ -138,10 +138,10 @@ static Class NSMutableAttributedString_concrete_class;
//NSCopying protocol //NSCopying protocol
- (id) copyWithZone: (NSZone*)zone - (id) copyWithZone: (NSZone*)zone
{ {
if ([self isKindOfClass: [NSMutableAttributedString class]] || if ([self isKindOfClass: [NSMutableAttributedString class]]
NSShouldRetainWithZone(self, zone) == NO) || NSShouldRetainWithZone(self, zone) == NO)
return [[[[self class] _concreteClass] allocWithZone: zone] return [[[[self class] _concreteClass] allocWithZone: zone]
initWithAttributedString: self]; initWithAttributedString: self];
else else
return RETAIN(self); return RETAIN(self);
} }
@ -150,7 +150,7 @@ static Class NSMutableAttributedString_concrete_class;
- (id) mutableCopyWithZone: (NSZone*)zone - (id) mutableCopyWithZone: (NSZone*)zone
{ {
return [[[[self class] _mutableConcreteClass] allocWithZone: zone] return [[[[self class] _mutableConcreteClass] allocWithZone: zone]
initWithAttributedString: self]; initWithAttributedString: self];
} }
//Creating an NSAttributedString //Creating an NSAttributedString
@ -182,7 +182,7 @@ static Class NSMutableAttributedString_concrete_class;
return [[self string] length]; return [[self string] length];
} }
- (NSString *) string - (NSString*) string
{ {
[self subclassResponsibility: _cmd];/* Primitive method! */ [self subclassResponsibility: _cmd];/* Primitive method! */
return nil; return nil;
@ -212,24 +212,28 @@ static Class NSMutableAttributedString_concrete_class;
if (!aRange) if (!aRange)
return attrDictionary; return attrDictionary;
while(aRange->location > rangeLimit.location) while (aRange->location > rangeLimit.location)
{ {
//Check extend range backwards //Check extend range backwards
tmpDictionary = tmpDictionary =
[self attributesAtIndex: aRange->location-1 [self attributesAtIndex: aRange->location-1
effectiveRange: &tmpRange]; effectiveRange: &tmpRange];
if ([tmpDictionary isEqualToDictionary: attrDictionary]) if ([tmpDictionary isEqualToDictionary: attrDictionary])
aRange->location = tmpRange.location; aRange->location = tmpRange.location;
} else
while(NSMaxRange(*aRange) < NSMaxRange(rangeLimit)) break;
{ }
//Check extend range forwards while (NSMaxRange(*aRange) < NSMaxRange(rangeLimit))
tmpDictionary = {
[self attributesAtIndex: NSMaxRange(*aRange) //Check extend range forwards
effectiveRange: &tmpRange]; tmpDictionary =
if ([tmpDictionary isEqualToDictionary: attrDictionary]) [self attributesAtIndex: NSMaxRange(*aRange)
aRange->length = NSMaxRange(tmpRange) - aRange->location; effectiveRange: &tmpRange];
} if ([tmpDictionary isEqualToDictionary: attrDictionary])
aRange->length = NSMaxRange(tmpRange) - aRange->location;
else
break;
}
*aRange = NSIntersectionRange(*aRange,rangeLimit);//Clip to rangeLimit *aRange = NSIntersectionRange(*aRange,rangeLimit);//Clip to rangeLimit
return attrDictionary; return attrDictionary;
} }
@ -245,29 +249,30 @@ static Class NSMutableAttributedString_concrete_class;
//Raises exception if index is out of range, so that I don't have to test this... //Raises exception if index is out of range, so that I don't have to test this...
if (!attributeName) if (!attributeName)
{ {
if (aRange) if (aRange)
*aRange = NSMakeRange(0,[self length]); *aRange = NSMakeRange(0,[self length]);
//If attributeName is nil, then the attribute will not exist in the //If attributeName is nil, then the attribute will not exist in the
//entire text - therefore aRange of the entire text must be correct //entire text - therefore aRange of the entire text must be correct
return nil; return nil;
} }
attrValue = [tmpDictionary objectForKey: attributeName]; attrValue = [tmpDictionary objectForKey: attributeName];
return attrValue; return attrValue;
} }
- (id) attribute: (NSString*)attributeName atIndex: (unsigned int)index longestEffectiveRange: (NSRange *)aRange inRange: (NSRange)rangeLimit - (id) attribute: (NSString*)attributeName atIndex: (unsigned int)index
longestEffectiveRange: (NSRange*)aRange inRange: (NSRange)rangeLimit
{ {
NSDictionary *tmpDictionary; NSDictionary *tmpDictionary;
id attrValue,tmpAttrValue; id attrValue,tmpAttrValue;
NSRange tmpRange; NSRange tmpRange;
if (rangeLimit.location < 0 || NSMaxRange(rangeLimit) > [self length]) if (rangeLimit.location < 0 || NSMaxRange(rangeLimit) > [self length])
{ {
[NSException raise: NSRangeException format: [NSException raise: NSRangeException format:
@"RangeError in method -attribute: atIndex: longestEffectiveRange: inRange: in class NSAttributedString"]; @"RangeError in method -attribute: atIndex: longestEffectiveRange: inRange: in class NSAttributedString"];
} }
attrValue = [self attribute: attributeName atIndex: index effectiveRange: aRange]; attrValue = [self attribute: attributeName atIndex: index effectiveRange: aRange];
//Raises exception if index is out of range, so that I don't have to test this... //Raises exception if index is out of range, so that I don't have to test this...
@ -277,32 +282,36 @@ static Class NSMutableAttributedString_concrete_class;
if (!aRange) if (!aRange)
return attrValue; return attrValue;
while(aRange->location > rangeLimit.location) while (aRange->location > rangeLimit.location)
{ {
//Check extend range backwards //Check extend range backwards
tmpDictionary = tmpDictionary =
[self attributesAtIndex: aRange->location-1 [self attributesAtIndex: aRange->location-1
effectiveRange: &tmpRange]; effectiveRange: &tmpRange];
tmpAttrValue = [tmpDictionary objectForKey: attributeName]; tmpAttrValue = [tmpDictionary objectForKey: attributeName];
if (tmpAttrValue == attrValue) if (tmpAttrValue == attrValue)
aRange->location = tmpRange.location; aRange->location = tmpRange.location;
} else
while(NSMaxRange(*aRange) < NSMaxRange(rangeLimit)) break;
{ }
//Check extend range forwards while (NSMaxRange(*aRange) < NSMaxRange(rangeLimit))
tmpDictionary = {
[self attributesAtIndex: NSMaxRange(*aRange) //Check extend range forwards
effectiveRange: &tmpRange]; tmpDictionary =
tmpAttrValue = [tmpDictionary objectForKey: attributeName]; [self attributesAtIndex: NSMaxRange(*aRange)
if (tmpAttrValue == attrValue) effectiveRange: &tmpRange];
aRange->length = NSMaxRange(tmpRange) - aRange->location; tmpAttrValue = [tmpDictionary objectForKey: attributeName];
} if (tmpAttrValue == attrValue)
aRange->length = NSMaxRange(tmpRange) - aRange->location;
else
break;
}
*aRange = NSIntersectionRange(*aRange,rangeLimit);//Clip to rangeLimit *aRange = NSIntersectionRange(*aRange,rangeLimit);//Clip to rangeLimit
return attrValue; return attrValue;
} }
//Comparing attributed strings //Comparing attributed strings
- (BOOL) isEqualToAttributedString: (NSAttributedString *)otherString - (BOOL) isEqualToAttributedString: (NSAttributedString*)otherString
{ {
NSRange ownEffectiveRange,otherEffectiveRange; NSRange ownEffectiveRange,otherEffectiveRange;
unsigned int length; unsigned int length;
@ -324,29 +333,29 @@ static Class NSMutableAttributedString_concrete_class;
effectiveRange: &otherEffectiveRange]; effectiveRange: &otherEffectiveRange];
result = YES; result = YES;
while(YES) while (YES)
{
if (NSIntersectionRange(ownEffectiveRange,otherEffectiveRange).length > 0 &&
![ownDictionary isEqualToDictionary: otherDictionary])
{ {
result = NO; if (NSIntersectionRange(ownEffectiveRange, otherEffectiveRange).length > 0
break; && ![ownDictionary isEqualToDictionary: otherDictionary])
{
result = NO;
break;
}
if (NSMaxRange(ownEffectiveRange) < NSMaxRange(otherEffectiveRange))
{
ownDictionary = [self
attributesAtIndex: NSMaxRange(ownEffectiveRange)
effectiveRange: &ownEffectiveRange];
}
else
{
if (NSMaxRange(otherEffectiveRange) >= length)
break;//End of strings
otherDictionary = [otherString
attributesAtIndex: NSMaxRange(otherEffectiveRange)
effectiveRange: &otherEffectiveRange];
}
} }
if (NSMaxRange(ownEffectiveRange) < NSMaxRange(otherEffectiveRange))
{
ownDictionary = [self
attributesAtIndex: NSMaxRange(ownEffectiveRange)
effectiveRange: &ownEffectiveRange];
}
else
{
if (NSMaxRange(otherEffectiveRange) >= length)
break;//End of strings
otherDictionary = [otherString
attributesAtIndex: NSMaxRange(otherEffectiveRange)
effectiveRange: &otherEffectiveRange];
}
}
return result; return result;
} }
@ -361,7 +370,7 @@ static Class NSMutableAttributedString_concrete_class;
//Extracting a substring //Extracting a substring
- (NSAttributedString *) attributedSubstringFromRange: (NSRange)aRange - (NSAttributedString*) attributedSubstringFromRange: (NSRange)aRange
{ {
NSAttributedString *newAttrString; NSAttributedString *newAttrString;
NSString *newSubstring; NSString *newSubstring;
@ -418,7 +427,7 @@ static Class NSMutableAttributedString_concrete_class;
} }
//Retrieving character information //Retrieving character information
- (NSMutableString *) mutableString - (NSMutableString*) mutableString
{ {
return [GSMutableAttributedStringTracker stringWithOwner: self]; return [GSMutableAttributedStringTracker stringWithOwner: self];
} }
@ -430,161 +439,172 @@ static Class NSMutableAttributedString_concrete_class;
} }
//Changing attributes //Changing attributes
- (void) setAttributes: (NSDictionary *)attributes range: (NSRange)aRange - (void) setAttributes: (NSDictionary*)attributes range: (NSRange)aRange
{ {
[self subclassResponsibility: _cmd];// Primitive method! [self subclassResponsibility: _cmd];// Primitive method!
} }
- (void) addAttribute: (NSString *)name value: (id)value range: (NSRange)aRange - (void) addAttribute: (NSString*)name value: (id)value range: (NSRange)aRange
{ {
NSRange effectiveRange; NSRange effectiveRange;
NSDictionary *attrDict; NSDictionary *attrDict;
NSMutableDictionary *newDict; NSMutableDictionary *newDict;
unsigned int tmpLength; unsigned int tmpLength;
tmpLength = [self length]; tmpLength = [self length];
GS_RANGE_CHECK(aRange, tmpLength); GS_RANGE_CHECK(aRange, tmpLength);
attrDict = [self attributesAtIndex: aRange.location attrDict = [self attributesAtIndex: aRange.location
effectiveRange: &effectiveRange]; effectiveRange: &effectiveRange];
while(effectiveRange.location < NSMaxRange(aRange)) while (effectiveRange.location < NSMaxRange(aRange))
{
effectiveRange = NSIntersectionRange(aRange,effectiveRange);
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
IF_NO_GC(AUTORELEASE(newDict));
[newDict setObject: value forKey: name];
[self setAttributes: newDict range: effectiveRange];
if (NSMaxRange(effectiveRange) >= NSMaxRange(aRange))
effectiveRange.location = NSMaxRange(aRange);//This stops the loop...
else if (NSMaxRange(effectiveRange) < tmpLength)
{ {
attrDict = [self attributesAtIndex: NSMaxRange(effectiveRange) effectiveRange = NSIntersectionRange(aRange, effectiveRange);
effectiveRange: &effectiveRange];
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
IF_NO_GC(AUTORELEASE(newDict));
[newDict setObject: value forKey: name];
[self setAttributes: newDict range: effectiveRange];
if (NSMaxRange(effectiveRange) >= NSMaxRange(aRange))
{
effectiveRange.location = NSMaxRange(aRange);//This stops the loop...
}
else if (NSMaxRange(effectiveRange) < tmpLength)
{
attrDict = [self attributesAtIndex: NSMaxRange(effectiveRange)
effectiveRange: &effectiveRange];
}
} }
}
} }
- (void) addAttributes: (NSDictionary *)attributes range: (NSRange)aRange - (void) addAttributes: (NSDictionary*)attributes range: (NSRange)aRange
{ {
NSRange effectiveRange; NSRange effectiveRange;
NSDictionary *attrDict; NSDictionary *attrDict;
NSMutableDictionary *newDict; NSMutableDictionary *newDict;
unsigned int tmpLength; unsigned int tmpLength;
if (!attributes) if (!attributes)
{ {
//I cannot use NSParameterAssert here, if is has to be an NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
[NSException raise: NSInvalidArgumentException format: @"attributes is nil in method -addAttributes:range: "
format: @"attributes is nil in method -addAttributes: range: in class NSMutableAtrributedString"]; @"in class NSMutableAtrributedString"];
} }
tmpLength = [self length]; tmpLength = [self length];
if (aRange.location <= 0 || NSMaxRange(aRange) > tmpLength) if (aRange.location <= 0 || NSMaxRange(aRange) > tmpLength)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
format: @"RangeError in method -addAttribute: value: range: in class NSMutableAttributedString"]; format: @"RangeError in method -addAttribute:value:range: "
} @"in class NSMutableAttributedString"];
}
attrDict = [self attributesAtIndex: aRange.location attrDict = [self attributesAtIndex: aRange.location
effectiveRange: &effectiveRange]; effectiveRange: &effectiveRange];
while(effectiveRange.location < NSMaxRange(aRange)) while (effectiveRange.location < NSMaxRange(aRange))
{
effectiveRange = NSIntersectionRange(aRange,effectiveRange);
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
IF_NO_GC(AUTORELEASE(newDict));
[newDict addEntriesFromDictionary: attributes];
[self setAttributes: newDict range: effectiveRange];
if (NSMaxRange(effectiveRange) >= NSMaxRange(aRange))
effectiveRange.location = NSMaxRange(aRange);//This stops the loop...
else if (NSMaxRange(effectiveRange) < tmpLength)
{ {
attrDict = [self attributesAtIndex: NSMaxRange(effectiveRange) effectiveRange = NSIntersectionRange(aRange,effectiveRange);
effectiveRange: &effectiveRange];
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
IF_NO_GC(AUTORELEASE(newDict));
[newDict addEntriesFromDictionary: attributes];
[self setAttributes: newDict range: effectiveRange];
if (NSMaxRange(effectiveRange) >= NSMaxRange(aRange))
{
effectiveRange.location = NSMaxRange(aRange);//This stops the loop...
}
else if (NSMaxRange(effectiveRange) < tmpLength)
{
attrDict = [self attributesAtIndex: NSMaxRange(effectiveRange)
effectiveRange: &effectiveRange];
}
} }
}
} }
- (void) removeAttribute: (NSString *)name range: (NSRange)aRange - (void) removeAttribute: (NSString*)name range: (NSRange)aRange
{ {
NSRange effectiveRange; NSRange effectiveRange;
NSDictionary *attrDict; NSDictionary *attrDict;
NSMutableDictionary *newDict; NSMutableDictionary *newDict;
unsigned int tmpLength; unsigned int tmpLength;
tmpLength = [self length]; tmpLength = [self length];
GS_RANGE_CHECK(aRange, tmpLength); GS_RANGE_CHECK(aRange, tmpLength);
attrDict = [self attributesAtIndex: aRange.location attrDict = [self attributesAtIndex: aRange.location
effectiveRange: &effectiveRange]; effectiveRange: &effectiveRange];
while(effectiveRange.location < NSMaxRange(aRange)) while (effectiveRange.location < NSMaxRange(aRange))
{
effectiveRange = NSIntersectionRange(aRange,effectiveRange);
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
IF_NO_GC(AUTORELEASE(newDict));
[newDict removeObjectForKey: name];
[self setAttributes: newDict range: effectiveRange];
if (NSMaxRange(effectiveRange) >= NSMaxRange(aRange))
effectiveRange.location = NSMaxRange(aRange);//This stops the loop...
else if (NSMaxRange(effectiveRange) < tmpLength)
{ {
attrDict = [self attributesAtIndex: NSMaxRange(effectiveRange) effectiveRange = NSIntersectionRange(aRange,effectiveRange);
effectiveRange: &effectiveRange];
newDict = [[NSMutableDictionary alloc] initWithDictionary: attrDict];
IF_NO_GC(AUTORELEASE(newDict));
[newDict removeObjectForKey: name];
[self setAttributes: newDict range: effectiveRange];
if (NSMaxRange(effectiveRange) >= NSMaxRange(aRange))
{
effectiveRange.location = NSMaxRange(aRange);//This stops the loop...
}
else if (NSMaxRange(effectiveRange) < tmpLength)
{
attrDict = [self attributesAtIndex: NSMaxRange(effectiveRange)
effectiveRange: &effectiveRange];
}
} }
}
} }
//Changing characters and attributes //Changing characters and attributes
- (void) appendAttributedString: (NSAttributedString *)attributedString - (void) appendAttributedString: (NSAttributedString*)attributedString
{ {
[self replaceCharactersInRange: NSMakeRange([self length],0) [self replaceCharactersInRange: NSMakeRange([self length],0)
withAttributedString: attributedString]; withAttributedString: attributedString];
} }
- (void) insertAttributedString: (NSAttributedString *)attributedString atIndex: (unsigned int)index - (void) insertAttributedString: (NSAttributedString*)attributedString
atIndex: (unsigned int)index
{ {
[self replaceCharactersInRange: NSMakeRange(index,0) [self replaceCharactersInRange: NSMakeRange(index,0)
withAttributedString: attributedString]; withAttributedString: attributedString];
} }
- (void) replaceCharactersInRange: (NSRange)aRange withAttributedString: (NSAttributedString *)attributedString - (void) replaceCharactersInRange: (NSRange)aRange
withAttributedString: (NSAttributedString*)attributedString
{ {
NSRange effectiveRange,clipRange,ownRange; NSRange effectiveRange;
NSDictionary *attrDict; NSRange clipRange;
NSString *tmpStr; NSRange ownRange;
NSDictionary *attrDict;
NSString *tmpStr;
tmpStr = [attributedString string]; tmpStr = [attributedString string];
[self replaceCharactersInRange: aRange [self replaceCharactersInRange: aRange withString: tmpStr];
withString: tmpStr];
effectiveRange = NSMakeRange(0,0); effectiveRange = NSMakeRange(0,0);
clipRange = NSMakeRange(0,[tmpStr length]); clipRange = NSMakeRange(0,[tmpStr length]);
while(NSMaxRange(effectiveRange) < NSMaxRange(clipRange)) while (NSMaxRange(effectiveRange) < NSMaxRange(clipRange))
{ {
attrDict = [attributedString attributesAtIndex: effectiveRange.location attrDict = [attributedString attributesAtIndex: effectiveRange.location
effectiveRange: &effectiveRange]; effectiveRange: &effectiveRange];
ownRange = NSIntersectionRange(clipRange,effectiveRange); ownRange = NSIntersectionRange(clipRange,effectiveRange);
ownRange.location += aRange.location; ownRange.location += aRange.location;
[self setAttributes: attrDict range: ownRange]; [self setAttributes: attrDict range: ownRange];
} }
} }
- (void) replaceCharactersInRange: (NSRange)aRange withString: (NSString *)aString - (void) replaceCharactersInRange: (NSRange)aRange
withString: (NSString*)aString
{ {
[self subclassResponsibility: _cmd];// Primitive method! [self subclassResponsibility: _cmd];// Primitive method!
} }
- (void) setAttributedString: (NSAttributedString *)attributedString - (void) setAttributedString: (NSAttributedString*)attributedString
{ {
[self replaceCharactersInRange: NSMakeRange(0,[self length]) [self replaceCharactersInRange: NSMakeRange(0,[self length])
withAttributedString: attributedString]; withAttributedString: attributedString];
} }
//Grouping changes //Grouping changes
@ -647,7 +667,7 @@ static Class NSMutableAttributedString_concrete_class;
return [[_owner string] getCharacters: buffer range: aRange]; return [[_owner string] getCharacters: buffer range: aRange];
} }
- (const char *) cString - (const char*) cString
{ {
return [[_owner string] cString]; return [[_owner string] cString];
} }