summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2021-06-05 16:46:33 +0200
committerAndreas Kling <kling@serenityos.org>2021-06-10 17:18:02 +0200
commitce9460de59e31ede6793432a86fa20f83ee6c753 (patch)
treebd3e66aa44253ab7c2cf3f9e10ed7fe4bc3faefb /Userland
parent13991eade72ef6f2c488f40e9cb1304f0133ed57 (diff)
downloadserenity-ce9460de59e31ede6793432a86fa20f83ee6c753.zip
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.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibVT/Range.h6
-rw-r--r--Userland/Libraries/LibVT/Terminal.cpp9
-rw-r--r--Userland/Libraries/LibVT/Terminal.h7
-rw-r--r--Userland/Libraries/LibVT/TerminalWidget.cpp5
-rw-r--r--Userland/Libraries/LibVT/TerminalWidget.h2
5 files changed, 21 insertions, 8 deletions
diff --git a/Userland/Libraries/LibVT/Range.h b/Userland/Libraries/LibVT/Range.h
index 2efcc4af3c..dcb51cb85f 100644
--- a/Userland/Libraries/LibVT/Range.h
+++ b/Userland/Libraries/LibVT/Range.h
@@ -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;
diff --git a/Userland/Libraries/LibVT/Terminal.cpp b/Userland/Libraries/LibVT/Terminal.cpp
index 7009a79db5..4d04d34176 100644
--- a/Userland/Libraries/LibVT/Terminal.cpp
+++ b/Userland/Libraries/LibVT/Terminal.cpp
@@ -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.
diff --git a/Userland/Libraries/LibVT/Terminal.h b/Userland/Libraries/LibVT/Terminal.h
index 3087a05c4f..160bf08e40 100644
--- a/Userland/Libraries/LibVT/Terminal.h
+++ b/Userland/Libraries/LibVT/Terminal.h
@@ -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;
}
diff --git a/Userland/Libraries/LibVT/TerminalWidget.cpp b/Userland/Libraries/LibVT/TerminalWidget.cpp
index aeb4996218..be866a0e10 100644
--- a/Userland/Libraries/LibVT/TerminalWidget.cpp
+++ b/Userland/Libraries/LibVT/TerminalWidget.cpp
@@ -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)
diff --git a/Userland/Libraries/LibVT/TerminalWidget.h b/Userland/Libraries/LibVT/TerminalWidget.h
index 73ef382d69..0935f98cf7 100644
--- a/Userland/Libraries/LibVT/TerminalWidget.h
+++ b/Userland/Libraries/LibVT/TerminalWidget.h
@@ -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;