aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/String.hpp28
-rw-r--r--include/cru/common/StringUtil.hpp73
-rw-r--r--include/cru/platform/graphics/Factory.hpp2
-rw-r--r--include/cru/ui/controls/TextHostControlService.hpp38
-rw-r--r--src/common/String.cpp24
-rw-r--r--src/common/StringUtil.cpp87
-rw-r--r--src/ui/controls/TextHostControlService.cpp39
7 files changed, 194 insertions, 97 deletions
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp
index 544d24a4..0a8d88a0 100644
--- a/include/cru/common/String.hpp
+++ b/include/cru/common/String.hpp
@@ -174,8 +174,7 @@ class CRU_BASE_API String {
void AppendCodePoint(CodePoint code_point);
Utf16CodePointIterator CodePointIterator() const {
- return Utf16CodePointIterator(
- std::u16string_view(reinterpret_cast<char16_t*>(buffer_), size_));
+ return Utf16CodePointIterator(buffer_, size_);
}
Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const;
@@ -378,6 +377,31 @@ inline void String::append(StringView str) {
inline String String::From(StringView str) { return str.ToString(); }
inline String ToString(StringView value) { return value.ToString(); }
+
+inline CodePoint Utf16PreviousCodePoint(StringView str, Index current,
+ Index* previous_position) {
+ return Utf16PreviousCodePoint(str.data(), str.size(), current,
+ previous_position);
+}
+
+inline CodePoint Utf16NextCodePoint(StringView str, Index current,
+ Index* next_position) {
+ return Utf16NextCodePoint(str.data(), str.size(), current, next_position);
+}
+
+inline bool Utf16IsValidInsertPosition(StringView str, Index position) {
+ return Utf16IsValidInsertPosition(str.data(), str.size(), position);
+}
+
+inline Index Utf16PreviousWord(StringView str, Index position,
+ bool* is_space = nullptr) {
+ return Utf16PreviousWord(str.data(), str.size(), position, is_space);
+}
+
+inline Index Utf16NextWord(StringView str, Index position,
+ bool* is_space = nullptr) {
+ return Utf16NextWord(str.data(), str.size(), position, is_space);
+}
} // namespace cru
template <>
diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp
index cd2f4e16..a24cf924 100644
--- a/include/cru/common/StringUtil.hpp
+++ b/include/cru/common/StringUtil.hpp
@@ -22,20 +22,21 @@ inline bool IsUtf16SurrogatePairTrailing(char16_t c) {
return c >= 0xDC00 && c <= 0xDFFF;
}
-CodePoint CRU_BASE_API Utf8NextCodePoint(std::string_view str, Index current,
- Index* next_position);
+CodePoint CRU_BASE_API Utf8NextCodePoint(const char* ptr, Index size,
+ Index current, Index* next_position);
-CodePoint CRU_BASE_API Utf16NextCodePoint(std::u16string_view str,
+CodePoint CRU_BASE_API Utf16NextCodePoint(const char16_t* ptr, Index size,
Index current, Index* next_position);
-CodePoint CRU_BASE_API Utf16PreviousCodePoint(std::u16string_view str,
+CodePoint CRU_BASE_API Utf16PreviousCodePoint(const char16_t* ptr, Index size,
Index current,
Index* previous_position);
-template <typename StringType>
-using NextCodePointFunctionType = CodePoint (*)(StringType, Index, Index*);
+template <typename CharType>
+using NextCodePointFunctionType = CodePoint (*)(const CharType*, Index, Index,
+ Index*);
-template <typename StringType,
- NextCodePointFunctionType<StringType> NextCodePointFunction>
+template <typename CharType,
+ NextCodePointFunctionType<CharType> NextCodePointFunction>
class CodePointIterator {
public:
using difference_type = Index;
@@ -47,10 +48,10 @@ class CodePointIterator {
public:
struct past_end_tag_t {};
- explicit CodePointIterator(StringType string)
- : string_(std::move(string)), position_(0) {}
- explicit CodePointIterator(StringType string, past_end_tag_t)
- : string_(std::move(string)), position_(string_.size()) {}
+ explicit CodePointIterator(const CharType* ptr, Index size, Index current = 0)
+ : ptr_(ptr), size_(size), position_(0) {}
+ explicit CodePointIterator(const CharType* ptr, Index size, past_end_tag_t)
+ : ptr_(ptr), size_(size), position_(size) {}
CRU_DEFAULT_COPY(CodePointIterator)
CRU_DEFAULT_MOVE(CodePointIterator)
@@ -58,17 +59,16 @@ class CodePointIterator {
~CodePointIterator() = default;
public:
- StringType GetString() const { return string_; }
+ const CharType* GetPtr() const { return ptr_; }
+ Index GetSize() const { return size_; }
Index GetPosition() const { return position_; }
- bool IsPastEnd() const {
- return position_ == static_cast<Index>(string_.size());
- }
+ bool IsPastEnd() const { return position_ == static_cast<Index>(size_); }
public:
CodePointIterator begin() const { return *this; }
CodePointIterator end() const {
- return CodePointIterator{string_, past_end_tag_t{}};
+ return CodePointIterator{ptr_, size_, past_end_tag_t{}};
}
public:
@@ -96,7 +96,7 @@ class CodePointIterator {
}
CodePoint operator*() const {
- return NextCodePointFunction(string_, position_, &next_position_cache_);
+ return NextCodePointFunction(ptr_, size_, position_, &next_position_cache_);
}
private:
@@ -104,21 +104,20 @@ class CodePointIterator {
if (next_position_cache_ > position_) {
position_ = next_position_cache_;
} else {
- NextCodePointFunction(string_, position_, &position_);
+ NextCodePointFunction(ptr_, size_, position_, &position_);
}
}
private:
- StringType string_;
+ const CharType* ptr_;
+ Index size_;
Index position_;
mutable Index next_position_cache_ = 0;
};
-using Utf8CodePointIterator =
- CodePointIterator<std::string_view, &Utf8NextCodePoint>;
+using Utf8CodePointIterator = CodePointIterator<char, &Utf8NextCodePoint>;
-using Utf16CodePointIterator =
- CodePointIterator<std::u16string_view, &Utf16NextCodePoint>;
+using Utf16CodePointIterator = CodePointIterator<char16_t, &Utf16NextCodePoint>;
void CRU_BASE_API Utf8EncodeCodePointAppend(CodePoint code_point,
std::string& str);
@@ -198,30 +197,28 @@ bool Utf16EncodeCodePointAppendWithFunc(CodePoint code_point,
}
}
-std::string CRU_BASE_API ToUtf8(std::u16string_view s);
-std::u16string CRU_BASE_API ToUtf16(std::string_view s);
+std::string CRU_BASE_API ToUtf8(const char16_t* ptr, Index size);
+std::u16string CRU_BASE_API ToUtf16(const char* s, Index size);
// If given s is not a valid utf16 string, return value is UD.
-bool CRU_BASE_API Utf16IsValidInsertPosition(std::u16string_view s,
- gsl::index position);
+bool CRU_BASE_API Utf16IsValidInsertPosition(const char16_t* ptr, Index size,
+ Index position);
// Return position after the character making predicate returns true or 0 if no
// character doing so.
-gsl::index CRU_BASE_API
-Utf16BackwardUntil(std::u16string_view str, gsl::index position,
+Index CRU_BASE_API
+Utf16BackwardUntil(const char16_t* ptr, Index size, Index position,
const std::function<bool(CodePoint)>& predicate);
// Return position before the character making predicate returns true or
// str.size() if no character doing so.
-gsl::index CRU_BASE_API
-Utf16ForwardUntil(std::u16string_view str, gsl::index position,
+Index CRU_BASE_API
+Utf16ForwardUntil(const char16_t* ptr, Index size, Index position,
const std::function<bool(CodePoint)>& predicate);
-gsl::index CRU_BASE_API Utf16PreviousWord(std::u16string_view str,
- gsl::index position,
- bool* is_space = nullptr);
-gsl::index CRU_BASE_API Utf16NextWord(std::u16string_view str,
- gsl::index position,
- bool* is_space = nullptr);
+Index CRU_BASE_API Utf16PreviousWord(const char16_t* ptr, Index size,
+ Index position, bool* is_space = nullptr);
+Index CRU_BASE_API Utf16NextWord(const char16_t* ptr, Index size,
+ Index position, bool* is_space = nullptr);
char16_t CRU_BASE_API ToLower(char16_t c);
char16_t CRU_BASE_API ToUpper(char16_t c);
diff --git a/include/cru/platform/graphics/Factory.hpp b/include/cru/platform/graphics/Factory.hpp
index ad198929..b79e1c4f 100644
--- a/include/cru/platform/graphics/Factory.hpp
+++ b/include/cru/platform/graphics/Factory.hpp
@@ -7,7 +7,7 @@
#include "TextLayout.hpp"
namespace cru::platform::graphics {
-// Entry point of the graph module.
+// Entry point of the graphics module.
struct IGraphicsFactory : virtual IPlatformResource {
virtual std::unique_ptr<ISolidColorBrush> CreateSolidColorBrush() = 0;
diff --git a/include/cru/ui/controls/TextHostControlService.hpp b/include/cru/ui/controls/TextHostControlService.hpp
index b56374dc..adf72d69 100644
--- a/include/cru/ui/controls/TextHostControlService.hpp
+++ b/include/cru/ui/controls/TextHostControlService.hpp
@@ -23,6 +23,44 @@ struct ITextHostControl : virtual Interface {
virtual render::ScrollRenderObject* GetScrollRenderObject() = 0;
};
+class TextHostControlService;
+
+class TextControlMovePattern : public Object {
+ public:
+ static TextControlMovePattern kLeft;
+ static TextControlMovePattern kRight;
+ static TextControlMovePattern kUp;
+ static TextControlMovePattern kDown;
+ static TextControlMovePattern kHome;
+ static TextControlMovePattern kEnd;
+ static TextControlMovePattern kPageUp;
+ static TextControlMovePattern kPageDown;
+
+ using MoveFunction =
+ std::function<gsl::index(TextHostControlService* service, StringView text,
+ gsl::index current_position)>;
+
+ TextControlMovePattern(helper::ShortcutKeyBind key_bind,
+ MoveFunction move_function)
+ : key_bind_(key_bind), move_function_(move_function) {}
+
+ CRU_DELETE_COPY(TextControlMovePattern)
+ CRU_DELETE_MOVE(TextControlMovePattern)
+
+ ~TextControlMovePattern() override = default;
+
+ public:
+ helper::ShortcutKeyBind GetKeyBind() const { return key_bind_; }
+ gsl::index Move(TextHostControlService* service, StringView text,
+ gsl::index current_position) {
+ return move_function_(service, text, current_position);
+ }
+
+ private:
+ helper::ShortcutKeyBind key_bind_;
+ MoveFunction move_function_;
+};
+
class TextHostControlService : public Object {
CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService")
diff --git a/src/common/String.cpp b/src/common/String.cpp
index ba31e6f6..8b53b16b 100644
--- a/src/common/String.cpp
+++ b/src/common/String.cpp
@@ -10,16 +10,6 @@
#include <string_view>
namespace cru {
-String String::FromUtf8(const char* str) {
- return FromUtf16(cru::ToUtf16(std::string_view(str)));
-}
-
-String String::FromUtf8(const char* str, Index size) {
- return FromUtf16(cru::ToUtf16(std::string_view(str, size)));
-}
-
-char16_t String::kEmptyBuffer[1] = {0};
-
template <typename C>
Index GetStrSize(const C* str) {
Index i = 0;
@@ -29,6 +19,16 @@ Index GetStrSize(const C* str) {
return i;
}
+String String::FromUtf8(const char* str) {
+ return FromUtf16(cru::ToUtf16(str, GetStrSize(str)));
+}
+
+String String::FromUtf8(const char* str, Index size) {
+ return FromUtf16(cru::ToUtf16(str, size));
+}
+
+char16_t String::kEmptyBuffer[1] = {0};
+
String::String(const_pointer str) : String(str, GetStrSize(str)) {}
String::String(const_pointer str, Index size) {
@@ -211,9 +211,7 @@ String::iterator String::erase(const_iterator start, const_iterator end) {
return s;
}
-std::string String::ToUtf8() const {
- return cru::ToUtf8(std::u16string_view(data(), size()));
-}
+std::string String::ToUtf8() const { return cru::ToUtf8(buffer_, size_); }
void String::AppendCodePoint(CodePoint code_point) {
if (!Utf16EncodeCodePointAppendWithFunc(
diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp
index 7492bdfd..850524b5 100644
--- a/src/common/StringUtil.cpp
+++ b/src/common/StringUtil.cpp
@@ -6,29 +6,29 @@
namespace cru {
using details::ExtractBits;
-CodePoint Utf8NextCodePoint(std::string_view str, Index current,
+CodePoint Utf8NextCodePoint(const char* ptr, Index size, Index current,
Index* next_position) {
CodePoint result;
- if (current >= static_cast<Index>(str.length())) {
+ if (current >= size) {
result = k_invalid_code_point;
} else {
- const auto cu0 = static_cast<std::uint8_t>(str[current++]);
+ const auto cu0 = static_cast<std::uint8_t>(ptr[current++]);
- auto read_next_folowing_code = [&str, &current]() -> CodePoint {
- if (current == static_cast<Index>(str.length()))
+ auto read_next_folowing_code = [ptr, size, &current]() -> CodePoint {
+ if (current == size)
throw TextEncodeException(
u"Unexpected end when read continuing byte of multi-byte code "
"point.");
- const auto u = static_cast<std::uint8_t>(str[current]);
+ const auto u = static_cast<std::uint8_t>(ptr[current]);
if (!(u & (1u << 7)) || (u & (1u << 6))) {
throw TextEncodeException(
u"Unexpected bad-format (not 0b10xxxxxx) continuing byte of "
"multi-byte code point.");
}
- return ExtractBits<std::uint8_t, 6, CodePoint>(str[current++]);
+ return ExtractBits<std::uint8_t, 6, CodePoint>(ptr[current++]);
};
if ((1u << 7) & cu0) {
@@ -73,23 +73,23 @@ CodePoint Utf8NextCodePoint(std::string_view str, Index current,
return result;
}
-CodePoint Utf16NextCodePoint(std::u16string_view str, Index current,
+CodePoint Utf16NextCodePoint(const char16_t* ptr, Index size, Index current,
Index* next_position) {
CodePoint result;
- if (current >= static_cast<Index>(str.length())) {
+ if (current >= size) {
result = k_invalid_code_point;
} else {
- const auto cu0 = str[current++];
+ const auto cu0 = ptr[current++];
if (!IsUtf16SurrogatePairCodeUnit(cu0)) { // 1-length code point
result = static_cast<CodePoint>(cu0);
} else if (IsUtf16SurrogatePairLeading(cu0)) { // 2-length code point
- if (current >= static_cast<Index>(str.length())) {
+ if (current >= size) {
throw TextEncodeException(
u"Unexpected end when reading second code unit of surrogate pair.");
}
- const auto cu1 = str[current++];
+ const auto cu1 = ptr[current++];
if (!IsUtf16SurrogatePairTrailing(cu1)) {
throw TextEncodeException(
@@ -111,13 +111,13 @@ CodePoint Utf16NextCodePoint(std::u16string_view str, Index current,
return result;
}
-CodePoint Utf16PreviousCodePoint(std::u16string_view str, Index current,
+CodePoint Utf16PreviousCodePoint(const char16_t* ptr, Index size, Index current,
Index* previous_position) {
CodePoint result;
if (current <= 0) {
result = k_invalid_code_point;
} else {
- const auto cu0 = str[--current];
+ const auto cu0 = ptr[--current];
if (!IsUtf16SurrogatePairCodeUnit(cu0)) { // 1-length code point
result = static_cast<CodePoint>(cu0);
@@ -126,7 +126,7 @@ CodePoint Utf16PreviousCodePoint(std::u16string_view str, Index current,
throw TextEncodeException(
u"Unexpected end when reading first code unit of surrogate pair.");
}
- const auto cu1 = str[--current];
+ const auto cu1 = ptr[--current];
if (!IsUtf16SurrogatePairLeading(cu1)) {
throw TextEncodeException(
@@ -160,48 +160,49 @@ void Utf16EncodeCodePointAppend(CodePoint code_point, std::u16string& str) {
throw TextEncodeException(u"Code point out of range.");
}
-std::string ToUtf8(std::u16string_view s) {
+std::string ToUtf8(const char16_t* ptr, Index size) {
std::string result;
- for (CodePoint cp : Utf16CodePointIterator{s}) {
+ for (CodePoint cp : Utf16CodePointIterator(ptr, size)) {
Utf8EncodeCodePointAppend(cp, result);
}
return result;
}
-std::u16string ToUtf16(std::string_view s) {
+std::u16string ToUtf16(const char* ptr, Index size) {
std::u16string result;
- for (CodePoint cp : Utf8CodePointIterator{s}) {
+ for (CodePoint cp : Utf8CodePointIterator(ptr, size)) {
Utf16EncodeCodePointAppend(cp, result);
}
return result;
}
-bool Utf16IsValidInsertPosition(std::u16string_view s, gsl::index position) {
+bool Utf16IsValidInsertPosition(const char16_t* ptr, Index size,
+ Index position) {
if (position < 0) return false;
- if (position > static_cast<gsl::index>(s.size())) return false;
+ if (position > size) return false;
if (position == 0) return true;
- if (position == static_cast<gsl::index>(s.size())) return true;
- return !IsUtf16SurrogatePairTrailing(s[position]);
+ if (position == size) return true;
+ return !IsUtf16SurrogatePairTrailing(ptr[position]);
}
-gsl::index Utf16BackwardUntil(std::u16string_view str, gsl::index position,
- const std::function<bool(CodePoint)>& predicate) {
+Index Utf16BackwardUntil(const char16_t* ptr, Index size, 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);
+ Index p = position;
+ auto c = Utf16PreviousCodePoint(ptr, size, 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;
+Index Utf16ForwardUntil(const char16_t* ptr, Index size, Index position,
+ const std::function<bool(CodePoint)>& predicate) {
+ if (position >= size) return position;
while (true) {
- gsl::index p = position;
- auto c = Utf16NextCodePoint(str, p, &position);
+ Index p = position;
+ auto c = Utf16NextCodePoint(ptr, size, p, &position);
if (predicate(c)) return p;
if (c == k_invalid_code_point) return p;
}
@@ -210,31 +211,31 @@ gsl::index Utf16ForwardUntil(std::u16string_view str, gsl::index position,
inline bool IsSpace(CodePoint c) { return c == 0x20 || c == 0xA; }
-gsl::index Utf16PreviousWord(std::u16string_view str, gsl::index position,
- bool* is_space) {
+Index Utf16PreviousWord(const char16_t* ptr, Index size, Index position,
+ bool* is_space) {
if (position <= 0) return position;
- auto c = Utf16PreviousCodePoint(str, position, nullptr);
+ auto c = Utf16PreviousCodePoint(ptr, size, position, nullptr);
if (IsSpace(c)) { // TODO: Currently only test against 0x20(space).
if (is_space) *is_space = true;
- return Utf16BackwardUntil(str, position,
+ return Utf16BackwardUntil(ptr, size, position,
[](CodePoint c) { return !IsSpace(c); });
} else {
if (is_space) *is_space = false;
- return Utf16BackwardUntil(str, position, IsSpace);
+ return Utf16BackwardUntil(ptr, size, 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);
+Index Utf16NextWord(const char16_t* ptr, Index size, Index position,
+ bool* is_space) {
+ if (position >= size) return position;
+ auto c = Utf16NextCodePoint(ptr, size, position, nullptr);
if (IsSpace(c)) { // TODO: Currently only test against 0x20(space).
if (is_space) *is_space = true;
- return Utf16ForwardUntil(str, position,
+ return Utf16ForwardUntil(ptr, size, position,
[](CodePoint c) { return !IsSpace(c); });
} else {
if (is_space) *is_space = false;
- return Utf16ForwardUntil(str, position, IsSpace);
+ return Utf16ForwardUntil(ptr, size, position, IsSpace);
}
}
diff --git a/src/ui/controls/TextHostControlService.cpp b/src/ui/controls/TextHostControlService.cpp
index 2233d1e6..9f5098db 100644
--- a/src/ui/controls/TextHostControlService.cpp
+++ b/src/ui/controls/TextHostControlService.cpp
@@ -18,6 +18,45 @@
#include "cru/ui/render/TextRenderObject.hpp"
namespace cru::ui::controls {
+TextControlMovePattern TextControlMovePattern::kLeft(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::Left),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) {
+ Utf16PreviousCodePoint(text, current_position, &current_position);
+ return current_position;
+ });
+TextControlMovePattern TextControlMovePattern::kRight(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::Right),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) {
+ Utf16NextCodePoint(text, current_position, &current_position);
+ return current_position;
+ });
+TextControlMovePattern TextControlMovePattern::kUp(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::Up),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) { return current_position; });
+TextControlMovePattern TextControlMovePattern::kDown(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::Down),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) { return current_position; });
+TextControlMovePattern TextControlMovePattern::kHome(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::Home),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) { return current_position; });
+TextControlMovePattern TextControlMovePattern::kEnd(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::End),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) { return current_position; });
+TextControlMovePattern TextControlMovePattern::kPageUp(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::PageUp),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) { return current_position; });
+TextControlMovePattern TextControlMovePattern::kPageDown(
+ helper::ShortcutKeyBind(platform::gui::KeyCode::PageDown),
+ [](TextHostControlService* service, StringView text,
+ gsl::index current_position) { return current_position; });
+
TextHostControlService::TextHostControlService(gsl::not_null<Control*> control)
: control_(control),
text_host_control_(dynamic_cast<ITextHostControl*>(control.get())) {