mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-31 22:00:46 +00:00
Changes for better cursor movement
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@8591 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
dee8285c46
commit
be17cfe3a9
2 changed files with 194 additions and 156 deletions
|
@ -94,7 +94,6 @@ typedef enum _NSSelectionAffinity {
|
||||||
|
|
||||||
/* manages layout information */
|
/* manages layout information */
|
||||||
NSLayoutManager *_layoutManager;
|
NSLayoutManager *_layoutManager;
|
||||||
|
|
||||||
/* container position */
|
/* container position */
|
||||||
NSSize _textContainerInset;
|
NSSize _textContainerInset;
|
||||||
NSPoint _textContainerOrigin;
|
NSPoint _textContainerOrigin;
|
||||||
|
@ -111,8 +110,20 @@ typedef enum _NSSelectionAffinity {
|
||||||
NSDictionary *_markedTextAttributes;
|
NSDictionary *_markedTextAttributes;
|
||||||
NSSelectionGranularity _selectionGranularity;
|
NSSelectionGranularity _selectionGranularity;
|
||||||
|
|
||||||
/* Column-stable cursor up/down */
|
/* Stores the insertion point rect - updated by
|
||||||
NSPoint _currentCursor;
|
updateInsertionPointStateAndRestartTimer: - we must make sure we
|
||||||
|
call the method every time that the insertion point rect might
|
||||||
|
need to be recomputed <eg, relayout>. */
|
||||||
|
NSRect _insertionPointRect;
|
||||||
|
|
||||||
|
/* This is used when you move the insertion point up or down. The
|
||||||
|
system remembers the horizontal position of the insertion point
|
||||||
|
at the beginning of the process, and always tries to put the
|
||||||
|
insertion point in that horizontal position on each line when you
|
||||||
|
go up or down. The memory of the horizontal position is changed
|
||||||
|
as soon as you do something different from moving the cursor
|
||||||
|
up/down. */
|
||||||
|
float _originalInsertPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************** Initializing ****************************/
|
/**************************** Initializing ****************************/
|
||||||
|
@ -282,6 +293,8 @@ shouldRemoveMarker: (NSRulerMarker *)marker;
|
||||||
- (void) setSelectedRange: (NSRange)charRange
|
- (void) setSelectedRange: (NSRange)charRange
|
||||||
affinity: (NSSelectionAffinity)affinity
|
affinity: (NSSelectionAffinity)affinity
|
||||||
stillSelecting: (BOOL)stillSelectingFlag;
|
stillSelecting: (BOOL)stillSelectingFlag;
|
||||||
|
/* Called by drawing routines to determine where to draw insertion
|
||||||
|
point */
|
||||||
- (NSSelectionAffinity) selectionAffinity;
|
- (NSSelectionAffinity) selectionAffinity;
|
||||||
- (NSSelectionGranularity) selectionGranularity;
|
- (NSSelectionGranularity) selectionGranularity;
|
||||||
- (void) setSelectionGranularity: (NSSelectionGranularity)granularity;
|
- (void) setSelectionGranularity: (NSSelectionGranularity)granularity;
|
||||||
|
|
|
@ -123,9 +123,7 @@ static NSNotificationCenter *nc;
|
||||||
* these NSLayoutManager- like methods are here only informally
|
* these NSLayoutManager- like methods are here only informally
|
||||||
*/
|
*/
|
||||||
- (unsigned) characterIndexForPoint: (NSPoint)point;
|
- (unsigned) characterIndexForPoint: (NSPoint)point;
|
||||||
- (NSRect) rectForCharacterIndex: (unsigned)index;
|
|
||||||
- (NSRect) rectForCharacterRange: (NSRange)aRange;
|
- (NSRect) rectForCharacterRange: (NSRange)aRange;
|
||||||
- (NSRect) rectForInsertionPointAtIndex: (unsigned)index;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* various GNU extensions
|
* various GNU extensions
|
||||||
|
@ -501,7 +499,7 @@ static NSNotificationCenter *nc;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setFont: font ofRange: NSMakeRange (0, [self textLength])];
|
[self setFont: font ofRange: NSMakeRange (0, [_textStorage length])];
|
||||||
[_typingAttributes setObject: font forKey: NSFontAttributeName];
|
[_typingAttributes setObject: font forKey: NSFontAttributeName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,27 +523,33 @@ static NSNotificationCenter *nc;
|
||||||
*/
|
*/
|
||||||
- (NSTextAlignment) alignment
|
- (NSTextAlignment) alignment
|
||||||
{
|
{
|
||||||
/* FIXME */
|
unsigned location = 0;
|
||||||
NSRange aRange = [self rangeForUserParagraphAttributeChange];
|
|
||||||
NSParagraphStyle *aStyle;
|
NSParagraphStyle *aStyle;
|
||||||
|
|
||||||
if (aRange.location != NSNotFound)
|
if (_tf.is_rich_text)
|
||||||
|
{
|
||||||
|
location = [self rangeForUserParagraphAttributeChange].location;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location != NSNotFound)
|
||||||
{
|
{
|
||||||
aStyle = [_textStorage attribute: NSParagraphStyleAttributeName
|
aStyle = [_textStorage attribute: NSParagraphStyleAttributeName
|
||||||
atIndex: aRange.location
|
atIndex: location
|
||||||
effectiveRange: NULL];
|
effectiveRange: NULL];
|
||||||
if (aStyle != nil)
|
if (aStyle != nil)
|
||||||
return [aStyle alignment];
|
{
|
||||||
|
return [aStyle alignment];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get alignment from typing attributes
|
/* Get alignment from typing attributes */
|
||||||
return [[_typingAttributes objectForKey: NSParagraphStyleAttributeName]
|
return [[_typingAttributes objectForKey: NSParagraphStyleAttributeName]
|
||||||
alignment];
|
alignment];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setAlignment: (NSTextAlignment)mode
|
- (void) setAlignment: (NSTextAlignment)mode
|
||||||
{
|
{
|
||||||
[self setAlignment: mode range: NSMakeRange (0, [self textLength])];
|
[self setAlignment: mode range: NSMakeRange (0, [_textStorage length])];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) alignCenter: (id)sender
|
- (void) alignCenter: (id)sender
|
||||||
|
@ -589,7 +593,7 @@ static NSNotificationCenter *nc;
|
||||||
- (void) setTextColor: (NSColor*)color
|
- (void) setTextColor: (NSColor*)color
|
||||||
{
|
{
|
||||||
/* FIXME: This should work also for non rich text objects */
|
/* FIXME: This should work also for non rich text objects */
|
||||||
NSRange fullRange = NSMakeRange (0, [self textLength]);
|
NSRange fullRange = NSMakeRange (0, [_textStorage length]);
|
||||||
|
|
||||||
[self setTextColor: color range: fullRange];
|
[self setTextColor: color range: fullRange];
|
||||||
}
|
}
|
||||||
|
@ -752,7 +756,7 @@ static NSNotificationCenter *nc;
|
||||||
{
|
{
|
||||||
[self setRichText: YES];
|
[self setRichText: YES];
|
||||||
}
|
}
|
||||||
[self replaceRange: NSMakeRange (0, [self textLength])
|
[self replaceRange: NSMakeRange (0, [_textStorage length])
|
||||||
withAttributedString: peek];
|
withAttributedString: peek];
|
||||||
RELEASE(peek);
|
RELEASE(peek);
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -763,7 +767,7 @@ static NSNotificationCenter *nc;
|
||||||
- (BOOL) writeRTFDToFile: (NSString*)path atomically: (BOOL)flag
|
- (BOOL) writeRTFDToFile: (NSString*)path atomically: (BOOL)flag
|
||||||
{
|
{
|
||||||
NSFileWrapper *wrapper;
|
NSFileWrapper *wrapper;
|
||||||
NSRange range = NSMakeRange (0, [self textLength]);
|
NSRange range = NSMakeRange (0, [_textStorage length]);
|
||||||
|
|
||||||
wrapper = [_textStorage RTFDFileWrapperFromRange: range
|
wrapper = [_textStorage RTFDFileWrapperFromRange: range
|
||||||
documentAttributes: nil];
|
documentAttributes: nil];
|
||||||
|
@ -1267,12 +1271,11 @@ static NSNotificationCenter *nc;
|
||||||
|
|
||||||
#undef NSTEXTVIEW_SYNC
|
#undef NSTEXTVIEW_SYNC
|
||||||
|
|
||||||
|
/* NB: Only NSSelectionAffinityDownstream works */
|
||||||
- (void) setSelectedRange: (NSRange)range
|
- (void) setSelectedRange: (NSRange)range
|
||||||
affinity: (NSSelectionAffinity)affinity
|
affinity: (NSSelectionAffinity)affinity
|
||||||
stillSelecting: (BOOL)flag
|
stillSelecting: (BOOL)flag
|
||||||
{
|
{
|
||||||
/* TODO: Use affinity to determine the insertion point */
|
|
||||||
|
|
||||||
/* The `official' (the last one the delegate approved of) selected
|
/* The `official' (the last one the delegate approved of) selected
|
||||||
range before this one. */
|
range before this one. */
|
||||||
NSRange oldRange;
|
NSRange oldRange;
|
||||||
|
@ -1318,6 +1321,9 @@ static NSNotificationCenter *nc;
|
||||||
/* Set the new selected range */
|
/* Set the new selected range */
|
||||||
_selected_range = range;
|
_selected_range = range;
|
||||||
|
|
||||||
|
/* FIXME: when and if to restart timer <and where to stop it before> */
|
||||||
|
[self updateInsertionPointStateAndRestartTimer: !flag];
|
||||||
|
|
||||||
if (flag == NO)
|
if (flag == NO)
|
||||||
{
|
{
|
||||||
[self updateFontPanel];
|
[self updateFontPanel];
|
||||||
|
@ -1351,7 +1357,6 @@ static NSNotificationCenter *nc;
|
||||||
}
|
}
|
||||||
[self setTypingAttributes: dict];
|
[self setTypingAttributes: dict];
|
||||||
}
|
}
|
||||||
/* <!>enable caret timed entry */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,10 +1425,8 @@ static NSNotificationCenter *nc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Override in subclasses to change the default selection affinity */
|
- (NSSelectionAffinity) selectionAffinity
|
||||||
- (NSSelectionAffinity) selectionAffinity
|
{
|
||||||
{
|
|
||||||
/* FIXME: which one should be the default ? */
|
|
||||||
return NSSelectionAffinityDownstream;
|
return NSSelectionAffinityDownstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1439,7 +1442,7 @@ static NSNotificationCenter *nc;
|
||||||
|
|
||||||
- (void) setInsertionPointColor: (NSColor*)aColor
|
- (void) setInsertionPointColor: (NSColor*)aColor
|
||||||
{
|
{
|
||||||
ASSIGN(_caret_color, aColor);
|
ASSIGN (_caret_color, aColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSColor*) insertionPointColor
|
- (NSColor*) insertionPointColor
|
||||||
|
@ -1449,9 +1452,85 @@ static NSNotificationCenter *nc;
|
||||||
|
|
||||||
- (void) updateInsertionPointStateAndRestartTimer: (BOOL)flag
|
- (void) updateInsertionPointStateAndRestartTimer: (BOOL)flag
|
||||||
{
|
{
|
||||||
// _caretLocation =
|
/* Update insertion point rect */
|
||||||
|
NSRange charRange;
|
||||||
|
NSRange glyphRange;
|
||||||
|
unsigned glyphIndex;
|
||||||
|
NSRect rect;
|
||||||
|
|
||||||
// restart blinking timer.
|
/* Simple case - no insertion point */
|
||||||
|
if ((_selected_range.length > 0) || _selected_range.location == NSNotFound)
|
||||||
|
{
|
||||||
|
_insertionPointRect = NSZeroRect;
|
||||||
|
|
||||||
|
/* FIXME: horizontal position of insertion point */
|
||||||
|
_originalInsertPoint = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
charRange = NSMakeRange (_selected_range.location, 1);
|
||||||
|
glyphRange = [_layoutManager glyphRangeForCharacterRange: charRange
|
||||||
|
actualCharacterRange: NULL];
|
||||||
|
glyphIndex = glyphRange.location;
|
||||||
|
|
||||||
|
rect = [_layoutManager lineFragmentRectForGlyphAtIndex: glyphIndex
|
||||||
|
effectiveRange: NULL];
|
||||||
|
|
||||||
|
if ([self selectionAffinity] != NSSelectionAffinityUpstream)
|
||||||
|
{
|
||||||
|
/* Standard case - draw the insertion point just before the
|
||||||
|
associated glyph index */
|
||||||
|
NSPoint loc = [_layoutManager locationForGlyphAtIndex: glyphIndex];
|
||||||
|
|
||||||
|
rect.origin.x += loc.x;
|
||||||
|
}
|
||||||
|
else /* _affinity == NSSelectionAffinityUpstream - non standard */
|
||||||
|
{
|
||||||
|
/* FIXME - THIS DOES NOT WORK - as a consequence,
|
||||||
|
NSSelectionAffinityUpstream DOES NOT WORK */
|
||||||
|
|
||||||
|
/* Check - if the previous glyph is on another line */
|
||||||
|
|
||||||
|
/* FIXME: Don't know how to do this check, this is a hack and
|
||||||
|
DOES NOT WORK - clearly this code should be inside the layout
|
||||||
|
manager anyway */
|
||||||
|
NSRect rect2;
|
||||||
|
|
||||||
|
rect2 = [_layoutManager lineFragmentRectForGlyphAtIndex: glyphIndex - 1
|
||||||
|
effectiveRange: NULL];
|
||||||
|
if (NSMinY (rect2) < NSMinY (rect))
|
||||||
|
{
|
||||||
|
/* Then we need to draw the insertion point just after the
|
||||||
|
previous glyph - DOES NOT WORK */
|
||||||
|
glyphRange = NSMakeRange (glyphIndex - 1, 1);
|
||||||
|
rect = [_layoutManager boundingRectForGlyphRange: glyphRange
|
||||||
|
inTextContainer:_textContainer];
|
||||||
|
rect.origin.x = NSMaxX (rect) - 1;
|
||||||
|
}
|
||||||
|
else /* Else, standard case again */
|
||||||
|
{
|
||||||
|
NSPoint loc = [_layoutManager locationForGlyphAtIndex: glyphIndex];
|
||||||
|
rect.origin.x += loc.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.size.width = 1;
|
||||||
|
|
||||||
|
if (rect.size.height == 0)
|
||||||
|
{
|
||||||
|
rect.size.height = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
_insertionPointRect = rect;
|
||||||
|
|
||||||
|
|
||||||
|
/* Remember horizontal position of insertion point */
|
||||||
|
_originalInsertPoint = _insertionPointRect.origin.x;
|
||||||
|
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
/* TODO: Restart blinking timer */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setSelectedTextAttributes: (NSDictionary *)attributes
|
- (void) setSelectedTextAttributes: (NSDictionary *)attributes
|
||||||
|
@ -1468,12 +1547,12 @@ static NSNotificationCenter *nc;
|
||||||
{
|
{
|
||||||
// calculate
|
// calculate
|
||||||
|
|
||||||
return NSMakeRange(NSNotFound, 0);
|
return NSMakeRange (NSNotFound, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setMarkedTextAttributes: (NSDictionary*)attributes
|
- (void) setMarkedTextAttributes: (NSDictionary*)attributes
|
||||||
{
|
{
|
||||||
ASSIGN(_markedTextAttributes, attributes);
|
ASSIGN (_markedTextAttributes, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary*) markedTextAttributes
|
- (NSDictionary*) markedTextAttributes
|
||||||
|
@ -1551,10 +1630,6 @@ static NSNotificationCenter *nc;
|
||||||
// move cursor <!> [self selectionRangeForProposedRange: ]
|
// move cursor <!> [self selectionRangeForProposedRange: ]
|
||||||
[self setSelectedRange:
|
[self setSelectedRange:
|
||||||
NSMakeRange (insertRange.location + [insertString length], 0)];
|
NSMakeRange (insertRange.location + [insertString length], 0)];
|
||||||
|
|
||||||
// remember x for row - stable cursor movements
|
|
||||||
_currentCursor = [self rectForCharacterIndex:
|
|
||||||
_selected_range.location].origin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setTypingAttributes: (NSDictionary*)dict
|
- (void) setTypingAttributes: (NSDictionary*)dict
|
||||||
|
@ -2049,9 +2124,6 @@ afterString in order over charRange. */
|
||||||
|
|
||||||
/* Remember granularity till a new selection destroys the memory */
|
/* Remember granularity till a new selection destroys the memory */
|
||||||
[self setSelectionGranularity: granularity];
|
[self setSelectionGranularity: granularity];
|
||||||
|
|
||||||
// remember for column stable cursor up/down
|
|
||||||
_currentCursor = [self rectForCharacterIndex: chosenRange.location].origin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) keyDown: (NSEvent*)theEvent
|
- (void) keyDown: (NSEvent*)theEvent
|
||||||
|
@ -2113,7 +2185,7 @@ afterString in order over charRange. */
|
||||||
character */
|
character */
|
||||||
if (range.length == 0)
|
if (range.length == 0)
|
||||||
{
|
{
|
||||||
if (range.location != [self textLength])
|
if (range.location != [_textStorage length])
|
||||||
{
|
{
|
||||||
/* Not at the end of text -- delete following character */
|
/* Not at the end of text -- delete following character */
|
||||||
range.length = 1;
|
range.length = 1;
|
||||||
|
@ -2140,11 +2212,6 @@ afterString in order over charRange. */
|
||||||
/* The new selected range is just the insertion point at the beginning
|
/* The new selected range is just the insertion point at the beginning
|
||||||
of deleted range */
|
of deleted range */
|
||||||
[self setSelectedRange: NSMakeRange (range.location, 0)];
|
[self setSelectedRange: NSMakeRange (range.location, 0)];
|
||||||
|
|
||||||
/* remember x for row - stable cursor movements - FIXME: Move this
|
|
||||||
inside setSelectedRange: */
|
|
||||||
_currentCursor = [self rectForCharacterIndex:
|
|
||||||
_selected_range.location].origin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) deleteBackward: (id)sender
|
- (void) deleteBackward: (id)sender
|
||||||
|
@ -2188,52 +2255,52 @@ afterString in order over charRange. */
|
||||||
/* The new selected range is just the insertion point at the beginning
|
/* The new selected range is just the insertion point at the beginning
|
||||||
of deleted range */
|
of deleted range */
|
||||||
[self setSelectedRange: NSMakeRange (range.location, 0)];
|
[self setSelectedRange: NSMakeRange (range.location, 0)];
|
||||||
|
|
||||||
/* remember x for row - stable cursor movements - FIXME: Move this
|
|
||||||
inside setSelectedRange: */
|
|
||||||
_currentCursor = [self rectForCharacterIndex:
|
|
||||||
_selected_range.location].origin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//<!> choose granularity according to keyboard modifier flags
|
|
||||||
- (void) moveUp: (id)sender
|
- (void) moveUp: (id)sender
|
||||||
{
|
{
|
||||||
unsigned cursorIndex;
|
float originalInsertionPoint;
|
||||||
NSPoint cursorPoint;
|
float startingY;
|
||||||
NSRange newRange;
|
unsigned newLocation;
|
||||||
|
|
||||||
if (_tf.is_field_editor)
|
if (_tf.is_field_editor)
|
||||||
{
|
{
|
||||||
[self _illegalMovement: NSUpTextMovement];
|
[self _illegalMovement: NSUpTextMovement];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do nothing if we are at beginning of text */
|
/* Do nothing if we are at beginning of text */
|
||||||
if (_selected_range.location == 0)
|
if (_selected_range.location == 0)
|
||||||
return;
|
|
||||||
|
|
||||||
if (_selected_range.length)
|
|
||||||
{
|
{
|
||||||
_currentCursor = [self rectForCharacterIndex:
|
return;
|
||||||
_selected_range.location].origin;
|
|
||||||
}
|
}
|
||||||
cursorIndex = _selected_range.location;
|
|
||||||
cursorPoint = [self rectForCharacterIndex: cursorIndex].origin;
|
/* Read from memory the horizontal position we aim to move the cursor
|
||||||
cursorIndex = [self characterIndexForPoint:
|
at on the next line */
|
||||||
NSMakePoint (_currentCursor.x + 0.001,
|
originalInsertionPoint = _originalInsertPoint;
|
||||||
MAX (0, cursorPoint.y - 0.001))];
|
|
||||||
|
|
||||||
newRange.location = cursorIndex;
|
/* Ask the layout manager to compute where to go */
|
||||||
newRange.length = 0;
|
startingY = NSMidY (_insertionPointRect);
|
||||||
[self setSelectedRange: newRange];
|
newLocation = [_layoutManager
|
||||||
|
_charIndexForInsertionPointMovingFromY: startingY
|
||||||
|
bestX: originalInsertionPoint
|
||||||
|
up: YES
|
||||||
|
textContainer: _textContainer];
|
||||||
|
|
||||||
|
/* Move the insertion point */
|
||||||
|
[self setSelectedRange: NSMakeRange (newLocation, 0)];
|
||||||
|
|
||||||
|
/* Restore the _originalInsertPoint (which was changed
|
||||||
|
by setSelectedRange:) because we don't want it to change between
|
||||||
|
moveUp:/moveDown: operations. */
|
||||||
|
_originalInsertPoint = originalInsertionPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) moveDown: (id)sender
|
- (void) moveDown: (id)sender
|
||||||
{
|
{
|
||||||
unsigned cursorIndex;
|
float originalInsertionPoint;
|
||||||
NSRect cursorRect;
|
float startingY;
|
||||||
NSRange newRange;
|
unsigned newLocation;
|
||||||
|
|
||||||
if (_tf.is_field_editor)
|
if (_tf.is_field_editor)
|
||||||
{
|
{
|
||||||
|
@ -2242,28 +2309,35 @@ afterString in order over charRange. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do nothing if we are at end of text */
|
/* Do nothing if we are at end of text */
|
||||||
if (_selected_range.location == [self textLength])
|
if (_selected_range.location == [_textStorage length])
|
||||||
return;
|
|
||||||
|
|
||||||
if (_selected_range.length != 0)
|
|
||||||
{
|
{
|
||||||
_currentCursor = [self rectForCharacterIndex:
|
return;
|
||||||
NSMaxRange (_selected_range)].origin;
|
|
||||||
}
|
}
|
||||||
cursorIndex = _selected_range.location;
|
|
||||||
cursorRect = [self rectForCharacterIndex: cursorIndex];
|
|
||||||
cursorIndex = [self characterIndexForPoint:
|
|
||||||
NSMakePoint(_currentCursor.x + 0.001,
|
|
||||||
NSMaxY (cursorRect) + 0.001)];
|
|
||||||
|
|
||||||
newRange.location = cursorIndex;
|
/* Read from memory the horizontal position we aim to move the cursor
|
||||||
newRange.length = 0;
|
at on the next line */
|
||||||
[self setSelectedRange: newRange];
|
originalInsertionPoint = _originalInsertPoint;
|
||||||
|
|
||||||
|
/* Ask the layout manager to compute where to go */
|
||||||
|
startingY = NSMidY (_insertionPointRect);
|
||||||
|
newLocation = [_layoutManager
|
||||||
|
_charIndexForInsertionPointMovingFromY: startingY
|
||||||
|
bestX: originalInsertionPoint
|
||||||
|
up: NO
|
||||||
|
textContainer: _textContainer];
|
||||||
|
|
||||||
|
/* Move the insertion point */
|
||||||
|
[self setSelectedRange: NSMakeRange (newLocation, 0)];
|
||||||
|
|
||||||
|
/* Restore the _originalInsertPoint (which was changed
|
||||||
|
by setSelectedRange:) because we don't want it to change between
|
||||||
|
moveUp:/moveDown: operations. */
|
||||||
|
_originalInsertPoint = originalInsertionPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) moveLeft: (id)sender
|
- (void) moveLeft: (id)sender
|
||||||
{
|
{
|
||||||
NSRange newSelectedRange;
|
unsigned newLocation;
|
||||||
|
|
||||||
/* Do nothing if we are at beginning of text with no selection */
|
/* Do nothing if we are at beginning of text with no selection */
|
||||||
if (_selected_range.location == 0 && _selected_range.length == 0)
|
if (_selected_range.location == 0 && _selected_range.length == 0)
|
||||||
|
@ -2276,21 +2350,21 @@ afterString in order over charRange. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_selected_range.location == 0)
|
if (_selected_range.location == 0)
|
||||||
newSelectedRange.location = 0;
|
{
|
||||||
|
newLocation = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
newSelectedRange.location = _selected_range.location - 1;
|
{
|
||||||
newSelectedRange.length = 0;
|
newLocation = _selected_range.location - 1;
|
||||||
|
}
|
||||||
|
|
||||||
[self setSelectedRange: newSelectedRange];
|
[self setSelectedRange: NSMakeRange (newLocation, 0)];
|
||||||
|
|
||||||
_currentCursor.x = [self rectForCharacterIndex:
|
|
||||||
_selected_range.location].origin.x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) moveRight: (id)sender
|
- (void) moveRight: (id)sender
|
||||||
{
|
{
|
||||||
NSRange newSelectedRange;
|
unsigned int length = [_textStorage length];
|
||||||
unsigned int length = [self textLength];
|
unsigned newLocation;
|
||||||
|
|
||||||
/* Do nothing if we are at end of text */
|
/* Do nothing if we are at end of text */
|
||||||
if (_selected_range.location == length)
|
if (_selected_range.location == length)
|
||||||
|
@ -2302,13 +2376,9 @@ afterString in order over charRange. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
newSelectedRange.location = MIN(NSMaxRange(_selected_range) + 1, length);
|
newLocation = MIN (NSMaxRange (_selected_range) + 1, length);
|
||||||
newSelectedRange.length = 0;
|
|
||||||
|
|
||||||
[self setSelectedRange: newSelectedRange];
|
[self setSelectedRange: NSMakeRange (newLocation, 0)];
|
||||||
|
|
||||||
_currentCursor.x = [self rectForCharacterIndex:
|
|
||||||
_selected_range.location].origin.x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2365,10 +2435,8 @@ afterString in order over charRange. */
|
||||||
|
|
||||||
if ([self shouldDrawInsertionPoint])
|
if ([self shouldDrawInsertionPoint])
|
||||||
{
|
{
|
||||||
NSRect rect;
|
[self setNeedsDisplayInRect: _insertionPointRect
|
||||||
|
avoidAdditionalLayout: YES];
|
||||||
rect = [self rectForInsertionPointAtIndex: _selected_range.location];
|
|
||||||
[self setNeedsDisplayInRect: rect avoidAdditionalLayout: YES];
|
|
||||||
//<!> stop timed entry
|
//<!> stop timed entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2434,10 +2502,8 @@ afterString in order over charRange. */
|
||||||
if (NSLocationInRange (location, drawnRange)
|
if (NSLocationInRange (location, drawnRange)
|
||||||
|| location == NSMaxRange (drawnRange))
|
|| location == NSMaxRange (drawnRange))
|
||||||
{
|
{
|
||||||
NSRect rect;
|
[self drawInsertionPointInRect: _insertionPointRect
|
||||||
|
color: _caret_color
|
||||||
rect = [self rectForInsertionPointAtIndex: location];
|
|
||||||
[self drawInsertionPointInRect: rect color: _caret_color
|
|
||||||
turnedOn: YES];
|
turnedOn: YES];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3076,8 +3142,9 @@ other than copy/paste or dragging. */
|
||||||
+ (NSDictionary*) defaultTypingAttributes
|
+ (NSDictionary*) defaultTypingAttributes
|
||||||
{
|
{
|
||||||
return [NSDictionary dictionaryWithObjectsAndKeys:
|
return [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName,
|
[NSParagraphStyle defaultParagraphStyle],
|
||||||
[NSFont userFontOfSize: 0], NSFontAttributeName,
|
NSParagraphStyleAttributeName,
|
||||||
|
[NSFont userFontOfSize: 0], NSFontAttributeName,
|
||||||
[NSColor textColor], NSForegroundColorAttributeName,
|
[NSColor textColor], NSForegroundColorAttributeName,
|
||||||
nil];
|
nil];
|
||||||
}
|
}
|
||||||
|
@ -3106,11 +3173,11 @@ other than copy/paste or dragging. */
|
||||||
|
|
||||||
- (void) _illegalMovement: (int)textMovement
|
- (void) _illegalMovement: (int)textMovement
|
||||||
{
|
{
|
||||||
// This is similar to [self resignFirstResponder],
|
// This is similar to [self resignFirstResponder], with the
|
||||||
// with the difference that in the notification we need
|
// difference that in the notification we need to put the
|
||||||
// to put the NSTextMovement, which resignFirstResponder
|
// NSTextMovement, which resignFirstResponder does not. Also, if we
|
||||||
// does not. Also, if we are ending editing, we are going
|
// are ending editing, we are going to be removed, so it's useless
|
||||||
// to be removed, so it's useless to update any drawing.
|
// to update any drawing.
|
||||||
NSNumber *number;
|
NSNumber *number;
|
||||||
NSDictionary *uiDictionary;
|
NSDictionary *uiDictionary;
|
||||||
|
|
||||||
|
@ -3160,13 +3227,6 @@ other than copy/paste or dragging. */
|
||||||
}
|
}
|
||||||
// end: drag accepting---------------------------------
|
// end: drag accepting---------------------------------
|
||||||
|
|
||||||
// central text deletion/backspace method
|
|
||||||
// (takes care of optimized redraw/ cursor positioning)
|
|
||||||
- (void) deleteRange: (NSRange) aRange backspace: (BOOL) flag
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
- (unsigned) characterIndexForPoint: (NSPoint)point
|
- (unsigned) characterIndexForPoint: (NSPoint)point
|
||||||
{
|
{
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
@ -3184,30 +3244,7 @@ other than copy/paste or dragging. */
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSRect) rectForCharacterIndex: (unsigned)index
|
- (NSRect) rectForCharacterRange: (NSRange)aRange
|
||||||
{
|
|
||||||
NSRange charRange;
|
|
||||||
NSRange glyphRange;
|
|
||||||
unsigned glyphIndex;
|
|
||||||
NSRect rect;
|
|
||||||
NSPoint loc;
|
|
||||||
|
|
||||||
charRange = NSMakeRange (index, 1);
|
|
||||||
glyphRange = [_layoutManager glyphRangeForCharacterRange: charRange
|
|
||||||
actualCharacterRange: NULL];
|
|
||||||
glyphIndex = glyphRange.location;
|
|
||||||
|
|
||||||
rect = [_layoutManager lineFragmentRectForGlyphAtIndex: glyphIndex
|
|
||||||
effectiveRange: NULL];
|
|
||||||
loc = [_layoutManager locationForGlyphAtIndex: glyphIndex];
|
|
||||||
|
|
||||||
rect.origin.x += loc.x;
|
|
||||||
rect.size.width -= loc.x;
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSRect) rectForCharacterRange: (NSRange) aRange
|
|
||||||
{
|
{
|
||||||
NSRange glyphRange;
|
NSRange glyphRange;
|
||||||
|
|
||||||
|
@ -3217,18 +3254,6 @@ other than copy/paste or dragging. */
|
||||||
return [_layoutManager boundingRectForGlyphRange: glyphRange
|
return [_layoutManager boundingRectForGlyphRange: glyphRange
|
||||||
inTextContainer: _textContainer];
|
inTextContainer: _textContainer];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSRect) rectForInsertionPointAtIndex: (unsigned)index
|
|
||||||
{
|
|
||||||
NSRect rect = [self rectForCharacterIndex: index];
|
|
||||||
rect.size.width = 1;
|
|
||||||
|
|
||||||
if (rect.size.height == 0)
|
|
||||||
rect.size.height = 12;
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation NSTextView(NSTextInput)
|
@implementation NSTextView(NSTextInput)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue