diff --git a/src/ncurses.cc b/src/ncurses.cc index 7f65a342..1a93d04d 100644 --- a/src/ncurses.cc +++ b/src/ncurses.cc @@ -689,45 +689,6 @@ static CharCoord compute_pos(CharCoord anchor, CharCoord size, return pos; } -static std::vector wrap_lines(StringView text, CharCount max_width) -{ - enum CharCategory { Word, Blank, Eol }; - static const auto categorize = [](Codepoint c) { - return is_blank(c) ? Blank - : is_eol(c) ? Eol : Word; - }; - - using Utf8It = utf8::iterator; - Utf8It word_begin{text.begin()}; - Utf8It word_end{word_begin}; - Utf8It end{text.end()}; - CharCount col = 0; - std::vector lines; - String line; - while (word_begin != end) - { - CharCategory cat = categorize(*word_begin); - do - { - ++word_end; - } while (word_end != end and categorize(*word_end) == cat); - - col += word_end - word_begin; - if (col > max_width or *word_begin == '\n') - { - lines.push_back(std::move(line)); - line = ""; - col = 0; - } - if (*word_begin != '\n') - line += String{word_begin.base(), word_end.base()}; - word_begin = word_end; - } - if (not line.empty()) - lines.push_back(std::move(line)); - return lines; -} - template static String make_info_box(StringView title, StringView message, CharCount max_width) @@ -746,7 +707,7 @@ static String make_info_box(StringView title, StringView message, assistant_size = { (int)assistant.size(), assistant[0].char_length() }; const CharCount max_bubble_width = max_width - assistant_size.column - 6; - std::vector lines = wrap_lines(message, max_bubble_width); + std::vector lines = wrap_lines(message, max_bubble_width); CharCount bubble_width = title.char_length() + 2; for (auto& line : lines) diff --git a/src/string.cc b/src/string.cc index 474b15b4..411f2ff8 100644 --- a/src/string.cc +++ b/src/string.cc @@ -147,6 +147,45 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col) return res; } +std::vector wrap_lines(StringView text, CharCount max_width) +{ + enum CharCategory { Word, Blank, Eol }; + static const auto categorize = [](Codepoint c) { + return is_blank(c) ? Blank + : is_eol(c) ? Eol : Word; + }; + + using Utf8It = utf8::iterator; + Utf8It word_begin{text.begin()}; + Utf8It word_end{word_begin}; + Utf8It end{text.end()}; + CharCount col = 0; + std::vector lines; + const char* line_begin = text.begin(); + while (word_begin != end) + { + CharCategory cat = categorize(*word_begin); + do + { + ++word_end; + } while (word_end != end and categorize(*word_end) == cat); + + col += word_end - word_begin; + if (col > max_width or *word_begin == '\n') + { + lines.emplace_back(line_begin, word_begin.base()); + line_begin = word_begin.base(); + if (*line_begin == '\n') + ++line_begin; + col = 0; + } + word_begin = word_end; + } + if (line_begin != word_begin.base()) + lines.emplace_back(line_begin, word_begin.base()); + return lines; +} + [[gnu::always_inline]] static inline uint32_t rotl(uint32_t x, int8_t r) { diff --git a/src/string.hh b/src/string.hh index bdb28dd7..0911948e 100644 --- a/src/string.hh +++ b/src/string.hh @@ -295,6 +295,8 @@ bool subsequence_match(StringView str, StringView subseq); String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0); +std::vector wrap_lines(StringView text, CharCount max_width); + size_t hash_data(const char* data, size_t len); }