diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index d1cd0f35..0f4831dd 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -38,6 +38,7 @@ namespace Kernel void putcodepoint(uint32_t codepoint); void putchar_at(uint32_t codepoint, uint32_t x, uint32_t y); void render_from_buffer(uint32_t x, uint32_t y); + void scroll_if_needed(); private: enum class State diff --git a/kernel/kernel/Terminal/FramebufferTerminal.cpp b/kernel/kernel/Terminal/FramebufferTerminal.cpp index 25ae047a..eb0d5e13 100644 --- a/kernel/kernel/Terminal/FramebufferTerminal.cpp +++ b/kernel/kernel/Terminal/FramebufferTerminal.cpp @@ -104,6 +104,11 @@ namespace Kernel void FramebufferTerminalDriver::show_cursor(bool use_data) { + // NOTE: cursor is allowed to be on width as scrolling only + // happens after character gets printed to next line + if (m_cursor_x == width()) + return; + if (!use_data) read_cursor(); diff --git a/kernel/kernel/Terminal/TextModeTerminal.cpp b/kernel/kernel/Terminal/TextModeTerminal.cpp index a5830215..94b6c3d6 100644 --- a/kernel/kernel/Terminal/TextModeTerminal.cpp +++ b/kernel/kernel/Terminal/TextModeTerminal.cpp @@ -140,6 +140,10 @@ namespace Kernel void TextModeTerminalDriver::set_cursor_position(uint32_t x, uint32_t y) { + // NOTE: cursor is allowed to be on width as scrolling only + // happens after character gets printed to next line + if (x == m_width) + return; const uint16_t pos = y * m_width + x; IO::outb(0x3D4, 0x0F); IO::outb(0x3D5, pos & 0xFF); diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index 5aa6b9a5..d52b97fa 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -385,6 +385,29 @@ namespace Kernel m_terminal_driver->putchar_at(codepoint, x, y, cell.foreground, cell.background); } + void VirtualTTY::scroll_if_needed() + { + while (m_row >= m_height) + { + memmove(m_buffer, m_buffer + m_width, m_width * (m_height - 1) * sizeof(Cell)); + + // Clear last line in buffer + for (uint32_t x = 0; x < m_width; x++) + m_buffer[(m_height - 1) * m_width + x] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' }; + + if (!m_terminal_driver->scroll(m_background)) + { + // No fast scrolling, render the whole buffer to the screen + for (uint32_t y = 0; y < m_height; y++) + for (uint32_t x = 0; x < m_width; x++) + render_from_buffer(x, y); + } + + m_column = 0; + m_row--; + } + } + void VirtualTTY::putcodepoint(uint32_t codepoint) { ASSERT(m_write_lock.current_processor_has_lock()); @@ -416,37 +439,19 @@ namespace Kernel m_state = State::WaitingAnsiEscape; break; default: + if (m_column >= m_width) + { + m_column = 0; + m_row++; + } + scroll_if_needed(); putchar_at(codepoint, m_column, m_row); m_last_graphic_char = codepoint; m_column++; break; } - if (m_column >= m_width) - { - m_column = 0; - m_row++; - } - - while (m_row >= m_height) - { - memmove(m_buffer, m_buffer + m_width, m_width * (m_height - 1) * sizeof(Cell)); - - // Clear last line in buffer - for (uint32_t x = 0; x < m_width; x++) - m_buffer[(m_height - 1) * m_width + x] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' }; - - if (!m_terminal_driver->scroll(m_background)) - { - // No fast scrolling, render the whole buffer to the screen - for (uint32_t y = 0; y < m_height; y++) - for (uint32_t x = 0; x < m_width; x++) - render_from_buffer(x, y); - } - - m_column = 0; - m_row--; - } + scroll_if_needed(); } void VirtualTTY::putchar_impl(uint8_t ch)