diff --git a/ChangeLog b/ChangeLog index d110a6e1a..171027258 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-08-12 01:42 Alexander Malmberg + + * Source/NSLayoutManager.m + (-textStorage:edited:range:changeInLength:invalidatedRange:): + Adjust the selected range even if there's no length change. Change + the handling of the in/in case. Set the selected range using a text + view if we have any attached. + * Source/NSTextView.m (-insertText:): Don't set the selected range. + (-setSelectedRange:affinity:stillSelecting:): Clamp the old range + to the length of the text. + * Source/NSTextView_actions.m (-deleteForward:, -deleteBackward:): + Don't set the selected range. + 2004-08-11 21:35 Alexander Malmberg * Source/NSButtonCell.m (-drawInteriorWithFrame:inView:): Move diff --git a/Source/NSLayoutManager.m b/Source/NSLayoutManager.m index 1a5f4d62d..8afcc2145 100644 --- a/Source/NSLayoutManager.m +++ b/Source/NSLayoutManager.m @@ -2094,7 +2094,7 @@ no_soft_invalidation: [self _didInvalidateLayout]; - if ((mask & NSTextStorageEditedCharacters) && lengthChange) + if (mask & NSTextStorageEditedCharacters) { /* Adjust the selected range so it's still valid. We don't try to @@ -2116,7 +2116,7 @@ no_soft_invalidation: -------------------------- after after location += lengthChange; in after length = NSMaxRange(sel)-NSMaxRange(range)-lengthChange; location=NSMaxRange(range); - in in length = 0; location=range.location; + in in length = 0; location=NSMaxRange(range); before after length += lengthChange; before in length = range.location-location; before before do nothing @@ -2127,34 +2127,43 @@ no_soft_invalidation: One important property of this behavior is that if length is 0 before, it will be 0 after. */ + NSRange newRange = _selected_range; + if (_selected_range.location >= NSMaxRange(range) - lengthChange) { /* after after */ - _selected_range.location += lengthChange; + newRange.location += lengthChange; } else if (_selected_range.location >= range.location) { if (NSMaxRange(_selected_range) > NSMaxRange(range) - lengthChange) { /* in after */ - _selected_range.length = NSMaxRange(_selected_range) - NSMaxRange(range) - lengthChange; - _selected_range.location = NSMaxRange(range); + newRange.length = NSMaxRange(_selected_range) - NSMaxRange(range) - lengthChange; + newRange.location = NSMaxRange(range); } else { /* in in */ - _selected_range.length = 0; - _selected_range.location = range.location; + newRange.length = 0; + newRange.location = NSMaxRange(range); } } else if (NSMaxRange(_selected_range) > NSMaxRange(range) - lengthChange) { /* before after */ - _selected_range.length += lengthChange; + newRange.length += lengthChange; } else if (NSMaxRange(_selected_range) > range.location) { /* before in */ - _selected_range.length = range.location - _selected_range.location; + newRange.length = range.location - _selected_range.location; } else { /* before before */ } + + /* If there are text views attached to use, let them handle the + change. */ + if ([self firstTextView]) + [[self firstTextView] setSelectedRange: newRange]; + else + _selected_range = newRange; } } diff --git a/Source/NSTextView.m b/Source/NSTextView.m index 2cb0815e7..be356342c 100644 --- a/Source/NSTextView.m +++ b/Source/NSTextView.m @@ -1793,10 +1793,6 @@ This method is for user changes; see NSTextView_actions.m. } [self didChangeText]; - - /* TODO? move cursor [self selectionRangeForProposedRange: ] */ - [self setSelectedRange: - NSMakeRange(insertRange.location + [insertString length], 0)]; } @@ -2711,6 +2707,14 @@ afterString in order over charRange. affinity: (NSSelectionAffinity)affinity stillSelecting: (BOOL)stillSelectingFlag { + /* + Note that this method might be called from the layout manager to update + the selection after the text storage has been changed. If text was deleted, + the old selected range might extend outside the current string. Also note + that this happens during the processing of the changes in the text storage. + Thus, it isn't safe to modify the text storage. + */ + /* The `official' (the last one the delegate approved of) selected range before this one. */ NSRange oldRange; @@ -2846,6 +2850,17 @@ afterString in order over charRange. NSMakeRange(charRange.location + charRange.length, 0)]; } + /* + If this call is caused by text being deleted, oldDisplayedRange might + extend outside the current text. We clamp it to the current length here + for safety. Redisplay might be a bit off in this case, but the text + change will cause any missing bits to be redisplayed anyway. + */ + if (oldDisplayedRange.location > length) + oldDisplayedRange.location = length; + if (NSMaxRange(oldDisplayedRange) > length) + oldDisplayedRange.length = length - oldDisplayedRange.location; + /* Try to optimize for overlapping ranges */ overlap = NSIntersectionRange (oldRange, charRange); if (overlap.length) diff --git a/Source/NSTextView_actions.m b/Source/NSTextView_actions.m index ccec00430..76b521545 100644 --- a/Source/NSTextView_actions.m +++ b/Source/NSTextView_actions.m @@ -583,10 +583,6 @@ static NSNumber *float_plus_one(NSNumber *cur) [_textStorage deleteCharactersInRange: range]; [_textStorage endEditing]; [self didChangeText]; - - /* The new selected range is just the insertion point at the beginning - of deleted range */ - [self setSelectedRange: NSMakeRange (range.location, 0)]; } - (void) deleteBackward: (id)sender @@ -626,10 +622,6 @@ static NSNumber *float_plus_one(NSNumber *cur) [_textStorage deleteCharactersInRange: range]; [_textStorage endEditing]; [self didChangeText]; - - /* The new selected range is just the insertion point at the beginning - of deleted range */ - [self setSelectedRange: NSMakeRange (range.location, 0)]; }