From c4a0051b2055145668d451cf3ce2c3f9691b6336 Mon Sep 17 00:00:00 2001 From: wlux Date: Sun, 30 May 2010 15:16:36 +0000 Subject: [PATCH] Fix keyed archiving and unarchiving of (mutable) attributed strings with multiple attribute ranges. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@30488 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 6 ++ Source/NSAttributedString.m | 111 +++++++++++++++++++++++++++--------- 2 files changed, 91 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a119805c..fbc32d57b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-05-30 Wolfgang Lux + + * Source/NSAttributedString.m (-initWithCoder:, -encodeWithCoder:): + Fix keyed archiving and unarchiving of (mutable) attributed + strings with multiple attribute ranges. + 2010-05-30 Richard Frith-Macdonald * NSTimeZones/NSTimeZones.tar: Update to latest zone info. diff --git a/Source/NSAttributedString.m b/Source/NSAttributedString.m index d062b18ce..efb7cd3e9 100644 --- a/Source/NSAttributedString.m +++ b/Source/NSAttributedString.m @@ -151,19 +151,70 @@ static Class GSMutableAttributedStringClass; return NSAttributedStringClass; } +static void +appendUIntData(NSMutableData *d, NSUInteger i) +{ + unsigned int aux = i; + unsigned int len = 1; + + while (aux >= 128) + { + aux /= 128; + len++; + } + + { + unsigned char *p, buf[len]; + + p = buf; + while (i >= 128) + { + *p++ = (i & 0x7f) + 128; + i /= 128; + } + *p = i; + + [d appendBytes: buf length: len]; + } +} + - (void) encodeWithCoder: (NSCoder*)aCoder { if ([aCoder allowsKeyedCoding]) { + NSUInteger length = [self length]; + [aCoder encodeObject: [self string] forKey: @"NSString"]; - if ([self length] > 0) + if (length > 0) { + NSRange range; NSDictionary *attrs; - // FIXME: This doesn't handle the case of different attributes - attrs = [self attributesAtIndex: 0 effectiveRange: NULL]; + attrs = [self attributesAtIndex: 0 effectiveRange: &range]; + if (range.length == length) + { + [aCoder encodeObject: attrs forKey: @"NSAttributes"]; + } + else + { + NSUInteger i = 0; + NSUInteger pos = 0; + NSMutableArray *attrs = [NSMutableArray arrayWithCapacity: 1]; + NSMutableData *info = [NSMutableData dataWithCapacity: 2]; - [aCoder encodeObject: attrs forKey: @"NSAttributes"]; + while (pos < length) + { + [attrs addObject: [self attributesAtIndex: pos + effectiveRange: &range]]; + appendUIntData(info, range.length); + appendUIntData(info, i++); + pos = NSMaxRange(range); + } + [aCoder encodeObject: [[attrs copy] autorelease] + forKey: @"NSAttributes"]; + [aCoder encodeObject: [[info copy] autorelease] + forKey: @"NSAttributeInfo"]; + } } } else @@ -211,20 +262,24 @@ static Class GSMutableAttributedStringClass; { unsigned int idx; unsigned int len; + unsigned int shift; NSRange r; - // FIXME: For huge strings we may need more bytes - len = *p++; - if (len & 0x8) - { - len = (len - 128) + ((*p++) << 7); - } + len = shift = 0; + while (*p & 0x80) + { + len += (*p++ - 128) << shift; + shift += 7; + } + len += *p++ << shift; - idx = *p++; - if (idx & 0x8) - { - idx = (idx - 128) + ((*p++) << 7); - } + idx = shift = 0; + while (*p & 0x80) + { + idx += (*p++ - 128) << shift; + shift += 7; + } + idx += *p++ << shift; r = NSMakeRange(pos, len); [m setAttributes: [attributes objectAtIndex: idx] range: r]; @@ -707,20 +762,24 @@ static Class GSMutableAttributedStringClass; { unsigned int idx; unsigned int len; + unsigned int shift; NSRange r; - // FIXME: For huge strings we may need more bytes - len = *p++; - if (len & 0x8) - { - len = (len - 128) + ((*p++) << 7); - } + len = shift = 0; + while (*p & 0x80) + { + len += (*p++ - 128) << shift; + shift += 7; + } + len += *p++ << shift; - idx = *p++; - if (idx & 0x8) - { - idx = (idx - 128) + ((*p++) << 7); - } + idx = shift = 0; + while (*p & 0x80) + { + idx += (*p++ - 128) << shift; + shift += 7; + } + idx += *p++ << shift; r = NSMakeRange(pos, len); [self setAttributes: [attributes objectAtIndex: idx] range: r];