summaryrefslogtreecommitdiff
path: root/src/display_buffer.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2022-12-06 17:51:28 +1100
committerMaxime Coste <mawww@kakoune.org>2022-12-06 17:51:28 +1100
commit93c50b3cd97ef78c678aa84010a5481ce0f11245 (patch)
tree22c616dafb1070f6c1e029818f6d0e58f20d2804 /src/display_buffer.cc
parent933e4a599cfd3fc09edd67a024b8af08bbec7c01 (diff)
Avoid calculating atom length in DisplayLine::trim_from
Calculating the length of an atom means we need to decode every codepoint and compute its column width. This can prove quite expensive in trim_from as we can have full buffer lines, so on buffer with long lines we might have to go through megabytes of undisplayed data.
Diffstat (limited to 'src/display_buffer.cc')
-rw-r--r--src/display_buffer.cc73
1 files changed, 47 insertions, 26 deletions
diff --git a/src/display_buffer.cc b/src/display_buffer.cc
index c9b74d04..02007d8f 100644
--- a/src/display_buffer.cc
+++ b/src/display_buffer.cc
@@ -55,24 +55,56 @@ ColumnCount DisplayAtom::length() const
return 0;
}
-void DisplayAtom::trim_begin(ColumnCount count)
+bool DisplayAtom::empty() const
{
if (m_type == Range)
- m_range.begin = utf8::advance(get_iterator(*m_buffer, m_range.begin),
- get_iterator(*m_buffer, m_range.end),
- count).coord();
+ return m_range.begin == m_range.end;
else
- m_text = m_text.substr(count).str();
+ return m_text.empty();
}
-void DisplayAtom::trim_end(ColumnCount count)
+ColumnCount DisplayAtom::trim_begin(ColumnCount count)
{
+ ColumnCount res = 0;
if (m_type == Range)
- m_range.end = utf8::advance(get_iterator(*m_buffer, m_range.end),
- get_iterator(*m_buffer, m_range.begin),
- -count).coord();
+ {
+ auto it = get_iterator(*m_buffer, m_range.begin);
+ auto end = get_iterator(*m_buffer, m_range.end);
+ while (it != end and res < count)
+ res += codepoint_width(utf8::read_codepoint(it, end));
+ m_range.begin = std::min(it.coord(), m_range.end);
+ }
+ else
+ {
+ auto it = m_text.begin();
+ while (it != m_text.end() and res < count)
+ res += codepoint_width(utf8::read_codepoint(it, m_text.end()));
+ m_text = String{it, m_text.end()};
+ }
+
+ return res;
+}
+
+ColumnCount DisplayAtom::trim_end_to_length(ColumnCount count)
+{
+ ColumnCount res = 0;
+ if (m_type == Range)
+ {
+ auto it = get_iterator(*m_buffer, m_range.begin);
+ auto end = get_iterator(*m_buffer, m_range.end);
+ while (it != end and res < count)
+ res += codepoint_width(utf8::read_codepoint(it, end));
+ m_range.end = std::min(it.coord(), m_range.end);
+ }
else
- m_text = m_text.substr(0, m_text.column_length() - count).str();
+ {
+ auto it = m_text.begin();
+ while (it != m_text.end() and res < count)
+ res += codepoint_width(utf8::read_codepoint(it, m_text.end()));
+ m_text = String{m_text.begin(), it};
+ }
+
+ return res;
}
DisplayLine::DisplayLine(AtomList atoms)
@@ -222,26 +254,15 @@ bool DisplayLine::trim_from(ColumnCount first_col, ColumnCount front, ColumnCoun
while (front > 0 and it != end())
{
- auto len = it->length();
- if (len <= front)
- {
- m_atoms.erase(it);
- front -= len;
- }
- else
- {
- it->trim_begin(front);
- front = 0;
- }
+ front -= it->trim_begin(front);
+ if (it->empty())
+ it = m_atoms.erase(it);
}
it = begin();
for (; it != end() and col_count > 0; ++it)
- col_count -= it->length();
-
- bool did_trim = it != end() || col_count < 0;
- if (col_count < 0)
- (it-1)->trim_end(-col_count);
+ col_count -= it->trim_end_to_length(col_count);
+ bool did_trim = it != end() && col_count == 0;
m_atoms.erase(it, end());
compute_range();