diff --git a/Kernel/Devices/GPU/Console/Console.h b/Kernel/Devices/GPU/Console/Console.h index e0c355a716..9b036d32e5 100644 --- a/Kernel/Devices/GPU/Console/Console.h +++ b/Kernel/Devices/GPU/Console/Console.h @@ -63,6 +63,8 @@ protected: virtual void hide_cursor() = 0; virtual void show_cursor() = 0; + virtual void scroll_up() = 0; + Console(size_t width, size_t height) : m_width(width) , m_height(height) diff --git a/Kernel/Devices/GPU/Console/GenericFramebufferConsole.cpp b/Kernel/Devices/GPU/Console/GenericFramebufferConsole.cpp index 78dd812f50..afe3efd24d 100644 --- a/Kernel/Devices/GPU/Console/GenericFramebufferConsole.cpp +++ b/Kernel/Devices/GPU/Console/GenericFramebufferConsole.cpp @@ -288,6 +288,22 @@ void GenericFramebufferConsoleImpl::disable() m_enabled.store(false); } +void GenericFramebufferConsoleImpl::scroll_up() +{ + for (size_t row = 1; row < max_row(); row++) { + auto prev_line = framebuffer_offset(0, row - 1); + auto line = framebuffer_offset(0, row); + for (size_t glyph_row = 0; glyph_row < m_glyph_rows; glyph_row++) { + memmove(prev_line.pixels, line.pixels, width() * sizeof(*line.pixels)); + prev_line.bytes += framebuffer_pitch(); + line.bytes += framebuffer_pitch(); + } + } + + for (size_t column = 0; column < max_column(); column++) + clear_glyph(column, m_y); +} + void GenericFramebufferConsoleImpl::write(size_t x, size_t y, char ch, Color background, Color foreground, bool critical) { if (!m_enabled.load()) @@ -298,15 +314,19 @@ void GenericFramebufferConsoleImpl::write(size_t x, size_t y, char ch, Color bac if (critical && (ch == '\r' || ch == '\n')) { m_x = 0; m_y += 1; - if (m_y >= max_row()) - m_y = 0; + if (m_y >= max_row()) { + m_y = max_row() - 1; + scroll_up(); + } return; } + if ((int)ch < 0x20 || (int)ch == 0x7f) { // FIXME: There's no point in printing empty glyphs... // Maybe try to add these special glyphs and print them. return; } + clear_glyph(x, y); auto bitmap = font_cathode_8x16[(int)ch]; auto offset_in_framebuffer = framebuffer_offset(x, y); @@ -322,12 +342,19 @@ void GenericFramebufferConsoleImpl::write(size_t x, size_t y, char ch, Color bac offset_in_framebuffer.bytes += framebuffer_pitch(); } flush_glyph(x, y); + m_x = x + 1; if (m_x >= max_column()) { m_x = 0; m_y = y + 1; - if (m_y >= max_row()) - m_y = 0; + if (m_y >= max_row()) { + if (critical) { + m_y = max_row() - 1; + scroll_up(); + } else { + m_y = 0; + } + } } } diff --git a/Kernel/Devices/GPU/Console/GenericFramebufferConsole.h b/Kernel/Devices/GPU/Console/GenericFramebufferConsole.h index 1065597b9a..bb3cbda7a9 100644 --- a/Kernel/Devices/GPU/Console/GenericFramebufferConsole.h +++ b/Kernel/Devices/GPU/Console/GenericFramebufferConsole.h @@ -39,6 +39,8 @@ protected: virtual void hide_cursor() override; virtual void show_cursor() override; + virtual void scroll_up() override; + GenericFramebufferConsoleImpl(size_t width, size_t height, size_t pitch) : Console(width, height) , m_pitch(pitch) diff --git a/Kernel/Devices/GPU/Console/VGATextModeConsole.cpp b/Kernel/Devices/GPU/Console/VGATextModeConsole.cpp index 24c319a3f4..88505443ac 100644 --- a/Kernel/Devices/GPU/Console/VGATextModeConsole.cpp +++ b/Kernel/Devices/GPU/Console/VGATextModeConsole.cpp @@ -112,6 +112,11 @@ void VGATextModeConsole::clear(size_t x, size_t y, size_t length) buf[index] = 0x0720; } } + +void VGATextModeConsole::scroll_up() +{ +} + void VGATextModeConsole::write(size_t x, size_t y, char ch, bool critical) { write(x, y, ch, m_default_background_color, m_default_foreground_color, critical); diff --git a/Kernel/Devices/GPU/Console/VGATextModeConsole.h b/Kernel/Devices/GPU/Console/VGATextModeConsole.h index 2c1533418d..543a5c29a0 100644 --- a/Kernel/Devices/GPU/Console/VGATextModeConsole.h +++ b/Kernel/Devices/GPU/Console/VGATextModeConsole.h @@ -34,6 +34,8 @@ private: virtual void hide_cursor() override; virtual void show_cursor() override; + virtual void scroll_up() override; + void clear_vga_row(u16 row); explicit VGATextModeConsole(NonnullOwnPtr);