aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/StringUtil.cpp55
-rw-r--r--src/ui/controls/TextHostControlService.cpp16
2 files changed, 71 insertions, 0 deletions
diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp
index 3c312d49..b13c0193 100644
--- a/src/common/StringUtil.cpp
+++ b/src/common/StringUtil.cpp
@@ -1,4 +1,5 @@
#include "cru/common/StringUtil.hpp"
+#include "cru/common/Base.hpp"
#include "gsl/gsl_util"
namespace cru {
@@ -229,4 +230,58 @@ bool Utf16IsValidInsertPosition(std::u16string_view s, gsl::index position) {
if (position == static_cast<gsl::index>(s.size())) return true;
return !IsUtf16SurrogatePairTrailing(s[position]);
}
+
+gsl::index Utf16BackwardUntil(std::u16string_view str, gsl::index position,
+ const std::function<bool(CodePoint)>& predicate) {
+ if (position <= 0) return position;
+ while (true) {
+ gsl::index p = position;
+ auto c = Utf16PreviousCodePoint(str, p, &position);
+ if (predicate(c)) return p;
+ if (c == k_invalid_code_point) return p;
+ }
+ UnreachableCode();
+}
+
+gsl::index Utf16ForwardUntil(std::u16string_view str, gsl::index position,
+ const std::function<bool(CodePoint)>& predicate) {
+ if (position >= static_cast<gsl::index>(str.size())) return position;
+ while (true) {
+ gsl::index p = position;
+ auto c = Utf16NextCodePoint(str, p, &position);
+ if (predicate(c)) return p;
+ if (c == k_invalid_code_point) return p;
+ }
+ UnreachableCode();
+}
+
+inline bool IsSpace(CodePoint c) { return c == 0x20; }
+
+gsl::index Utf16PreviousWord(std::u16string_view str, gsl::index position,
+ bool* is_space) {
+ if (position <= 0) return position;
+ auto c = Utf16PreviousCodePoint(str, position, nullptr);
+ if (IsSpace(c)) { // TODO: Currently only test against 0x20(space).
+ if (is_space) *is_space = true;
+ return Utf16BackwardUntil(str, position,
+ [](CodePoint c) { return !IsSpace(c); });
+ } else {
+ if (is_space) *is_space = false;
+ return Utf16BackwardUntil(str, position, IsSpace);
+ }
+}
+
+gsl::index Utf16NextWord(std::u16string_view str, gsl::index position,
+ bool* is_space) {
+ if (position >= static_cast<gsl::index>(str.size())) return position;
+ auto c = Utf16NextCodePoint(str, position, nullptr);
+ if (IsSpace(c)) { // TODO: Currently only test against 0x20(space).
+ if (is_space) *is_space = true;
+ return Utf16ForwardUntil(str, position,
+ [](CodePoint c) { return !IsSpace(c); });
+ } else {
+ if (is_space) *is_space = false;
+ return Utf16ForwardUntil(str, position, IsSpace);
+ }
+}
} // namespace cru
diff --git a/src/ui/controls/TextHostControlService.cpp b/src/ui/controls/TextHostControlService.cpp
index 91ec53ff..4bfd6715 100644
--- a/src/ui/controls/TextHostControlService.cpp
+++ b/src/ui/controls/TextHostControlService.cpp
@@ -419,6 +419,14 @@ void TextHostControlService::SetUpShortcuts() {
return true;
});
+ shortcut_hub_.RegisterShortcut(
+ u"CtrlLeft", {KeyCode::Left, KeyModifiers::ctrl}, [this] {
+ auto text = this->GetTextView();
+ auto caret = this->GetCaretPosition();
+ this->SetSelection(Utf16PreviousWord(text, caret));
+ return true;
+ });
+
shortcut_hub_.RegisterShortcut(u"Right", KeyCode::Right, [this] {
auto text = this->GetTextView();
const auto caret = this->GetCaretPosition();
@@ -438,5 +446,13 @@ void TextHostControlService::SetUpShortcuts() {
this->SetSelection(selection);
return true;
});
+
+ shortcut_hub_.RegisterShortcut(
+ u"CtrlRight", {KeyCode::Right, KeyModifiers::ctrl}, [this] {
+ auto text = this->GetTextView();
+ auto caret = this->GetCaretPosition();
+ this->SetSelection(Utf16NextWord(text, caret));
+ return true;
+ });
}
} // namespace cru::ui::controls