mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-06-02 11:00:59 +00:00
Fix index beyond range in text attachment processing in mouseDown
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/branches/gnustep_testplant_branch@38227 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
0dc0c821f9
commit
fd815172ac
1 changed files with 284 additions and 274 deletions
|
@ -5521,332 +5521,342 @@ other than copy/paste or dragging. */
|
||||||
NSRange chosenRange, proposedRange;
|
NSRange chosenRange, proposedRange;
|
||||||
NSPoint point, startPoint;
|
NSPoint point, startPoint;
|
||||||
NSUInteger startIndex, endIndex;
|
NSUInteger startIndex, endIndex;
|
||||||
|
|
||||||
/* If non selectable then ignore the mouse down. */
|
/* If non selectable then ignore the mouse down. */
|
||||||
if (_tf.is_selectable == NO)
|
if (_tf.is_selectable == NO)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_layoutManager)
|
if (!_layoutManager)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Otherwise, NSWindow has already made us first responder (if
|
/* Otherwise, NSWindow has already made us first responder (if
|
||||||
possible) */
|
possible) */
|
||||||
|
|
||||||
startPoint = [self convertPoint: [theEvent locationInWindow] fromView: nil];
|
startPoint = [self convertPoint: [theEvent locationInWindow] fromView: nil];
|
||||||
startIndex = [self _characterIndexForPoint: startPoint
|
startIndex = [self _characterIndexForPoint: startPoint
|
||||||
respectFraction: [theEvent clickCount] == 1];
|
respectFraction: [theEvent clickCount] == 1];
|
||||||
|
|
||||||
if ([theEvent modifierFlags] & NSShiftKeyMask)
|
if ([theEvent modifierFlags] & NSShiftKeyMask)
|
||||||
{
|
{
|
||||||
/* Shift-click is for extending or shrinking an existing selection using
|
/* Shift-click is for extending or shrinking an existing selection using
|
||||||
the existing granularity */
|
the existing granularity */
|
||||||
proposedRange = _layoutManager->_selected_range;
|
proposedRange = _layoutManager->_selected_range;
|
||||||
granularity = _layoutManager->_selectionGranularity;
|
granularity = _layoutManager->_selectionGranularity;
|
||||||
|
|
||||||
/* If the clicked point is closer to the left end of the current selection
|
/* If the clicked point is closer to the left end of the current selection
|
||||||
adjust the left end of the selected range */
|
adjust the left end of the selected range */
|
||||||
if (startIndex < proposedRange.location + proposedRange.length / 2)
|
if (startIndex < proposedRange.location + proposedRange.length / 2)
|
||||||
{
|
{
|
||||||
proposedRange = NSMakeRange(startIndex,
|
proposedRange = NSMakeRange(startIndex,
|
||||||
NSMaxRange(proposedRange) - startIndex);
|
NSMaxRange(proposedRange) - startIndex);
|
||||||
proposedRange = [self selectionRangeForProposedRange: proposedRange
|
proposedRange = [self selectionRangeForProposedRange: proposedRange
|
||||||
granularity: granularity];
|
granularity: granularity];
|
||||||
/* Prepare for shift-dragging. Anchor is at the right end. */
|
/* Prepare for shift-dragging. Anchor is at the right end. */
|
||||||
startIndex = NSMaxRange(proposedRange);
|
startIndex = NSMaxRange(proposedRange);
|
||||||
}
|
}
|
||||||
/* otherwise, adjust the right end of the selected range */
|
/* otherwise, adjust the right end of the selected range */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
proposedRange = NSMakeRange(proposedRange.location,
|
proposedRange = NSMakeRange(proposedRange.location,
|
||||||
startIndex - proposedRange.location);
|
startIndex - proposedRange.location);
|
||||||
proposedRange = [self selectionRangeForProposedRange: proposedRange
|
proposedRange = [self selectionRangeForProposedRange: proposedRange
|
||||||
granularity: granularity];
|
granularity: granularity];
|
||||||
/* Prepare for shift-dragging. Anchor is at the left end. */
|
/* Prepare for shift-dragging. Anchor is at the left end. */
|
||||||
startIndex = proposedRange.location;
|
startIndex = proposedRange.location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* No shift */
|
else /* No shift */
|
||||||
{
|
{
|
||||||
switch ([theEvent clickCount])
|
switch ([theEvent clickCount])
|
||||||
{
|
{
|
||||||
case 1: granularity = NSSelectByCharacter;
|
case 1: granularity = NSSelectByCharacter;
|
||||||
break;
|
break;
|
||||||
case 2: granularity = NSSelectByWord;
|
case 2: granularity = NSSelectByWord;
|
||||||
break;
|
break;
|
||||||
case 3: granularity = NSSelectByParagraph;
|
case 3: granularity = NSSelectByParagraph;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A single click into the selected range can start a drag operation */
|
/* A single click into the selected range can start a drag operation */
|
||||||
canDrag = granularity == NSSelectByCharacter
|
canDrag = granularity == NSSelectByCharacter && NSLocationInRange(startIndex, _layoutManager->_selected_range);
|
||||||
&& NSLocationInRange(startIndex, _layoutManager->_selected_range);
|
proposedRange = NSMakeRange (startIndex, 0);
|
||||||
proposedRange = NSMakeRange (startIndex, 0);
|
|
||||||
|
/* We manage clicks on attachments and links only on the first
|
||||||
/* We manage clicks on attachments and links only on the first
|
click, so that if you double-click on them, only the first
|
||||||
click, so that if you double-click on them, only the first
|
click gets sent to them; the other clicks select by
|
||||||
click gets sent to them; the other clicks select by
|
word/paragraph as usual. */
|
||||||
word/paragraph as usual. */
|
if (granularity == NSSelectByCharacter)
|
||||||
if (granularity == NSSelectByCharacter)
|
{
|
||||||
{
|
NSTextAttachment *attachment;
|
||||||
NSTextAttachment *attachment;
|
|
||||||
|
/* Check if the click was on an attachment cell. */
|
||||||
/* Check if the click was on an attachment cell. */
|
attachment = [_textStorage attribute: NSAttachmentAttributeName
|
||||||
attachment = [_textStorage attribute: NSAttachmentAttributeName
|
atIndex: startIndex
|
||||||
atIndex: startIndex
|
effectiveRange: NULL];
|
||||||
effectiveRange: NULL];
|
|
||||||
|
if (attachment != nil)
|
||||||
if (attachment != nil)
|
{
|
||||||
{
|
id <NSTextAttachmentCell> cell = [attachment attachmentCell];
|
||||||
id <NSTextAttachmentCell> cell = [attachment attachmentCell];
|
|
||||||
|
if (cell != nil)
|
||||||
if (cell != nil)
|
{
|
||||||
{
|
NSRect cellFrame = NSZeroRect;
|
||||||
NSRect cellFrame;
|
|
||||||
NSRect lfRect;
|
|
||||||
NSUInteger glyphIndex;
|
|
||||||
|
|
||||||
glyphIndex =
|
|
||||||
[_layoutManager
|
|
||||||
glyphRangeForCharacterRange: NSMakeRange(startIndex, 1)
|
|
||||||
actualCharacterRange: NULL].location;
|
|
||||||
lfRect =
|
|
||||||
[_layoutManager
|
|
||||||
lineFragmentRectForGlyphAtIndex: glyphIndex
|
|
||||||
effectiveRange: NULL];
|
|
||||||
cellFrame.origin =
|
|
||||||
[_layoutManager
|
|
||||||
locationForGlyphAtIndex: glyphIndex];
|
|
||||||
cellFrame.size =
|
|
||||||
[_layoutManager
|
|
||||||
attachmentSizeForGlyphAtIndex: glyphIndex];
|
|
||||||
cellFrame.origin.y -= cellFrame.size.height;
|
|
||||||
cellFrame.origin.x += lfRect.origin.x;
|
|
||||||
cellFrame.origin.y += lfRect.origin.y;
|
|
||||||
|
|
||||||
/* TODO: What about the insertion point ? */
|
|
||||||
if ([cell wantsToTrackMouseForEvent: theEvent
|
|
||||||
inRect: cellFrame
|
|
||||||
ofView: self
|
|
||||||
atCharacterIndex: startIndex]
|
|
||||||
&& [cell trackMouse: theEvent
|
|
||||||
inRect: cellFrame
|
|
||||||
ofView: self
|
|
||||||
atCharacterIndex: startIndex
|
|
||||||
untilMouseUp: NO])
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is the code for handling click event on a link (a link
|
|
||||||
is some chars with the NSLinkAttributeName set to something
|
|
||||||
which is not-null, a NSURL object usually). */
|
|
||||||
{
|
|
||||||
/* What exactly is this link object, it's up to the
|
|
||||||
programmer who is using the NSTextView and who
|
|
||||||
originally created the link object and saved it under
|
|
||||||
the NSLinkAttributeName in the text. Normally, a NSURL
|
|
||||||
object is used. */
|
|
||||||
/* TODO: should call -clickedOnLink:atIndex: instead */
|
|
||||||
id link = [_textStorage attribute: NSLinkAttributeName
|
|
||||||
atIndex: startIndex
|
|
||||||
effectiveRange: NULL];
|
|
||||||
if (link != nil && _delegate != nil)
|
|
||||||
{
|
|
||||||
SEL selector = @selector(textView:clickedOnLink:atIndex:);
|
|
||||||
|
|
||||||
if ([_delegate respondsToSelector: selector])
|
|
||||||
{
|
|
||||||
/* Move the insertion point over the link. */
|
|
||||||
chosenRange = [self selectionRangeForProposedRange:
|
|
||||||
proposedRange
|
|
||||||
granularity: granularity];
|
|
||||||
|
|
||||||
[self setSelectedRange: chosenRange affinity: affinity
|
|
||||||
stillSelecting: NO];
|
|
||||||
|
|
||||||
[self displayIfNeeded];
|
|
||||||
|
|
||||||
/* Now 'activate' the link. The _delegate returns
|
|
||||||
YES if it handles the click, NO if it doesn't
|
|
||||||
-- and if it doesn't, we need to pass the click
|
|
||||||
to the next responder. */
|
|
||||||
if ([_delegate textView: self
|
|
||||||
clickedOnLink: link
|
|
||||||
atIndex: startIndex])
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[super mouseDown: theEvent];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (startIndex >= [_textStorage length])
|
||||||
|
{
|
||||||
|
NSUInteger glyphIndex = [_textStorage length]-1;
|
||||||
|
NSRect lfRect = [_layoutManager lineFragmentRectForGlyphAtIndex: glyphIndex
|
||||||
|
effectiveRange: NULL];
|
||||||
|
cellFrame.origin = [_layoutManager locationForGlyphAtIndex: glyphIndex];
|
||||||
|
cellFrame.size = [_layoutManager attachmentSizeForGlyphAtIndex: glyphIndex];
|
||||||
|
cellFrame.origin.y -= cellFrame.size.height;
|
||||||
|
cellFrame.origin.x += lfRect.origin.x;
|
||||||
|
cellFrame.origin.y += lfRect.origin.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSRect lfRect;
|
||||||
|
NSUInteger glyphIndex;
|
||||||
|
|
||||||
|
glyphIndex = [_layoutManager glyphRangeForCharacterRange: NSMakeRange(startIndex, 1)
|
||||||
|
actualCharacterRange: NULL].location;
|
||||||
|
lfRect = [_layoutManager lineFragmentRectForGlyphAtIndex: glyphIndex
|
||||||
|
effectiveRange: NULL];
|
||||||
|
cellFrame.origin = [_layoutManager locationForGlyphAtIndex: glyphIndex];
|
||||||
|
cellFrame.size = [_layoutManager attachmentSizeForGlyphAtIndex: glyphIndex];
|
||||||
|
cellFrame.origin.y -= cellFrame.size.height;
|
||||||
|
cellFrame.origin.x += lfRect.origin.x;
|
||||||
|
cellFrame.origin.y += lfRect.origin.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NSEqualRects(NSZeroRect, cellFrame) == NO)
|
||||||
|
{
|
||||||
|
/* TODO: What about the insertion point ? */
|
||||||
|
if ([cell wantsToTrackMouseForEvent: theEvent
|
||||||
|
inRect: cellFrame
|
||||||
|
ofView: self
|
||||||
|
atCharacterIndex: startIndex]
|
||||||
|
&& [cell trackMouse: theEvent
|
||||||
|
inRect: cellFrame
|
||||||
|
ofView: self
|
||||||
|
atCharacterIndex: startIndex
|
||||||
|
untilMouseUp: NO])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the code for handling click event on a link (a link
|
||||||
|
is some chars with the NSLinkAttributeName set to something
|
||||||
|
which is not-null, a NSURL object usually). */
|
||||||
|
{
|
||||||
|
/* What exactly is this link object, it's up to the
|
||||||
|
programmer who is using the NSTextView and who
|
||||||
|
originally created the link object and saved it under
|
||||||
|
the NSLinkAttributeName in the text. Normally, a NSURL
|
||||||
|
object is used. */
|
||||||
|
/* TODO: should call -clickedOnLink:atIndex: instead */
|
||||||
|
id link = [_textStorage attribute: NSLinkAttributeName
|
||||||
|
atIndex: startIndex
|
||||||
|
effectiveRange: NULL];
|
||||||
|
if (link != nil && _delegate != nil)
|
||||||
|
{
|
||||||
|
SEL selector = @selector(textView:clickedOnLink:atIndex:);
|
||||||
|
|
||||||
|
if ([_delegate respondsToSelector: selector])
|
||||||
|
{
|
||||||
|
/* Move the insertion point over the link. */
|
||||||
|
chosenRange = [self selectionRangeForProposedRange: proposedRange
|
||||||
|
granularity: granularity];
|
||||||
|
|
||||||
|
[self setSelectedRange: chosenRange affinity: affinity
|
||||||
|
stillSelecting: NO];
|
||||||
|
|
||||||
|
[self displayIfNeeded];
|
||||||
|
|
||||||
|
/* Now 'activate' the link. The _delegate returns
|
||||||
|
YES if it handles the click, NO if it doesn't
|
||||||
|
-- and if it doesn't, we need to pass the click
|
||||||
|
to the next responder. */
|
||||||
|
if ([_delegate textView: self
|
||||||
|
clickedOnLink: link
|
||||||
|
atIndex: startIndex])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[super mouseDown: theEvent];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chosenRange = [self selectionRangeForProposedRange: proposedRange
|
chosenRange = [self selectionRangeForProposedRange: proposedRange
|
||||||
granularity: granularity];
|
granularity: granularity];
|
||||||
if (canDrag)
|
if (canDrag)
|
||||||
{
|
{
|
||||||
NSUInteger mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask;
|
NSUInteger mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask;
|
||||||
NSEvent *currentEvent;
|
NSEvent *currentEvent;
|
||||||
|
|
||||||
currentEvent = [_window nextEventMatchingMask: mask
|
currentEvent = [_window nextEventMatchingMask: mask
|
||||||
untilDate: [NSDate distantFuture]
|
untilDate: [NSDate distantFuture]
|
||||||
inMode: NSEventTrackingRunLoopMode
|
inMode: NSEventTrackingRunLoopMode
|
||||||
dequeue: NO];
|
dequeue: NO];
|
||||||
if ([currentEvent type] == NSLeftMouseDragged)
|
if ([currentEvent type] == NSLeftMouseDragged)
|
||||||
{
|
{
|
||||||
if (![self dragSelectionWithEvent: theEvent
|
if (![self dragSelectionWithEvent: theEvent
|
||||||
offset: NSMakeSize(0, 0)
|
offset: NSMakeSize(0, 0)
|
||||||
slideBack: YES])
|
slideBack: YES])
|
||||||
{
|
{
|
||||||
NSBeep();
|
NSBeep();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter modal loop tracking the mouse */
|
/* Enter modal loop tracking the mouse */
|
||||||
{
|
{
|
||||||
NSUInteger mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask
|
NSUInteger mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask
|
||||||
| NSPeriodicMask;
|
| NSPeriodicMask;
|
||||||
NSEvent *currentEvent;
|
NSEvent *currentEvent;
|
||||||
NSEvent *lastEvent = nil; /* Last non-periodic event. */
|
NSEvent *lastEvent = nil; /* Last non-periodic event. */
|
||||||
NSDate *distantPast = [NSDate distantPast];
|
NSDate *distantPast = [NSDate distantPast];
|
||||||
BOOL gettingPeriodic, gotPeriodic;
|
BOOL gettingPeriodic, gotPeriodic;
|
||||||
|
|
||||||
[self setSelectedRange: chosenRange affinity: affinity
|
[self setSelectedRange: chosenRange affinity: affinity
|
||||||
stillSelecting: YES];
|
stillSelecting: YES];
|
||||||
|
|
||||||
currentEvent = [_window nextEventMatchingMask: mask
|
currentEvent = [_window nextEventMatchingMask: mask
|
||||||
untilDate: [NSDate distantFuture]
|
untilDate: [NSDate distantFuture]
|
||||||
inMode: NSEventTrackingRunLoopMode
|
inMode: NSEventTrackingRunLoopMode
|
||||||
dequeue: YES];
|
dequeue: YES];
|
||||||
gettingPeriodic = NO;
|
gettingPeriodic = NO;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
gotPeriodic = NO;
|
gotPeriodic = NO;
|
||||||
while (currentEvent && [currentEvent type] != NSLeftMouseUp)
|
while (currentEvent && [currentEvent type] != NSLeftMouseUp)
|
||||||
{
|
{
|
||||||
if ([currentEvent type] == NSPeriodic)
|
if ([currentEvent type] == NSPeriodic)
|
||||||
{
|
{
|
||||||
gotPeriodic = YES;
|
gotPeriodic = YES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lastEvent = currentEvent;
|
{
|
||||||
currentEvent = [_window nextEventMatchingMask: mask
|
lastEvent = currentEvent;
|
||||||
untilDate: distantPast
|
}
|
||||||
inMode: NSEventTrackingRunLoopMode
|
currentEvent = [_window nextEventMatchingMask: mask
|
||||||
dequeue: YES];
|
untilDate: distantPast
|
||||||
}
|
inMode: NSEventTrackingRunLoopMode
|
||||||
if (currentEvent && [currentEvent type] == NSLeftMouseUp)
|
dequeue: YES];
|
||||||
break;
|
}
|
||||||
|
if (currentEvent && [currentEvent type] == NSLeftMouseUp)
|
||||||
/*
|
break;
|
||||||
Automatic scrolling.
|
|
||||||
|
/*
|
||||||
If we aren't getting periodic events, we check all events. If any of
|
Automatic scrolling.
|
||||||
them causes us to scroll, we scroll and start up the periodic events.
|
|
||||||
|
If we aren't getting periodic events, we check all events. If any of
|
||||||
If we are getting periodic events, we only scroll when we receive a
|
them causes us to scroll, we scroll and start up the periodic events.
|
||||||
periodic event (and we use the last non-periodic event to determine
|
|
||||||
how far). If no scrolling occurred, we stop the periodic events.
|
If we are getting periodic events, we only scroll when we receive a
|
||||||
*/
|
periodic event (and we use the last non-periodic event to determine
|
||||||
if (!gettingPeriodic)
|
how far). If no scrolling occurred, we stop the periodic events.
|
||||||
{
|
*/
|
||||||
if ([self autoscroll: lastEvent])
|
if (!gettingPeriodic)
|
||||||
{
|
{
|
||||||
gettingPeriodic = YES;
|
if ([self autoscroll: lastEvent])
|
||||||
[NSEvent startPeriodicEventsAfterDelay: 0.1
|
{
|
||||||
withPeriod: 0.1];
|
gettingPeriodic = YES;
|
||||||
|
[NSEvent startPeriodicEventsAfterDelay: 0.1
|
||||||
}
|
withPeriod: 0.1];
|
||||||
}
|
|
||||||
else if (gotPeriodic)
|
}
|
||||||
{
|
}
|
||||||
if (![self autoscroll: lastEvent])
|
else if (gotPeriodic)
|
||||||
{
|
{
|
||||||
gettingPeriodic = NO;
|
if (![self autoscroll: lastEvent])
|
||||||
[NSEvent stopPeriodicEvents];
|
{
|
||||||
}
|
gettingPeriodic = NO;
|
||||||
}
|
[NSEvent stopPeriodicEvents];
|
||||||
|
}
|
||||||
|
}
|
||||||
point = [self convertPoint: [lastEvent locationInWindow]
|
|
||||||
fromView: nil];
|
|
||||||
|
point = [self convertPoint: [lastEvent locationInWindow]
|
||||||
endIndex = [self _characterIndexForPoint: point
|
fromView: nil];
|
||||||
respectFraction: YES];
|
|
||||||
|
endIndex = [self _characterIndexForPoint: point
|
||||||
/**
|
respectFraction: YES];
|
||||||
* If the mouse is not inside the receiver, see if it is over another
|
|
||||||
* text view with the same layout manager. If so, use that text view
|
/**
|
||||||
* to compute endIndex
|
* If the mouse is not inside the receiver, see if it is over another
|
||||||
*/
|
* text view with the same layout manager. If so, use that text view
|
||||||
if (![self mouse: point inRect: [self bounds]])
|
* to compute endIndex
|
||||||
{
|
*/
|
||||||
BOOL found = NO;
|
if (![self mouse: point inRect: [self bounds]])
|
||||||
// FIXME: Is there an easier way to find the view under a point?
|
{
|
||||||
NSView *winContentView = [[self window] contentView];
|
BOOL found = NO;
|
||||||
NSView *view = [winContentView hitTest:
|
// FIXME: Is there an easier way to find the view under a point?
|
||||||
[[winContentView superview] convertPoint: [lastEvent locationInWindow]
|
NSView *winContentView = [[self window] contentView];
|
||||||
fromView: nil]];
|
NSView *view = [winContentView hitTest:
|
||||||
for (; view != nil; view = [view superview])
|
[[winContentView superview] convertPoint: [lastEvent locationInWindow]
|
||||||
{
|
fromView: nil]];
|
||||||
if ([view isKindOfClass: [NSTextView class]] &&
|
for (; view != nil; view = [view superview])
|
||||||
[(NSTextView*)view layoutManager] == [self layoutManager])
|
{
|
||||||
{
|
if ([view isKindOfClass: [NSTextView class]] &&
|
||||||
found = YES;
|
[(NSTextView*)view layoutManager] == [self layoutManager])
|
||||||
break;
|
{
|
||||||
}
|
found = YES;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
if (found)
|
}
|
||||||
{
|
|
||||||
NSTextView *textview = (NSTextView*)view;
|
if (found)
|
||||||
NSPoint mouse = [textview convertPoint: [lastEvent locationInWindow]
|
{
|
||||||
fromView: nil];
|
NSTextView *textview = (NSTextView*)view;
|
||||||
|
NSPoint mouse = [textview convertPoint: [lastEvent locationInWindow]
|
||||||
endIndex = [textview _characterIndexForPoint: mouse
|
fromView: nil];
|
||||||
respectFraction: YES];
|
|
||||||
}
|
endIndex = [textview _characterIndexForPoint: mouse
|
||||||
}
|
respectFraction: YES];
|
||||||
|
}
|
||||||
proposedRange = MakeRangeFromAbs(endIndex,
|
}
|
||||||
startIndex);
|
|
||||||
|
proposedRange = MakeRangeFromAbs(endIndex,
|
||||||
chosenRange = [self selectionRangeForProposedRange: proposedRange
|
startIndex);
|
||||||
granularity: granularity];
|
|
||||||
|
chosenRange = [self selectionRangeForProposedRange: proposedRange
|
||||||
[self setSelectedRange: chosenRange affinity: affinity
|
granularity: granularity];
|
||||||
stillSelecting: YES];
|
|
||||||
|
[self setSelectedRange: chosenRange affinity: affinity
|
||||||
currentEvent = [_window nextEventMatchingMask: mask
|
stillSelecting: YES];
|
||||||
untilDate: [NSDate distantFuture]
|
|
||||||
inMode: NSEventTrackingRunLoopMode
|
currentEvent = [_window nextEventMatchingMask: mask
|
||||||
dequeue: YES];
|
untilDate: [NSDate distantFuture]
|
||||||
|
inMode: NSEventTrackingRunLoopMode
|
||||||
|
dequeue: YES];
|
||||||
} while ([currentEvent type] != NSLeftMouseUp);
|
} while ([currentEvent type] != NSLeftMouseUp);
|
||||||
|
|
||||||
if (gettingPeriodic)
|
if (gettingPeriodic)
|
||||||
{
|
{
|
||||||
[NSEvent stopPeriodicEvents];
|
[NSEvent stopPeriodicEvents];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDebugLog(@"chosenRange. location = %d, length = %d\n",
|
NSDebugLog(@"chosenRange. location = %d, length = %d\n",
|
||||||
(int)chosenRange.location, (int)chosenRange.length);
|
(int)chosenRange.location, (int)chosenRange.length);
|
||||||
|
|
||||||
[self setSelectedRange: chosenRange affinity: affinity
|
[self setSelectedRange: chosenRange affinity: affinity
|
||||||
stillSelecting: NO];
|
stillSelecting: NO];
|
||||||
|
|
||||||
/* Remember granularity till a new selection destroys the memory */
|
/* Remember granularity till a new selection destroys the memory */
|
||||||
[self setSelectionGranularity: granularity];
|
[self setSelectionGranularity: granularity];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue