diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-10-27 23:42:20 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-10-27 23:42:20 +0200 |
commit | 8289a5c93cabc3cfb4cf6e5e551d8ad6fca58a9f (patch) | |
tree | 35b40937c6128a9462bd5c142d3f4a3c453fa6ca | |
parent | cc7e3519a67c8080c44a104ab1b5d4d61b6b35c5 (diff) | |
download | serenity-8289a5c93cabc3cfb4cf6e5e551d8ad6fca58a9f.zip |
Implement 'H' and 'J' escape sequences.
-rw-r--r-- | AK/Vector.h | 3 | ||||
-rw-r--r-- | Kernel/Console.cpp | 154 | ||||
-rw-r--r-- | Kernel/Console.h | 17 | ||||
-rw-r--r-- | Kernel/VGA.cpp | 6 | ||||
-rw-r--r-- | Kernel/VGA.h | 2 |
5 files changed, 168 insertions, 14 deletions
diff --git a/AK/Vector.h b/AK/Vector.h index 7c258eb659..330d33cd0d 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -87,6 +87,9 @@ public: size_t size() const { return m_impl ? m_impl->size() : 0; } size_t capacity() const { return m_impl ? m_impl->capacity() : 0; } + T* data() { return m_impl ? &at(0) : nullptr; } + const T* data() const { return m_impl ? &at(0) : nullptr; } + const T& at(size_t i) const { return m_impl->at(i); } T& at(size_t i) { return m_impl->at(i); } diff --git a/Kernel/Console.cpp b/Kernel/Console.cpp index 08ecedd0d8..5a95d8d982 100644 --- a/Kernel/Console.cpp +++ b/Kernel/Console.cpp @@ -1,6 +1,8 @@ #include "Console.h" #include "VGA.h" #include "IO.h" +#include "kprintf.h" +#include <AK/String.h> // Bytes output to 0xE9 end up on the Bochs console. It's very handy. #define CONSOLE_OUT_TO_E9 @@ -34,21 +36,153 @@ ssize_t Console::read(byte* buffer, size_t bufferSize) return 0; } +inline bool isParameter(byte ch) +{ + return ch >= 0x30 && ch <= 0x3f; +} + +inline bool isIntermediate(byte ch) +{ + return ch >= 0x20 && ch <= 0x2f; +} + +inline bool isFinal(byte ch) +{ + return ch >= 0x40 && ch <= 0x7e; +} + +unsigned parseUInt(const String& str, bool& ok) +{ + unsigned value = 0; + for (size_t i = 0; i < str.length(); ++i) { + if (str[i] < '0' || str[i] > '9') { + ok = false; + return 0; + } + value = value * 10; + value += str[i] - '0'; + } + ok = true; + return value; +} + +void Console::escape$H(const Vector<unsigned>& params) +{ + unsigned row = 1; + unsigned col = 1; + + if (params.size() >= 1) + row = params[0]; + if (params.size() >= 2) + col = params[1]; + m_cursorRow = row - 1; + m_cursorColumn = col - 1; + vga_set_cursor(row - 1, col - 1); +} + +void Console::escape$J(const Vector<unsigned>& params) +{ + int mode = 0; + if (params.size() >= 1) + mode = params[0]; + switch (mode) { + case 0: + // FIXME: Clear from cursor to end of screen. + notImplemented(); + break; + case 1: + // FIXME: Clear from cursor to beginning of screen. + notImplemented(); + break; + case 2: + vga_clear(); + break; + case 3: + // FIXME: <esc>[3J should also clear the scrollback buffer. + vga_clear(); + break; + } +} + +void Console::executeEscapeSequence(byte final) +{ + auto paramparts = String((const char*)m_parameters.data(), m_parameters.size()).split(';'); + Vector<unsigned> params; + for (auto& parampart : paramparts) { + bool ok; + unsigned value = parseUInt(parampart, ok); + if (!ok) { + // FIXME: Should we do something else? + return; + } + params.append(value); + } + switch (final) { + case 'H': escape$H(params); break; + case 'J': escape$J(params); break; + default: break; + } + + m_parameters.clear(); + m_intermediates.clear(); +} + void Console::putChar(char ch) { #ifdef CONSOLE_OUT_TO_E9 + //if (ch != 27) IO::out8(0xe9, ch); #endif - switch (ch) { - case '\0': - return; - case '\n': - m_cursorColumn = 0; + auto scrollup = [&] { if (m_cursorRow == (m_rows - 1)) { vga_scroll_up(); } else { ++m_cursorRow; } + m_cursorColumn = 0; + }; + + switch (m_escState) { + case ExpectBracket: + if (ch == '[') + m_escState = ExpectParameter; + else + m_escState = Normal; + return; + case ExpectParameter: + if (isParameter(ch)) { + m_parameters.append(ch); + return; + } + m_escState = ExpectIntermediate; + // fall through + case ExpectIntermediate: + if (isIntermediate(ch)) { + m_intermediates.append(ch); + return; + } + m_escState = ExpectFinal; + // fall through + case ExpectFinal: + if (isFinal(ch)) { + m_escState = Normal; + executeEscapeSequence(ch); + return; + } + m_escState = Normal; + return; + case Normal: + break; + } + + switch (ch) { + case '\0': + return; + case '\033': + m_escState = ExpectBracket; + return; + case '\n': + scrollup(); vga_set_cursor(m_cursorRow, m_cursorColumn); return; } @@ -56,14 +190,8 @@ void Console::putChar(char ch) vga_putch_at(m_cursorRow, m_cursorColumn, ch); ++m_cursorColumn; - if (m_cursorColumn >= m_columns) { - if (m_cursorRow == (m_rows - 1)) { - vga_scroll_up(); - } else { - ++m_cursorRow; - } - m_cursorColumn = 0; - } + if (m_cursorColumn >= m_columns) + scrollup(); vga_set_cursor(m_cursorRow, m_cursorColumn); } diff --git a/Kernel/Console.h b/Kernel/Console.h index 196f9cb6ad..7b7d69c743 100644 --- a/Kernel/Console.h +++ b/Kernel/Console.h @@ -1,6 +1,7 @@ #pragma once #include <AK/Compiler.h> +#include <AK/Vector.h> #include <VirtualFileSystem/CharacterDevice.h> class Console final : public CharacterDevice { @@ -17,6 +18,9 @@ public: void putChar(char); private: + void escape$H(const Vector<unsigned>&); + void escape$J(const Vector<unsigned>&); + const byte m_rows { 25 }; const byte m_columns { 80 }; byte m_cursorRow { 0 }; @@ -24,6 +28,19 @@ private: byte m_currentAttribute { 0x07 }; + void executeEscapeSequence(byte final); + + enum EscapeState { + Normal, + ExpectBracket, + ExpectParameter, + ExpectIntermediate, + ExpectFinal, + }; + EscapeState m_escState { Normal }; + Vector<byte> m_parameters; + Vector<byte> m_intermediates; + const byte* s_vgaMemory { (const byte*)0xb8000 }; }; diff --git a/Kernel/VGA.cpp b/Kernel/VGA.cpp index 59e3c73267..b2571ecdd8 100644 --- a/Kernel/VGA.cpp +++ b/Kernel/VGA.cpp @@ -15,6 +15,12 @@ void vga_scroll_up() memset(vga_mem + (160 * 24), 0, 160); } +void vga_clear() +{ + InterruptDisabler disabler; + memset(vga_mem, 0, 160 * 25); +} + void vga_putch_at(byte row, byte column, byte ch) { word cur = (row * 160) + (column * 2); diff --git a/Kernel/VGA.h b/Kernel/VGA.h index b13f84b32f..a1e505f53c 100644 --- a/Kernel/VGA.h +++ b/Kernel/VGA.h @@ -10,4 +10,4 @@ void vga_set_cursor(BYTE row, BYTE column); WORD vga_get_cursor(); void vga_putch_at(byte row, byte column, byte ch); void vga_scroll_up(); - +void vga_clear(); |