Kernel+LibVT: Fix selection with scrollback wrap-around

If lines are removed from the tail of the scrollback buffer, the
previous line indices will refer to different lines; therefore we need
to offset them.
This commit is contained in:
Daniel Bertalan 2021-06-05 16:46:33 +02:00 committed by Andreas Kling
parent 13991eade7
commit ce9460de59
7 changed files with 23 additions and 10 deletions

View file

@ -353,7 +353,7 @@ void VirtualConsole::terminal_did_resize(u16 columns, u16 rows)
dbgln("VC {}: Resized to {} x {}", index(), columns, rows);
}
void VirtualConsole::terminal_history_changed()
void VirtualConsole::terminal_history_changed(int)
{
// Do nothing, I guess?
}

View file

@ -100,7 +100,7 @@ private:
virtual void set_window_title(const StringView&) override;
virtual void set_window_progress(int, int) override;
virtual void terminal_did_resize(u16 columns, u16 rows) override;
virtual void terminal_history_changed() override;
virtual void terminal_history_changed(int) override;
virtual void emit(const u8*, size_t) override;
virtual void set_cursor_style(VT::CursorStyle) override;

View file

@ -42,6 +42,12 @@ public:
m_end = end;
}
void offset_row(int delta)
{
m_start = Position(m_start.row() + delta, m_start.column());
m_end = Position(m_end.row() + delta, m_end.column());
}
bool operator==(const Range& other) const
{
return m_start == other.m_start && m_end == other.m_end;

View file

@ -39,9 +39,10 @@ void Terminal::clear()
void Terminal::clear_history()
{
dbgln_if(TERMINAL_DEBUG, "Clear history");
auto previous_history_size = m_history.size();
m_history.clear();
m_history_start = 0;
m_client.terminal_history_changed();
m_client.terminal_history_changed(-previous_history_size);
}
#endif
@ -744,8 +745,11 @@ void Terminal::scroll_up(u16 region_top, u16 region_bottom, size_t count)
// NOTE: We have to invalidate the cursor first.
invalidate_cursor();
int history_delta = -count;
bool should_move_to_scrollback = !m_use_alternate_screen_buffer && max_history_size() != 0;
if (should_move_to_scrollback) {
auto remaining_lines = max_history_size() - history_size();
history_delta = (count > remaining_lines) ? remaining_lines - count : 0;
for (size_t i = 0; i < count; ++i)
add_line_to_history(move(active_buffer().ptr_at(region_top + i)));
}
@ -767,8 +771,7 @@ void Terminal::scroll_up(u16 region_top, u16 region_bottom, size_t count)
// The other lines have implicitly been set dirty by being cleared.
for (u16 row = region_top; row <= region_bottom - count; ++row)
active_buffer()[row].set_dirty(true);
if (!m_use_alternate_screen_buffer && max_history_size() != 0)
m_client.terminal_history_changed();
m_client.terminal_history_changed(history_delta);
}
// Insert `count` blank lines at the top of the region. Text moves down. Does not affect the scrollback buffer.

View file

@ -45,7 +45,7 @@ public:
virtual void set_window_title(const StringView&) = 0;
virtual void set_window_progress(int value, int max) = 0;
virtual void terminal_did_resize(u16 columns, u16 rows) = 0;
virtual void terminal_history_changed() = 0;
virtual void terminal_history_changed(int delta) = 0;
virtual void emit(const u8*, size_t) = 0;
virtual void set_cursor_style(CursorStyle) = 0;
};
@ -141,10 +141,11 @@ public:
void set_max_history_size(size_t value)
{
if (value == 0) {
auto previous_size = m_history.size();
m_max_history_lines = 0;
m_history_start = 0;
m_history.clear();
m_client.terminal_history_changed();
m_client.terminal_history_changed(-previous_size);
return;
}
@ -158,7 +159,7 @@ public:
}
m_history = move(new_history);
m_history_start = 0;
m_client.terminal_history_changed();
m_client.terminal_history_changed(value - existing_line_count);
}
m_max_history_lines = value;
}

View file

@ -947,13 +947,16 @@ int TerminalWidget::last_selection_column_on_row(int row) const
return row == normalized_selection_end.row() || m_rectangle_selection ? normalized_selection_end.column() : m_terminal.columns() - 1;
}
void TerminalWidget::terminal_history_changed()
void TerminalWidget::terminal_history_changed(int delta)
{
bool was_max = m_scrollbar->value() == m_scrollbar->max();
m_scrollbar->set_max(m_terminal.history_size());
if (was_max)
m_scrollbar->set_value(m_scrollbar->max());
m_scrollbar->update();
// If the history buffer wrapped around, the selection needs to be offset accordingly.
if (m_selection.is_valid() && delta < 0)
m_selection.offset_row(delta);
}
void TerminalWidget::terminal_did_resize(u16 columns, u16 rows)

View file

@ -119,7 +119,7 @@ private:
virtual void set_window_title(const StringView&) override;
virtual void set_window_progress(int value, int max) override;
virtual void terminal_did_resize(u16 columns, u16 rows) override;
virtual void terminal_history_changed() override;
virtual void terminal_history_changed(int delta) override;
virtual void emit(const u8*, size_t) override;
virtual void set_cursor_style(CursorStyle) override;