mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 03:11:18 +00:00
Fix a crash during undo/redo when a text storage is shared among
multiple text views and some of these views are closed. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27360 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
e906e7378d
commit
232de18e5e
2 changed files with 86 additions and 18 deletions
|
@ -1,3 +1,11 @@
|
|||
2008-12-20 Wolfgang Lux <wolfgang.lux@gmail.com>
|
||||
|
||||
* Source/NSTextView.m (-shouldChangeTextInRange:replacementString:):
|
||||
Fix a crash during undo/redo when a text storage is shared among
|
||||
multiple text views and some of these views are closed by
|
||||
recording the undo/redo operations for the text storage rather
|
||||
than the text view.
|
||||
|
||||
2008-12-20 Wolfgang Lux <wolfgang.lux@gmail.com>
|
||||
|
||||
* Source/NSApplication.m (-sendEvent:): Attempt to perform key
|
||||
|
|
|
@ -128,6 +128,14 @@ Interface for a bunch of internal methods that need to be cleaned up.
|
|||
- (void) pasteSelection;
|
||||
@end
|
||||
|
||||
|
||||
@interface NSTextStorage(NSTextViewUndoSupport)
|
||||
- (NSTextView *)_bestTextViewForUndo;
|
||||
- (void)_undoReplaceCharactersInRange: (NSRange)undoRange
|
||||
withAttributedString: (NSAttributedString *)undoString
|
||||
selectedRange: (NSRange)selectedRange;
|
||||
@end
|
||||
|
||||
// This class is a helper for keyed unarchiving only
|
||||
@interface NSTextViewSharedData : NSObject
|
||||
{
|
||||
|
@ -2388,20 +2396,6 @@ Move to NSTextView_actions.m?
|
|||
return undo;
|
||||
}
|
||||
|
||||
- (void)undoReplaceCharactersInRange: (NSRange)undoRange
|
||||
withAttributedString: (NSAttributedString *)undoString
|
||||
selectedRange: (NSRange)selectedRange
|
||||
{
|
||||
if ([self shouldChangeTextInRange: undoRange
|
||||
replacementString: undoString ? [undoString string] : @""])
|
||||
{
|
||||
[self replaceCharactersInRange: undoRange
|
||||
withAttributedString: undoString];
|
||||
[self setSelectedRange: selectedRange];
|
||||
[self didChangeText];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Began editing flag. There are quite some different ways in which
|
||||
* editing can be started. Each time editing is started, we need to check
|
||||
|
@ -2504,10 +2498,10 @@ TextDidEndEditing notification _without_ asking the delegate
|
|||
undoRange = affectedCharRange;
|
||||
}
|
||||
undoString = [self attributedSubstringFromRange: affectedCharRange];
|
||||
[[undo prepareWithInvocationTarget: self]
|
||||
undoReplaceCharactersInRange: undoRange
|
||||
withAttributedString: undoString
|
||||
selectedRange: [self selectedRange]];
|
||||
[[undo prepareWithInvocationTarget: [self textStorage]]
|
||||
_undoReplaceCharactersInRange: undoRange
|
||||
withAttributedString: undoString
|
||||
selectedRange: [self selectedRange]];
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -5265,3 +5259,69 @@ configuation! */
|
|||
|
||||
@end
|
||||
|
||||
@implementation NSTextStorage(NSTextViewUndo)
|
||||
/* FIXME: Should this code be moved to NSTextStorage? */
|
||||
- (NSTextView *)_bestTextViewForUndo
|
||||
{
|
||||
int i, j;
|
||||
NSArray *textContainers;
|
||||
NSTextView *tv, *first = nil, *best = nil;
|
||||
NSWindow *win;
|
||||
|
||||
/* The "best" view will be one in the key window followed by one in the
|
||||
* main window. In either case, we prefer the window's first responder.
|
||||
* If no view is in the key or main window, we simply use the first text
|
||||
* view. Since -shouldChangeTextInRange:replacementString: returns NO
|
||||
* by default if a NSTextView is not editable, we consider only editable
|
||||
* views here.
|
||||
*/
|
||||
for (i = 0; i < [_layoutManagers count]; i++)
|
||||
{
|
||||
textContainers = [[_layoutManagers objectAtIndex: i] textContainers];
|
||||
for (j = 0; j < [textContainers count]; j++)
|
||||
{
|
||||
tv = [[textContainers objectAtIndex: j] textView];
|
||||
if ([tv isEditable])
|
||||
{
|
||||
win = [tv window];
|
||||
if (first == nil)
|
||||
first = tv;
|
||||
if ([win isKeyWindow])
|
||||
{
|
||||
if ([win firstResponder] == tv)
|
||||
return tv;
|
||||
else if (best == nil)
|
||||
best = tv;
|
||||
}
|
||||
else if ([win isMainWindow])
|
||||
{
|
||||
if ([win firstResponder] == tv)
|
||||
{
|
||||
if (best == nil || ![[best window] isKeyWindow])
|
||||
best = tv;
|
||||
}
|
||||
else if (best == nil)
|
||||
best = tv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return best != nil ? best : first;
|
||||
}
|
||||
|
||||
- (void)_undoReplaceCharactersInRange: (NSRange)undoRange
|
||||
withAttributedString: (NSAttributedString *)undoString
|
||||
selectedRange: (NSRange)selectedRange
|
||||
{
|
||||
NSTextView *tv = [self _bestTextViewForUndo];
|
||||
|
||||
if ([tv shouldChangeTextInRange: undoRange
|
||||
replacementString: undoString ? [undoString string] : @""])
|
||||
{
|
||||
[tv replaceCharactersInRange: undoRange
|
||||
withAttributedString: undoString];
|
||||
[tv setSelectedRange: selectedRange];
|
||||
[tv didChangeText];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue