aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/input_method/main.cpp20
-rw-r--r--demos/main/main.cpp8
-rw-r--r--drafts/String.cpp (renamed from src/win/String.cpp)0
-rw-r--r--drafts/String.hpp (renamed from include/cru/win/String.hpp)0
-rw-r--r--include/cru/common/Base.hpp2
-rw-r--r--include/cru/common/Logger.hpp37
-rw-r--r--include/cru/common/PreConfig.hpp1
-rw-r--r--include/cru/common/StringUtil.hpp79
-rw-r--r--include/cru/platform/Check.hpp10
-rw-r--r--include/cru/platform/Resource.hpp2
-rw-r--r--include/cru/platform/graph/Factory.hpp4
-rw-r--r--include/cru/platform/graph/TextLayout.hpp6
-rw-r--r--include/cru/platform/native/InputMethod.hpp21
-rw-r--r--include/cru/ui/ClickDetector.hpp2
-rw-r--r--include/cru/ui/Control.hpp2
-rw-r--r--include/cru/ui/UiEvent.hpp6
-rw-r--r--include/cru/ui/UiHost.hpp2
-rw-r--r--include/cru/ui/Window.hpp4
-rw-r--r--include/cru/ui/controls/Button.hpp4
-rw-r--r--include/cru/ui/controls/Container.hpp4
-rw-r--r--include/cru/ui/controls/FlexLayout.hpp4
-rw-r--r--include/cru/ui/controls/StackLayout.hpp4
-rw-r--r--include/cru/ui/controls/TextBlock.hpp8
-rw-r--r--include/cru/ui/controls/TextBox.hpp4
-rw-r--r--include/cru/ui/render/BorderRenderObject.hpp2
-rw-r--r--include/cru/ui/render/FlexLayoutRenderObject.hpp2
-rw-r--r--include/cru/ui/render/LayoutHelper.hpp4
-rw-r--r--include/cru/ui/render/RenderObject.hpp2
-rw-r--r--include/cru/ui/render/StackLayoutRenderObject.hpp2
-rw-r--r--include/cru/ui/render/TextRenderObject.hpp6
-rw-r--r--include/cru/win/Exception.hpp9
-rw-r--r--include/cru/win/graph/direct/Factory.hpp4
-rw-r--r--include/cru/win/graph/direct/Font.hpp3
-rw-r--r--include/cru/win/graph/direct/Resource.hpp4
-rw-r--r--include/cru/win/graph/direct/TextLayout.hpp11
-rw-r--r--include/cru/win/native/Cursor.hpp2
-rw-r--r--include/cru/win/native/GodWindow.hpp2
-rw-r--r--include/cru/win/native/InputMethod.hpp10
-rw-r--r--include/cru/win/native/Resource.hpp4
-rw-r--r--include/cru/win/native/Window.hpp2
-rw-r--r--src/common/Logger.cpp34
-rw-r--r--src/common/StringUtil.cpp179
-rw-r--r--src/ui/ClickDetector.cpp14
-rw-r--r--src/ui/RoutedEventDispatch.hpp21
-rw-r--r--src/ui/UiHost.cpp17
-rw-r--r--src/ui/UiManager.cpp2
-rw-r--r--src/ui/Window.cpp2
-rw-r--r--src/ui/controls/TextBlock.cpp4
-rw-r--r--src/ui/controls/TextControlService.hpp15
-rw-r--r--src/ui/render/BorderRenderObject.cpp10
-rw-r--r--src/ui/render/FlexLayoutRenderObject.cpp8
-rw-r--r--src/ui/render/LayoutHelper.cpp4
-rw-r--r--src/ui/render/RenderObject.cpp8
-rw-r--r--src/ui/render/ScrollRenderObject.cpp1
-rw-r--r--src/ui/render/StackLayoutRenderObject.cpp8
-rw-r--r--src/ui/render/TextRenderObject.cpp10
-rw-r--r--src/win/CMakeLists.txt2
-rw-r--r--src/win/DebugLogger.hpp6
-rw-r--r--src/win/Exception.cpp12
-rw-r--r--src/win/graph/direct/Factory.cpp10
-rw-r--r--src/win/graph/direct/Font.cpp12
-rw-r--r--src/win/graph/direct/TextLayout.cpp51
-rw-r--r--src/win/native/Cursor.cpp2
-rw-r--r--src/win/native/GodWindow.cpp2
-rw-r--r--src/win/native/InputMethod.cpp72
-rw-r--r--src/win/native/Window.cpp23
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/common/CMakeLists.txt6
-rw-r--r--test/common/StringUtilTest.cpp53
-rw-r--r--test/win/CMakeLists.txt6
-rw-r--r--test/win/String.cpp53
71 files changed, 517 insertions, 435 deletions
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp
index b109f5e7..215eba16 100644
--- a/demos/input_method/main.cpp
+++ b/demos/input_method/main.cpp
@@ -31,19 +31,19 @@ int main() {
auto target_clause_brush = graph_factory->CreateSolidColorBrush();
target_clause_brush->SetColor(colors::blue);
- std::shared_ptr<IFont> font = graph_factory->CreateFont("等线", 30);
+ std::shared_ptr<IFont> font = graph_factory->CreateFont(u"等线", 30);
float window_width = 10000;
auto prompt_text_layout =
graph_factory->CreateTextLayout(font,
- "Alt+F1: Enable IME\n"
- "Alt+F2: Disable IME\n"
- "Alt+F3: Complete composition.\n"
- "Alt+F4: Cancel composition.");
+ u"Alt+F1: Enable IME\n"
+ u"Alt+F2: Disable IME\n"
+ u"Alt+F3: Complete composition.\n"
+ u"Alt+F4: Cancel composition.");
std::optional<CompositionText> optional_composition_text;
- std::string committed_text;
+ std::u16string committed_text;
window->ResizeEvent()->AddHandler(
[&prompt_text_layout, &window_width](const Size& size) {
@@ -60,9 +60,9 @@ int main() {
const auto anchor_y = prompt_text_layout->GetTextBounds().height;
auto text_layout = graph_factory->CreateTextLayout(
- font,
- committed_text +
- (optional_composition_text ? optional_composition_text->text : ""));
+ font, committed_text + (optional_composition_text
+ ? optional_composition_text->text
+ : u""));
text_layout->SetMaxWidth(window_width);
if (optional_composition_text) {
@@ -123,7 +123,7 @@ int main() {
});
input_method_context->TextEvent()->AddHandler(
- [window, &committed_text](const std::string_view& c) {
+ [window, &committed_text](const std::u16string_view& c) {
committed_text += c;
window->RequestRepaint();
});
diff --git a/demos/main/main.cpp b/demos/main/main.cpp
index 832ef75e..a0d4cd88 100644
--- a/demos/main/main.cpp
+++ b/demos/main/main.cpp
@@ -34,15 +34,15 @@ int main() {
const auto button = Button::Create();
const auto text_block1 = TextBlock::Create();
- text_block1->SetText("Hello World!");
+ text_block1->SetText(u"Hello World!");
button->SetChild(text_block1);
flex_layout->AddChild(button, 0);
const auto text_block2 = TextBlock::Create();
- text_block2->SetText("Hello World!");
+ text_block2->SetText(u"Hello World!");
const auto text_block3 = TextBlock::Create();
- text_block3->SetText("Overlapped text");
+ text_block3->SetText(u"Overlapped text");
const auto stack_layout = StackLayout::Create();
stack_layout->AddChild(text_block2, 0);
@@ -50,7 +50,7 @@ int main() {
flex_layout->AddChild(stack_layout, 1);
const auto text_block4 = TextBlock::Create();
- text_block4->SetText("Hello World!!!");
+ text_block4->SetText(u"Hello World!!!");
flex_layout->AddChild(text_block4, 2);
window->GetUiHost()->GetNativeWindowResolver()->Resolve()->SetVisible(true);
diff --git a/src/win/String.cpp b/drafts/String.cpp
index eb585523..eb585523 100644
--- a/src/win/String.cpp
+++ b/drafts/String.cpp
diff --git a/include/cru/win/String.hpp b/drafts/String.hpp
index ac07f57b..ac07f57b 100644
--- a/include/cru/win/String.hpp
+++ b/drafts/String.hpp
diff --git a/include/cru/common/Base.hpp b/include/cru/common/Base.hpp
index 409c2b0e..93d6f9a6 100644
--- a/include/cru/common/Base.hpp
+++ b/include/cru/common/Base.hpp
@@ -47,5 +47,5 @@ using Index = gsl::index;
#define CRU_DEFINE_CLASS_LOG_TAG(tag) \
private: \
- constexpr static std::string_view log_tag = tag;
+ constexpr static std::u16string_view log_tag = tag;
} // namespace cru
diff --git a/include/cru/common/Logger.hpp b/include/cru/common/Logger.hpp
index f76e4626..f83ba8dc 100644
--- a/include/cru/common/Logger.hpp
+++ b/include/cru/common/Logger.hpp
@@ -15,30 +15,7 @@ enum class LogLevel { Debug, Info, Warn, Error };
struct ILogSource : virtual Interface {
// Write the string s. LogLevel is just a helper. It has no effect on the
// content to write.
- virtual void Write(LogLevel level, std::string_view s) = 0;
-};
-
-class StdioLogSource : public virtual ILogSource {
- public:
- StdioLogSource() = default;
-
- CRU_DELETE_COPY(StdioLogSource)
- CRU_DELETE_MOVE(StdioLogSource)
-
- ~StdioLogSource() override = default;
-
- void Write(LogLevel level, std::string_view s) override {
- // TODO: Emmm... Since it is buggy to use narrow char in UTF-8 on Windows. I
- // think this implementation might be broken. (However, I didn't test it.)
- // Maybe, I should detect Windows and use wide char (And I didn't test this
- // either) or other more complicated implementation. Currently, I settled
- // with this.
- if (level == LogLevel::Error) {
- std::cerr << s;
- } else {
- std::cout << s;
- }
- }
+ virtual void Write(LogLevel level, const std::u16string& s) = 0;
};
class Logger : public Object {
@@ -58,8 +35,8 @@ class Logger : public Object {
void RemoveSource(ILogSource* source);
public:
- void Log(LogLevel level, std::string_view s);
- void Log(LogLevel level, std::string_view tag, std::string_view s);
+ void Log(LogLevel level, std::u16string_view s);
+ void Log(LogLevel level, std::u16string_view tag, std::u16string_view s);
public:
std::list<std::unique_ptr<ILogSource>> sources_;
@@ -92,7 +69,7 @@ void Error(TArgs&&... args) {
}
template <typename... TArgs>
-void TagDebug([[maybe_unused]] std::string_view tag,
+void TagDebug([[maybe_unused]] std::u16string_view tag,
[[maybe_unused]] TArgs&&... args) {
#ifdef CRU_DEBUG
Logger::GetInstance()->Log(LogLevel::Debug, tag,
@@ -101,19 +78,19 @@ void TagDebug([[maybe_unused]] std::string_view tag,
}
template <typename... TArgs>
-void TagInfo(std::string_view tag, TArgs&&... args) {
+void TagInfo(std::u16string_view tag, TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Info, tag,
fmt::format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
-void TagWarn(std::string_view tag, TArgs&&... args) {
+void TagWarn(std::u16string_view tag, TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Warn, tag,
fmt::format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
-void TagError(std::string_view tag, TArgs&&... args) {
+void TagError(std::u16string_view tag, TArgs&&... args) {
Logger::GetInstance()->Log(LogLevel::Error, tag,
fmt::format(std::forward<TArgs>(args)...));
}
diff --git a/include/cru/common/PreConfig.hpp b/include/cru/common/PreConfig.hpp
index 4bccef1d..802f17f8 100644
--- a/include/cru/common/PreConfig.hpp
+++ b/include/cru/common/PreConfig.hpp
@@ -6,3 +6,4 @@
#endif
#define _CRT_SECURE_NO_WARNINGS
+#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp
index a44ae6b4..714f1d49 100644
--- a/include/cru/common/StringUtil.hpp
+++ b/include/cru/common/StringUtil.hpp
@@ -3,37 +3,90 @@
namespace cru {
using CodePoint = std::int32_t;
-constexpr CodePoint k_code_point_end = -1;
+constexpr CodePoint k_invalid_code_point = -1;
class TextEncodeException : public std::runtime_error {
public:
using runtime_error::runtime_error;
};
-class Utf8Iterator : public Object {
+inline bool IsSurrogatePair(char16_t c) { return c >= 0xD800 && c <= 0xDFFF; }
+
+inline bool IsSurrogatePairLeading(char16_t c) {
+ return c >= 0xD800 && c <= 0xDBFF;
+}
+
+inline bool IsSurrogatePairTrailing(char16_t c) {
+ return c >= 0xDC00 && c <= 0xDFFF;
+}
+
+class Utf16Iterator : public Object {
public:
- explicit Utf8Iterator(const std::string_view& string) : string_(string) {}
- Utf8Iterator(const std::string_view& string, Index position)
- : string_(string), position_(position) {}
+ explicit Utf16Iterator(std::u16string_view string)
+ : string_(std::move(string)) {}
+ Utf16Iterator(std::u16string_view string, Index position)
+ : string_(std::move(string)), position_(position) {}
- CRU_DEFAULT_COPY(Utf8Iterator)
- CRU_DEFAULT_MOVE(Utf8Iterator)
+ CRU_DEFAULT_COPY(Utf16Iterator)
+ CRU_DEFAULT_MOVE(Utf16Iterator)
- ~Utf8Iterator() = default;
+ ~Utf16Iterator() = default;
public:
- void SetToHead() { position_ = 0; }
+ void SetPositionToHead() { position_ = 0; }
void SetPosition(Index position) { position_ = position; }
- // Advance current position and get next code point. Return k_code_point_end
- // if there is no next code unit(point). Throw TextEncodeException if decoding
- // fails.
+ // Backward current position and get previous code point. Return
+ // k_invalid_code_point if reach head. Throw TextEncodeException if encounter
+ // encoding problem.
+ CodePoint Previous();
+
+ // Advance current position and get next code point. Return
+ // k_invalid_code_point if reach tail. Throw TextEncodeException if encounter
+ // encoding problem.
CodePoint Next();
Index CurrentPosition() const { return this->position_; }
private:
- std::string_view string_;
+ std::u16string_view string_;
Index position_ = 0;
};
+
+Index PreviousIndex(std::u16string_view string, Index current);
+Index NextIndex(std::u16string_view string, Index current);
+
+std::string ToUtf8(const std::u16string& s);
+inline std::string ToUtf8(std::u16string_view s) {
+ return ToUtf8(std::u16string{s});
+}
+
+// class Utf8Iterator : public Object {
+// public:
+// explicit Utf8Iterator(const std::string_view& string) : string_(string) {}
+// Utf8Iterator(const std::string_view& string, Index position)
+// : string_(string), position_(position) {}
+
+// CRU_DEFAULT_COPY(Utf8Iterator)
+// CRU_DEFAULT_MOVE(Utf8Iterator)
+
+// ~Utf8Iterator() = default;
+
+// public:
+// void SetToHead() { position_ = 0; }
+// void SetPosition(Index position) { position_ = position; }
+
+// // Advance current position and get next code point. Return
+// k_invalid_code_point
+// // if there is no next code unit(point). Throw TextEncodeException if
+// decoding
+// // fails.
+// CodePoint Next();
+
+// Index CurrentPosition() const { return this->position_; }
+
+// private:
+// std::string_view string_;
+// Index position_ = 0;
+// };
} // namespace cru
diff --git a/include/cru/platform/Check.hpp b/include/cru/platform/Check.hpp
index f4bbcfe8..d3180582 100644
--- a/include/cru/platform/Check.hpp
+++ b/include/cru/platform/Check.hpp
@@ -2,6 +2,8 @@
#include "Exception.hpp"
#include "Resource.hpp"
+#include "cru/common/StringUtil.hpp"
+
#include <fmt/format.h>
#include <memory>
#include <type_traits>
@@ -9,14 +11,14 @@
namespace cru::platform {
template <typename TTarget>
TTarget* CheckPlatform(INativeResource* resource,
- const std::string_view& target_platform) {
+ const std::u16string_view& target_platform) {
Expects(resource);
const auto result = dynamic_cast<TTarget*>(resource);
if (result == nullptr) {
throw UnsupportPlatformException(fmt::format(
"Try to convert resource to target platform failed. Platform id of "
"resource to convert: {} . Target platform id: {} .",
- resource->GetPlatformId(), target_platform));
+ ToUtf8(resource->GetPlatformId()), ToUtf8(target_platform)));
}
return result;
}
@@ -24,7 +26,7 @@ TTarget* CheckPlatform(INativeResource* resource,
template <typename TTarget, typename TSource>
std::shared_ptr<TTarget> CheckPlatform(
const std::shared_ptr<TSource>& resource,
- const std::string_view& target_platform) {
+ const std::u16string_view& target_platform) {
static_assert(std::is_base_of_v<INativeResource, TSource>,
"TSource must be a subclass of INativeResource.");
Expects(resource);
@@ -33,7 +35,7 @@ std::shared_ptr<TTarget> CheckPlatform(
throw UnsupportPlatformException(fmt::format(
"Try to convert resource to target platform failed. Platform id of "
"resource to convert: {} . Target platform id: {} .",
- resource->GetPlatformId(), target_platform));
+ ToUtf8(resource->GetPlatformId()), ToUtf8(target_platform)));
}
return result;
}
diff --git a/include/cru/platform/Resource.hpp b/include/cru/platform/Resource.hpp
index 72cfaf52..7a85d9c1 100644
--- a/include/cru/platform/Resource.hpp
+++ b/include/cru/platform/Resource.hpp
@@ -5,6 +5,6 @@
namespace cru::platform {
struct INativeResource : virtual Interface {
- virtual std::string_view GetPlatformId() const = 0;
+ virtual std::u16string_view GetPlatformId() const = 0;
};
} // namespace cru::platform
diff --git a/include/cru/platform/graph/Factory.hpp b/include/cru/platform/graph/Factory.hpp
index 0a425d15..b4e68f12 100644
--- a/include/cru/platform/graph/Factory.hpp
+++ b/include/cru/platform/graph/Factory.hpp
@@ -16,10 +16,10 @@ struct IGraphFactory : virtual INativeResource {
virtual std::unique_ptr<IGeometryBuilder> CreateGeometryBuilder() = 0;
- virtual std::unique_ptr<IFont> CreateFont(const std::string_view& font_family,
+ virtual std::unique_ptr<IFont> CreateFont(std::u16string font_family,
float font_size) = 0;
virtual std::unique_ptr<ITextLayout> CreateTextLayout(
- std::shared_ptr<IFont> font, std::string text) = 0;
+ std::shared_ptr<IFont> font, std::u16string text) = 0;
};
} // namespace cru::platform::graph
diff --git a/include/cru/platform/graph/TextLayout.hpp b/include/cru/platform/graph/TextLayout.hpp
index 4086ac56..7dd20987 100644
--- a/include/cru/platform/graph/TextLayout.hpp
+++ b/include/cru/platform/graph/TextLayout.hpp
@@ -6,8 +6,8 @@
namespace cru::platform::graph {
struct ITextLayout : virtual IGraphResource {
- virtual std::string GetText() = 0;
- virtual void SetText(std::string new_text) = 0;
+ virtual std::u16string GetText() = 0;
+ virtual void SetText(std::u16string new_text) = 0;
virtual std::shared_ptr<IFont> GetFont() = 0;
virtual void SetFont(std::shared_ptr<IFont> font) = 0;
@@ -17,7 +17,7 @@ struct ITextLayout : virtual IGraphResource {
virtual Rect GetTextBounds() = 0;
virtual std::vector<Rect> TextRangeRect(const TextRange& text_range) = 0;
- virtual Point TextSinglePoint(gsl::index position, bool trailing) = 0;
+ virtual Point TextSinglePoint(Index position, bool trailing) = 0;
virtual TextHitTestResult HitTest(const Point& point) = 0;
};
} // namespace cru::platform::graph
diff --git a/include/cru/platform/native/InputMethod.hpp b/include/cru/platform/native/InputMethod.hpp
index 1ede15b2..1c5b287e 100644
--- a/include/cru/platform/native/InputMethod.hpp
+++ b/include/cru/platform/native/InputMethod.hpp
@@ -18,28 +18,11 @@ struct CompositionClause {
using CompositionClauses = std::vector<CompositionClause>;
struct CompositionText {
- std::string text;
+ std::u16string text;
CompositionClauses clauses;
TextRange selection;
};
-inline std::ostream& operator<<(std::ostream& stream,
- const CompositionText& composition_text) {
- stream << "text: " << composition_text.text << "\n"
- << "clauses:\n";
- for (int i = 0; i < static_cast<int>(composition_text.clauses.size()); i++) {
- const auto& clause = composition_text.clauses[i];
- stream << "\t" << i << ". start:" << clause.start << " end:" << clause.end;
- if (clause.target) {
- stream << " target";
- }
- stream << "\n";
- }
- stream << "selection: position:" << composition_text.selection.position
- << " count:" << composition_text.selection.count;
- return stream;
-}
-
struct IInputMethodContext : virtual INativeResource {
// Return true if you should draw composition text manually. Return false if
// system will take care of that for you.
@@ -67,7 +50,7 @@ struct IInputMethodContext : virtual INativeResource {
// Triggered every time composition text changes.
virtual IEvent<std::nullptr_t>* CompositionEvent() = 0;
- virtual IEvent<std::string_view>* TextEvent() = 0;
+ virtual IEvent<std::u16string_view>* TextEvent() = 0;
};
struct IInputMethodManager : virtual INativeResource {
diff --git a/include/cru/ui/ClickDetector.hpp b/include/cru/ui/ClickDetector.hpp
index 3977fb8e..4ffe5d05 100644
--- a/include/cru/ui/ClickDetector.hpp
+++ b/include/cru/ui/ClickDetector.hpp
@@ -36,7 +36,7 @@ enum class ClickState {
};
class ClickDetector : public Object {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::ClickDetector")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::ClickDetector")
public:
explicit ClickDetector(Control* control);
diff --git a/include/cru/ui/Control.hpp b/include/cru/ui/Control.hpp
index 347163be..bd86bc2f 100644
--- a/include/cru/ui/Control.hpp
+++ b/include/cru/ui/Control.hpp
@@ -22,7 +22,7 @@ class Control : public Object {
~Control() override = default;
public:
- virtual std::string_view GetControlType() const = 0;
+ virtual std::u16string_view GetControlType() const = 0;
//*************** region: tree ***************
public:
diff --git a/include/cru/ui/UiEvent.hpp b/include/cru/ui/UiEvent.hpp
index 39f26aee..5adace8a 100644
--- a/include/cru/ui/UiEvent.hpp
+++ b/include/cru/ui/UiEvent.hpp
@@ -212,7 +212,7 @@ class KeyEventArgs : public UiEventArgs {
class CharEventArgs : public UiEventArgs {
public:
- CharEventArgs(Object* sender, Object* original_sender, std::string c)
+ CharEventArgs(Object* sender, Object* original_sender, std::u16string c)
: UiEventArgs(sender, original_sender), c_(std::move(c)) {}
CharEventArgs(const CharEventArgs& other) = default;
CharEventArgs(CharEventArgs&& other) = default;
@@ -220,9 +220,9 @@ class CharEventArgs : public UiEventArgs {
CharEventArgs& operator=(CharEventArgs&& other) = default;
~CharEventArgs() override = default;
- std::string GetChar() const { return c_; }
+ std::u16string GetChar() const { return c_; }
private:
- std::string c_;
+ std::u16string c_;
};
} // namespace cru::ui::event
diff --git a/include/cru/ui/UiHost.hpp b/include/cru/ui/UiHost.hpp
index 1a5c6302..b1658ef6 100644
--- a/include/cru/ui/UiHost.hpp
+++ b/include/cru/ui/UiHost.hpp
@@ -32,7 +32,7 @@ struct AfterLayoutEventArgs {};
// 4. Delete Window when deleting_ is false and IsRetainAfterDestroy is false in
// OnNativeDestroy.
class UiHost : public Object, public SelfResolvable<UiHost> {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::UiHost")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::UiHost")
public:
// This will create root window render object and attach it to window.
diff --git a/include/cru/ui/Window.hpp b/include/cru/ui/Window.hpp
index eb2ecfbb..450ea97b 100644
--- a/include/cru/ui/Window.hpp
+++ b/include/cru/ui/Window.hpp
@@ -6,7 +6,7 @@ class Window final : public ContentControl {
friend UiHost;
public:
- static constexpr std::string_view control_type = "Window";
+ static constexpr std::u16string_view control_type = u"Window";
public:
static Window* CreateOverlapped();
@@ -24,7 +24,7 @@ class Window final : public ContentControl {
~Window() override;
public:
- std::string_view GetControlType() const final;
+ std::u16string_view GetControlType() const final;
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/Button.hpp b/include/cru/ui/controls/Button.hpp
index 8a11409c..a4f727d6 100644
--- a/include/cru/ui/controls/Button.hpp
+++ b/include/cru/ui/controls/Button.hpp
@@ -7,7 +7,7 @@
namespace cru::ui::controls {
class Button : public ContentControl {
public:
- static constexpr std::string_view control_type = "Button";
+ static constexpr std::u16string_view control_type = u"Button";
static Button* Create() { return new Button(); }
@@ -21,7 +21,7 @@ class Button : public ContentControl {
Button& operator=(Button&& other) = delete;
~Button() override;
- std::string_view GetControlType() const final { return control_type; }
+ std::u16string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/Container.hpp b/include/cru/ui/controls/Container.hpp
index e3d78365..304d402c 100644
--- a/include/cru/ui/controls/Container.hpp
+++ b/include/cru/ui/controls/Container.hpp
@@ -3,7 +3,7 @@
namespace cru::ui::controls {
class Container : public ContentControl {
- static constexpr std::string_view control_type = "Container";
+ static constexpr std::u16string_view control_type = u"Container";
protected:
Container();
@@ -15,7 +15,7 @@ class Container : public ContentControl {
~Container() override;
public:
- std::string_view GetControlType() const final { return control_type; }
+ std::u16string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/FlexLayout.hpp b/include/cru/ui/controls/FlexLayout.hpp
index 3d6087c2..87162569 100644
--- a/include/cru/ui/controls/FlexLayout.hpp
+++ b/include/cru/ui/controls/FlexLayout.hpp
@@ -4,7 +4,7 @@
namespace cru::ui::controls {
class FlexLayout : public LayoutControl {
public:
- static constexpr std::string_view control_type = "FlexLayout";
+ static constexpr std::u16string_view control_type = u"FlexLayout";
static FlexLayout* Create() { return new FlexLayout(); }
@@ -18,7 +18,7 @@ class FlexLayout : public LayoutControl {
FlexLayout& operator=(FlexLayout&& other) = delete;
~FlexLayout() override;
- std::string_view GetControlType() const final { return control_type; }
+ std::u16string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/StackLayout.hpp b/include/cru/ui/controls/StackLayout.hpp
index d5998cc4..c0b95044 100644
--- a/include/cru/ui/controls/StackLayout.hpp
+++ b/include/cru/ui/controls/StackLayout.hpp
@@ -4,7 +4,7 @@
namespace cru::ui::controls {
class StackLayout : public LayoutControl {
public:
- static constexpr std::string_view control_type = "StackLayout";
+ static constexpr std::u16string_view control_type = u"StackLayout";
static StackLayout* Create() { return new StackLayout(); }
@@ -17,7 +17,7 @@ class StackLayout : public LayoutControl {
~StackLayout() override;
- std::string_view GetControlType() const final { return control_type; }
+ std::u16string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/controls/TextBlock.hpp b/include/cru/ui/controls/TextBlock.hpp
index 1b1b4a5c..8a9a3bff 100644
--- a/include/cru/ui/controls/TextBlock.hpp
+++ b/include/cru/ui/controls/TextBlock.hpp
@@ -7,7 +7,7 @@ class TextControlService;
class TextBlock : public NoChildControl {
public:
- static constexpr std::string_view control_type = "TextBlock";
+ static constexpr std::u16string_view control_type = u"TextBlock";
static TextBlock* Create() { return new TextBlock(); }
@@ -21,12 +21,12 @@ class TextBlock : public NoChildControl {
TextBlock& operator=(TextBlock&& other) = delete;
~TextBlock() override;
- std::string_view GetControlType() const final { return control_type; }
+ std::u16string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
- std::string GetText() const;
- void SetText(std::string text);
+ std::u16string GetText() const;
+ void SetText(std::u16string text);
gsl::not_null<render::TextRenderObject*> GetTextRenderObject();
render::ScrollRenderObject* GetScrollRenderObject() { return nullptr; }
diff --git a/include/cru/ui/controls/TextBox.hpp b/include/cru/ui/controls/TextBox.hpp
index 3d4de7c0..5976f6da 100644
--- a/include/cru/ui/controls/TextBox.hpp
+++ b/include/cru/ui/controls/TextBox.hpp
@@ -10,7 +10,7 @@ class TextControlService;
class TextBox : public NoChildControl {
public:
- static constexpr std::string_view control_type = "TextBox";
+ static constexpr std::u16string_view control_type = u"TextBox";
static TextBox* Create() { return new TextBox(); }
@@ -23,7 +23,7 @@ class TextBox : public NoChildControl {
~TextBox() override;
- std::string_view GetControlType() const final { return control_type; }
+ std::u16string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
diff --git a/include/cru/ui/render/BorderRenderObject.hpp b/include/cru/ui/render/BorderRenderObject.hpp
index 94e888d4..587f051a 100644
--- a/include/cru/ui/render/BorderRenderObject.hpp
+++ b/include/cru/ui/render/BorderRenderObject.hpp
@@ -3,7 +3,7 @@
namespace cru::ui::render {
class BorderRenderObject : public RenderObject {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::render::BorderRenderObject")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::BorderRenderObject")
public:
BorderRenderObject();
diff --git a/include/cru/ui/render/FlexLayoutRenderObject.hpp b/include/cru/ui/render/FlexLayoutRenderObject.hpp
index 87a41c7e..ee29d1e4 100644
--- a/include/cru/ui/render/FlexLayoutRenderObject.hpp
+++ b/include/cru/ui/render/FlexLayoutRenderObject.hpp
@@ -74,7 +74,7 @@ namespace cru::ui::render {
// and just fill the rest space with blank.
//
class FlexLayoutRenderObject : public LayoutRenderObject<FlexChildLayoutData> {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::render::FlexLayoutRenderObject")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::FlexLayoutRenderObject")
public:
FlexLayoutRenderObject() = default;
diff --git a/include/cru/ui/render/LayoutHelper.hpp b/include/cru/ui/render/LayoutHelper.hpp
index 3469ccf0..518dc5a3 100644
--- a/include/cru/ui/render/LayoutHelper.hpp
+++ b/include/cru/ui/render/LayoutHelper.hpp
@@ -9,6 +9,6 @@ float CalculateAnchorByAlignment(Alignment alignment, float start_point,
MeasureLength StackLayoutCalculateChildMaxLength(
MeasureLength parent_preferred_size, MeasureLength parent_max_size,
- MeasureLength child_min_size, std::string_view log_tag,
- std::string_view exceeds_message);
+ MeasureLength child_min_size, std::u16string_view log_tag,
+ std::u16string_view exceeds_message);
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp
index 2e784afc..f820f029 100644
--- a/include/cru/ui/render/RenderObject.hpp
+++ b/include/cru/ui/render/RenderObject.hpp
@@ -37,7 +37,7 @@ namespace cru::ui::render {
class RenderObject : public Object {
friend WindowRenderObject;
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::render::RenderObject")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::RenderObject")
protected:
enum class ChildMode {
diff --git a/include/cru/ui/render/StackLayoutRenderObject.hpp b/include/cru/ui/render/StackLayoutRenderObject.hpp
index 534d7f22..303241c5 100644
--- a/include/cru/ui/render/StackLayoutRenderObject.hpp
+++ b/include/cru/ui/render/StackLayoutRenderObject.hpp
@@ -23,7 +23,7 @@ namespace cru::ui::render {
// to min size.
class StackLayoutRenderObject
: public LayoutRenderObject<StackChildLayoutData> {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::render:StackLayoutRenderObject")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render:StackLayoutRenderObject")
public:
StackLayoutRenderObject() = default;
diff --git a/include/cru/ui/render/TextRenderObject.hpp b/include/cru/ui/render/TextRenderObject.hpp
index 77a92b4f..32d96797 100644
--- a/include/cru/ui/render/TextRenderObject.hpp
+++ b/include/cru/ui/render/TextRenderObject.hpp
@@ -18,7 +18,7 @@ namespace cru::ui::render {
// If the result layout box is bigger than actual text box, then text is center
// aligned.
class TextRenderObject : public RenderObject {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::render::TextRenderObject")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::TextRenderObject")
public:
constexpr static float default_caret_width = 2;
@@ -34,8 +34,8 @@ class TextRenderObject : public RenderObject {
TextRenderObject& operator=(TextRenderObject&& other) = delete;
~TextRenderObject() override;
- std::string GetText() const;
- void SetText(std::string new_text);
+ std::u16string GetText() const;
+ void SetText(std::u16string new_text);
std::shared_ptr<platform::graph::IBrush> GetBrush() const { return brush_; }
void SetBrush(std::shared_ptr<platform::graph::IBrush> new_brush);
diff --git a/include/cru/win/Exception.hpp b/include/cru/win/Exception.hpp
index 234aea69..3a95aa5d 100644
--- a/include/cru/win/Exception.hpp
+++ b/include/cru/win/Exception.hpp
@@ -10,7 +10,7 @@ namespace cru::platform::win {
class HResultError : public platform::PlatformException {
public:
explicit HResultError(HRESULT h_result);
- explicit HResultError(HRESULT h_result, const std::string_view& message);
+ explicit HResultError(HRESULT h_result, std::string_view message);
CRU_DEFAULT_COPY(HResultError)
CRU_DEFAULT_MOVE(HResultError)
@@ -27,8 +27,7 @@ inline void ThrowIfFailed(const HRESULT h_result) {
if (FAILED(h_result)) throw HResultError(h_result);
}
-inline void ThrowIfFailed(const HRESULT h_result,
- const std::string_view& message) {
+inline void ThrowIfFailed(const HRESULT h_result, std::string_view message) {
if (FAILED(h_result)) throw HResultError(h_result, message);
}
@@ -36,8 +35,8 @@ class Win32Error : public platform::PlatformException {
public:
// ::GetLastError is automatically called to get the error code.
// The same as Win32Error(::GetLastError(), message)
- explicit Win32Error(const std::string_view& message);
- Win32Error(DWORD error_code, const std::string_view& message);
+ explicit Win32Error(std::string_view message);
+ Win32Error(DWORD error_code, std::string_view message);
CRU_DEFAULT_COPY(Win32Error)
CRU_DEFAULT_MOVE(Win32Error)
diff --git a/include/cru/win/graph/direct/Factory.hpp b/include/cru/win/graph/direct/Factory.hpp
index 763d4b2b..e70454f5 100644
--- a/include/cru/win/graph/direct/Factory.hpp
+++ b/include/cru/win/graph/direct/Factory.hpp
@@ -38,11 +38,11 @@ class DirectGraphFactory : public DirectResource, public virtual IGraphFactory {
std::unique_ptr<IGeometryBuilder> CreateGeometryBuilder() override;
- std::unique_ptr<IFont> CreateFont(const std::string_view& font_family,
+ std::unique_ptr<IFont> CreateFont(std::u16string font_family,
float font_size) override;
std::unique_ptr<ITextLayout> CreateTextLayout(std::shared_ptr<IFont> font,
- std::string text) override;
+ std::u16string text) override;
private:
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
diff --git a/include/cru/win/graph/direct/Font.hpp b/include/cru/win/graph/direct/Font.hpp
index ecf9fd81..2195f3e4 100644
--- a/include/cru/win/graph/direct/Font.hpp
+++ b/include/cru/win/graph/direct/Font.hpp
@@ -11,7 +11,7 @@ class DWriteFont : public DirectGraphResource,
public virtual IFont,
public virtual IComResource<IDWriteTextFormat> {
public:
- DWriteFont(DirectGraphFactory* factory, const std::string_view& font_family,
+ DWriteFont(DirectGraphFactory* factory, std::u16string font_family,
float font_size);
CRU_DELETE_COPY(DWriteFont)
@@ -27,6 +27,7 @@ class DWriteFont : public DirectGraphResource,
float GetFontSize() override;
private:
+ std::u16string font_family_;
Microsoft::WRL::ComPtr<IDWriteTextFormat> text_format_;
};
} // namespace cru::platform::graph::win::direct
diff --git a/include/cru/win/graph/direct/Resource.hpp b/include/cru/win/graph/direct/Resource.hpp
index d0a30dbd..6162ebd8 100644
--- a/include/cru/win/graph/direct/Resource.hpp
+++ b/include/cru/win/graph/direct/Resource.hpp
@@ -10,7 +10,7 @@ class DirectGraphFactory;
class DirectResource : public Object, public virtual INativeResource {
public:
- static constexpr std::string_view k_platform_id = "Windows Direct";
+ static constexpr std::u16string_view k_platform_id = u"Windows Direct";
protected:
DirectResource() = default;
@@ -22,7 +22,7 @@ class DirectResource : public Object, public virtual INativeResource {
~DirectResource() override = default;
public:
- std::string_view GetPlatformId() const final { return k_platform_id; }
+ std::u16string_view GetPlatformId() const final { return k_platform_id; }
};
class DirectGraphResource : public DirectResource,
diff --git a/include/cru/win/graph/direct/TextLayout.hpp b/include/cru/win/graph/direct/TextLayout.hpp
index 40c63dbe..c53cf655 100644
--- a/include/cru/win/graph/direct/TextLayout.hpp
+++ b/include/cru/win/graph/direct/TextLayout.hpp
@@ -15,7 +15,7 @@ class DWriteTextLayout : public DirectGraphResource,
public virtual IComResource<IDWriteTextLayout> {
public:
DWriteTextLayout(DirectGraphFactory* factory, std::shared_ptr<IFont> font,
- std::string text);
+ std::u16string text);
CRU_DELETE_COPY(DWriteTextLayout)
CRU_DELETE_MOVE(DWriteTextLayout)
@@ -28,8 +28,8 @@ class DWriteTextLayout : public DirectGraphResource,
}
public:
- std::string GetText() override;
- void SetText(std::string new_text) override;
+ std::u16string GetText() override;
+ void SetText(std::u16string new_text) override;
std::shared_ptr<IFont> GetFont() override;
void SetFont(std::shared_ptr<IFont> font) override;
@@ -41,12 +41,11 @@ class DWriteTextLayout : public DirectGraphResource,
// Return empty vector if text_range.count is 0. Text range could be in
// reverse direction, it should be normalized first in implementation.
std::vector<Rect> TextRangeRect(const TextRange& text_range) override;
- Point TextSinglePoint(gsl::index position, bool trailing) override;
+ Point TextSinglePoint(Index position, bool trailing) override;
TextHitTestResult HitTest(const Point& point) override;
private:
- std::string text_;
- std::wstring w_text_;
+ std::u16string text_;
std::shared_ptr<DWriteFont> font_;
float max_width_ = std::numeric_limits<float>::max();
float max_height_ = std::numeric_limits<float>::max();
diff --git a/include/cru/win/native/Cursor.hpp b/include/cru/win/native/Cursor.hpp
index 44a6a362..373b9170 100644
--- a/include/cru/win/native/Cursor.hpp
+++ b/include/cru/win/native/Cursor.hpp
@@ -7,7 +7,7 @@
namespace cru::platform::native::win {
class WinCursor : public WinNativeResource, public virtual ICursor {
- CRU_DEFINE_CLASS_LOG_TAG("cru::platform::native::win::WinCursor")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::native::win::WinCursor")
public:
WinCursor(HCURSOR handle, bool auto_destroy);
diff --git a/include/cru/win/native/GodWindow.hpp b/include/cru/win/native/GodWindow.hpp
index 0820bdb3..8b20e01f 100644
--- a/include/cru/win/native/GodWindow.hpp
+++ b/include/cru/win/native/GodWindow.hpp
@@ -5,7 +5,7 @@
namespace cru::platform::native::win {
class GodWindow : public Object {
- CRU_DEFINE_CLASS_LOG_TAG("cru::platform::native::win::GodWindow")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::native::win::GodWindow")
public:
explicit GodWindow(WinUiApplication* application);
diff --git a/include/cru/win/native/InputMethod.hpp b/include/cru/win/native/InputMethod.hpp
index 45422ace..113f460d 100644
--- a/include/cru/win/native/InputMethod.hpp
+++ b/include/cru/win/native/InputMethod.hpp
@@ -12,7 +12,7 @@
namespace cru::platform::native::win {
class AutoHIMC : public Object {
- CRU_DEFINE_CLASS_LOG_TAG("cru::platform::native::win::AutoHIMC")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::native::win::AutoHIMC")
public:
explicit AutoHIMC(HWND hwnd);
@@ -35,7 +35,7 @@ class AutoHIMC : public Object {
class WinInputMethodContext : public WinNativeResource,
public virtual IInputMethodContext {
- CRU_DEFINE_CLASS_LOG_TAG("cru::platform::native::win::WinInputMethodContext")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::native::win::WinInputMethodContext")
public:
WinInputMethodContext(gsl::not_null<WinNativeWindow*> window);
@@ -65,12 +65,12 @@ class WinInputMethodContext : public WinNativeResource,
IEvent<std::nullptr_t>* CompositionEvent() override;
- IEvent<std::string_view>* TextEvent() override;
+ IEvent<std::u16string_view>* TextEvent() override;
private:
void OnWindowNativeMessage(WindowNativeMessageEventArgs& args);
- std::string GetResultString();
+ std::u16string GetResultString();
std::optional<AutoHIMC> TryGetHIMC();
@@ -82,7 +82,7 @@ class WinInputMethodContext : public WinNativeResource,
Event<std::nullptr_t> composition_start_event_;
Event<std::nullptr_t> composition_end_event_;
Event<std::nullptr_t> composition_event_;
- Event<std::string_view> text_event_;
+ Event<std::u16string_view> text_event_;
};
class WinInputMethodManager : public WinNativeResource,
diff --git a/include/cru/win/native/Resource.hpp b/include/cru/win/native/Resource.hpp
index 7afaca0f..0de0e1a8 100644
--- a/include/cru/win/native/Resource.hpp
+++ b/include/cru/win/native/Resource.hpp
@@ -6,7 +6,7 @@
namespace cru::platform::native::win {
class WinNativeResource : public Object, public virtual INativeResource {
public:
- static constexpr std::string_view k_platform_id = "Windows";
+ static constexpr std::u16string_view k_platform_id = u"Windows";
protected:
WinNativeResource() = default;
@@ -18,6 +18,6 @@ class WinNativeResource : public Object, public virtual INativeResource {
~WinNativeResource() override = default;
public:
- std::string_view GetPlatformId() const final { return k_platform_id; }
+ std::u16string_view GetPlatformId() const final { return k_platform_id; }
};
} // namespace cru::platform::native::win
diff --git a/include/cru/win/native/Window.hpp b/include/cru/win/native/Window.hpp
index 521a0a06..3e0b11cd 100644
--- a/include/cru/win/native/Window.hpp
+++ b/include/cru/win/native/Window.hpp
@@ -8,7 +8,7 @@
namespace cru::platform::native::win {
class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
- CRU_DEFINE_CLASS_LOG_TAG("cru::platform::native::win::WinNativeWindow")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::native::win::WinNativeWindow")
public:
WinNativeWindow(WinUiApplication* application, WindowClass* window_class,
diff --git a/src/common/Logger.cpp b/src/common/Logger.cpp
index da55047a..dfa25347 100644
--- a/src/common/Logger.cpp
+++ b/src/common/Logger.cpp
@@ -10,7 +10,6 @@ namespace cru::log {
namespace {
Logger *CreateLogger() {
const auto logger = new Logger();
- logger->AddSource(std::make_unique<StdioLogSource>());
return logger;
}
} // namespace
@@ -31,39 +30,43 @@ void Logger::RemoveSource(ILogSource *source) {
}
namespace {
-std::string_view LogLevelToString(LogLevel level) {
+std::u16string_view LogLevelToString(LogLevel level) {
switch (level) {
case LogLevel::Debug:
- return "DEBUG";
+ return u"DEBUG";
case LogLevel::Info:
- return "INFO";
+ return u"INFO";
case LogLevel::Warn:
- return "WARN";
+ return u"WARN";
case LogLevel::Error:
- return "ERROR";
+ return u"ERROR";
default:
std::terminate();
}
}
+
+std::u16string GetLogTime() {
+ auto time = std::time(nullptr);
+ auto calendar = std::localtime(&time);
+ return fmt::format(u"{}:{}:{}", calendar->tm_hour, calendar->tm_min,
+ calendar->tm_sec);
+}
} // namespace
-void Logger::Log(LogLevel level, std::string_view s) {
+void Logger::Log(LogLevel level, std::u16string_view s) {
#ifndef CRU_DEBUG
if (level == LogLevel::Debug) {
return;
}
#endif
for (const auto &source : sources_) {
- auto now = std::time(nullptr);
- std::array<char, 50> buffer;
- std::strftime(buffer.data(), 50, "%c", std::localtime(&now));
-
- source->Write(level, fmt::format("[{}] {}: {}\n", buffer.data(),
+ source->Write(level, fmt::format(u"[{}] {}: {}\n", GetLogTime(),
LogLevelToString(level), s));
}
}
-void Logger::Log(LogLevel level, std::string_view tag, std::string_view s) {
+void Logger::Log(LogLevel level, std::u16string_view tag,
+ std::u16string_view s) {
#ifndef CRU_DEBUG
if (level == LogLevel::Debug) {
return;
@@ -71,10 +74,7 @@ void Logger::Log(LogLevel level, std::string_view tag, std::string_view s) {
#endif
for (const auto &source : sources_) {
auto now = std::time(nullptr);
- std::array<char, 50> buffer;
- std::strftime(buffer.data(), 50, "%c", std::localtime(&now));
-
- source->Write(level, fmt::format("[{}] {} {}: {}\n", buffer.data(),
+ source->Write(level, fmt::format(u"[{}] {} {}: {}\n", GetLogTime(),
LogLevelToString(level), tag, s));
}
}
diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp
index 31a5effd..0b6332ce 100644
--- a/src/common/StringUtil.cpp
+++ b/src/common/StringUtil.cpp
@@ -1,5 +1,7 @@
#include "cru/common/StringUtil.hpp"
+#include <codecvt>
+
namespace cru {
template <typename UInt, int number_of_bit>
inline std::enable_if_t<std::is_unsigned_v<UInt>, CodePoint> ExtractBits(
@@ -7,63 +9,154 @@ inline std::enable_if_t<std::is_unsigned_v<UInt>, CodePoint> ExtractBits(
return static_cast<CodePoint>(n & ((1u << number_of_bit) - 1));
}
-CodePoint Utf8Iterator::Next() {
- if (position_ == static_cast<Index>(string_.length()))
- return k_code_point_end;
+CodePoint Utf16Iterator::Previous() {
+ if (position_ <= 0) return k_invalid_code_point;
- const auto cu0 = static_cast<std::uint8_t>(string_[position_++]);
+ const auto cu0 = static_cast<std::uint16_t>(string_[--position_]);
- auto read_next_folowing_code = [this]() -> CodePoint {
- if (this->position_ == static_cast<Index>(string_.length()))
+ if (cu0 < 0xd800u || cu0 >= 0xe000u) { // 1-length code point
+ return static_cast<CodePoint>(cu0);
+ } else if (cu0 < 0xdc00u || cu0 > 0xdfffu) { // 2-length code point
+ if (position_ <= 0) {
throw TextEncodeException(
- "Unexpected end when read continuing byte of multi-byte code point.");
+ "Unexpected end when reading first code unit of surrogate pair "
+ "during backward.");
+ }
+ const auto cu1 = static_cast<std::uint16_t>(string_[--position_]);
#ifdef CRU_DEBUG
- const auto u = static_cast<std::uint8_t>(string_[position_]);
- if (!(u & (1u << 7)) || (u & (1u << 6))) {
+ if (cu1 <= 0xdbffu) {
throw TextEncodeException(
- "Unexpected bad-format (not 0b10xxxxxx) continuing byte of "
- "multi-byte code point.");
+ "Unexpected bad-range first code unit of surrogate pair during "
+ "backward.");
}
#endif
- return ExtractBits<std::uint8_t, 6>(string_[position_++]);
- };
+ const auto s0 = ExtractBits<std::uint16_t, 10>(cu1) << 10;
+ const auto s1 = ExtractBits<std::uint16_t, 10>(cu0);
- if ((1u << 7) & cu0) {
- if ((1u << 6) & cu0) { // 2~4-length code point
- if ((1u << 5) & cu0) { // 3~4-length code point
- if ((1u << 4) & cu0) { // 4-length code point
-#ifdef CRU_DEBUG
- if (cu0 & (1u << 3)) {
- throw TextEncodeException(
- "Unexpected bad-format begin byte (not 0b10xxxxxx) of 4-byte "
- "code point.");
- }
-#endif
+ return s0 + s1 + 0x10000;
+
+ } else {
+ throw TextEncodeException(
+ "Unexpected bad-range second code unit of surrogate pair during "
+ "backward.");
+ }
+}
- const CodePoint s0 = ExtractBits<std::uint8_t, 3>(cu0) << (6 * 3);
- const CodePoint s1 = read_next_folowing_code() << (6 * 2);
- const CodePoint s2 = read_next_folowing_code() << 6;
- const CodePoint s3 = read_next_folowing_code();
- return s0 + s1 + s2 + s3;
- } else { // 3-length code point
- const CodePoint s0 = ExtractBits<std::uint8_t, 4>(cu0) << (6 * 2);
- const CodePoint s1 = read_next_folowing_code() << 6;
- const CodePoint s2 = read_next_folowing_code();
- return s0 + s1 + s2;
- }
- } else { // 2-length code point
- const CodePoint s0 = ExtractBits<std::uint8_t, 5>(cu0) << 6;
- const CodePoint s1 = read_next_folowing_code();
- return s0 + s1;
- }
- } else {
+CodePoint Utf16Iterator::Next() {
+ if (position_ >= static_cast<Index>(string_.length()))
+ return k_invalid_code_point;
+
+ const auto cu0 = static_cast<std::uint16_t>(string_[position_++]);
+
+ if (cu0 < 0xd800u || cu0 >= 0xe000u) { // 1-length code point
+ return static_cast<CodePoint>(cu0);
+ } else if (cu0 <= 0xdbffu) { // 2-length code point
+ if (position_ >= static_cast<Index>(string_.length())) {
throw TextEncodeException(
- "Unexpected bad-format (0b10xxxxxx) begin byte of a code point.");
+ "Unexpected end when reading second code unit of surrogate pair "
+ "during forward.");
}
+ const auto cu1 = static_cast<std::uint16_t>(string_[position_++]);
+
+#ifdef CRU_DEBUG
+ if (cu1 < 0xdc00u || cu1 > 0xdfffu) {
+ throw TextEncodeException(
+ "Unexpected bad-format second code unit of surrogate pair during "
+ "forward.");
+ }
+#endif
+
+ const auto s0 = ExtractBits<std::uint16_t, 10>(cu0) << 10;
+ const auto s1 = ExtractBits<std::uint16_t, 10>(cu1);
+
+ return s0 + s1 + 0x10000;
+
} else {
- return static_cast<CodePoint>(cu0);
+ throw TextEncodeException(
+ "Unexpected bad-format first code unit of surrogate pair during "
+ "forward.");
}
}
+
+Index PreviousIndex(std::u16string_view string, Index current) {
+ Utf16Iterator iterator{string, current};
+ iterator.Previous();
+ return iterator.CurrentPosition();
+}
+
+Index NextIndex(std::u16string_view string, Index current) {
+ Utf16Iterator iterator{string, current};
+ iterator.Next();
+ return iterator.CurrentPosition();
+}
+
+std::string ToUtf8(const std::u16string& s) {
+ // TODO: Implement this by myself.
+ return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}
+ .to_bytes(s);
+}
+
+// CodePoint Utf8Iterator::Next() {
+// if (position_ == static_cast<Index>(string_.length()))
+// return k_invalid_code_point;
+
+// const auto cu0 = static_cast<std::uint8_t>(string_[position_++]);
+
+// auto read_next_folowing_code = [this]() -> CodePoint {
+// if (this->position_ == static_cast<Index>(string_.length()))
+// throw TextEncodeException(
+// "Unexpected end when read continuing byte of multi-byte code
+// point.");
+
+// #ifdef CRU_DEBUG
+// const auto u = static_cast<std::uint8_t>(string_[position_]);
+// if (!(u & (1u << 7)) || (u & (1u << 6))) {
+// throw TextEncodeException(
+// "Unexpected bad-format (not 0b10xxxxxx) continuing byte of "
+// "multi-byte code point.");
+// }
+// #endif
+
+// return ExtractBits<std::uint8_t, 6>(string_[position_++]);
+// };
+
+// if ((1u << 7) & cu0) {
+// if ((1u << 6) & cu0) { // 2~4-length code point
+// if ((1u << 5) & cu0) { // 3~4-length code point
+// if ((1u << 4) & cu0) { // 4-length code point
+// #ifdef CRU_DEBUG
+// if (cu0 & (1u << 3)) {
+// throw TextEncodeException(
+// "Unexpected bad-format begin byte (not 0b10xxxxxx) of 4-byte
+// " "code point.");
+// }
+// #endif
+
+// const CodePoint s0 = ExtractBits<std::uint8_t, 3>(cu0) << (6 * 3);
+// const CodePoint s1 = read_next_folowing_code() << (6 * 2);
+// const CodePoint s2 = read_next_folowing_code() << 6;
+// const CodePoint s3 = read_next_folowing_code();
+// return s0 + s1 + s2 + s3;
+// } else { // 3-length code point
+// const CodePoint s0 = ExtractBits<std::uint8_t, 4>(cu0) << (6 * 2);
+// const CodePoint s1 = read_next_folowing_code() << 6;
+// const CodePoint s2 = read_next_folowing_code();
+// return s0 + s1 + s2;
+// }
+// } else { // 2-length code point
+// const CodePoint s0 = ExtractBits<std::uint8_t, 5>(cu0) << 6;
+// const CodePoint s1 = read_next_folowing_code();
+// return s0 + s1;
+// }
+// } else {
+// throw TextEncodeException(
+// "Unexpected bad-format (0b10xxxxxx) begin byte of a code point.");
+// }
+// } else {
+// return static_cast<CodePoint>(cu0);
+// }
+// }
+
} // namespace cru
diff --git a/src/ui/ClickDetector.cpp b/src/ui/ClickDetector.cpp
index 93e6f303..09f208cd 100644
--- a/src/ui/ClickDetector.cpp
+++ b/src/ui/ClickDetector.cpp
@@ -45,7 +45,7 @@ ClickDetector::ClickDetector(Control* control) {
this->state_ == ClickState::Hover) {
if (!this->control_->CaptureMouse()) {
log::TagDebug(log_tag,
- "Failed to capture mouse when begin click.");
+ u"Failed to capture mouse when begin click.");
return;
}
this->down_point_ = args.GetPoint();
@@ -107,21 +107,21 @@ void ClickDetector::SetTriggerButton(MouseButton trigger_button) {
void ClickDetector::SetState(ClickState state) {
#ifdef CRU_DEBUG
- auto to_string = [](ClickState state) -> std::string_view {
+ auto to_string = [](ClickState state) -> std::u16string_view {
switch (state) {
case ClickState::None:
- return "None";
+ return u"None";
case ClickState::Hover:
- return "Hover";
+ return u"Hover";
case ClickState::Press:
- return "Press";
+ return u"Press";
case ClickState::PressInactive:
- return "PressInvactive";
+ return u"PressInvactive";
default:
UnreachableCode();
}
};
- log::TagDebug(log_tag, "Click state changed, new state: {}.",
+ log::TagDebug(log_tag, u"Click state changed, new state: {}.",
to_string(state));
#endif
diff --git a/src/ui/RoutedEventDispatch.hpp b/src/ui/RoutedEventDispatch.hpp
index 5ff21a74..9337e9ec 100644
--- a/src/ui/RoutedEventDispatch.hpp
+++ b/src/ui/RoutedEventDispatch.hpp
@@ -20,7 +20,7 @@ namespace cru::ui {
// "original_sender", which is unchanged. And "args" will be perfectly forwarded
// as the rest arguments.
template <typename EventArgs, typename... Args>
-void DispatchEvent(const std::string_view& event_name,
+void DispatchEvent(const std::u16string_view& event_name,
Control* const original_sender,
event::RoutedEvent<EventArgs>* (Control::*event_ptr)(),
Control* const last_receiver, Args&&... args) {
@@ -30,7 +30,7 @@ void DispatchEvent(const std::string_view& event_name,
#ifdef CRU_DEBUG
bool do_log = true;
- if (event_name == "MouseMove") do_log = false;
+ if (event_name == u"MouseMove") do_log = false;
#endif
if (original_sender == last_receiver) {
@@ -56,14 +56,14 @@ void DispatchEvent(const std::string_view& event_name,
#ifdef CRU_DEBUG
if (do_log) {
- std::string log = "Dispatch routed event ";
+ std::u16string log = u"Dispatch routed event ";
log += event_name;
- log += ". Path (parent first): ";
+ log += u". Path (parent first): ";
auto i = receive_list.crbegin();
const auto end = --receive_list.crend();
for (; i != end; ++i) {
log += (*i)->GetControlType();
- log += " -> ";
+ log += u" -> ";
}
log += (*i)->GetControlType();
log::Debug(log);
@@ -89,8 +89,8 @@ void DispatchEvent(const std::string_view& event_name,
#ifdef CRU_DEBUG
if (do_log)
log::Debug(
- "Routed event is short-circuit in TUNNEL at {}-st control (count "
- "from parent).",
+ u"Routed event is short-circuit in TUNNEL at {}-st control (count "
+ u"from parent).",
count);
#endif
break;
@@ -110,9 +110,8 @@ void DispatchEvent(const std::string_view& event_name,
#ifdef CRU_DEBUG
if (do_log)
log::Debug(
- "Routed event is short-circuit in BUBBLE at {}-st control "
- "(count "
- "from parent).",
+ u"Routed event is short-circuit in BUBBLE at {}-st control "
+ u"(count from parent).",
count);
#endif
break;
@@ -128,7 +127,7 @@ void DispatchEvent(const std::string_view& event_name,
}
#ifdef CRU_DEBUG
- if (do_log) log::Debug("Routed event dispatch finished.");
+ if (do_log) log::Debug(u"Routed event dispatch finished.");
#endif
}
} // namespace cru::ui
diff --git a/src/ui/UiHost.cpp b/src/ui/UiHost.cpp
index 975d0ffe..5eee3925 100644
--- a/src/ui/UiHost.cpp
+++ b/src/ui/UiHost.cpp
@@ -14,9 +14,11 @@ using platform::native::IUiApplication;
namespace event_names {
#ifdef CRU_DEBUG
-#define CRU_DEFINE_EVENT_NAME(name) constexpr const char* name = #name;
+// clang-format off
+#define CRU_DEFINE_EVENT_NAME(name) constexpr const char16_t* name = u#name;
+// clang-format on
#else
-#define CRU_DEFINE_EVENT_NAME(name) constexpr const char* name = "";
+#define CRU_DEFINE_EVENT_NAME(name) constexpr const char16_t* name = u"";
#endif
CRU_DEFINE_EVENT_NAME(LoseFocus)
@@ -146,7 +148,7 @@ void UiHost::InvalidatePaint() {
}
void UiHost::InvalidateLayout() {
- log::TagDebug(log_tag, "A relayout is requested.");
+ log::TagDebug(log_tag, u"A relayout is requested.");
if (!need_layout_) {
platform::native::IUiApplication::GetInstance()->InvokeLater(
[resolver = this->CreateResolver()] {
@@ -171,7 +173,7 @@ void UiHost::Relayout() {
render::MeasureSize::NotSpecified());
root_render_object_->Layout(Point{});
after_layout_event_.Raise(AfterLayoutEventArgs{});
- log::TagDebug(log_tag, "A relayout is finished.");
+ log::TagDebug(log_tag, u"A relayout is finished.");
}
bool UiHost::RequestFocusFor(Control* control) {
@@ -368,6 +370,11 @@ void UiHost::UpdateCursor() {
Control* UiHost::HitTest(const Point& point) {
const auto render_object = root_render_object_->HitTest(point);
- return render_object ? render_object->GetAttachedControl() : nullptr;
+ if (render_object) {
+ const auto control = render_object->GetAttachedControl();
+ Ensures(control);
+ return control;
+ }
+ return window_control_;
}
} // namespace cru::ui
diff --git a/src/ui/UiManager.cpp b/src/ui/UiManager.cpp
index b8effdfd..b50a9775 100644
--- a/src/ui/UiManager.cpp
+++ b/src/ui/UiManager.cpp
@@ -30,7 +30,7 @@ UiManager* UiManager::GetInstance() {
UiManager::UiManager() {
const auto factory = GetGraphFactory();
- theme_resource_.default_font = factory->CreateFont("等线", 24.0f);
+ theme_resource_.default_font = factory->CreateFont(u"等线", 24.0f);
const auto black_brush = std::shared_ptr<platform::graph::ISolidColorBrush>(
CreateSolidColorBrush(factory, colors::black));
diff --git a/src/ui/Window.cpp b/src/ui/Window.cpp
index de7044dd..dca95ebb 100644
--- a/src/ui/Window.cpp
+++ b/src/ui/Window.cpp
@@ -17,7 +17,7 @@ Window::~Window() {
managed_ui_host_.reset();
}
-std::string_view Window::GetControlType() const { return control_type; }
+std::u16string_view Window::GetControlType() const { return control_type; }
render::RenderObject* Window::GetRenderObject() const { return render_object_; }
diff --git a/src/ui/controls/TextBlock.cpp b/src/ui/controls/TextBlock.cpp
index 5ec15796..7f7ee38b 100644
--- a/src/ui/controls/TextBlock.cpp
+++ b/src/ui/controls/TextBlock.cpp
@@ -30,11 +30,11 @@ render::RenderObject* TextBlock::GetRenderObject() const {
return text_render_object_.get();
}
-std::string TextBlock::GetText() const {
+std::u16string TextBlock::GetText() const {
return text_render_object_->GetText();
}
-void TextBlock::SetText(std::string text) {
+void TextBlock::SetText(std::u16string text) {
text_render_object_->SetText(std::move(text));
}
diff --git a/src/ui/controls/TextControlService.hpp b/src/ui/controls/TextControlService.hpp
index 94d9ebf8..93a48c44 100644
--- a/src/ui/controls/TextControlService.hpp
+++ b/src/ui/controls/TextControlService.hpp
@@ -19,7 +19,7 @@ constexpr int k_default_caret_blink_duration = 500;
// ```
template <typename TControl>
class TextControlService : public Object {
- CRU_DEFINE_CLASS_LOG_TAG("cru::ui::controls::TextControlService")
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::controls::TextControlService")
public:
TextControlService(gsl::not_null<TControl*> control) : control_(control) {}
@@ -126,22 +126,21 @@ class TextControlService : public Object {
const auto text_render_object = this->GetTextRenderObject();
text_render_object->SetSelectionRange(TextRange{start, 0});
text_render_object->SetCaretPosition(start);
- log::TagDebug(log_tag, "Text selection started, position: {}.", position);
+ log::TagDebug(log_tag, u"Text selection started, position: {}.", start);
}
void UpdateSelection(Index new_end) {
- if (!old_selection.has_value()) return;
-
const auto text_render_object = this->GetTextRenderObject();
const auto old_selection = text_render_object->GetSelectionRange();
+ if (!old_selection.has_value()) return;
const auto old_start = old_selection->GetStart();
this->GetTextRenderObject()->SetSelectionRange(
TextRange::FromTwoSides(old_start, new_end));
text_render_object->SetCaretPosition(new_end);
- log::TagDebug(log_tag, "Text selection updated, range: {}, {}.", old_start,
+ log::TagDebug(log_tag, u"Text selection updated, range: {}, {}.", old_start,
new_end);
if (const auto scroll_render_object = this->GetScrollRenderObject()) {
- //TODO: Implement this.
+ // TODO: Implement this.
}
}
@@ -194,9 +193,9 @@ class TextControlService : public Object {
}
}
- void KeyDownHandler(event::KeyEventArgs& args) {}
+ void KeyDownHandler(event::KeyEventArgs& args) { CRU_UNUSED(args); }
- void KeyUpHandler(event::KeyEventArgs& args) {}
+ void KeyUpHandler(event::KeyEventArgs& args) { CRU_UNUSED(args); }
void LoseFocusHandler(event::FocusChangeEventArgs& args) {
if (!args.IsWindow()) this->AbortSelection();
diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp
index f2e3eb9b..b7e1e709 100644
--- a/src/ui/render/BorderRenderObject.cpp
+++ b/src/ui/render/BorderRenderObject.cpp
@@ -57,7 +57,7 @@ void BorderRenderObject::OnDrawCore(platform::graph::IPainter* painter) {
background_brush_.get());
if (is_border_enabled_) {
if (border_brush_ == nullptr) {
- log::TagWarn(log_tag, "Border is enabled but border brush is null.");
+ log::TagWarn(log_tag, u"Border is enabled but border brush is null.");
} else {
painter->FillGeometry(geometry_.get(), border_brush_.get());
}
@@ -94,8 +94,8 @@ Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const auto max_width = requirement.max.width.GetLengthOrMax();
if (coerced_space_size.width > max_width) {
log::TagWarn(log_tag,
- "(Measure) Horizontal length of padding, border and margin "
- "is bigger than required max length.");
+ u"(Measure) Horizontal length of padding, border and margin "
+ u"is bigger than required max length.");
coerced_space_size.width = max_width;
}
content_requirement.max.width = max_width - coerced_space_size.width;
@@ -110,8 +110,8 @@ Size BorderRenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const auto max_height = requirement.max.height.GetLengthOrMax();
if (coerced_space_size.height > max_height) {
log::TagWarn(log_tag,
- "(Measure) Vertical length of padding, border and margin is "
- "bigger than required max length.");
+ u"(Measure) Vertical length of padding, border and margin is "
+ u"bigger than required max length.");
coerced_space_size.height = max_height;
}
content_requirement.max.height = max_height - coerced_space_size.height;
diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp
index 8e6b41fe..ade230b5 100644
--- a/src/ui/render/FlexLayoutRenderObject.cpp
+++ b/src/ui/render/FlexLayoutRenderObject.cpp
@@ -88,7 +88,7 @@ Size FlexLayoutMeasureContentImpl(
const MeasureRequirement& requirement, const MeasureSize& preferred_size,
const std::vector<RenderObject*>& children,
const std::vector<FlexChildLayoutData>& layout_data,
- std::string_view log_tag) {
+ std::u16string_view log_tag) {
Expects(children.size() == layout_data.size());
direction_tag_t direction_tag;
@@ -111,8 +111,8 @@ Size FlexLayoutMeasureContentImpl(
StackLayoutCalculateChildMaxLength(
preferred_cross_length, max_cross_length,
GetCross(child->GetMinSize(), direction_tag), log_tag,
- "(Measure) Child's min cross size is bigger than parent's max "
- "cross size."));
+ u"(Measure) Child's min cross size is bigger than parent's max "
+ u"cross size."));
}
// step 1.
@@ -315,7 +315,7 @@ Size FlexLayoutMeasureContentImpl(
total_length > max_main_length.GetLengthOrUndefined()) {
log::TagWarn(
log_tag,
- "(Measure) Children's main axis length exceeds required max length.");
+ u"(Measure) Children's main axis length exceeds required max length.");
total_length = max_main_length.GetLengthOrUndefined();
} else if (min_main_length.IsSpecified() &&
total_length < min_main_length.GetLengthOrUndefined()) {
diff --git a/src/ui/render/LayoutHelper.cpp b/src/ui/render/LayoutHelper.cpp
index 9f94b84d..9ad2d862 100644
--- a/src/ui/render/LayoutHelper.cpp
+++ b/src/ui/render/LayoutHelper.cpp
@@ -19,8 +19,8 @@ float CalculateAnchorByAlignment(Alignment alignment, float start_point,
MeasureLength StackLayoutCalculateChildMaxLength(
MeasureLength parent_preferred_size, MeasureLength parent_max_size,
- MeasureLength child_min_size, std::string_view log_tag,
- std::string_view exceeds_message) {
+ MeasureLength child_min_size, std::u16string_view log_tag,
+ std::u16string_view exceeds_message) {
if (parent_max_size.GetLengthOrMax() < child_min_size.GetLengthOr0()) {
log::TagWarn(log_tag, exceeds_message);
return parent_max_size;
diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp
index 66b62e6e..30433868 100644
--- a/src/ui/render/RenderObject.cpp
+++ b/src/ui/render/RenderObject.cpp
@@ -152,8 +152,8 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const auto max_width = requirement.max.width.GetLengthOrMax();
if (coerced_space_size.width > max_width) {
log::TagWarn(log_tag,
- "(Measure) Horizontal length of padding and margin is "
- "bigger than required max length.");
+ u"(Measure) Horizontal length of padding and margin is "
+ u"bigger than required max length.");
coerced_space_size.width = max_width;
}
content_requirement.max.width = max_width - coerced_space_size.width;
@@ -168,8 +168,8 @@ Size RenderObject::OnMeasureCore(const MeasureRequirement& requirement,
const auto max_height = requirement.max.height.GetLengthOrMax();
if (coerced_space_size.height > max_height) {
log::TagWarn(log_tag,
- "(Measure) Vertical length of padding and margin is bigger "
- "than required max length.");
+ u"(Measure) Vertical length of padding and margin is bigger "
+ u"than required max length.");
coerced_space_size.height = max_height;
}
content_requirement.max.height = max_height - coerced_space_size.height;
diff --git a/src/ui/render/ScrollRenderObject.cpp b/src/ui/render/ScrollRenderObject.cpp
index 77367970..d3996b98 100644
--- a/src/ui/render/ScrollRenderObject.cpp
+++ b/src/ui/render/ScrollRenderObject.cpp
@@ -69,6 +69,7 @@ void ScrollRenderObject::SetScrollOffset(const Point& offset) {
void ScrollToContain(const Rect& rect) {
// TODO: Implement this.
+ CRU_UNUSED(rect);
throw std::runtime_error("Not implemented.");
}
diff --git a/src/ui/render/StackLayoutRenderObject.cpp b/src/ui/render/StackLayoutRenderObject.cpp
index 168ff379..75ab0ee3 100644
--- a/src/ui/render/StackLayoutRenderObject.cpp
+++ b/src/ui/render/StackLayoutRenderObject.cpp
@@ -15,13 +15,13 @@ Size StackLayoutRenderObject::OnMeasureContent(
MeasureSize{StackLayoutCalculateChildMaxLength(
preferred_size.width, requirement.max.width,
child->GetMinSize().width, log_tag,
- "(Measure) Child's min width is bigger than "
- "parent's max width."),
+ u"(Measure) Child's min width is bigger than "
+ u"parent's max width."),
StackLayoutCalculateChildMaxLength(
preferred_size.height, requirement.max.height,
child->GetMinSize().height, log_tag,
- "(Measure) Child's min height is bigger than "
- "parent's max height.")},
+ u"(Measure) Child's min height is bigger than "
+ u"parent's max height.")},
MeasureSize::NotSpecified()},
MeasureSize::NotSpecified());
const auto size = child->GetSize();
diff --git a/src/ui/render/TextRenderObject.cpp b/src/ui/render/TextRenderObject.cpp
index 87a3c352..8a4a4ba1 100644
--- a/src/ui/render/TextRenderObject.cpp
+++ b/src/ui/render/TextRenderObject.cpp
@@ -28,16 +28,16 @@ TextRenderObject::TextRenderObject(
caret_brush.swap(caret_brush_);
const auto graph_factory = GetGraphFactory();
- text_layout_ = graph_factory->CreateTextLayout(font_, "");
+ text_layout_ = graph_factory->CreateTextLayout(font_, u"");
}
TextRenderObject::~TextRenderObject() = default;
-std::string TextRenderObject::GetText() const {
+std::u16string TextRenderObject::GetText() const {
return text_layout_->GetText();
}
-void TextRenderObject::SetText(std::string new_text) {
+void TextRenderObject::SetText(std::u16string new_text) {
text_layout_->SetText(std::move(new_text));
}
@@ -171,7 +171,7 @@ Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
if (requirement.max.width.IsSpecified() &&
text_size.width > requirement.max.width.GetLengthOrUndefined()) {
log::TagWarn(log_tag,
- "(Measure) Text actual width exceeds the required max width.");
+ u"(Measure) Text actual width exceeds the required max width.");
result.width = requirement.max.width.GetLengthOrUndefined();
} else {
result.width = std::max(result.width, preferred_size.width.GetLengthOr0());
@@ -182,7 +182,7 @@ Size TextRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
text_size.height > requirement.max.height.GetLengthOrUndefined()) {
log::TagWarn(
log_tag,
- "(Measure) Text actual height exceeds the required max height.");
+ u"(Measure) Text actual height exceeds the required max height.");
result.height = requirement.max.height.GetLengthOrUndefined();
} else {
result.height =
diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt
index f4062411..75b0a7ca 100644
--- a/src/win/CMakeLists.txt
+++ b/src/win/CMakeLists.txt
@@ -5,11 +5,9 @@ add_library(cru_win_base STATIC
Exception.cpp
HeapDebug.cpp
- String.cpp
)
target_sources(cru_win_base PUBLIC
${CRU_WIN_BASE_INCLUDE_DIR}/Exception.hpp
- ${CRU_WIN_BASE_INCLUDE_DIR}/String.hpp
${CRU_WIN_BASE_INCLUDE_DIR}/WinPreConfig.hpp
)
target_compile_definitions(cru_win_base PUBLIC UNICODE _UNICODE) # use unicode
diff --git a/src/win/DebugLogger.hpp b/src/win/DebugLogger.hpp
index 4ca1567b..598ee9e8 100644
--- a/src/win/DebugLogger.hpp
+++ b/src/win/DebugLogger.hpp
@@ -1,7 +1,6 @@
#include "cru/win/WinPreConfig.hpp"
#include "cru/common/Logger.hpp"
-#include "cru/win/String.hpp"
namespace cru::platform::win {
@@ -14,11 +13,10 @@ class WinDebugLoggerSource : public ::cru::log::ILogSource {
~WinDebugLoggerSource() = default;
- void Write(::cru::log::LogLevel level, std::string_view s) override {
+ void Write(::cru::log::LogLevel level, const std::u16string& s) override {
CRU_UNUSED(level)
- const std::wstring&& ws = ToUtf16String(s);
- ::OutputDebugStringW(ws.data());
+ ::OutputDebugStringW(reinterpret_cast<const wchar_t*>(s.c_str()));
}
};
} // namespace cru::platform::win
diff --git a/src/win/Exception.cpp b/src/win/Exception.cpp
index 9f9fb03d..8d2eee23 100644
--- a/src/win/Exception.cpp
+++ b/src/win/Exception.cpp
@@ -5,8 +5,8 @@
namespace cru::platform::win {
-inline std::string HResultMakeMessage(HRESULT h_result,
- std::optional<std::string_view> message) {
+inline std::string HResultMakeMessage(
+ HRESULT h_result, std::optional<std::string_view> message) {
if (message.has_value())
return fmt::format(FMT_STRING("HRESULT: {:#08x}. Message: {}"), h_result,
*message);
@@ -19,20 +19,20 @@ HResultError::HResultError(HRESULT h_result)
h_result_(h_result) {}
HResultError::HResultError(HRESULT h_result,
- const std::string_view& additional_message)
+ std::string_view additional_message)
: PlatformException(HResultMakeMessage(h_result, additional_message)),
h_result_(h_result) {}
inline std::string Win32MakeMessage(DWORD error_code,
- std::string_view message) {
+ std::string_view message) {
return fmt::format("Last error code: {:#04x}.\nMessage: {}\n", error_code,
message);
}
-Win32Error::Win32Error(const std::string_view& message)
+Win32Error::Win32Error(std::string_view message)
: Win32Error(::GetLastError(), message) {}
-Win32Error::Win32Error(DWORD error_code, const std::string_view& message)
+Win32Error::Win32Error(DWORD error_code, std::string_view message)
: PlatformException(Win32MakeMessage(error_code, message)),
error_code_(error_code) {}
} // namespace cru::platform::win
diff --git a/src/win/graph/direct/Factory.cpp b/src/win/graph/direct/Factory.cpp
index d9213994..03e64e13 100644
--- a/src/win/graph/direct/Factory.cpp
+++ b/src/win/graph/direct/Factory.cpp
@@ -19,8 +19,8 @@ void InitializeCom() {
}
if (hresult == S_FALSE) {
log::Debug(
- "Try to call CoInitializeEx, but it seems COM is already "
- "initialized.");
+ u"Try to call CoInitializeEx, but it seems COM is already "
+ u"initialized.");
}
}
@@ -95,12 +95,12 @@ std::unique_ptr<IGeometryBuilder> DirectGraphFactory::CreateGeometryBuilder() {
}
std::unique_ptr<IFont> DirectGraphFactory::CreateFont(
- const std::string_view& font_family, float font_size) {
- return std::make_unique<DWriteFont>(this, font_family, font_size);
+ std::u16string font_family, float font_size) {
+ return std::make_unique<DWriteFont>(this, std::move(font_family), font_size);
}
std::unique_ptr<ITextLayout> DirectGraphFactory::CreateTextLayout(
- std::shared_ptr<IFont> font, std::string text) {
+ std::shared_ptr<IFont> font, std::u16string text) {
return std::make_unique<DWriteTextLayout>(this, std::move(font),
std::move(text));
}
diff --git a/src/win/graph/direct/Font.cpp b/src/win/graph/direct/Font.cpp
index edbbc59d..34de5b71 100644
--- a/src/win/graph/direct/Font.cpp
+++ b/src/win/graph/direct/Font.cpp
@@ -2,15 +2,14 @@
#include "cru/win/graph/direct/Exception.hpp"
#include "cru/win/graph/direct/Factory.hpp"
-#include "cru/win/String.hpp"
#include <array>
#include <utility>
namespace cru::platform::graph::win::direct {
-DWriteFont::DWriteFont(DirectGraphFactory* factory,
- const std::string_view& font_family, float font_size)
- : DirectGraphResource(factory) {
+DWriteFont::DWriteFont(DirectGraphFactory* factory, std::u16string font_family,
+ float font_size)
+ : DirectGraphResource(factory), font_family_(std::move(font_family)) {
// Get locale
std::array<wchar_t, LOCALE_NAME_MAX_LENGTH> buffer;
if (!::GetUserDefaultLocaleName(buffer.data(),
@@ -18,10 +17,9 @@ DWriteFont::DWriteFont(DirectGraphFactory* factory,
throw platform::win::Win32Error(
::GetLastError(), "Failed to get locale when create dwrite font.");
- const std::wstring&& wff = cru::platform::win::ToUtf16String(font_family);
-
ThrowIfFailed(factory->GetDWriteFactory()->CreateTextFormat(
- wff.data(), nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
+ reinterpret_cast<const wchar_t*>(font_family_.c_str()), nullptr,
+ DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, font_size, buffer.data(), &text_format_));
ThrowIfFailed(text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING));
diff --git a/src/win/graph/direct/TextLayout.cpp b/src/win/graph/direct/TextLayout.cpp
index 16db77f0..7b5b230f 100644
--- a/src/win/graph/direct/TextLayout.cpp
+++ b/src/win/graph/direct/TextLayout.cpp
@@ -5,38 +5,33 @@
#include "cru/win/graph/direct/Exception.hpp"
#include "cru/win/graph/direct/Factory.hpp"
#include "cru/win/graph/direct/Font.hpp"
-#include "cru/win/String.hpp"
#include <utility>
namespace cru::platform::graph::win::direct {
-using cru::platform::win::IndexUtf16ToUtf8;
-using cru::platform::win::IndexUtf8ToUtf16;
-
DWriteTextLayout::DWriteTextLayout(DirectGraphFactory* factory,
std::shared_ptr<IFont> font,
- std::string text)
+ std::u16string text)
: DirectGraphResource(factory), text_(std::move(text)) {
Expects(font);
font_ = CheckPlatform<DWriteFont>(font, GetPlatformId());
- w_text_ = cru::platform::win::ToUtf16String(text_);
-
ThrowIfFailed(factory->GetDWriteFactory()->CreateTextLayout(
- w_text_.c_str(), static_cast<UINT32>(w_text_.size()),
- font_->GetComInterface(), max_width_, max_height_, &text_layout_));
+ reinterpret_cast<const wchar_t*>(text_.c_str()),
+ static_cast<UINT32>(text_.size()), font_->GetComInterface(), max_width_,
+ max_height_, &text_layout_));
}
DWriteTextLayout::~DWriteTextLayout() = default;
-std::string DWriteTextLayout::GetText() { return text_; }
+std::u16string DWriteTextLayout::GetText() { return text_; }
-void DWriteTextLayout::SetText(std::string new_text) {
+void DWriteTextLayout::SetText(std::u16string new_text) {
text_.swap(new_text);
- w_text_ = cru::platform::win::ToUtf16String(text_);
ThrowIfFailed(GetDirectFactory()->GetDWriteFactory()->CreateTextLayout(
- w_text_.c_str(), static_cast<UINT32>(w_text_.size()),
- font_->GetComInterface(), max_width_, max_height_, &text_layout_));
+ reinterpret_cast<const wchar_t*>(text_.c_str()),
+ static_cast<UINT32>(text_.size()), font_->GetComInterface(), max_width_,
+ max_height_, &text_layout_));
}
std::shared_ptr<IFont> DWriteTextLayout::GetFont() {
@@ -46,8 +41,9 @@ std::shared_ptr<IFont> DWriteTextLayout::GetFont() {
void DWriteTextLayout::SetFont(std::shared_ptr<IFont> font) {
font_ = CheckPlatform<DWriteFont>(font, GetPlatformId());
ThrowIfFailed(GetDirectFactory()->GetDWriteFactory()->CreateTextLayout(
- w_text_.c_str(), static_cast<UINT32>(w_text_.size()),
- font_->GetComInterface(), max_width_, max_height_, &text_layout_));
+ reinterpret_cast<const wchar_t*>(text_.c_str()),
+ static_cast<UINT32>(text_.size()), font_->GetComInterface(), max_width_,
+ max_height_, &text_layout_));
}
void DWriteTextLayout::SetMaxWidth(float max_width) {
@@ -73,12 +69,6 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(
}
const auto text_range = text_range_arg.Normalize();
- // TODO: This can be faster with one iteration.
- const int start_index =
- IndexUtf8ToUtf16(text_, static_cast<int>(text_range.position), w_text_);
- const int end_index = IndexUtf8ToUtf16(
- text_, static_cast<int>(text_range.position + text_range.count), w_text_);
-
DWRITE_TEXT_METRICS text_metrics;
ThrowIfFailed(text_layout_->GetMetrics(&text_metrics));
const auto metrics_count =
@@ -87,9 +77,9 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(
std::vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count);
UINT32 actual_count;
ThrowIfFailed(text_layout_->HitTestTextRange(
- static_cast<UINT32>(start_index),
- static_cast<UINT32>(end_index - start_index), 0, 0,
- hit_test_metrics.data(), metrics_count, &actual_count));
+ static_cast<UINT32>(text_range.position),
+ static_cast<UINT32>(text_range.count), 0, 0, hit_test_metrics.data(),
+ metrics_count, &actual_count));
hit_test_metrics.erase(hit_test_metrics.cbegin() + actual_count,
hit_test_metrics.cend());
@@ -105,14 +95,11 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(
return result;
}
-Point DWriteTextLayout::TextSinglePoint(gsl::index position, bool trailing) {
- const auto index =
- IndexUtf8ToUtf16(text_, static_cast<int>(position), w_text_);
-
+Point DWriteTextLayout::TextSinglePoint(Index position, bool trailing) {
DWRITE_HIT_TEST_METRICS metrics;
FLOAT left;
FLOAT top;
- ThrowIfFailed(text_layout_->HitTestTextPosition(static_cast<UINT32>(index),
+ ThrowIfFailed(text_layout_->HitTestTextPosition(static_cast<UINT32>(position),
static_cast<BOOL>(trailing),
&left, &top, &metrics));
return Point{left, top};
@@ -126,10 +113,8 @@ TextHitTestResult DWriteTextLayout::HitTest(const Point& point) {
ThrowIfFailed(text_layout_->HitTestPoint(point.x, point.y, &trailing, &inside,
&metrics));
- const auto index =
- IndexUtf16ToUtf8(w_text_, static_cast<int>(metrics.textPosition), text_);
TextHitTestResult result;
- result.position = index;
+ result.position = metrics.textPosition;
result.trailing = trailing != 0;
result.insideText = inside != 0;
return result;
diff --git a/src/win/native/Cursor.cpp b/src/win/native/Cursor.cpp
index a6ab5bfc..429f6e7c 100644
--- a/src/win/native/Cursor.cpp
+++ b/src/win/native/Cursor.cpp
@@ -16,7 +16,7 @@ WinCursor::~WinCursor() {
if (!::DestroyCursor(handle_)) {
// This is not a fetal error but might still need notice because it may
// cause leak.
- log::TagWarn(log_tag, "Failed to destroy a cursor. Last error code: {}",
+ log::TagWarn(log_tag, u"Failed to destroy a cursor. Last error code: {}",
::GetLastError());
}
}
diff --git a/src/win/native/GodWindow.cpp b/src/win/native/GodWindow.cpp
index 8ef2788e..b1e7275e 100644
--- a/src/win/native/GodWindow.cpp
+++ b/src/win/native/GodWindow.cpp
@@ -45,7 +45,7 @@ GodWindow::GodWindow(WinUiApplication* application) {
GodWindow::~GodWindow() {
if (!::DestroyWindow(hwnd_)) {
// Although this could be "safely" ignore.
- log::TagWarn(log_tag, "Failed to destroy god window.");
+ log::TagWarn(log_tag, u"Failed to destroy god window.");
}
}
diff --git a/src/win/native/InputMethod.cpp b/src/win/native/InputMethod.cpp
index d3d989f3..5fc6c934 100644
--- a/src/win/native/InputMethod.cpp
+++ b/src/win/native/InputMethod.cpp
@@ -2,9 +2,9 @@
#include "DpiUtil.hpp"
#include "cru/common/Logger.hpp"
+#include "cru/common/StringUtil.hpp"
#include "cru/platform/Check.hpp"
#include "cru/win/Exception.hpp"
-#include "cru/win/String.hpp"
#include "cru/win/native/Window.hpp"
#include <vector>
@@ -35,7 +35,7 @@ AutoHIMC& AutoHIMC::operator=(AutoHIMC&& other) {
AutoHIMC::~AutoHIMC() {
if (handle_) {
if (!::ImmReleaseContext(hwnd_, handle_))
- log::TagWarn(log_tag, "Failed to release HIMC.");
+ log::TagWarn(log_tag, u"Failed to release HIMC.");
}
}
@@ -104,19 +104,19 @@ CompositionClauses GetCompositionClauses(HIMC imm_context, int target_start,
return result;
}
-std::wstring GetString(HIMC imm_context) {
+std::u16string GetString(HIMC imm_context) {
LONG string_size =
::ImmGetCompositionString(imm_context, GCS_COMPSTR, NULL, 0);
- std::wstring result((string_size / sizeof(wchar_t)), 0);
+ std::u16string result((string_size / sizeof(char16_t)), 0);
::ImmGetCompositionString(imm_context, GCS_COMPSTR, result.data(),
string_size);
return result;
}
-std::wstring GetResultString(HIMC imm_context) {
+std::u16string GetResultString(HIMC imm_context) {
LONG string_size =
::ImmGetCompositionString(imm_context, GCS_RESULTSTR, NULL, 0);
- std::wstring result((string_size / sizeof(wchar_t)), 0);
+ std::u16string result((string_size / sizeof(char16_t)), 0);
::ImmGetCompositionString(imm_context, GCS_RESULTSTR, result.data(),
string_size);
return result;
@@ -126,25 +126,17 @@ CompositionText GetCompositionInfo(HIMC imm_context) {
// We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and
// convert them into underlines and selection range respectively.
- auto w_text = GetString(imm_context);
+ auto text = GetString(imm_context);
- int w_length = static_cast<int>(w_text.length());
+ int length = static_cast<int>(text.length());
// Find out the range selected by the user.
- int w_target_start = w_length;
- int w_target_end = w_length;
- GetCompositionTargetRange(imm_context, &w_target_start, &w_target_end);
+ int target_start = length;
+ int target_end = length;
+ GetCompositionTargetRange(imm_context, &target_start, &target_end);
- auto clauses =
- GetCompositionClauses(imm_context, w_target_start, w_target_end);
+ auto clauses = GetCompositionClauses(imm_context, target_start, target_end);
- int w_cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0);
-
- auto text = platform::win::ToUtf8String(w_text);
- for (auto& clause : clauses) {
- clause.start = platform::win::IndexUtf16ToUtf8(w_text, clause.start, text);
- clause.end = platform::win::IndexUtf16ToUtf8(w_text, clause.end, text);
- }
- int cursor = platform::win::IndexUtf16ToUtf8(w_text, w_cursor, text);
+ int cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0);
return CompositionText{std::move(text), std::move(clauses),
TextRange{cursor}};
@@ -169,7 +161,7 @@ void WinInputMethodContext::EnableIME() {
const auto hwnd = native_window->GetWindowHandle();
if (::ImmAssociateContextEx(hwnd, nullptr, IACE_DEFAULT) == FALSE) {
- log::TagWarn(log_tag, "Failed to enable ime.");
+ log::TagWarn(log_tag, u"Failed to enable ime.");
}
}
@@ -181,11 +173,12 @@ void WinInputMethodContext::DisableIME() {
AutoHIMC himc{hwnd};
if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) {
- log::TagWarn(log_tag, "Failed to complete composition before disable ime.");
+ log::TagWarn(log_tag,
+ u"Failed to complete composition before disable ime.");
}
if (::ImmAssociateContextEx(hwnd, nullptr, 0) == FALSE) {
- log::TagWarn(log_tag, "Failed to disable ime.");
+ log::TagWarn(log_tag, u"Failed to disable ime.");
}
}
@@ -195,7 +188,7 @@ void WinInputMethodContext::CompleteComposition() {
auto himc = *std::move(optional_himc);
if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) {
- log::TagWarn(log_tag, "Failed to complete composition.");
+ log::TagWarn(log_tag, u"Failed to complete composition.");
}
}
@@ -205,7 +198,7 @@ void WinInputMethodContext::CancelComposition() {
auto himc = *std::move(optional_himc);
if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_CANCEL, 0)) {
- log::TagWarn(log_tag, "Failed to complete composition.");
+ log::TagWarn(log_tag, u"Failed to complete composition.");
}
}
@@ -229,7 +222,7 @@ void WinInputMethodContext::SetCandidateWindowPosition(const Point& point) {
if (!::ImmSetCandidateWindow(himc.Get(), &form))
log::TagDebug(log_tag,
- "Failed to set input method candidate window position.");
+ u"Failed to set input method candidate window position.");
}
IEvent<std::nullptr_t>* WinInputMethodContext::CompositionStartEvent() {
@@ -244,7 +237,7 @@ IEvent<std::nullptr_t>* WinInputMethodContext::CompositionEvent() {
return &composition_event_;
}
-IEvent<std::string_view>* WinInputMethodContext::TextEvent() {
+IEvent<std::u16string_view>* WinInputMethodContext::TextEvent() {
return &text_event_;
}
@@ -253,18 +246,17 @@ void WinInputMethodContext::OnWindowNativeMessage(
const auto& message = args.GetWindowMessage();
switch (message.msg) {
case WM_CHAR: {
- const auto c = static_cast<wchar_t>(message.w_param);
- if (platform::win::IsSurrogatePair(c)) {
+ const auto c = static_cast<char16_t>(message.w_param);
+ if (IsSurrogatePair(c)) {
// I don't think this will happen because normal key strike without ime
// should only trigger ascci character. If it is a charater from
// supplementary planes, it should be handled with ime messages.
log::TagWarn(log_tag,
- "A WM_CHAR message for character from supplementary "
- "planes is ignored.");
+ u"A WM_CHAR message for character from supplementary "
+ u"planes is ignored.");
} else {
- wchar_t s[1] = {c};
- auto str = platform::win::ToUtf8String({s, 1});
- text_event_.Raise(str);
+ char16_t s[1] = {c};
+ text_event_.Raise({s, 1});
}
args.HandleWithResult(0);
break;
@@ -272,8 +264,6 @@ void WinInputMethodContext::OnWindowNativeMessage(
case WM_IME_COMPOSITION: {
composition_event_.Raise(nullptr);
auto composition_text = GetCompositionText();
- log::TagDebug(log_tag, "WM_IME_COMPOSITION composition text:\n{}",
- composition_text);
if (message.l_param & GCS_RESULTSTR) {
auto result_string = GetResultString();
text_event_.Raise(result_string);
@@ -291,13 +281,13 @@ void WinInputMethodContext::OnWindowNativeMessage(
}
}
-std::string WinInputMethodContext::GetResultString() {
+std::u16string WinInputMethodContext::GetResultString() {
auto optional_himc = TryGetHIMC();
- if (!optional_himc.has_value()) return "";
+ if (!optional_himc.has_value()) return u"";
auto himc = *std::move(optional_himc);
- auto w_result = win::GetResultString(himc.Get());
- return platform::win::ToUtf8String(w_result);
+ auto result = win::GetResultString(himc.Get());
+ return result;
}
std::optional<AutoHIMC> WinInputMethodContext::TryGetHIMC() {
diff --git a/src/win/native/Window.cpp b/src/win/native/Window.cpp
index 22505bd6..81642451 100644
--- a/src/win/native/Window.cpp
+++ b/src/win/native/Window.cpp
@@ -5,7 +5,6 @@
#include "WindowManager.hpp"
#include "cru/common/Logger.hpp"
#include "cru/platform/Check.hpp"
-#include "cru/win/String.hpp"
#include "cru/win/native/Cursor.hpp"
#include "cru/win/native/Exception.hpp"
#include "cru/win/native/Keyboard.hpp"
@@ -124,7 +123,7 @@ bool WinNativeWindow::ReleaseMouse() {
}
void WinNativeWindow::RequestRepaint() {
- log::TagDebug(log_tag, "A repaint is requested.");
+ log::TagDebug(log_tag, u"A repaint is requested.");
if (!::InvalidateRect(hwnd_, nullptr, FALSE))
throw Win32Error(::GetLastError(), "Failed to invalidate window.");
if (!::UpdateWindow(hwnd_))
@@ -145,43 +144,43 @@ void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
if (!::SetClassLongPtrW(hwnd_, GCLP_HCURSOR,
reinterpret_cast<LONG_PTR>(cursor_->GetHandle()))) {
log::TagWarn(log_tag,
- "Failed to set cursor because failed to set class long. Last "
- "error code: {}.",
+ u"Failed to set cursor because failed to set class long. Last "
+ u"error code: {}.",
::GetLastError());
return;
}
if (!IsVisible()) return;
- auto lg = [](const std::string_view& reason) {
+ auto lg = [](const std::u16string_view& reason) {
log::TagWarn(
log_tag,
- "Failed to set cursor because {} when window is visible. (We need to "
- "update cursor if it is inside the window.) Last error code: {}.",
+ u"Failed to set cursor because {} when window is visible. (We need to "
+ u"update cursor if it is inside the window.) Last error code: {}.",
reason, ::GetLastError());
};
::POINT point;
if (!::GetCursorPos(&point)) {
- lg("failed to get cursor pos");
+ lg(u"failed to get cursor pos");
return;
}
::RECT rect;
if (!::GetClientRect(hwnd_, &rect)) {
- lg("failed to get window's client rect");
+ lg(u"failed to get window's client rect");
return;
}
::POINT lefttop{rect.left, rect.top};
::POINT rightbottom{rect.right, rect.bottom};
if (!::ClientToScreen(hwnd_, &lefttop)) {
- lg("failed to call ClientToScreen on lefttop");
+ lg(u"failed to call ClientToScreen on lefttop");
return;
}
if (!::ClientToScreen(hwnd_, &rightbottom)) {
- lg("failed to call ClientToScreen on rightbottom");
+ lg(u"failed to call ClientToScreen on rightbottom");
return;
}
@@ -354,7 +353,7 @@ void WinNativeWindow::OnDestroyInternal() {
void WinNativeWindow::OnPaintInternal() {
paint_event_.Raise(nullptr);
ValidateRect(hwnd_, nullptr);
- log::TagDebug(log_tag, "A repaint is finished.");
+ log::TagDebug(log_tag, u"A repaint is finished.");
}
void WinNativeWindow::OnResizeInternal(const int new_width,
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index d41e3467..c534b909 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,7 +2,7 @@ find_package(GTest CONFIG REQUIRED)
include(GoogleTest)
-add_subdirectory(win)
+add_subdirectory(common)
add_library(cru_test_base INTERFACE)
target_link_libraries(cru_test_base INTERFACE GTest::gtest GTest::gtest_main)
diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt
new file mode 100644
index 00000000..c1fd078d
--- /dev/null
+++ b/test/common/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_executable(cru_base_test
+ StringUtilTest.cpp
+)
+target_link_libraries(cru_base_test PRIVATE cru_base cru_test_base)
+
+gtest_discover_tests(cru_base_test)
diff --git a/test/common/StringUtilTest.cpp b/test/common/StringUtilTest.cpp
new file mode 100644
index 00000000..e454505b
--- /dev/null
+++ b/test/common/StringUtilTest.cpp
@@ -0,0 +1,53 @@
+#include "cru/common/StringUtil.hpp"
+
+#include <gtest/gtest.h>
+
+using cru::k_invalid_code_point;
+
+// TEST(WinString, Utf8Iterator) {
+// using cru::platform::win::Utf8Iterator;
+// std::string_view text = "aπ你🤣!";
+// Utf8Iterator i{text};
+// ASSERT_EQ(i.Next(), 0x0061);
+// ASSERT_EQ(i.Next(), 0x03C0);
+// ASSERT_EQ(i.Next(), 0x4F60);
+// ASSERT_EQ(i.Next(), 0x1F923);
+// ASSERT_EQ(i.Next(), 0x0021);
+// ASSERT_EQ(i.Next(), k_invalid_code_point);
+// }
+
+TEST(WinString, Utf16Iterator) {
+ using cru::Utf16Iterator;
+ std::u16string_view text = u"aπ你🤣!";
+ Utf16Iterator i{text};
+ ASSERT_EQ(i.Next(), 0x0061);
+ ASSERT_EQ(i.Next(), 0x03C0);
+ ASSERT_EQ(i.Next(), 0x4F60);
+ ASSERT_EQ(i.Next(), 0x1F923);
+ ASSERT_EQ(i.Next(), 0x0021);
+ ASSERT_EQ(i.Next(), k_invalid_code_point);
+}
+
+// TEST(WinString, IndexUtf8ToUtf16) {
+// using cru::platform::win::IndexUtf8ToUtf16;
+// std::string_view utf8_string = "aπ你🤣!";
+// std::wstring_view utf16_string = L"aπ你🤣!";
+// ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 0, utf16_string), 0);
+// ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 1, utf16_string), 1);
+// ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 3, utf16_string), 2);
+// ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 6, utf16_string), 3);
+// ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 10, utf16_string), 5);
+// ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 11, utf16_string), 6);
+// }
+
+// TEST(WinString, IndexUtf16ToUtf8) {
+// using cru::platform::win::IndexUtf16ToUtf8;
+// std::string_view utf8_string = "aπ你🤣!";
+// std::wstring_view utf16_string = L"aπ你🤣!";
+// ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 0, utf8_string), 0);
+// ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 1, utf8_string), 1);
+// ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 2, utf8_string), 3);
+// ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 3, utf8_string), 6);
+// ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 5, utf8_string), 10);
+// ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 6, utf8_string), 11);
+// }
diff --git a/test/win/CMakeLists.txt b/test/win/CMakeLists.txt
deleted file mode 100644
index 138af96b..00000000
--- a/test/win/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-add_executable(cru_test_win_base
- String.cpp
-)
-target_link_libraries(cru_test_win_base PRIVATE cru_win_base cru_test_base)
-
-gtest_discover_tests(cru_test_win_base)
diff --git a/test/win/String.cpp b/test/win/String.cpp
deleted file mode 100644
index a666dc81..00000000
--- a/test/win/String.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "cru/win/String.hpp"
-
-#include <gtest/gtest.h>
-
-using cru::platform::win::k_code_point_end;
-
-TEST(WinString, Utf8Iterator) {
- using cru::platform::win::Utf8Iterator;
- std::string_view text = "aπ你🤣!";
- Utf8Iterator i{text};
- ASSERT_EQ(i.Next(), 0x0061);
- ASSERT_EQ(i.Next(), 0x03C0);
- ASSERT_EQ(i.Next(), 0x4F60);
- ASSERT_EQ(i.Next(), 0x1F923);
- ASSERT_EQ(i.Next(), 0x0021);
- ASSERT_EQ(i.Next(), k_code_point_end);
-}
-
-TEST(WinString, Utf16Iterator) {
- using cru::platform::win::Utf16Iterator;
- std::wstring_view text = L"aπ你🤣!";
- Utf16Iterator i{text};
- ASSERT_EQ(i.Next(), 0x0061);
- ASSERT_EQ(i.Next(), 0x03C0);
- ASSERT_EQ(i.Next(), 0x4F60);
- ASSERT_EQ(i.Next(), 0x1F923);
- ASSERT_EQ(i.Next(), 0x0021);
- ASSERT_EQ(i.Next(), k_code_point_end);
-}
-
-TEST(WinString, IndexUtf8ToUtf16) {
- using cru::platform::win::IndexUtf8ToUtf16;
- std::string_view utf8_string = "aπ你🤣!";
- std::wstring_view utf16_string = L"aπ你🤣!";
- ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 0, utf16_string), 0);
- ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 1, utf16_string), 1);
- ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 3, utf16_string), 2);
- ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 6, utf16_string), 3);
- ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 10, utf16_string), 5);
- ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 11, utf16_string), 6);
-}
-
-TEST(WinString, IndexUtf16ToUtf8) {
- using cru::platform::win::IndexUtf16ToUtf8;
- std::string_view utf8_string = "aπ你🤣!";
- std::wstring_view utf16_string = L"aπ你🤣!";
- ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 0, utf8_string), 0);
- ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 1, utf8_string), 1);
- ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 2, utf8_string), 3);
- ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 3, utf8_string), 6);
- ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 5, utf8_string), 10);
- ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 6, utf8_string), 11);
-}