mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-02-18 11:54:40 +01:00
use NSTextStorage for speedups
Replace NSMutableAttributesString with a concrete instance of NSTextStorage that performs optimizations when processing attribute changes.
This commit is contained in:
@@ -25,7 +25,7 @@ typedef struct {
|
||||
|
||||
|
||||
@interface MMTextStorage : NSTextStorage {
|
||||
NSMutableAttributedString *attribString;
|
||||
NSTextStorage *backingStore;
|
||||
int maxRows, maxColumns;
|
||||
int actualRows, actualColumns;
|
||||
NSAttributedString *emptyRowString;
|
||||
|
||||
@@ -72,7 +72,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
attribString = [[NSMutableAttributedString alloc] initWithString:@""];
|
||||
backingStore = [[NSTextStorage alloc] init];
|
||||
// NOTE! It does not matter which font is set here, Vim will set its
|
||||
// own font on startup anyway. Just set some bogus values.
|
||||
font = [[NSFont userFixedPitchFontOfSize:0] retain];
|
||||
@@ -104,19 +104,19 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
[font release]; font = nil;
|
||||
[defaultBackgroundColor release]; defaultBackgroundColor = nil;
|
||||
[defaultForegroundColor release]; defaultForegroundColor = nil;
|
||||
[attribString release]; attribString = nil;
|
||||
[backingStore release]; backingStore = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *)string
|
||||
{
|
||||
return [attribString string];
|
||||
return [backingStore string];
|
||||
}
|
||||
|
||||
- (NSDictionary *)attributesAtIndex:(NSUInteger)index
|
||||
effectiveRange:(NSRangePointer)range
|
||||
{
|
||||
return [attribString attributesAtIndex:index effectiveRange:range];
|
||||
return [backingStore attributesAtIndex:index effectiveRange:range];
|
||||
}
|
||||
|
||||
- (void)replaceCharactersInRange:(NSRange)range
|
||||
@@ -126,7 +126,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
ASLogWarn(@"Calling %@ on MMTextStorage is unsupported",
|
||||
NSStringFromSelector(_cmd));
|
||||
#endif
|
||||
//[attribString replaceCharactersInRange:range withString:string];
|
||||
//[backingStore replaceCharactersInRange:range withString:string];
|
||||
}
|
||||
|
||||
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)range
|
||||
@@ -134,7 +134,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
// NOTE! This method must be implemented since the text system calls it
|
||||
// constantly to 'fix attributes', apply font substitution, etc.
|
||||
#if 0
|
||||
[attribString setAttributes:attributes range:range];
|
||||
[backingStore setAttributes:attributes range:range];
|
||||
#elif 1
|
||||
// HACK! If the font attribute is being modified, then ensure that the new
|
||||
// font has a fixed advancement which is either the same as the current
|
||||
@@ -153,7 +153,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
return;
|
||||
|
||||
float adv = cellSize.width;
|
||||
if ([attribString attribute:MMWideCharacterAttributeName
|
||||
if ([backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:range.location
|
||||
effectiveRange:NULL])
|
||||
adv += adv;
|
||||
@@ -170,9 +170,9 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
dictionaryWithDictionary:attributes];
|
||||
[newAttr setObject:newFont forKey:NSFontAttributeName];
|
||||
|
||||
[attribString setAttributes:newAttr range:range];
|
||||
[backingStore setAttributes:newAttr range:range];
|
||||
} else {
|
||||
[attribString setAttributes:attributes range:range];
|
||||
[backingStore setAttributes:attributes range:range];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -329,15 +329,15 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
}
|
||||
|
||||
// Mark these characters as wide. This attribute is subsequently checked
|
||||
// when translating (row,col) pairs to offsets within 'attribString'.
|
||||
// when translating (row,col) pairs to offsets within 'backingStore'.
|
||||
if (flags & DRAW_WIDE)
|
||||
[attributes setObject:[NSNull null]
|
||||
forKey:MMWideCharacterAttributeName];
|
||||
|
||||
// Replace characters in text storage and apply new attributes.
|
||||
NSRange r = NSMakeRange(range.location, [string length]);
|
||||
[attribString replaceCharactersInRange:range withString:string];
|
||||
[attribString setAttributes:attributes range:r];
|
||||
[backingStore replaceCharactersInRange:range withString:string];
|
||||
[backingStore setAttributes:attributes range:r];
|
||||
|
||||
NSInteger changeInLength = [string length] - range.length;
|
||||
if (acells != cells || acol != col) {
|
||||
@@ -345,18 +345,18 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
// NOTE: A normal width character replaced a double width
|
||||
// character. To maintain the invariant that each row covers the
|
||||
// same amount of cells, we compensate by adding an empty column.
|
||||
[attribString replaceCharactersInRange:NSMakeRange(NSMaxRange(r),0)
|
||||
[backingStore replaceCharactersInRange:NSMakeRange(NSMaxRange(r),0)
|
||||
withAttributedString:[emptyRowString
|
||||
attributedSubstringFromRange:NSMakeRange(0,1)]];
|
||||
++changeInLength;
|
||||
#if 0
|
||||
} else if (acol == col - 1) {
|
||||
[attribString replaceCharactersInRange:NSMakeRange(r.location,0)
|
||||
[backingStore replaceCharactersInRange:NSMakeRange(r.location,0)
|
||||
withAttributedString:[emptyRowString
|
||||
attributedSubstringFromRange:NSMakeRange(0,1)]];
|
||||
++changeInLength;
|
||||
} else if (acol == col + 1) {
|
||||
[attribString replaceCharactersInRange:NSMakeRange(r.location-1,1)
|
||||
[backingStore replaceCharactersInRange:NSMakeRange(r.location-1,1)
|
||||
withAttributedString:[emptyRowString
|
||||
attributedSubstringFromRange:NSMakeRange(0,2)]];
|
||||
++changeInLength;
|
||||
@@ -435,10 +435,10 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
return;
|
||||
}
|
||||
|
||||
NSAttributedString *srcString = [attribString
|
||||
NSAttributedString *srcString = [backingStore
|
||||
attributedSubstringFromRange:srcRange];
|
||||
|
||||
[attribString replaceCharactersInRange:destRange
|
||||
[backingStore replaceCharactersInRange:destRange
|
||||
withAttributedString:srcString];
|
||||
[self edited:(NSTextStorageEditedCharacters
|
||||
| NSTextStorageEditedAttributes) range:destRange
|
||||
@@ -471,9 +471,9 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
return;
|
||||
}
|
||||
|
||||
[attribString replaceCharactersInRange:destRange
|
||||
[backingStore replaceCharactersInRange:destRange
|
||||
withAttributedString:emptyString];
|
||||
[attribString setAttributes:attribs
|
||||
[backingStore setAttributes:attribs
|
||||
range:NSMakeRange(destRange.location, width)];
|
||||
|
||||
[self edited:(NSTextStorageEditedAttributes
|
||||
@@ -531,9 +531,9 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
return;
|
||||
}
|
||||
|
||||
NSAttributedString *srcString = [attribString
|
||||
NSAttributedString *srcString = [backingStore
|
||||
attributedSubstringFromRange:srcRange];
|
||||
[attribString replaceCharactersInRange:destRange
|
||||
[backingStore replaceCharactersInRange:destRange
|
||||
withAttributedString:srcString];
|
||||
[self edited:(NSTextStorageEditedCharacters
|
||||
| NSTextStorageEditedAttributes) range:destRange
|
||||
@@ -566,9 +566,9 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
return;
|
||||
}
|
||||
|
||||
[attribString replaceCharactersInRange:destRange
|
||||
[backingStore replaceCharactersInRange:destRange
|
||||
withAttributedString:emptyString];
|
||||
[attribString setAttributes:attribs
|
||||
[backingStore setAttributes:attribs
|
||||
range:NSMakeRange(destRange.location, width)];
|
||||
|
||||
[self edited:(NSTextStorageEditedAttributes
|
||||
@@ -613,9 +613,9 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
return;
|
||||
}
|
||||
|
||||
[attribString replaceCharactersInRange:range
|
||||
[backingStore replaceCharactersInRange:range
|
||||
withAttributedString:emptyString];
|
||||
[attribString setAttributes:attribs
|
||||
[backingStore setAttributes:attribs
|
||||
range:NSMakeRange(range.location, cells)];
|
||||
|
||||
[self edited:(NSTextStorageEditedAttributes
|
||||
@@ -917,7 +917,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
int cells = 1;
|
||||
NSRange r = [self charRangeForRow:row column:&col cells:&cells];
|
||||
if (NSNotFound != r.location
|
||||
&& [attribString attribute:MMWideCharacterAttributeName
|
||||
&& [backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:r.location
|
||||
effectiveRange:nil])
|
||||
rect.size.width += rect.size.width;
|
||||
@@ -958,7 +958,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
if (!force && actualRows == maxRows && actualColumns == maxColumns)
|
||||
return;
|
||||
|
||||
NSRange oldRange = NSMakeRange(0, [attribString length]);
|
||||
NSRange oldRange = NSMakeRange(0, [backingStore length]);
|
||||
|
||||
actualRows = maxRows;
|
||||
actualColumns = maxColumns;
|
||||
@@ -990,16 +990,16 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
emptyRowString = [[NSAttributedString alloc] initWithString:rowString
|
||||
attributes:dict];
|
||||
|
||||
[attribString release];
|
||||
attribString = [[NSMutableAttributedString alloc] init];
|
||||
[backingStore release];
|
||||
backingStore = [[NSMutableAttributedString alloc] init];
|
||||
for (i=0; i<maxRows; ++i) {
|
||||
#if MM_USE_ROW_CACHE
|
||||
rowCache[i].length = actualColumns + 1;
|
||||
#endif
|
||||
[attribString appendAttributedString:emptyRowString];
|
||||
[backingStore appendAttributedString:emptyRowString];
|
||||
}
|
||||
|
||||
NSRange fullRange = NSMakeRange(0, [attribString length]);
|
||||
NSRange fullRange = NSMakeRange(0, [backingStore length]);
|
||||
[self edited:(NSTextStorageEditedCharacters|NSTextStorageEditedAttributes)
|
||||
range:oldRange changeInLength:fullRange.length-oldRange.length];
|
||||
}
|
||||
@@ -1014,7 +1014,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
if (characterEqualsColumn)
|
||||
return NSMakeRange(row*(actualColumns+1) + col, cells);
|
||||
|
||||
NSString *string = [attribString string];
|
||||
NSString *string = [backingStore string];
|
||||
unsigned stringLen = [string length];
|
||||
NSRange r, range = { NSNotFound, 0 };
|
||||
unsigned idx;
|
||||
@@ -1082,7 +1082,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
r = [string rangeOfComposedCharacterSequenceAtIndex:idx];
|
||||
|
||||
// Wide chars take up two display cells.
|
||||
if ([attribString attribute:MMWideCharacterAttributeName
|
||||
if ([backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:idx
|
||||
effectiveRange:nil])
|
||||
++i;
|
||||
@@ -1100,7 +1100,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
--i;
|
||||
|
||||
// Wide chars take up two display cells.
|
||||
if ([attribString attribute:MMWideCharacterAttributeName
|
||||
if ([backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:idx
|
||||
effectiveRange:nil])
|
||||
--i;
|
||||
@@ -1127,7 +1127,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
r = [string rangeOfComposedCharacterSequenceAtIndex:idx];
|
||||
|
||||
// Wide chars take up two display cells.
|
||||
if ([attribString attribute:MMWideCharacterAttributeName
|
||||
if ([backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:idx
|
||||
effectiveRange:nil])
|
||||
++i;
|
||||
@@ -1149,7 +1149,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
r = [string rangeOfComposedCharacterSequenceAtIndex:idx];
|
||||
|
||||
// Wide chars take up two display cells.
|
||||
if ([attribString attribute:MMWideCharacterAttributeName
|
||||
if ([backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:idx
|
||||
effectiveRange:nil])
|
||||
++i;
|
||||
@@ -1166,7 +1166,7 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
r = [string rangeOfComposedCharacterSequenceAtIndex:idx];
|
||||
|
||||
// Wide chars take up two display cells.
|
||||
if ([attribString attribute:MMWideCharacterAttributeName
|
||||
if ([backingStore attribute:MMWideCharacterAttributeName
|
||||
atIndex:idx
|
||||
effectiveRange:nil])
|
||||
++i;
|
||||
@@ -1218,14 +1218,14 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
// TODO: Treat these separately inside of Vim so we don't have to bother
|
||||
// here.
|
||||
while (range.length > 0) {
|
||||
invalidRange = [[attribString string]
|
||||
invalidRange = [[backingStore string]
|
||||
rangeOfCharacterFromSet:invalidCharacterSet
|
||||
options:NSLiteralSearch
|
||||
range:range];
|
||||
if (NSNotFound == invalidRange.location)
|
||||
break;
|
||||
|
||||
[attribString replaceCharactersInRange:invalidRange withString:@" "];
|
||||
[backingStore replaceCharactersInRange:invalidRange withString:@" "];
|
||||
|
||||
end = NSMaxRange(invalidRange);
|
||||
range.length -= end - range.location;
|
||||
|
||||
Reference in New Issue
Block a user