TextView: Update navigation shortcuts
* Command+Left goes to beginning of line, ignoring softwrap * Command+Right goes to the end of line, ignoring softwrap * Home goes to beginning of line, accounting for softwrap * End goes to end of line, accounting for softwrap * Option+Left goes to previous word * Option+Right goes to next word * Command+Home and Command+Up go to beginning of document * Command+End and Command+Down go to end of document Shift with any of the above also selects the text. This is similar to how the text editor Eddie works.
This commit is contained in:
@@ -292,10 +292,10 @@ private:
|
|||||||
|
|
||||||
void _HandleBackspace();
|
void _HandleBackspace();
|
||||||
void _HandleArrowKey(uint32 arrowKey,
|
void _HandleArrowKey(uint32 arrowKey,
|
||||||
bool commandKeyDown = false);
|
int32 modifiers = -1);
|
||||||
void _HandleDelete();
|
void _HandleDelete();
|
||||||
void _HandlePageKey(uint32 pageKey,
|
void _HandlePageKey(uint32 pageKey,
|
||||||
bool commandKeyDown = false);
|
int32 modifiers = -1);
|
||||||
void _HandleAlphaKey(const char* bytes,
|
void _HandleAlphaKey(const char* bytes,
|
||||||
int32 numBytes);
|
int32 numBytes);
|
||||||
|
|
||||||
@@ -382,6 +382,9 @@ private:
|
|||||||
int32 _NextInitialByte(int32 offset) const;
|
int32 _NextInitialByte(int32 offset) const;
|
||||||
int32 _PreviousInitialByte(int32 offset) const;
|
int32 _PreviousInitialByte(int32 offset) const;
|
||||||
|
|
||||||
|
int32 _PreviousLineStart(int32 offset);
|
||||||
|
int32 _NextLineEnd(int32 offset);
|
||||||
|
|
||||||
int32 _PreviousWordBoundary(int32 offset);
|
int32 _PreviousWordBoundary(int32 offset);
|
||||||
int32 _NextWordBoundary(int32 offset);
|
int32 _NextWordBoundary(int32 offset);
|
||||||
|
|
||||||
@@ -449,9 +452,15 @@ private:
|
|||||||
float fMinTextRectWidth;
|
float fMinTextRectWidth;
|
||||||
LayoutData* fLayoutData;
|
LayoutData* fLayoutData;
|
||||||
int32 fLastClickOffset;
|
int32 fLastClickOffset;
|
||||||
|
|
||||||
|
bool fInstalledNavigateLinewiseShortcuts;
|
||||||
bool fInstalledNavigateWordwiseShortcuts;
|
bool fInstalledNavigateWordwiseShortcuts;
|
||||||
|
bool fInstalledNavigateDocwiseShortcuts;
|
||||||
bool fInstalledNavigateToTopOrBottomShortcuts;
|
bool fInstalledNavigateToTopOrBottomShortcuts;
|
||||||
|
|
||||||
|
bool fInstalledSelectLinewiseShortcuts;
|
||||||
bool fInstalledSelectWordwiseShortcuts;
|
bool fInstalledSelectWordwiseShortcuts;
|
||||||
|
bool fInstalledSelectDocwiseShortcuts;
|
||||||
bool fInstalledSelectToTopOrBottomShortcuts;
|
bool fInstalledSelectToTopOrBottomShortcuts;
|
||||||
|
|
||||||
uint32 _reserved[6];
|
uint32 _reserved[6];
|
||||||
|
|||||||
+340
-154
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2009 Haiku, Inc. All rights reserved.
|
* Copyright 2001-2014 Haiku, Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
* Stefano Ceccherini, [email protected]
|
* Stefano Ceccherini, [email protected]
|
||||||
* Marc Flerackers, [email protected]
|
* Marc Flerackers, [email protected]
|
||||||
* Hiroshi Lockheimer (BTextView is based on his STEEngine)
|
* Hiroshi Lockheimer (BTextView is based on his STEEngine)
|
||||||
|
* John Scipione, [email protected]
|
||||||
* Oliver Tappe, [email protected]
|
* Oliver Tappe, [email protected]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -191,13 +192,8 @@ static const rgb_color kRedInputColor = { 255, 152, 152, 255 };
|
|||||||
static const float kHorizontalScrollBarStep = 10.0;
|
static const float kHorizontalScrollBarStep = 10.0;
|
||||||
static const float kVerticalScrollBarStep = 12.0;
|
static const float kVerticalScrollBarStep = 12.0;
|
||||||
|
|
||||||
|
static const int32 kMsgNavigateArrow = '_NvA';
|
||||||
enum {
|
static const int32 kMsgNavigatePage = '_NvP';
|
||||||
NAVIGATE_TO_PREVIOUS_WORD = '_NVP',
|
|
||||||
NAVIGATE_TO_NEXT_WORD = '_NVN',
|
|
||||||
NAVIGATE_TO_TOP = '_NVT',
|
|
||||||
NAVIGATE_TO_BOTTOM = '_NVB',
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static property_info sPropertyList[] = {
|
static property_info sPropertyList[] = {
|
||||||
@@ -958,19 +954,21 @@ BTextView::MessageReceived(BMessage* message)
|
|||||||
_TrackDrag(fWhere);
|
_TrackDrag(fWhere);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAVIGATE_TO_PREVIOUS_WORD:
|
case kMsgNavigateArrow:
|
||||||
_HandleArrowKey(B_LEFT_ARROW, true);
|
{
|
||||||
break;
|
int32 key = message->GetInt32("key", 0);
|
||||||
case NAVIGATE_TO_NEXT_WORD:
|
int32 modifiers = message->GetInt32("modifiers", 0);
|
||||||
_HandleArrowKey(B_RIGHT_ARROW, true);
|
_HandleArrowKey(key, modifiers);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NAVIGATE_TO_TOP:
|
case kMsgNavigatePage:
|
||||||
_HandlePageKey(B_HOME, true);
|
{
|
||||||
break;
|
int32 key = message->GetInt32("key", 0);
|
||||||
case NAVIGATE_TO_BOTTOM:
|
int32 modifiers = message->GetInt32("modifiers", 0);
|
||||||
_HandlePageKey(B_END, true);
|
_HandlePageKey(key, modifiers);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BView::MessageReceived(message);
|
BView::MessageReceived(message);
|
||||||
@@ -3110,9 +3108,14 @@ BTextView::_InitObject(BRect textRect, const BFont* initialFont,
|
|||||||
fLines = new LineBuffer;
|
fLines = new LineBuffer;
|
||||||
fStyles = new StyleBuffer(&font, initialColor);
|
fStyles = new StyleBuffer(&font, initialColor);
|
||||||
|
|
||||||
|
fInstalledNavigateLinewiseShortcuts = false;
|
||||||
fInstalledNavigateWordwiseShortcuts = false;
|
fInstalledNavigateWordwiseShortcuts = false;
|
||||||
|
fInstalledNavigateDocwiseShortcuts = false;
|
||||||
fInstalledNavigateToTopOrBottomShortcuts = false;
|
fInstalledNavigateToTopOrBottomShortcuts = false;
|
||||||
|
|
||||||
|
fInstalledSelectLinewiseShortcuts = false;
|
||||||
fInstalledSelectWordwiseShortcuts = false;
|
fInstalledSelectWordwiseShortcuts = false;
|
||||||
|
fInstalledSelectDocwiseShortcuts = false;
|
||||||
fInstalledSelectToTopOrBottomShortcuts = false;
|
fInstalledSelectToTopOrBottomShortcuts = false;
|
||||||
|
|
||||||
// We put these here instead of in the constructor initializer list
|
// We put these here instead of in the constructor initializer list
|
||||||
@@ -3195,7 +3198,7 @@ BTextView::_HandleBackspace()
|
|||||||
|
|
||||||
// Handles when any arrow key is pressed.
|
// Handles when any arrow key is pressed.
|
||||||
void
|
void
|
||||||
BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
|
BTextView::_HandleArrowKey(uint32 arrowKey, int32 modifiers)
|
||||||
{
|
{
|
||||||
// return if there's nowhere to go
|
// return if there's nowhere to go
|
||||||
if (fText->Length() == 0)
|
if (fText->Length() == 0)
|
||||||
@@ -3204,26 +3207,36 @@ BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
|
|||||||
int32 selStart = fSelStart;
|
int32 selStart = fSelStart;
|
||||||
int32 selEnd = fSelEnd;
|
int32 selEnd = fSelEnd;
|
||||||
|
|
||||||
int32 modifiers = 0;
|
if (modifiers < 0) {
|
||||||
BMessage* message = Window()->CurrentMessage();
|
BMessage* currentMessage = Window()->CurrentMessage();
|
||||||
if (message != NULL)
|
if (currentMessage == NULL
|
||||||
message->FindInt32("modifiers", &modifiers);
|
|| currentMessage->FindInt32("modifiers", &modifiers) != B_OK) {
|
||||||
|
modifiers = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool shiftDown = modifiers & B_SHIFT_KEY;
|
bool shiftKeyDown = (modifiers & B_SHIFT_KEY) != 0;
|
||||||
|
bool controlKeyDown = (modifiers & B_CONTROL_KEY) != 0;
|
||||||
|
bool optionKeyDown = (modifiers & B_OPTION_KEY) != 0;
|
||||||
|
bool commandKeyDown = (modifiers & B_COMMAND_KEY) != 0;
|
||||||
|
|
||||||
int32 lastClickOffset = fCaretOffset;
|
int32 lastClickOffset = fCaretOffset;
|
||||||
|
|
||||||
switch (arrowKey) {
|
switch (arrowKey) {
|
||||||
case B_LEFT_ARROW:
|
case B_LEFT_ARROW:
|
||||||
if (!fEditable)
|
if (!fEditable)
|
||||||
_ScrollBy(-1 * kHorizontalScrollBarStep, 0);
|
_ScrollBy(-1 * kHorizontalScrollBarStep, 0);
|
||||||
else if (fSelStart != fSelEnd && !shiftDown)
|
else if (fSelStart != fSelEnd && !shiftKeyDown)
|
||||||
fCaretOffset = fSelStart;
|
fCaretOffset = fSelStart;
|
||||||
else {
|
else {
|
||||||
fCaretOffset
|
if (commandKeyDown && !optionKeyDown && !controlKeyDown)
|
||||||
= commandKeyDown
|
fCaretOffset = _PreviousLineStart(fCaretOffset);
|
||||||
? _PreviousWordStart(fCaretOffset - 1)
|
else if (optionKeyDown && !commandKeyDown && !controlKeyDown)
|
||||||
: _PreviousInitialByte(fCaretOffset);
|
fCaretOffset = _PreviousWordStart(fCaretOffset - 1);
|
||||||
if (shiftDown && fCaretOffset != lastClickOffset) {
|
else
|
||||||
|
fCaretOffset = _PreviousInitialByte(fCaretOffset);
|
||||||
|
|
||||||
|
if (shiftKeyDown && fCaretOffset != lastClickOffset) {
|
||||||
if (fCaretOffset < fSelStart) {
|
if (fCaretOffset < fSelStart) {
|
||||||
// extend selection to the left
|
// extend selection to the left
|
||||||
selStart = fCaretOffset;
|
selStart = fCaretOffset;
|
||||||
@@ -3242,14 +3255,17 @@ BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
|
|||||||
case B_RIGHT_ARROW:
|
case B_RIGHT_ARROW:
|
||||||
if (!fEditable)
|
if (!fEditable)
|
||||||
_ScrollBy(kHorizontalScrollBarStep, 0);
|
_ScrollBy(kHorizontalScrollBarStep, 0);
|
||||||
else if (fSelStart != fSelEnd && !shiftDown)
|
else if (fSelStart != fSelEnd && !shiftKeyDown)
|
||||||
fCaretOffset = fSelEnd;
|
fCaretOffset = fSelEnd;
|
||||||
else {
|
else {
|
||||||
fCaretOffset
|
if (commandKeyDown && !controlKeyDown && !optionKeyDown)
|
||||||
= commandKeyDown
|
fCaretOffset = _NextLineEnd(fCaretOffset);
|
||||||
? _NextWordEnd(fCaretOffset)
|
else if (optionKeyDown && !controlKeyDown && !commandKeyDown)
|
||||||
: _NextInitialByte(fCaretOffset);
|
fCaretOffset = _NextWordEnd(fCaretOffset);
|
||||||
if (shiftDown && fCaretOffset != lastClickOffset) {
|
else
|
||||||
|
fCaretOffset = _NextInitialByte(fCaretOffset);
|
||||||
|
|
||||||
|
if (shiftKeyDown && fCaretOffset != lastClickOffset) {
|
||||||
if (fCaretOffset > fSelEnd) {
|
if (fCaretOffset > fSelEnd) {
|
||||||
// extend selection to the right
|
// extend selection to the right
|
||||||
selEnd = fCaretOffset;
|
selEnd = fCaretOffset;
|
||||||
@@ -3269,23 +3285,28 @@ BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
|
|||||||
{
|
{
|
||||||
if (!fEditable)
|
if (!fEditable)
|
||||||
_ScrollBy(0, -1 * kVerticalScrollBarStep);
|
_ScrollBy(0, -1 * kVerticalScrollBarStep);
|
||||||
else if (fSelStart != fSelEnd && !shiftDown)
|
else if (fSelStart != fSelEnd && !shiftKeyDown)
|
||||||
fCaretOffset = fSelStart;
|
fCaretOffset = fSelStart;
|
||||||
else {
|
else {
|
||||||
float height;
|
if (commandKeyDown && !controlKeyDown && !optionKeyDown) {
|
||||||
BPoint point = PointAt(fCaretOffset, &height);
|
_ScrollTo(0, 0);
|
||||||
// find the caret position on the previous
|
fCaretOffset = 0;
|
||||||
// line by gently stepping onto this line
|
} else {
|
||||||
for (int i = 1; i <= height; i++) {
|
float height;
|
||||||
point.y--;
|
BPoint point = PointAt(fCaretOffset, &height);
|
||||||
int32 offset = OffsetAt(point);
|
// find the caret position on the previous
|
||||||
if (offset < fCaretOffset || i == height) {
|
// line by gently stepping onto this line
|
||||||
fCaretOffset = offset;
|
for (int i = 1; i <= height; i++) {
|
||||||
break;
|
point.y--;
|
||||||
|
int32 offset = OffsetAt(point);
|
||||||
|
if (offset < fCaretOffset || i == height) {
|
||||||
|
fCaretOffset = offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shiftDown && fCaretOffset != lastClickOffset) {
|
if (shiftKeyDown && fCaretOffset != lastClickOffset) {
|
||||||
if (fCaretOffset < fSelStart) {
|
if (fCaretOffset < fSelStart) {
|
||||||
// extend selection to the top
|
// extend selection to the top
|
||||||
selStart = fCaretOffset;
|
selStart = fCaretOffset;
|
||||||
@@ -3306,14 +3327,20 @@ BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
|
|||||||
{
|
{
|
||||||
if (!fEditable)
|
if (!fEditable)
|
||||||
_ScrollBy(0, kVerticalScrollBarStep);
|
_ScrollBy(0, kVerticalScrollBarStep);
|
||||||
else if (fSelStart != fSelEnd && !shiftDown)
|
else if (fSelStart != fSelEnd && !shiftKeyDown)
|
||||||
fCaretOffset = fSelEnd;
|
fCaretOffset = fSelEnd;
|
||||||
else {
|
else {
|
||||||
float height;
|
if (commandKeyDown && !optionKeyDown && !controlKeyDown) {
|
||||||
BPoint point = PointAt(fCaretOffset, &height);
|
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
|
||||||
point.y += height;
|
fCaretOffset = fText->Length();
|
||||||
fCaretOffset = OffsetAt(point);
|
} else {
|
||||||
if (shiftDown && fCaretOffset != lastClickOffset) {
|
float height;
|
||||||
|
BPoint point = PointAt(fCaretOffset, &height);
|
||||||
|
point.y += height;
|
||||||
|
fCaretOffset = OffsetAt(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shiftKeyDown && fCaretOffset != lastClickOffset) {
|
||||||
if (fCaretOffset > fSelEnd) {
|
if (fCaretOffset > fSelEnd) {
|
||||||
// extend selection to the bottom
|
// extend selection to the bottom
|
||||||
selEnd = fCaretOffset;
|
selEnd = fCaretOffset;
|
||||||
@@ -3335,7 +3362,7 @@ BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
|
|||||||
fStyles->InvalidateNullStyle();
|
fStyles->InvalidateNullStyle();
|
||||||
|
|
||||||
if (fEditable) {
|
if (fEditable) {
|
||||||
if (shiftDown)
|
if (shiftKeyDown)
|
||||||
Select(selStart, selEnd);
|
Select(selStart, selEnd);
|
||||||
else
|
else
|
||||||
Select(fCaretOffset, fCaretOffset);
|
Select(fCaretOffset, fCaretOffset);
|
||||||
@@ -3377,15 +3404,21 @@ BTextView::_HandleDelete()
|
|||||||
|
|
||||||
// Handles when the Page Up or Page Down key is pressed.
|
// Handles when the Page Up or Page Down key is pressed.
|
||||||
void
|
void
|
||||||
BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
|
BTextView::_HandlePageKey(uint32 pageKey, int32 modifiers)
|
||||||
{
|
{
|
||||||
int32 mods = 0;
|
if (modifiers < 0) {
|
||||||
BMessage* currentMessage = Window()->CurrentMessage();
|
BMessage* currentMessage = Window()->CurrentMessage();
|
||||||
if (currentMessage)
|
if (currentMessage == NULL
|
||||||
currentMessage->FindInt32("modifiers", &mods);
|
|| currentMessage->FindInt32("modifiers", &modifiers) != B_OK) {
|
||||||
|
modifiers = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shiftKeyDown = (modifiers & B_SHIFT_KEY) != 0;
|
||||||
|
bool controlKeyDown = (modifiers & B_CONTROL_KEY) != 0;
|
||||||
|
bool optionKeyDown = (modifiers & B_OPTION_KEY) != 0;
|
||||||
|
bool commandKeyDown = (modifiers & B_COMMAND_KEY) != 0;
|
||||||
|
|
||||||
bool shiftDown = mods & B_SHIFT_KEY;
|
|
||||||
bool controlDown = mods & B_CONTROL_KEY;
|
|
||||||
STELine* line = NULL;
|
STELine* line = NULL;
|
||||||
int32 selStart = fSelStart;
|
int32 selStart = fSelStart;
|
||||||
int32 selEnd = fSelEnd;
|
int32 selEnd = fSelEnd;
|
||||||
@@ -3397,33 +3430,34 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
|
|||||||
fCaretOffset = 0;
|
fCaretOffset = 0;
|
||||||
_ScrollTo(0, 0);
|
_ScrollTo(0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
} else if (fSelStart != fSelEnd && !shiftKeyDown)
|
||||||
|
fCaretOffset = fSelEnd;
|
||||||
if (commandKeyDown || controlDown) {
|
else {
|
||||||
_ScrollTo(0, 0);
|
if (commandKeyDown && !optionKeyDown && !controlKeyDown) {
|
||||||
fCaretOffset = 0;
|
_ScrollTo(0, 0);
|
||||||
} else {
|
fCaretOffset = 0;
|
||||||
// get the start of the last line if caret is on it
|
|
||||||
line = (*fLines)[_LineAt(lastClickOffset)];
|
|
||||||
fCaretOffset = line->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shiftDown)
|
|
||||||
selStart = selEnd = fCaretOffset;
|
|
||||||
else if (fCaretOffset != lastClickOffset) {
|
|
||||||
if (fCaretOffset < fSelStart) {
|
|
||||||
// extend selection to the left
|
|
||||||
selStart = fCaretOffset;
|
|
||||||
if (lastClickOffset > fSelStart) {
|
|
||||||
// caret has jumped across "anchor"
|
|
||||||
selEnd = fSelStart;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// shrink selection from the right
|
// get the start of the last line if caret is on it
|
||||||
selEnd = fCaretOffset;
|
line = (*fLines)[_LineAt(lastClickOffset)];
|
||||||
|
fCaretOffset = line->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shiftKeyDown)
|
||||||
|
selStart = selEnd = fCaretOffset;
|
||||||
|
else if (fCaretOffset != lastClickOffset) {
|
||||||
|
if (fCaretOffset < fSelStart) {
|
||||||
|
// extend selection to the left
|
||||||
|
selStart = fCaretOffset;
|
||||||
|
if (lastClickOffset > fSelStart) {
|
||||||
|
// caret has jumped across "anchor"
|
||||||
|
selEnd = fSelStart;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// shrink selection from the right
|
||||||
|
selEnd = fCaretOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_END:
|
case B_END:
|
||||||
@@ -3431,47 +3465,48 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
|
|||||||
fCaretOffset = fText->Length();
|
fCaretOffset = fText->Length();
|
||||||
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
|
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
|
||||||
break;
|
break;
|
||||||
}
|
} else if (fSelStart != fSelEnd && !shiftKeyDown)
|
||||||
|
fCaretOffset = fSelEnd;
|
||||||
if (commandKeyDown || controlDown) {
|
else {
|
||||||
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
|
if (commandKeyDown && !optionKeyDown && !controlKeyDown) {
|
||||||
fCaretOffset = fText->Length();
|
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
|
||||||
} else {
|
fCaretOffset = fText->Length();
|
||||||
// If we are on the last line, just go to the last
|
|
||||||
// character in the buffer, otherwise get the starting
|
|
||||||
// offset of the next line, and go to the previous character
|
|
||||||
int32 currentLine = _LineAt(lastClickOffset);
|
|
||||||
if (currentLine + 1 < fLines->NumLines()) {
|
|
||||||
line = (*fLines)[currentLine + 1];
|
|
||||||
fCaretOffset = _PreviousInitialByte(line->offset);
|
|
||||||
} else {
|
} else {
|
||||||
// This check is needed to avoid moving the cursor
|
// If we are on the last line, just go to the last
|
||||||
// when the cursor is on the last line, and that line
|
// character in the buffer, otherwise get the starting
|
||||||
// is empty
|
// offset of the next line, and go to the previous character
|
||||||
if (fCaretOffset != fText->Length()) {
|
int32 currentLine = _LineAt(lastClickOffset);
|
||||||
fCaretOffset = fText->Length();
|
if (currentLine + 1 < fLines->NumLines()) {
|
||||||
if (ByteAt(fCaretOffset - 1) == B_ENTER)
|
line = (*fLines)[currentLine + 1];
|
||||||
fCaretOffset--;
|
fCaretOffset = _PreviousInitialByte(line->offset);
|
||||||
|
} else {
|
||||||
|
// This check is needed to avoid moving the cursor
|
||||||
|
// when the cursor is on the last line, and that line
|
||||||
|
// is empty
|
||||||
|
if (fCaretOffset != fText->Length()) {
|
||||||
|
fCaretOffset = fText->Length();
|
||||||
|
if (ByteAt(fCaretOffset - 1) == B_ENTER)
|
||||||
|
fCaretOffset--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shiftKeyDown)
|
||||||
|
selStart = selEnd = fCaretOffset;
|
||||||
|
else if (fCaretOffset != lastClickOffset) {
|
||||||
|
if (fCaretOffset > fSelEnd) {
|
||||||
|
// extend selection to the right
|
||||||
|
selEnd = fCaretOffset;
|
||||||
|
if (lastClickOffset < fSelEnd) {
|
||||||
|
// caret has jumped across "anchor"
|
||||||
|
selStart = fSelEnd;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// shrink selection from the left
|
||||||
|
selStart = fCaretOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shiftDown)
|
|
||||||
selStart = selEnd = fCaretOffset;
|
|
||||||
else if (fCaretOffset != lastClickOffset) {
|
|
||||||
if (fCaretOffset > fSelEnd) {
|
|
||||||
// extend selection to the right
|
|
||||||
selEnd = fCaretOffset;
|
|
||||||
if (lastClickOffset < fSelEnd) {
|
|
||||||
// caret has jumped across "anchor"
|
|
||||||
selStart = fSelEnd;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// shrink selection from the left
|
|
||||||
selStart = fCaretOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_PAGE_UP:
|
case B_PAGE_UP:
|
||||||
@@ -3487,7 +3522,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
|
|||||||
if (!fEditable)
|
if (!fEditable)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!shiftDown)
|
if (!shiftKeyDown)
|
||||||
selStart = selEnd = fCaretOffset;
|
selStart = selEnd = fCaretOffset;
|
||||||
else if (fCaretOffset != lastClickOffset) {
|
else if (fCaretOffset != lastClickOffset) {
|
||||||
if (fCaretOffset < fSelStart) {
|
if (fCaretOffset < fSelStart) {
|
||||||
@@ -3517,7 +3552,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
|
|||||||
if (!fEditable)
|
if (!fEditable)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!shiftDown)
|
if (!shiftKeyDown)
|
||||||
selStart = selEnd = fCaretOffset;
|
selStart = selEnd = fCaretOffset;
|
||||||
else if (fCaretOffset != lastClickOffset) {
|
else if (fCaretOffset != lastClickOffset) {
|
||||||
if (fCaretOffset > fSelEnd) {
|
if (fCaretOffset > fSelEnd) {
|
||||||
@@ -3538,7 +3573,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fEditable) {
|
if (fEditable) {
|
||||||
if (shiftDown)
|
if (shiftKeyDown)
|
||||||
Select(selStart, selEnd);
|
Select(selStart, selEnd);
|
||||||
else
|
else
|
||||||
Select(fCaretOffset, fCaretOffset);
|
Select(fCaretOffset, fCaretOffset);
|
||||||
@@ -3903,6 +3938,43 @@ BTextView::_FindLineBreak(int32 fromOffset, float* _ascent, float* _descent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BTextView::_PreviousLineStart(int32 offset)
|
||||||
|
{
|
||||||
|
if (offset <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (offset > 0) {
|
||||||
|
offset = _PreviousInitialByte(offset);
|
||||||
|
if (_CharClassification(offset) == CHAR_CLASS_WHITESPACE
|
||||||
|
&& ByteAt(offset) == B_ENTER) {
|
||||||
|
return offset + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BTextView::_NextLineEnd(int32 offset)
|
||||||
|
{
|
||||||
|
int32 textLen = fText->Length();
|
||||||
|
if (offset >= textLen)
|
||||||
|
return textLen;
|
||||||
|
|
||||||
|
while (offset < textLen) {
|
||||||
|
if (_CharClassification(offset) == CHAR_CLASS_WHITESPACE
|
||||||
|
&& ByteAt(offset) == B_ENTER) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset = _NextInitialByte(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BTextView::_PreviousWordBoundary(int32 offset)
|
BTextView::_PreviousWordBoundary(int32 offset)
|
||||||
{
|
{
|
||||||
@@ -3940,7 +4012,8 @@ BTextView::_PreviousWordStart(int32 offset)
|
|||||||
if (offset <= 1)
|
if (offset <= 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
--offset; // need to look at previous char
|
--offset;
|
||||||
|
// need to look at previous char
|
||||||
if (_CharClassification(offset) != CHAR_CLASS_DEFAULT) {
|
if (_CharClassification(offset) != CHAR_CLASS_DEFAULT) {
|
||||||
// skip non-word characters
|
// skip non-word characters
|
||||||
while (offset > 0) {
|
while (offset > 0) {
|
||||||
@@ -4909,44 +4982,132 @@ BTextView::_Activate()
|
|||||||
_TrackMouse(where, NULL);
|
_TrackMouse(where, NULL);
|
||||||
|
|
||||||
if (Window() != NULL) {
|
if (Window() != NULL) {
|
||||||
|
BMessage* message;
|
||||||
|
|
||||||
if (!Window()->HasShortcut(B_LEFT_ARROW, B_COMMAND_KEY)
|
if (!Window()->HasShortcut(B_LEFT_ARROW, B_COMMAND_KEY)
|
||||||
&& !Window()->HasShortcut(B_RIGHT_ARROW, B_COMMAND_KEY)) {
|
&& !Window()->HasShortcut(B_RIGHT_ARROW, B_COMMAND_KEY)) {
|
||||||
Window()->AddShortcut(B_LEFT_ARROW, B_COMMAND_KEY,
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
new BMessage(NAVIGATE_TO_PREVIOUS_WORD), this);
|
message->AddInt32("key", B_LEFT_ARROW);
|
||||||
Window()->AddShortcut(B_RIGHT_ARROW, B_COMMAND_KEY,
|
message->AddInt32("modifiers", B_COMMAND_KEY);
|
||||||
new BMessage(NAVIGATE_TO_NEXT_WORD), this);
|
Window()->AddShortcut(B_LEFT_ARROW, B_COMMAND_KEY, message, this);
|
||||||
fInstalledNavigateWordwiseShortcuts = true;
|
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_RIGHT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY);
|
||||||
|
Window()->AddShortcut(B_RIGHT_ARROW, B_COMMAND_KEY, message, this);
|
||||||
|
|
||||||
|
fInstalledNavigateLinewiseShortcuts = true;
|
||||||
}
|
}
|
||||||
if (!Window()->HasShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY)
|
if (!Window()->HasShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY)
|
||||||
&& !Window()->HasShortcut(B_RIGHT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY)) {
|
&& !Window()->HasShortcut(B_RIGHT_ARROW,
|
||||||
BMessage* message = new BMessage(NAVIGATE_TO_PREVIOUS_WORD);
|
B_COMMAND_KEY | B_SHIFT_KEY)) {
|
||||||
message->AddInt32("modifiers", B_SHIFT_KEY);
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_LEFT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
Window()->AddShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
|
Window()->AddShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
|
||||||
message, this);
|
message, this);
|
||||||
message = new BMessage(NAVIGATE_TO_NEXT_WORD);
|
|
||||||
message->AddInt32("modifiers", B_SHIFT_KEY);
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_RIGHT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
Window()->AddShortcut(B_RIGHT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
|
Window()->AddShortcut(B_RIGHT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
|
||||||
message, this);
|
message, this);
|
||||||
|
|
||||||
|
fInstalledSelectLinewiseShortcuts = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Window()->HasShortcut(B_LEFT_ARROW, B_OPTION_KEY)
|
||||||
|
&& !Window()->HasShortcut(B_RIGHT_ARROW, B_OPTION_KEY)) {
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_LEFT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_OPTION_KEY);
|
||||||
|
Window()->AddShortcut(B_LEFT_ARROW, B_OPTION_KEY, message, this);
|
||||||
|
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_RIGHT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_OPTION_KEY);
|
||||||
|
Window()->AddShortcut(B_RIGHT_ARROW, B_OPTION_KEY, message, this);
|
||||||
|
|
||||||
|
fInstalledNavigateWordwiseShortcuts = true;
|
||||||
|
}
|
||||||
|
if (!Window()->HasShortcut(B_LEFT_ARROW, B_OPTION_KEY | B_SHIFT_KEY)
|
||||||
|
&& !Window()->HasShortcut(B_RIGHT_ARROW,
|
||||||
|
B_OPTION_KEY | B_SHIFT_KEY)) {
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_LEFT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_OPTION_KEY | B_SHIFT_KEY);
|
||||||
|
Window()->AddShortcut(B_LEFT_ARROW, B_OPTION_KEY | B_SHIFT_KEY,
|
||||||
|
message, this);
|
||||||
|
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_RIGHT_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_OPTION_KEY | B_SHIFT_KEY);
|
||||||
|
Window()->AddShortcut(B_RIGHT_ARROW, B_OPTION_KEY | B_SHIFT_KEY,
|
||||||
|
message, this);
|
||||||
|
|
||||||
fInstalledSelectWordwiseShortcuts = true;
|
fInstalledSelectWordwiseShortcuts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Window()->HasShortcut(B_UP_ARROW, B_COMMAND_KEY)
|
||||||
|
&& !Window()->HasShortcut(B_DOWN_ARROW, B_COMMAND_KEY)) {
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_UP_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY);
|
||||||
|
Window()->AddShortcut(B_UP_ARROW, B_COMMAND_KEY, message, this);
|
||||||
|
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_DOWN_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY);
|
||||||
|
Window()->AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, message, this);
|
||||||
|
|
||||||
|
fInstalledNavigateDocwiseShortcuts = true;
|
||||||
|
}
|
||||||
|
if (!Window()->HasShortcut(B_UP_ARROW, B_COMMAND_KEY | B_SHIFT_KEY)
|
||||||
|
&& !Window()->HasShortcut(B_DOWN_ARROW,
|
||||||
|
B_COMMAND_KEY | B_SHIFT_KEY)) {
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_UP_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
|
Window()->AddShortcut(B_UP_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
|
||||||
|
message, this);
|
||||||
|
|
||||||
|
message = new BMessage(kMsgNavigateArrow);
|
||||||
|
message->AddInt32("key", B_DOWN_ARROW);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
|
Window()->AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY | B_SHIFT_KEY,
|
||||||
|
message, this);
|
||||||
|
|
||||||
|
fInstalledSelectDocwiseShortcuts = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Window()->HasShortcut(B_HOME, B_COMMAND_KEY)
|
if (!Window()->HasShortcut(B_HOME, B_COMMAND_KEY)
|
||||||
&& !Window()->HasShortcut(B_END, B_COMMAND_KEY)) {
|
&& !Window()->HasShortcut(B_END, B_COMMAND_KEY)) {
|
||||||
Window()->AddShortcut(B_HOME, B_COMMAND_KEY,
|
message = new BMessage(kMsgNavigatePage);
|
||||||
new BMessage(NAVIGATE_TO_TOP), this);
|
message->AddInt32("key", B_HOME);
|
||||||
Window()->AddShortcut(B_END, B_COMMAND_KEY,
|
message->AddInt32("modifiers", B_COMMAND_KEY);
|
||||||
new BMessage(NAVIGATE_TO_BOTTOM), this);
|
Window()->AddShortcut(B_HOME, B_COMMAND_KEY, message, this);
|
||||||
|
|
||||||
|
message = new BMessage(kMsgNavigatePage);
|
||||||
|
message->AddInt32("key", B_END);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY);
|
||||||
|
Window()->AddShortcut(B_END, B_COMMAND_KEY, message, this);
|
||||||
|
|
||||||
fInstalledNavigateToTopOrBottomShortcuts = true;
|
fInstalledNavigateToTopOrBottomShortcuts = true;
|
||||||
}
|
}
|
||||||
if (!Window()->HasShortcut(B_HOME, B_COMMAND_KEY | B_SHIFT_KEY)
|
if (!Window()->HasShortcut(B_HOME, B_COMMAND_KEY | B_SHIFT_KEY)
|
||||||
&& !Window()->HasShortcut(B_END, B_COMMAND_KEY | B_SHIFT_KEY)) {
|
&& !Window()->HasShortcut(B_END, B_COMMAND_KEY | B_SHIFT_KEY)) {
|
||||||
BMessage* message = new BMessage(NAVIGATE_TO_TOP);
|
message = new BMessage(kMsgNavigatePage);
|
||||||
message->AddInt32("modifiers", B_SHIFT_KEY);
|
message->AddInt32("key", B_HOME);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
Window()->AddShortcut(B_HOME, B_COMMAND_KEY | B_SHIFT_KEY,
|
Window()->AddShortcut(B_HOME, B_COMMAND_KEY | B_SHIFT_KEY,
|
||||||
message, this);
|
message, this);
|
||||||
message = new BMessage(NAVIGATE_TO_BOTTOM);
|
|
||||||
message->AddInt32("modifiers", B_SHIFT_KEY);
|
message = new BMessage(kMsgNavigatePage);
|
||||||
|
message->AddInt32("key", B_END);
|
||||||
|
message->AddInt32("modifiers", B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
Window()->AddShortcut(B_END, B_COMMAND_KEY | B_SHIFT_KEY,
|
Window()->AddShortcut(B_END, B_COMMAND_KEY | B_SHIFT_KEY,
|
||||||
message, this);
|
message, this);
|
||||||
|
|
||||||
fInstalledSelectToTopOrBottomShortcuts = true;
|
fInstalledSelectToTopOrBottomShortcuts = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4969,16 +5130,41 @@ BTextView::_Deactivate()
|
|||||||
_HideCaret();
|
_HideCaret();
|
||||||
|
|
||||||
if (Window() != NULL) {
|
if (Window() != NULL) {
|
||||||
if (fInstalledNavigateWordwiseShortcuts) {
|
if (fInstalledNavigateLinewiseShortcuts) {
|
||||||
Window()->RemoveShortcut(B_LEFT_ARROW, B_COMMAND_KEY);
|
Window()->RemoveShortcut(B_LEFT_ARROW, B_COMMAND_KEY);
|
||||||
Window()->RemoveShortcut(B_RIGHT_ARROW, B_COMMAND_KEY);
|
Window()->RemoveShortcut(B_RIGHT_ARROW, B_COMMAND_KEY);
|
||||||
|
fInstalledNavigateLinewiseShortcuts = false;
|
||||||
|
}
|
||||||
|
if (fInstalledSelectLinewiseShortcuts) {
|
||||||
|
Window()->RemoveShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
|
Window()->RemoveShortcut(B_RIGHT_ARROW,
|
||||||
|
B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
|
fInstalledSelectLinewiseShortcuts = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fInstalledNavigateWordwiseShortcuts) {
|
||||||
|
Window()->RemoveShortcut(B_LEFT_ARROW, B_OPTION_KEY);
|
||||||
|
Window()->RemoveShortcut(B_RIGHT_ARROW, B_OPTION_KEY);
|
||||||
fInstalledNavigateWordwiseShortcuts = false;
|
fInstalledNavigateWordwiseShortcuts = false;
|
||||||
}
|
}
|
||||||
if (fInstalledSelectWordwiseShortcuts) {
|
if (fInstalledSelectWordwiseShortcuts) {
|
||||||
Window()->RemoveShortcut(B_LEFT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY);
|
Window()->RemoveShortcut(B_LEFT_ARROW, B_OPTION_KEY | B_SHIFT_KEY);
|
||||||
Window()->RemoveShortcut(B_RIGHT_ARROW, B_COMMAND_KEY | B_SHIFT_KEY);
|
Window()->RemoveShortcut(B_RIGHT_ARROW, B_OPTION_KEY | B_SHIFT_KEY);
|
||||||
fInstalledSelectWordwiseShortcuts = false;
|
fInstalledSelectWordwiseShortcuts = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fInstalledNavigateDocwiseShortcuts) {
|
||||||
|
Window()->RemoveShortcut(B_UP_ARROW, B_COMMAND_KEY);
|
||||||
|
Window()->RemoveShortcut(B_DOWN_ARROW, B_COMMAND_KEY);
|
||||||
|
fInstalledNavigateDocwiseShortcuts = false;
|
||||||
|
}
|
||||||
|
if (fInstalledSelectDocwiseShortcuts) {
|
||||||
|
Window()->RemoveShortcut(B_UP_ARROW, B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
|
Window()->RemoveShortcut(B_DOWN_ARROW,
|
||||||
|
B_COMMAND_KEY | B_SHIFT_KEY);
|
||||||
|
fInstalledSelectDocwiseShortcuts = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (fInstalledNavigateToTopOrBottomShortcuts) {
|
if (fInstalledNavigateToTopOrBottomShortcuts) {
|
||||||
Window()->RemoveShortcut(B_HOME, B_COMMAND_KEY);
|
Window()->RemoveShortcut(B_HOME, B_COMMAND_KEY);
|
||||||
Window()->RemoveShortcut(B_END, B_COMMAND_KEY);
|
Window()->RemoveShortcut(B_END, B_COMMAND_KEY);
|
||||||
@@ -5033,8 +5219,7 @@ BTextView::_SetRunArray(int32 startOffset, int32 endOffset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns a value which tells if the given character is a separator
|
// Returns the character class of the character at the given offset.
|
||||||
// character or not.
|
|
||||||
// offset The offset where the wanted character can be found.
|
// offset The offset where the wanted character can be found.
|
||||||
// return A value which represents the character's classification.
|
// return A value which represents the character's classification.
|
||||||
uint32
|
uint32
|
||||||
@@ -5306,7 +5491,8 @@ BTextView::_HandleInputMethodChanged(BMessage* message)
|
|||||||
while ((*currPos & 0xC0) == 0x80)
|
while ((*currPos & 0xC0) == 0x80)
|
||||||
++currPos;
|
++currPos;
|
||||||
} else if ((*currPos & 0xC0) == 0x80) {
|
} else if ((*currPos & 0xC0) == 0x80) {
|
||||||
// illegal: character starts with utf-8 intermediate byte, skip it
|
// illegal: character starts with utf-8 intermediate byte,
|
||||||
|
// skip it
|
||||||
prevPos = ++currPos;
|
prevPos = ++currPos;
|
||||||
} else {
|
} else {
|
||||||
// single byte character/code, just feed that
|
// single byte character/code, just feed that
|
||||||
|
|||||||
Reference in New Issue
Block a user