diff --git a/Libraries/LibLine/Editor.cpp b/Libraries/LibLine/Editor.cpp index 9ad08389a3..1fa95c996c 100644 --- a/Libraries/LibLine/Editor.cpp +++ b/Libraries/LibLine/Editor.cpp @@ -111,24 +111,64 @@ void Editor::register_character_input_callback(char ch, Function m_key_callbacks.set(ch, make(move(callback))); } +static size_t codepoint_length_in_utf8(u32 codepoint) +{ + if (codepoint <= 0x7f) + return 1; + if (codepoint <= 0x07ff) + return 2; + if (codepoint <= 0xffff) + return 3; + if (codepoint <= 0x10ffff) + return 4; + return 3; +} + void Editor::stylize(const Span& span, const Style& style) { - auto starting_map = m_spans_starting.get(span.beginning()).value_or({}); + auto start = span.beginning(); + auto end = span.end(); - if (!starting_map.contains(span.end())) + if (span.mode() == Span::ByteOriented) { + size_t byte_offset = 0; + size_t codepoint_offset = 0; + size_t start_codepoint_offset = 0, end_codepoint_offset = 0; + + for (;;) { + if (codepoint_offset >= m_buffer.size()) + break; + + if (byte_offset > end) + break; + + if (byte_offset < start) + ++start_codepoint_offset; + + ++end_codepoint_offset; + + byte_offset += codepoint_length_in_utf8(m_buffer[codepoint_offset++]); + } + + start = start_codepoint_offset; + end = end_codepoint_offset; + } + + auto starting_map = m_spans_starting.get(start).value_or({}); + + if (!starting_map.contains(end)) m_refresh_needed = true; - starting_map.set(span.end(), style); + starting_map.set(end, style); - m_spans_starting.set(span.beginning(), starting_map); + m_spans_starting.set(start, starting_map); - auto ending_map = m_spans_ending.get(span.end()).value_or({}); + auto ending_map = m_spans_ending.get(end).value_or({}); - if (!ending_map.contains(span.beginning())) + if (!ending_map.contains(start)) m_refresh_needed = true; - ending_map.set(span.beginning(), style); + ending_map.set(start, style); - m_spans_ending.set(span.end(), ending_map); + m_spans_ending.set(end, ending_map); } String Editor::get_line(const String& prompt) diff --git a/Libraries/LibLine/Span.h b/Libraries/LibLine/Span.h index 080ab7d6cf..2d12145b1d 100644 --- a/Libraries/LibLine/Span.h +++ b/Libraries/LibLine/Span.h @@ -30,17 +30,25 @@ namespace Line { class Span { public: - Span(size_t start, size_t end) + enum Mode { + ByteOriented, + CodepointOriented, + }; + + Span(size_t start, size_t end, Mode mode = ByteOriented) : m_beginning(start) , m_end(end) + , m_mode(mode) { } size_t beginning() const { return m_beginning; } size_t end() const { return m_end; } + Mode mode() const { return m_mode; } private: size_t m_beginning { 0 }; size_t m_end { 0 }; + Mode m_mode { CodepointOriented }; }; }