summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorFausto Tommasi <fgtommasi@gmail.com>2023-02-15 07:49:01 -0600
committerTim Flynn <trflynn89@pm.me>2023-02-17 07:50:09 -0500
commitf7458b3e177fe847113e20b202e6c667a23f6b42 (patch)
tree3b7d59caf153f7c87781f4acabb331060f017024 /Userland
parent782b1d20f5e5f14c7107be2942a2ac00747a8e65 (diff)
downloadserenity-f7458b3e177fe847113e20b202e6c667a23f6b42.zip
LibGUI: Update TextEditor to delete emoji based on gbp cluster
Updated TextDocument and TextEditor to use calls to `find_grapheme_segmentation_boundary` in order to make "correct-feeling" deletions on backspace and delete keys being pressed
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibGUI/TextDocument.cpp28
-rw-r--r--Userland/Libraries/LibGUI/TextDocument.h3
-rw-r--r--Userland/Libraries/LibGUI/TextEditor.cpp6
3 files changed, 37 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGUI/TextDocument.cpp b/Userland/Libraries/LibGUI/TextDocument.cpp
index 1c33dabb0b..6fb2cee439 100644
--- a/Userland/Libraries/LibGUI/TextDocument.cpp
+++ b/Userland/Libraries/LibGUI/TextDocument.cpp
@@ -384,6 +384,34 @@ DeprecatedString TextDocument::text_in_range(TextRange const& a_range) const
return builder.to_deprecated_string();
}
+// This function will return the position of the previous grapheme cluster
+// break, relative to the cursor, for "correct looking" parsing of unicode based
+// on grapheme cluster boundary algorithm.
+size_t TextDocument::get_previous_grapheme_cluster_boundary(TextPosition const& cursor) const
+{
+ if (!cursor.is_valid())
+ return 0;
+
+ auto const& line = this->line(cursor.line());
+
+ auto index = Unicode::previous_grapheme_segmentation_boundary(line.view(), cursor.column());
+ return index.value_or(cursor.column() - 1);
+}
+
+// This function will return the position of the next grapheme cluster break,
+// relative to the cursor, for "correct looking" parsing of unicode based on
+// grapheme cluster boundary algorithm.
+size_t TextDocument::get_next_grapheme_cluster_boundary(TextPosition const& cursor) const
+{
+ if (!cursor.is_valid())
+ return 0;
+
+ auto const& line = this->line(cursor.line());
+
+ auto index = Unicode::next_grapheme_segmentation_boundary(line.view(), cursor.column());
+ return index.value_or(cursor.column() + 1);
+}
+
u32 TextDocument::code_point_at(TextPosition const& position) const
{
VERIFY(position.line() < line_count());
diff --git a/Userland/Libraries/LibGUI/TextDocument.h b/Userland/Libraries/LibGUI/TextDocument.h
index 3bae9594fa..48c1452055 100644
--- a/Userland/Libraries/LibGUI/TextDocument.h
+++ b/Userland/Libraries/LibGUI/TextDocument.h
@@ -102,6 +102,9 @@ public:
TextPosition next_position_after(TextPosition const&, SearchShouldWrap = SearchShouldWrap::Yes) const;
TextPosition previous_position_before(TextPosition const&, SearchShouldWrap = SearchShouldWrap::Yes) const;
+ size_t get_next_grapheme_cluster_boundary(TextPosition const& cursor) const;
+ size_t get_previous_grapheme_cluster_boundary(TextPosition const& cursor) const;
+
u32 code_point_at(TextPosition const&) const;
TextRange range_for_entire_line(size_t line_index) const;
diff --git a/Userland/Libraries/LibGUI/TextEditor.cpp b/Userland/Libraries/LibGUI/TextEditor.cpp
index 62896900d8..f27dd14c67 100644
--- a/Userland/Libraries/LibGUI/TextEditor.cpp
+++ b/Userland/Libraries/LibGUI/TextEditor.cpp
@@ -961,6 +961,9 @@ void TextEditor::keydown_event(KeyEvent& event)
if (event.modifiers() == Mod_Ctrl) {
auto word_break_pos = document().first_word_break_after(m_cursor);
erase_count = word_break_pos.column() - m_cursor.column();
+ } else {
+ auto grapheme_break_position = document().get_next_grapheme_cluster_boundary(m_cursor);
+ erase_count = grapheme_break_position - m_cursor.column();
}
TextRange erased_range(m_cursor, { m_cursor.line(), m_cursor.column() + erase_count });
execute<RemoveTextCommand>(document().text_in_range(erased_range), erased_range);
@@ -1001,6 +1004,9 @@ void TextEditor::keydown_event(KeyEvent& event)
else
new_column = (m_cursor.column() / m_soft_tab_width) * m_soft_tab_width;
erase_count = m_cursor.column() - new_column;
+ } else {
+ auto grapheme_break_position = document().get_previous_grapheme_cluster_boundary(m_cursor);
+ erase_count = m_cursor.column() - grapheme_break_position;
}
// Backspace within line