mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:07:47 +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
3 changed files with 36 additions and 21 deletions
|
@ -10,43 +10,52 @@ namespace VT {
|
||||||
|
|
||||||
Line::Line(size_t length)
|
Line::Line(size_t length)
|
||||||
{
|
{
|
||||||
set_length(length, nullptr, nullptr);
|
set_length(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
Line::~Line()
|
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();
|
size_t old_length = length();
|
||||||
if (old_length == new_length)
|
if (old_length == new_length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Drop the empty cells
|
// 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());
|
m_cells.remove(m_terminated_at.value(), m_cells.size() - m_terminated_at.value());
|
||||||
|
|
||||||
if (!next_line)
|
if (!next_line)
|
||||||
return m_cells.resize(new_length);
|
return m_cells.resize(new_length);
|
||||||
|
|
||||||
if (old_length < 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
|
else
|
||||||
push_cells_into_next_line(old_length, new_length, next_line, cursor_is_on_next_line, cursor);
|
push_cells_into_next_line(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))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// 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_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)
|
if (!cells_to_push_into_next_line)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto preserved_cells = length() - cells_to_push_into_next_line;
|
|
||||||
if (next_line->m_terminated_at.has_value())
|
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;
|
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;
|
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
|
// Take as many cells as would fit from the next line
|
||||||
if (m_terminated_at.has_value())
|
if (m_terminated_at.has_value())
|
||||||
return;
|
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;
|
auto clear_next_line = false;
|
||||||
if (next_line->m_terminated_at.has_value()) {
|
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) {
|
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();
|
next_line->m_terminated_at.clear();
|
||||||
clear_next_line = true;
|
clear_next_line = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -53,7 +53,8 @@ public:
|
||||||
{
|
{
|
||||||
return m_cells.size();
|
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
|
u32 code_point(size_t index) const
|
||||||
{
|
{
|
||||||
|
@ -78,8 +79,8 @@ public:
|
||||||
void set_terminated(u16 column) { m_terminated_at = column; }
|
void set_terminated(u16 column) { m_terminated_at = column; }
|
||||||
|
|
||||||
private:
|
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 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 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 new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
|
||||||
|
|
||||||
Vector<Cell> m_cells;
|
Vector<Cell> m_cells;
|
||||||
bool m_dirty { false };
|
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 next_line = is_at_seam ? nullptr : &buffer[buffer.size() - i + 1];
|
||||||
auto& line = buffer[buffer.size() - i];
|
auto& line = buffer[buffer.size() - i];
|
||||||
auto next_cursor = cursor_on_line(buffer.size() - i + 1);
|
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 {
|
} else {
|
||||||
for (size_t i = 0; i < buffer.size(); ++i) {
|
for (size_t i = 0; i < buffer.size(); ++i) {
|
||||||
auto is_at_seam = i + 1 == buffer.size();
|
auto is_at_seam = i + 1 == buffer.size();
|
||||||
auto next_line = is_at_seam ? nullptr : &buffer[i + 1];
|
auto next_line = is_at_seam ? nullptr : &buffer[i + 1];
|
||||||
auto next_cursor = cursor_on_line(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 next_line = is_at_seam ? nullptr : &buffer[index + 1];
|
||||||
auto& line = buffer[index];
|
auto& line = buffer[index];
|
||||||
auto next_cursor = cursor_on_line(index + 1);
|
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) {
|
if (line.length() > columns) {
|
||||||
auto current_cursor = cursor_on_line(index);
|
auto current_cursor = cursor_on_line(index);
|
||||||
// Split the line into two (or more)
|
// Split the line into two (or more)
|
||||||
|
@ -1486,7 +1486,7 @@ void Terminal::set_size(u16 columns, u16 rows)
|
||||||
++rows_inserted;
|
++rows_inserted;
|
||||||
buffer.insert(index, make<Line>(0));
|
buffer.insert(index, make<Line>(0));
|
||||||
VERIFY(buffer[index].length() == 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 we inserted a line and the old cursor was after that line, increment its row
|
||||||
if (!current_cursor && old_cursor.row >= index)
|
if (!current_cursor && old_cursor.row >= index)
|
||||||
++old_cursor.row;
|
++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;
|
return old_cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue