diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2021-06-02 15:36:31 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-10 17:18:02 +0200 |
commit | ae6bdc4e29a6e38d0305d620b2301de6328dde0e (patch) | |
tree | af6f77e57e6edca30af3539e64c5883ee66bd529 /Kernel | |
parent | 5f927904899b5ef6391d702979ef1e6048cecdf0 (diff) | |
download | serenity-ae6bdc4e29a6e38d0305d620b2301de6328dde0e.zip |
LibVT+Kernel: Clean up scroll API
This commit cleans up some of the `#ifdef`-ed code smell in
`Terminal`, by extending the scroll APIs to take a range of lines as a
parameter. This makes it possible to use the same code for `IL`/`DL` as
for scrolling.
Note that the current scrolling implementation is very naive, and does
many insertions/deletions in the middle of arrays, whereas swaps should
be enough. This optimization will come in a later commit.
The `linefeed` override was removed from `VirtualConsole`. Previously,
it exhibited incorrect behavior by moving to column 0. Now that we use
the method defined in `Terminal`, code which relied on this behavior
stopped working. We go instead go through the TTY layer which handles
the various output flags. Passing the input character-by-character
seems a bit excessive, so a fix for it will come in another PR.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/TTY/TTY.h | 5 | ||||
-rw-r--r-- | Kernel/TTY/VirtualConsole.cpp | 82 | ||||
-rw-r--r-- | Kernel/TTY/VirtualConsole.h | 13 |
3 files changed, 51 insertions, 49 deletions
diff --git a/Kernel/TTY/TTY.h b/Kernel/TTY/TTY.h index 9e5ee61bfd..7813b0abf9 100644 --- a/Kernel/TTY/TTY.h +++ b/Kernel/TTY/TTY.h @@ -58,7 +58,7 @@ protected: TTY(unsigned major, unsigned minor); void emit(u8, bool do_evaluate_block_conditions = false); - virtual void echo(u8) = 0; + void echo_with_processing(u8); bool can_do_backspace() const; void do_backspace(); @@ -80,7 +80,8 @@ protected: private: // ^CharacterDevice virtual bool is_tty() const final override { return true; } - inline void echo_with_processing(u8); + + virtual void echo(u8) = 0; template<typename Functor> void process_output(u8, Functor put_char); diff --git a/Kernel/TTY/VirtualConsole.cpp b/Kernel/TTY/VirtualConsole.cpp index ceef83cd0a..2684783ab1 100644 --- a/Kernel/TTY/VirtualConsole.cpp +++ b/Kernel/TTY/VirtualConsole.cpp @@ -48,6 +48,9 @@ void ConsoleImpl::set_size(u16 determined_columns, u16 determined_rows) m_columns = determined_columns; m_rows = determined_rows; + m_scroll_region_top = 0; + m_scroll_region_bottom = determined_rows - 1; + m_current_state.cursor.clamp(rows() - 1, columns() - 1); m_normal_saved_state.cursor.clamp(rows() - 1, columns() - 1); m_alternate_saved_state.cursor.clamp(rows() - 1, columns() - 1); @@ -59,52 +62,34 @@ void ConsoleImpl::set_size(u16 determined_columns, u16 determined_rows) m_horizontal_tabs[determined_columns - 1] = 1; m_client.terminal_did_resize(m_columns, m_rows); } -void ConsoleImpl::scroll_up() +void ConsoleImpl::scroll_up(u16 region_top, u16 region_bottom, size_t count) { // NOTE: We have to invalidate the cursor first. m_client.invalidate_cursor(cursor_row()); - m_client.scroll_up(); -} -void ConsoleImpl::scroll_down() -{ + m_client.scroll_up(region_top, region_bottom, count); } -void ConsoleImpl::linefeed() + +void ConsoleImpl::scroll_down(u16 region_top, u16 region_bottom, size_t count) { - u16 new_row = cursor_row(); - u16 max_row = rows() - 1; - if (new_row == max_row) { - // NOTE: We have to invalidate the cursor first. - m_client.invalidate_cursor(new_row); - m_client.scroll_up(); - } else { - ++new_row; - } - set_cursor(new_row, 0); + m_client.invalidate_cursor(cursor_row()); + m_client.scroll_down(region_top, region_bottom, count); } + void ConsoleImpl::put_character_at(unsigned row, unsigned column, u32 ch) { m_client.put_character_at(row, column, ch, m_current_state.attribute); m_last_code_point = ch; } -void ConsoleImpl::set_window_title(const String&) -{ -} + void ConsoleImpl::ICH(Parameters) { // FIXME: Implement this } -void ConsoleImpl::IL(Parameters) -{ - // FIXME: Implement this -} + void ConsoleImpl::DCH(Parameters) { // FIXME: Implement this } -void ConsoleImpl::DL(Parameters) -{ - // FIXME: Implement this -} void VirtualConsole::set_graphical(bool graphical) { @@ -196,8 +181,11 @@ UNMAP_AFTER_INIT VirtualConsole::VirtualConsole(const unsigned index, const Circ , m_console_impl(*this) { initialize(); - for (auto& ch : log) { - echo(ch); + // HACK: We have to go through the TTY layer for correct newline handling. + // It would be nice to not have to make all these calls, but we can't get the underlying data pointer + // and head index. If we did that, we could reduce this to at most 2 calls. + for (auto ch : log) { + emit_char(ch); } } @@ -305,7 +293,9 @@ void VirtualConsole::set_active(bool active) void VirtualConsole::emit_char(char ch) { - echo(ch); + // Since we are standards-compliant by not moving to column 1 on '\n', we have to add an extra carriage return to + // do newlines properly. The `TTY` layer handles adding it. + echo_with_processing(static_cast<u8>(ch)); } void VirtualConsole::flush_dirty_lines() @@ -381,10 +371,7 @@ String VirtualConsole::device_name() const void VirtualConsole::echo(u8 ch) { - if (should_echo_input()) { - auto buffer = UserOrKernelBuffer::for_kernel_buffer(&ch); - on_tty_write(buffer, 1); - } + m_console_impl.on_input(ch); } VirtualConsole::Cell& VirtualConsole::cell_at(size_t x, size_t y) @@ -407,11 +394,30 @@ void VirtualConsole::clear() m_console_impl.set_cursor(0, 0); } -void VirtualConsole::scroll_up() +void VirtualConsole::scroll_up(u16 region_top, u16 region_bottom, size_t count) { - memmove(m_cells->vaddr().as_ptr(), m_cells->vaddr().offset(columns() * sizeof(Cell)).as_ptr(), ((rows() - 1) * columns() * sizeof(Cell))); - clear_line(rows() - 1); - m_console_impl.m_need_full_flush = true; + VERIFY(region_top <= region_bottom); + size_t region_size = region_bottom - region_top + 1; + count = min(count, region_size); + size_t line_bytes = (columns() * sizeof(Cell)); + memmove(m_cells->vaddr().offset(line_bytes * region_top).as_ptr(), m_cells->vaddr().offset(line_bytes * (region_top + count)).as_ptr(), line_bytes * (region_size - count)); + for (size_t i = 0; i < count; ++i) + clear_line(region_bottom - i); + for (u16 row = region_top; row <= region_bottom; ++row) + m_lines[row].dirty = true; +} + +void VirtualConsole::scroll_down(u16 region_top, u16 region_bottom, size_t count) +{ + VERIFY(region_top <= region_bottom); + size_t region_size = region_bottom - region_top + 1; + count = min(count, region_size); + size_t line_bytes = (columns() * sizeof(Cell)); + memmove(m_cells->vaddr().offset(line_bytes * (region_top + count)).as_ptr(), m_cells->vaddr().offset(line_bytes * region_top).as_ptr(), line_bytes * (region_size - count)); + for (size_t i = 0; i < count; ++i) + clear_line(region_top + i); + for (u16 row = region_top; row <= region_bottom; ++row) + m_lines[row].dirty = true; } void VirtualConsole::clear_line(size_t y_index) diff --git a/Kernel/TTY/VirtualConsole.h b/Kernel/TTY/VirtualConsole.h index fe0b62a23c..69f6eecf90 100644 --- a/Kernel/TTY/VirtualConsole.h +++ b/Kernel/TTY/VirtualConsole.h @@ -37,17 +37,12 @@ private: virtual void clear() override; virtual void clear_including_history() override; - virtual void scroll_up() override; - virtual void scroll_down() override; - virtual void linefeed() override; + virtual void scroll_up(u16 region_top, u16 region_bottom, size_t count) override; + virtual void scroll_down(u16 region_top, u16 region_bottom, size_t count) override; virtual void put_character_at(unsigned row, unsigned column, u32 ch) override; - virtual void set_window_title(const String&) override; virtual void ICH(Parameters) override; - - virtual void IL(Parameters) override; virtual void DCH(Parameters) override; - virtual void DL(Parameters) override; }; class VirtualConsole final : public TTY @@ -140,8 +135,8 @@ private: void on_code_point(u32); - void scroll_down(); - void scroll_up(); + void scroll_down(u16 region_top, u16 region_bottom, size_t count); + void scroll_up(u16 region_top, u16 region_bottom, size_t count); void clear_line(size_t index); void put_character_at(unsigned row, unsigned column, u32 ch, const VT::Attribute&); |