LibVT: Only resize the line after all rewrapping is done

Otherwise we would end up inserting empty cells into the wrapped lines.
Fixes #8227.
This commit is contained in:
Ali Mohammad Pur 2021-06-24 20:07:33 +04:30 committed by Andreas Kling
parent ffb118265b
commit 7c88caf99f
Notes: sideshowbarker 2024-07-18 11:34:19 +09:00
3 changed files with 36 additions and 21 deletions

View file

@ -10,43 +10,52 @@ namespace VT {
Line::Line(size_t length)
{
set_length(length, nullptr, nullptr);
set_length(length);
}
Line::~Line()
{
}
void Line::set_length(size_t new_length, Line* next_line, CursorPosition* cursor, bool cursor_is_on_next_line)
void Line::rewrap(size_t new_length, Line* next_line, CursorPosition* cursor, bool cursor_is_on_next_line)
{
size_t old_length = length();
if (old_length == new_length)
return;
// Drop the empty cells
if (m_terminated_at.has_value())
if (m_terminated_at.has_value() && m_cells.size() > m_terminated_at.value())
m_cells.remove(m_terminated_at.value(), m_cells.size() - m_terminated_at.value());
if (!next_line)
return m_cells.resize(new_length);
if (old_length < new_length)
take_cells_from_next_line(old_length, new_length, next_line, cursor_is_on_next_line, cursor);
take_cells_from_next_line(new_length, next_line, cursor_is_on_next_line, cursor);
else
push_cells_into_next_line(old_length, new_length, next_line, cursor_is_on_next_line, cursor);
m_cells.resize(max(new_length, static_cast<size_t>(m_terminated_at.value_or(new_length))));
push_cells_into_next_line(new_length, next_line, cursor_is_on_next_line, cursor);
}
void Line::push_cells_into_next_line(size_t old_length, size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor)
void Line::set_length(size_t new_length)
{
m_cells.resize(new_length);
}
void Line::push_cells_into_next_line(size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor)
{
if (is_empty())
return;
if (length() <= new_length)
return;
// Push as many cells as _wouldn't_ fit into the next line.
auto cells_to_preserve = !next_line->m_terminated_at.has_value() && next_line->is_empty() ? 0 : m_terminated_at.value_or(0);
auto cells_to_push_into_next_line = min(old_length - new_length, length() - cells_to_preserve);
auto preserved_cells = max(new_length, cells_to_preserve);
auto cells_to_push_into_next_line = length() - preserved_cells;
if (!cells_to_push_into_next_line)
return;
auto preserved_cells = length() - cells_to_push_into_next_line;
if (next_line->m_terminated_at.has_value())
next_line->m_terminated_at = next_line->m_terminated_at.value() + cells_to_push_into_next_line;
@ -71,18 +80,20 @@ void Line::push_cells_into_next_line(size_t old_length, size_t new_length, Line*
m_terminated_at = m_terminated_at.value() - cells_to_push_into_next_line;
}
void Line::take_cells_from_next_line(size_t old_length, size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor)
void Line::take_cells_from_next_line(size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor)
{
// Take as many cells as would fit from the next line
if (m_terminated_at.has_value())
return;
auto cells_to_grab_from_next_line = min(new_length - old_length, next_line->length());
if (length() >= new_length)
return;
auto cells_to_grab_from_next_line = min(new_length - length(), next_line->length());
auto clear_next_line = false;
if (next_line->m_terminated_at.has_value()) {
cells_to_grab_from_next_line = min(cells_to_grab_from_next_line, static_cast<size_t>(next_line->m_terminated_at.value()));
if (cells_to_grab_from_next_line == *next_line->m_terminated_at) {
m_terminated_at = old_length + *next_line->m_terminated_at;
m_terminated_at = length() + *next_line->m_terminated_at;
next_line->m_terminated_at.clear();
clear_next_line = true;
} else {

View file

@ -53,7 +53,8 @@ public:
{
return m_cells.size();
}
void set_length(size_t, Line* next_line, CursorPosition* cursor, bool cursor_is_on_next_line = true);
void set_length(size_t);
void rewrap(size_t new_length, Line* next_line, CursorPosition* cursor, bool cursor_is_on_next_line = true);
u32 code_point(size_t index) const
{
@ -78,8 +79,8 @@ public:
void set_terminated(u16 column) { m_terminated_at = column; }
private:
void take_cells_from_next_line(size_t old_length, size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
void push_cells_into_next_line(size_t old_length, size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
void take_cells_from_next_line(size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
void push_cells_into_next_line(size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
Vector<Cell> m_cells;
bool m_dirty { false };

View file

@ -1455,14 +1455,14 @@ void Terminal::set_size(u16 columns, u16 rows)
auto next_line = is_at_seam ? nullptr : &buffer[buffer.size() - i + 1];
auto& line = buffer[buffer.size() - i];
auto next_cursor = cursor_on_line(buffer.size() - i + 1);
line.set_length(columns, next_line, next_cursor ?: cursor_on_line(buffer.size() - i), !!next_cursor);
line.rewrap(columns, next_line, next_cursor ?: cursor_on_line(buffer.size() - i), !!next_cursor);
}
} else {
for (size_t i = 0; i < buffer.size(); ++i) {
auto is_at_seam = i + 1 == buffer.size();
auto next_line = is_at_seam ? nullptr : &buffer[i + 1];
auto next_cursor = cursor_on_line(i + 1);
buffer[i].set_length(columns, next_line, next_cursor ?: cursor_on_line(i), !!next_cursor);
buffer[i].rewrap(columns, next_line, next_cursor ?: cursor_on_line(i), !!next_cursor);
}
}
@ -1478,7 +1478,7 @@ void Terminal::set_size(u16 columns, u16 rows)
auto next_line = is_at_seam ? nullptr : &buffer[index + 1];
auto& line = buffer[index];
auto next_cursor = cursor_on_line(index + 1);
line.set_length(columns, next_line, next_cursor ?: cursor_on_line(index), !!next_cursor);
line.rewrap(columns, next_line, next_cursor ?: cursor_on_line(index), !!next_cursor);
if (line.length() > columns) {
auto current_cursor = cursor_on_line(index);
// Split the line into two (or more)
@ -1486,7 +1486,7 @@ void Terminal::set_size(u16 columns, u16 rows)
++rows_inserted;
buffer.insert(index, make<Line>(0));
VERIFY(buffer[index].length() == 0);
line.set_length(columns, &buffer[index], current_cursor, false);
line.rewrap(columns, &buffer[index], current_cursor, false);
// If we inserted a line and the old cursor was after that line, increment its row
if (!current_cursor && old_cursor.row >= index)
++old_cursor.row;
@ -1499,6 +1499,9 @@ void Terminal::set_size(u16 columns, u16 rows)
}
}
for (auto& line : buffer)
line.set_length(columns);
return old_cursor;
};