diff --git a/Kernel/TTY/VirtualConsole.cpp b/Kernel/TTY/VirtualConsole.cpp index 36d027a33c..8acc248f9f 100644 --- a/Kernel/TTY/VirtualConsole.cpp +++ b/Kernel/TTY/VirtualConsole.cpp @@ -81,6 +81,11 @@ void ConsoleImpl::put_character_at(unsigned row, unsigned column, u32 ch) m_last_code_point = ch; } +void ConsoleImpl::clear_in_line(u16 row, u16 first_column, u16 last_column) +{ + m_client.clear_in_line(row, first_column, last_column); +} + void ConsoleImpl::ICH(Parameters) { // FIXME: Implement this @@ -420,13 +425,14 @@ void VirtualConsole::scroll_down(u16 region_top, u16 region_bottom, size_t count m_lines[row].dirty = true; } -void VirtualConsole::clear_line(size_t y_index) +void VirtualConsole::clear_in_line(u16 row, u16 first_column, u16 last_column) { - m_lines[y_index].dirty = true; - for (size_t x = 0; x < columns(); x++) { - auto& cell = cell_at(x, y_index); - cell.clear(); - } + VERIFY(row < rows()); + VERIFY(first_column <= last_column); + VERIFY(last_column < columns()); + m_lines[row].dirty = true; + for (size_t x = first_column; x <= last_column; x++) + cell_at(x, row).clear(); } void VirtualConsole::put_character_at(unsigned row, unsigned column, u32 code_point, const VT::Attribute& attribute) diff --git a/Kernel/TTY/VirtualConsole.h b/Kernel/TTY/VirtualConsole.h index 6442998bc3..a25c5a3731 100644 --- a/Kernel/TTY/VirtualConsole.h +++ b/Kernel/TTY/VirtualConsole.h @@ -40,6 +40,7 @@ private: 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 clear_in_line(u16 row, u16 first_column, u16 last_column) override; virtual void ICH(Parameters) override; virtual void DCH(Parameters) override; @@ -137,7 +138,11 @@ private: 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 clear_line(size_t index) + { + clear_in_line(index, 0, m_console_impl.columns() - 1); + } + void clear_in_line(u16 row, u16 first_column, u16 last_column); void put_character_at(unsigned row, unsigned column, u32 ch, const VT::Attribute&); OwnPtr m_cells; diff --git a/Userland/Libraries/LibVT/Attribute.h b/Userland/Libraries/LibVT/Attribute.h index f63f0aab20..1bc2c8c51e 100644 --- a/Userland/Libraries/LibVT/Attribute.h +++ b/Userland/Libraries/LibVT/Attribute.h @@ -15,8 +15,6 @@ namespace VT { struct Attribute { - Attribute() { reset(); } - static constexpr Color default_foreground_color = Color::named(Color::ANSIColor::DefaultForeground); static constexpr Color default_background_color = Color::named(Color::ANSIColor::DefaultBackground); @@ -25,12 +23,17 @@ struct Attribute { foreground_color = default_foreground_color; background_color = default_background_color; flags = Flags::NoAttributes; +#ifndef KERNEL + href = {}; + href_id = {}; +#endif } + Color foreground_color { default_foreground_color }; Color background_color { default_background_color }; - Color effective_background_color() const { return flags & Negative ? foreground_color : background_color; } - Color effective_foreground_color() const { return flags & Negative ? background_color : foreground_color; } + constexpr Color effective_background_color() const { return flags & Negative ? foreground_color : background_color; } + constexpr Color effective_foreground_color() const { return flags & Negative ? background_color : foreground_color; } #ifndef KERNEL String href; @@ -47,17 +50,17 @@ struct Attribute { Touched = 0x20, }; - bool is_untouched() const { return !(flags & Touched); } + constexpr bool is_untouched() const { return !(flags & Touched); } // TODO: it would be really nice if we had a helper for enums that // exposed bit ops for class enums... - u8 flags = Flags::NoAttributes; + u8 flags { Flags::NoAttributes }; - bool operator==(const Attribute& other) const + constexpr bool operator==(const Attribute& other) const { return foreground_color == other.foreground_color && background_color == other.background_color && flags == other.flags; } - bool operator!=(const Attribute& other) const + constexpr bool operator!=(const Attribute& other) const { return !(*this == other); } diff --git a/Userland/Libraries/LibVT/Line.cpp b/Userland/Libraries/LibVT/Line.cpp index d807877f17..30b971b9d9 100644 --- a/Userland/Libraries/LibVT/Line.cpp +++ b/Userland/Libraries/LibVT/Line.cpp @@ -25,15 +25,12 @@ void Line::set_length(size_t new_length) m_cells.resize(new_length); } -void Line::clear(const Attribute& attribute) +void Line::clear_range(size_t first_column, size_t last_column, const Attribute& attribute) { - if (m_dirty) { - for (auto& cell : m_cells) { - cell = Cell { .code_point = ' ', .attribute = attribute }; - } - return; - } - for (auto& cell : m_cells) { + VERIFY(first_column <= last_column); + VERIFY(last_column < m_cells.size()); + for (size_t i = first_column; i <= last_column; ++i) { + auto& cell = m_cells[i]; if (!m_dirty) m_dirty = cell.code_point != ' ' || cell.attribute != attribute; cell = Cell { .code_point = ' ', .attribute = attribute }; diff --git a/Userland/Libraries/LibVT/Line.h b/Userland/Libraries/LibVT/Line.h index ecc9fdc19b..1bc21b5bef 100644 --- a/Userland/Libraries/LibVT/Line.h +++ b/Userland/Libraries/LibVT/Line.h @@ -33,7 +33,11 @@ public: Cell& cell_at(size_t index) { return m_cells[index]; } const Cell& cell_at(size_t index) const { return m_cells[index]; } - void clear(const Attribute&); + void clear(const Attribute& attribute = Attribute()) + { + clear_range(0, m_cells.size() - 1, attribute); + } + void clear_range(size_t first_column, size_t last_column, const Attribute& attribute = Attribute()); bool has_only_one_background_color() const; size_t length() const { return m_cells.size(); } diff --git a/Userland/Libraries/LibVT/Terminal.cpp b/Userland/Libraries/LibVT/Terminal.cpp index 8a965ed7f5..5641e44cfc 100644 --- a/Userland/Libraries/LibVT/Terminal.cpp +++ b/Userland/Libraries/LibVT/Terminal.cpp @@ -32,7 +32,7 @@ void Terminal::clear() { dbgln_if(TERMINAL_DEBUG, "Clear the entire screen"); for (size_t i = 0; i < rows(); ++i) - active_buffer()[i].clear(Attribute()); + active_buffer()[i].clear(); set_cursor(0, 0); } @@ -559,9 +559,7 @@ void Terminal::ECH(Parameters params) // Clear num characters from the right of the cursor. auto clear_end = min(m_columns, cursor_column() + num - 1); dbgln_if(TERMINAL_DEBUG, "Erase characters {}-{} on line {}", cursor_column(), clear_end, cursor_row()); - for (unsigned i = cursor_column(); i <= clear_end; ++i) { - put_character_at(cursor_row(), i, ' '); - } + clear_in_line(cursor_row(), cursor_column(), clear_end); } void Terminal::EL(Parameters params) @@ -572,21 +570,15 @@ void Terminal::EL(Parameters params) switch (mode) { case 0: dbgln_if(TERMINAL_DEBUG, "Clear line {} from cursor column ({}) to the end", cursor_row(), cursor_column()); - for (int i = cursor_column(); i < m_columns; ++i) { - put_character_at(cursor_row(), i, ' '); - } + clear_in_line(cursor_row(), cursor_column(), m_columns - 1); break; case 1: dbgln_if(TERMINAL_DEBUG, "Clear line {} from the start to cursor column ({})", cursor_row(), cursor_column()); - for (int i = 0; i <= cursor_column(); ++i) { - put_character_at(cursor_row(), i, ' '); - } + clear_in_line(cursor_row(), 0, cursor_column()); break; case 2: dbgln_if(TERMINAL_DEBUG, "Clear line {} completely", cursor_row()); - for (int i = 0; i < m_columns; ++i) { - put_character_at(cursor_row(), i, ' '); - } + clear_in_line(cursor_row(), 0, m_columns - 1); break; default: unimplemented_csi_sequence(params, {}, 'K'); @@ -602,23 +594,15 @@ void Terminal::ED(Parameters params) switch (mode) { case 0: dbgln_if(TERMINAL_DEBUG, "Clear from cursor ({},{}) to end of screen", cursor_row(), cursor_column()); - for (int i = cursor_column(); i < m_columns; ++i) - put_character_at(cursor_row(), i, ' '); - for (int row = cursor_row() + 1; row < m_rows; ++row) { - for (int column = 0; column < m_columns; ++column) { - put_character_at(row, column, ' '); - } - } + clear_in_line(cursor_row(), cursor_column(), m_columns - 1); + for (int row = cursor_row() + 1; row < m_rows; ++row) + clear_in_line(row, 0, m_columns - 1); break; case 1: dbgln_if(TERMINAL_DEBUG, "Clear from beginning of screen to cursor ({},{})", cursor_row(), cursor_column()); - for (int i = cursor_column(); i >= 0; --i) - put_character_at(cursor_row(), i, ' '); - for (int row = cursor_row() - 1; row >= 0; --row) { - for (int column = 0; column < m_columns; ++column) { - put_character_at(row, column, ' '); - } - } + clear_in_line(cursor_row(), 0, cursor_column()); + for (int row = cursor_row() - 1; row >= 0; --row) + clear_in_line(row, 0, m_columns - 1); break; case 2: clear(); @@ -789,7 +773,7 @@ void Terminal::scroll_up(u16 region_top, u16 region_bottom, size_t count) } else { // The new lines haven't been moved and we don't want to leak memory. for (u16 row = region_bottom + 1 - count; row <= region_bottom; ++row) - active_buffer()[row].clear(Attribute()); + active_buffer()[row].clear(); } // Set dirty flag on swapped lines. // The other lines have implicitly been set dirty by being cleared. @@ -816,7 +800,7 @@ void Terminal::scroll_down(u16 region_top, u16 region_bottom, size_t count) swap(active_buffer().ptr_at(row), active_buffer().ptr_at(row - count)); // Clear the 'new' lines at the top. for (u16 row = region_top; row < region_top + count; ++row) - active_buffer()[row].clear(Attribute()); + active_buffer()[row].clear(); // Set dirty flag on swapped lines. // The other lines have implicitly been set dirty by being cleared. for (u16 row = region_top + count; row <= region_bottom; ++row) @@ -835,6 +819,12 @@ void Terminal::put_character_at(unsigned row, unsigned column, u32 code_point) m_last_code_point = code_point; } + +void Terminal::clear_in_line(u16 row, u16 first_column, u16 last_column) +{ + VERIFY(row < rows()); + active_buffer()[row].clear_range(first_column, last_column); +} #endif void Terminal::set_cursor(unsigned a_row, unsigned a_column, bool skip_debug) diff --git a/Userland/Libraries/LibVT/Terminal.h b/Userland/Libraries/LibVT/Terminal.h index 8a52aa81ce..def255546e 100644 --- a/Userland/Libraries/LibVT/Terminal.h +++ b/Userland/Libraries/LibVT/Terminal.h @@ -217,10 +217,12 @@ protected: void scroll_up(u16 region_top, u16 region_bottom, size_t count); void scroll_down(u16 region_top, u16 region_bottom, size_t count); void put_character_at(unsigned row, unsigned column, u32 ch); + void clear_in_line(u16 row, u16 first_column, u16 last_column); #else virtual void scroll_up(u16 region_top, u16 region_bottom, size_t count) = 0; virtual void scroll_down(u16 region_top, u16 region_bottom, size_t count) = 0; virtual void put_character_at(unsigned row, unsigned column, u32 ch) = 0; + virtual void clear_in_line(u16 row, u16 first_column, u16 last_column) = 0; #endif void unimplemented_control_code(u8);