/* * Name: OgreTextViewUndoer.m * Project: OgreKit * * Creation Date: May 20 2004 * Author: Isao Sonobe * Copyright: Copyright (c) 2003 Isao Sonobe, All rights reserved. * License: OgreKit License * * Encoding: UTF8 * Tabsize: 4 */ #import @implementation OgreTextViewUndoer - (id)initWithCapacity:(unsigned)aCapacity { self = [super init]; if (self != nil) { _tail = 0; _count = aCapacity; _rangeArray = (NSRange*)NSZoneMalloc([self zone], sizeof(NSRange) * aCapacity); if (_rangeArray == NULL) { // ERROR! } _attributedStringArray = [[NSMutableArray alloc] initWithCapacity:aCapacity]; } return self; } - (void)dealloc { //NSLog(@"dealloc %@", self); [_attributedStringArray release]; NSZoneFree([self zone], _rangeArray); [super dealloc]; } - (void)addRange:(NSRange)aRange attributedString:(NSAttributedString*)anAttributedString { if (_tail == _count) { // ERROR } *(_rangeArray + _tail) = aRange; [_attributedStringArray addObject:anAttributedString]; _tail++; } /* Undo/Redo Replace */ - (void)undoTextView:(id)aTarget jumpToSelection:(BOOL)jumpToSelection invocationTarget:(id)myself { NSTextStorage *textStorage = [aTarget textStorage]; NSRange aRange, newRange; NSAttributedString *aString; unsigned i; OgreTextViewUndoer *redoArray = [[OgreTextViewUndoer alloc] initWithCapacity:_count]; [textStorage beginEditing]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; i = _count; while (i > 0) { i--; aRange = *(_rangeArray + i); aString = [_attributedStringArray objectAtIndex:i]; //NSLog(@"(%d, %d), %@", aRange.location, aRange.length, [aString string]); newRange = NSMakeRange(aRange.location, [aString length]); [redoArray addRange:newRange attributedString:[[[NSAttributedString alloc] initWithAttributedString:[textStorage attributedSubstringFromRange:aRange]] autorelease]]; // undo [textStorage replaceCharactersInRange:aRange withAttributedString:aString]; if (jumpToSelection) [aTarget scrollRangeToVisible:newRange]; if ((_count - i) % 1000 == 0) { [pool release]; pool = [[NSAutoreleasePool alloc] init]; } } // redo registeration [[[aTarget undoManager] prepareWithInvocationTarget:redoArray] undoTextView:aTarget jumpToSelection:jumpToSelection invocationTarget:redoArray]; [redoArray release]; [pool release]; [textStorage endEditing]; [aTarget setSelectedRange:newRange]; } @end