diff --git a/Userland/Libraries/LibGUI/TextDocument.cpp b/Userland/Libraries/LibGUI/TextDocument.cpp index 4d71222529..1880d459e7 100644 --- a/Userland/Libraries/LibGUI/TextDocument.cpp +++ b/Userland/Libraries/LibGUI/TextDocument.cpp @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -57,28 +58,48 @@ TextDocument::~TextDocument() { } -void TextDocument::set_text(const StringView& text) +bool TextDocument::set_text(const StringView& text) { m_client_notifications_enabled = false; m_spans.clear(); remove_all_lines(); + ArmedScopeGuard clear_text_guard([this]() { + set_text({}); + }); + size_t start_of_current_line = 0; - auto add_line = [&](size_t current_position) { + auto add_line = [&](size_t current_position) -> bool { size_t line_length = current_position - start_of_current_line; auto line = make(*this); + + bool success = true; if (line_length) - line->set_text(*this, text.substring_view(start_of_current_line, current_position - start_of_current_line)); + success = line->set_text(*this, text.substring_view(start_of_current_line, current_position - start_of_current_line)); + + if (!success) + return false; + append_line(move(line)); start_of_current_line = current_position + 1; + + return true; }; + size_t i = 0; for (i = 0; i < text.length(); ++i) { - if (text[i] == '\n') - add_line(i); + if (text[i] != '\n') + continue; + + auto success = add_line(i); + if (!success) + return false; } - add_line(i); + + auto success = add_line(i); + if (!success) + return false; // Don't show the file's trailing newline as an actual new line. if (line_count() > 1 && line(line_count() - 1).is_empty()) @@ -88,6 +109,9 @@ void TextDocument::set_text(const StringView& text) for (auto* client : m_clients) client->document_did_set_text(); + + clear_text_guard.disarm(); + return true; } size_t TextDocumentLine::first_non_whitespace_column() const @@ -157,17 +181,21 @@ void TextDocumentLine::set_text(TextDocument& document, const Vector text) document.update_views({}); } -void TextDocumentLine::set_text(TextDocument& document, const StringView& text) +bool TextDocumentLine::set_text(TextDocument& document, const StringView& text) { if (text.is_empty()) { clear(document); - return; + return true; } m_text.clear(); Utf8View utf8_view(text); + if (!utf8_view.validate()) { + return false; + } for (auto code_point : utf8_view) m_text.append(code_point); document.update_views({}); + return true; } void TextDocumentLine::append(TextDocument& document, const u32* code_points, size_t length) diff --git a/Userland/Libraries/LibGUI/TextDocument.h b/Userland/Libraries/LibGUI/TextDocument.h index d559373f9b..8affc92d81 100644 --- a/Userland/Libraries/LibGUI/TextDocument.h +++ b/Userland/Libraries/LibGUI/TextDocument.h @@ -81,7 +81,7 @@ public: void set_spans(Vector spans) { m_spans = move(spans); } - void set_text(const StringView&); + bool set_text(const StringView&); const NonnullOwnPtrVector& lines() const { return m_lines; } NonnullOwnPtrVector& lines() { return m_lines; } @@ -176,7 +176,7 @@ public: Utf32View view() const { return { code_points(), length() }; } const u32* code_points() const { return m_text.data(); } size_t length() const { return m_text.size(); } - void set_text(TextDocument&, const StringView&); + bool set_text(TextDocument&, const StringView&); void set_text(TextDocument&, Vector); void append(TextDocument&, u32); void prepend(TextDocument&, u32);