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:
John Scipione
2014-01-30 19:48:31 -05:00
parent cc94643724
commit eb774c2948
2 changed files with 351 additions and 156 deletions
+11 -2
View File
@@ -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];
+271 -85
View File
@@ -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,9 +3285,13 @@ 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 {
if (commandKeyDown && !controlKeyDown && !optionKeyDown) {
_ScrollTo(0, 0);
fCaretOffset = 0;
} else {
float height; float height;
BPoint point = PointAt(fCaretOffset, &height); BPoint point = PointAt(fCaretOffset, &height);
// find the caret position on the previous // find the caret position on the previous
@@ -3284,8 +3304,9 @@ BTextView::_HandleArrowKey(uint32 arrowKey, bool commandKeyDown)
break; 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 {
if (commandKeyDown && !optionKeyDown && !controlKeyDown) {
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
fCaretOffset = fText->Length();
} else {
float height; float height;
BPoint point = PointAt(fCaretOffset, &height); BPoint point = PointAt(fCaretOffset, &height);
point.y += height; point.y += height;
fCaretOffset = OffsetAt(point); fCaretOffset = OffsetAt(point);
if (shiftDown && fCaretOffset != lastClickOffset) { }
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,9 +3430,10 @@ 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 {
if (commandKeyDown && !optionKeyDown && !controlKeyDown) {
_ScrollTo(0, 0); _ScrollTo(0, 0);
fCaretOffset = 0; fCaretOffset = 0;
} else { } else {
@@ -3408,7 +3442,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
fCaretOffset = line->offset; fCaretOffset = line->offset;
} }
if (!shiftDown) if (!shiftKeyDown)
selStart = selEnd = fCaretOffset; selStart = selEnd = fCaretOffset;
else if (fCaretOffset != lastClickOffset) { else if (fCaretOffset != lastClickOffset) {
if (fCaretOffset < fSelStart) { if (fCaretOffset < fSelStart) {
@@ -3423,7 +3457,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
selEnd = fCaretOffset; selEnd = fCaretOffset;
} }
} }
}
break; break;
case B_END: case B_END:
@@ -3431,9 +3465,10 @@ 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 {
if (commandKeyDown && !optionKeyDown && !controlKeyDown) {
_ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset); _ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset);
fCaretOffset = fText->Length(); fCaretOffset = fText->Length();
} else { } else {
@@ -3456,7 +3491,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
} }
} }
if (!shiftDown) if (!shiftKeyDown)
selStart = selEnd = fCaretOffset; selStart = selEnd = fCaretOffset;
else if (fCaretOffset != lastClickOffset) { else if (fCaretOffset != lastClickOffset) {
if (fCaretOffset > fSelEnd) { if (fCaretOffset > fSelEnd) {
@@ -3471,7 +3506,7 @@ BTextView::_HandlePageKey(uint32 pageKey, bool commandKeyDown)
selStart = fCaretOffset; 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