diff --git a/targets/_any/include/os/tty.hpp b/targets/_any/include/os/tty.hpp index 2f0687f..73095c2 100644 --- a/targets/_any/include/os/tty.hpp +++ b/targets/_any/include/os/tty.hpp @@ -34,12 +34,26 @@ struct VgaDoubleColor { VgaColor foreground : 4 = VgaColor::LIGHT_GREY; VgaColor background : 4 = VgaColor::BLACK; + + [[nodiscard]] VgaDoubleColor swapped() const noexcept + { + return VgaDoubleColor{.foreground = background, .background = foreground}; + } +}; + +struct VgaCharacter +{ + char character = '\0'; + VgaDoubleColor color = {}; }; void initialize() noexcept; void setColor(VgaDoubleColor color) noexcept; +const VgaDoubleColor& getColor() noexcept; void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept; +VgaCharacter getEntryAt(size_t posX, size_t posY) noexcept; void putChar(char chr) noexcept; +void putChar(char chr, VgaDoubleColor color) noexcept; void deleteChar() noexcept; void write(const char* data, size_t size) noexcept; void write(const char* data) noexcept; diff --git a/targets/_any/src/os/tty.cpp b/targets/_any/src/os/tty.cpp index bdb6ef7..06a974e 100644 --- a/targets/_any/src/os/tty.cpp +++ b/targets/_any/src/os/tty.cpp @@ -18,7 +18,7 @@ size_t gTerminalWidth = 0; size_t gTerminalHeight = 0; VgaDoubleColor gTerminalColor = VgaDoubleColor(); // uint16_t* gTerminalBuffer = reinterpret_cast(0xB8000); -std::vector gTerminalBuffer; +std::vector gTerminalBuffer; psf::Font gTerminalFont; std::string gReadBuffer; @@ -42,6 +42,10 @@ void newline() else { draw::scrollBy(0, static_cast(gTerminalFont.getGlyphHeight()) + 1); + std::memmove(&gTerminalBuffer[0], &gTerminalBuffer[gTerminalWidth], (gTerminalHeight - 1) * gTerminalWidth * sizeof(VgaCharacter)); + for (std::size_t posX = 0; posX < gTerminalWidth; ++posX) { + putEntryAt('\0', gTerminalColor, posX, gTerminalHeight - 1); + } } } } @@ -56,19 +60,38 @@ void setColor(VgaDoubleColor color) noexcept gTerminalColor = color; } +const VgaDoubleColor& getColor() noexcept +{ + return gTerminalColor; +} + void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept { draw::character( /* posX = */ (gTerminalFont.getGlyphWidth() + 1) * posX, /* posY = */ (gTerminalFont.getGlyphHeight() + 1) * posY, /* font = */ gTerminalFont, - /* chr = */ chr, + /* chr = */ chr ? chr : ' ', /* fgColor = */ draw::VGA_PIXELS[static_cast(color.foreground)], /* bgColor = */ draw::VGA_PIXELS[static_cast(color.background)] ); + gTerminalBuffer[posY * gTerminalHeight + posX] = { + .character = chr, + .color = color + }; +} + +VgaCharacter getEntryAt(size_t posX, size_t posY) noexcept +{ + return gTerminalBuffer[posY * gTerminalHeight + posX]; } void putChar(char chr) noexcept +{ + putChar(chr, gTerminalColor); +} + +void putChar(char chr, VgaDoubleColor color) noexcept { if (chr == '\n') { @@ -76,7 +99,7 @@ void putChar(char chr) noexcept return; } - putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow); + putEntryAt(chr, color, gTerminalColumn, gTerminalRow); if (++gTerminalColumn == gTerminalWidth) { newline(); @@ -107,13 +130,26 @@ void write(const char* data) noexcept write(data, std::strlen(data)); } +unsigned rowLength(unsigned row) +{ + unsigned length = 0; + for (; length < gTerminalWidth; ++length) + { + if (getEntryAt(length, row).character == '\0') { + break; + } + } + return length; +} + const std::string& readLine() noexcept { gReadBuffer.clear(); while(true) { char chr = '\0'; - putChar('_'); + + putChar(' ', gTerminalColor.swapped()); while (!baos::ps2::readChar(chr)); // TODO: arrow key navigation and stuff deleteChar(); if (chr == '\b') @@ -142,6 +178,7 @@ bool setPSFFont(const void* data, size_t length) noexcept gTerminalFont = newFont; gTerminalWidth = draw::getPrimaryFramebuffer().getWidth() / (gTerminalFont.getGlyphWidth() + 1); gTerminalHeight = draw::getPrimaryFramebuffer().getHeight() / (gTerminalFont.getGlyphHeight() + 1); + gTerminalBuffer.resize(gTerminalWidth * gTerminalHeight); return true; } }