mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 17:40:27 +00:00
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:
parent
ffb118265b
commit
7c88caf99f
Notes:
sideshowbarker
2024-07-18 11:34:19 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/7c88caf99f5 Pull-request: https://github.com/SerenityOS/serenity/pull/8231 Issue: https://github.com/SerenityOS/serenity/issues/8227
3 changed files with 36 additions and 21 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue