ソースを参照

Kernel: Port VirtualConsole to LibVT :^)

Unfortunately this drops the feature of preserving VGA buffer contents.

Resolves https://github.com/SerenityOS/serenity/issues/2399
Sergey Bugaev 5 年 前
コミット
f11270e7ce
6 ファイル変更126 行追加440 行削除
  1. 6 0
      Kernel/CMakeLists.txt
  2. 0 8
      Kernel/Console.cpp
  3. 0 12
      Kernel/Console.h
  4. 103 370
      Kernel/TTY/VirtualConsole.cpp
  5. 16 49
      Kernel/TTY/VirtualConsole.h
  6. 1 1
      Kernel/init.cpp

+ 6 - 0
Kernel/CMakeLists.txt

@@ -139,10 +139,16 @@ set(ELF_SOURCES
     ../Libraries/LibELF/Validation.cpp
 )
 
+set(VT_SOURCES
+    ../Libraries/LibVT/Terminal.cpp
+    ../Libraries/LibVT/Line.cpp
+)
+
 set(SOURCES
     ${KERNEL_SOURCES}
     ${AK_SOURCES}
     ${ELF_SOURCES}
+    ${VT_SOURCES}
 )
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKERNEL")

+ 0 - 8
Kernel/Console.cpp

@@ -70,8 +70,6 @@ ssize_t Console::write(Kernel::FileDescription&, size_t, const u8* data, ssize_t
 {
     if (!size)
         return 0;
-    if (!m_implementation)
-        return 0;
     for (ssize_t i = 0; i < size; ++i)
         put_char(data[i]);
     return size;
@@ -84,10 +82,4 @@ void Console::put_char(char ch)
     IO::out8(0xe9, ch);
 #endif
     m_logbuffer.enqueue(ch);
-    if (m_implementation)
-        m_implementation->on_sysconsole_receive(ch);
-}
-
-ConsoleImplementation::~ConsoleImplementation()
-{
 }

+ 0 - 12
Kernel/Console.h

@@ -30,12 +30,6 @@
 #include <AK/Vector.h>
 #include <Kernel/Devices/CharacterDevice.h>
 
-class ConsoleImplementation {
-public:
-    virtual ~ConsoleImplementation();
-    virtual void on_sysconsole_receive(u8) = 0;
-};
-
 class Console final : public Kernel::CharacterDevice {
     AK_MAKE_ETERNAL
 public:
@@ -52,16 +46,10 @@ public:
     virtual ssize_t write(Kernel::FileDescription&, size_t, const u8*, ssize_t) override;
     virtual const char* class_name() const override { return "Console"; }
 
-    void set_implementation(ConsoleImplementation* implementation)
-    {
-        m_implementation = implementation;
-    }
-
     void put_char(char);
 
     const CircularQueue<char, 16384>& logbuffer() const { return m_logbuffer; }
 
 private:
-    ConsoleImplementation* m_implementation { nullptr };
     CircularQueue<char, 16384> m_logbuffer;
 };

+ 103 - 370
Kernel/TTY/VirtualConsole.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2020 Sergey Bugaev <bugaevc@serenityos.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,20 +39,9 @@ static u8* s_vga_buffer;
 static VirtualConsole* s_consoles[6];
 static int s_active_console;
 
-void VirtualConsole::get_vga_cursor(u8& row, u8& column)
-{
-    u16 value;
-    IO::out8(0x3d4, 0x0e);
-    value = IO::in8(0x3d5) << 8;
-    IO::out8(0x3d4, 0x0f);
-    value |= IO::in8(0x3d5);
-    row = value / columns();
-    column = value % columns();
-}
-
 void VirtualConsole::flush_vga_cursor()
 {
-    u16 value = m_current_vga_start_address + (m_cursor_row * columns() + m_cursor_column);
+    u16 value = m_current_vga_start_address + (m_terminal.cursor_row() * columns() + m_terminal.cursor_column());
     IO::out8(0x3d4, 0x0e);
     IO::out8(0x3d5, MSB(value));
     IO::out8(0x3d4, 0x0f);
@@ -61,7 +51,6 @@ void VirtualConsole::flush_vga_cursor()
 void VirtualConsole::initialize()
 {
     s_vga_buffer = (u8*)0xc00b8000;
-    memset(s_consoles, 0, sizeof(s_consoles));
     s_active_console = -1;
 }
 
@@ -73,28 +62,15 @@ void VirtualConsole::set_graphical(bool graphical)
     m_graphical = graphical;
 }
 
-VirtualConsole::VirtualConsole(unsigned index, InitialContents initial_contents)
+VirtualConsole::VirtualConsole(unsigned index)
     : TTY(4, index)
     , m_index(index)
+    , m_terminal(*this)
 {
-    sprintf(m_tty_name, "/dev/tty%u", m_index);
-    set_size(80, 25);
-    m_horizontal_tabs = static_cast<u8*>(kmalloc_eternal(columns()));
-    for (unsigned i = 0; i < columns(); ++i)
-        m_horizontal_tabs[i] = (i % 8) == 0;
-    // Rightmost column is always last tab on line.
-    m_horizontal_tabs[columns() - 1] = 1;
+    m_tty_name = String::format("/dev/tty%u", m_index);
+    m_terminal.set_size(80, 25);
 
     s_consoles[index] = this;
-    m_buffer = (u8*)kmalloc_eternal(rows() * columns() * 2);
-    if (initial_contents == AdoptCurrentVGABuffer) {
-        memcpy(m_buffer, s_vga_buffer, rows() * columns() * 2);
-        get_vga_cursor(m_cursor_row, m_cursor_column);
-    } else {
-        u16* line_mem = reinterpret_cast<u16*>(m_buffer);
-        for (u16 i = 0; i < rows() * columns(); ++i)
-            line_mem[i] = 0x0720;
-    }
 }
 
 VirtualConsole::~VirtualConsole()
@@ -102,16 +78,6 @@ VirtualConsole::~VirtualConsole()
     ASSERT_NOT_REACHED();
 }
 
-void VirtualConsole::clear()
-{
-    u16* linemem = m_active ? (u16*)s_vga_buffer : (u16*)m_buffer;
-    for (u16 i = 0; i < rows() * columns(); ++i)
-        linemem[i] = 0x0720;
-    if (m_active)
-        set_vga_start_row(0);
-    set_cursor(0, 0);
-}
-
 void VirtualConsole::switch_to(unsigned index)
 {
     if ((int)index == s_active_console)
@@ -125,50 +91,35 @@ void VirtualConsole::switch_to(unsigned index)
         // We won't know how to switch away from a graphical console until we
         // can set the video mode on our own. Just stop anyone from trying for
         // now.
-        if (active_console->is_graphical())
+        if (active_console->is_graphical()) {
+            dbg() << "Cannot switch away from graphical console yet :(";
             return;
+        }
         active_console->set_active(false);
     }
     dbg() << "VC: Switch to " << index << " (" << s_consoles[index] << ")";
     s_active_console = index;
     s_consoles[s_active_console]->set_active(true);
-    Console::the().set_implementation(s_consoles[s_active_console]);
 }
 
-void VirtualConsole::set_active(bool b)
+void VirtualConsole::set_active(bool active)
 {
-    if (b == m_active)
+    if (active == m_active)
         return;
 
     InterruptDisabler disabler;
 
-    m_active = b;
-    if (!m_active) {
-        memcpy(m_buffer, m_current_vga_window, rows() * columns() * 2);
-        KeyboardDevice::the().set_client(nullptr);
-        return;
-    }
-
-    memcpy(s_vga_buffer, m_buffer, rows() * columns() * 2);
-    set_vga_start_row(0);
-    flush_vga_cursor();
-
-    KeyboardDevice::the().set_client(this);
-}
+    m_active = active;
 
-inline bool is_valid_parameter_character(u8 ch)
-{
-    return ch >= 0x30 && ch <= 0x3f;
-}
-
-inline bool is_valid_intermediate_character(u8 ch)
-{
-    return ch >= 0x20 && ch <= 0x2f;
-}
+    if (active) {
+        set_vga_start_row(0);
+        KeyboardDevice::the().set_client(this);
 
-inline bool is_valid_final_character(u8 ch)
-{
-    return ch >= 0x40 && ch <= 0x7e;
+        m_terminal.m_need_full_flush = true;
+        flush_dirty_lines();
+    } else {
+        KeyboardDevice::the().set_client(nullptr);
+    }
 }
 
 enum class VGAColor : u8 {
@@ -207,6 +158,7 @@ enum class ANSIColor : u8 {
     BrightMagenta,
     BrightCyan,
     White,
+    __Count,
 };
 
 static inline VGAColor ansi_color_to_vga(ANSIColor color)
@@ -244,165 +196,18 @@ static inline VGAColor ansi_color_to_vga(ANSIColor color)
         return VGAColor::BrightCyan;
     case ANSIColor::White:
         return VGAColor::White;
-    }
-    ASSERT_NOT_REACHED();
-    return VGAColor::LightGray;
-}
-
-static inline u8 ansi_color_to_vga(u8 color)
-{
-    return (u8)ansi_color_to_vga((ANSIColor)color);
-}
-
-void VirtualConsole::escape$m(const Vector<unsigned>& params)
-{
-    for (auto param : params) {
-        switch (param) {
-        case 0:
-            // Reset
-            m_current_attribute = 0x07;
-            break;
-        case 1:
-            // Bold
-            m_current_attribute |= 8;
-            break;
-        case 30:
-        case 31:
-        case 32:
-        case 33:
-        case 34:
-        case 35:
-        case 36:
-        case 37:
-            // Foreground color
-            m_current_attribute &= ~0x7;
-            m_current_attribute |= ansi_color_to_vga(param - 30);
-            break;
-        case 40:
-        case 41:
-        case 42:
-        case 43:
-        case 44:
-        case 45:
-        case 46:
-        case 47:
-            // Background color
-            m_current_attribute &= ~0x70;
-            m_current_attribute |= ansi_color_to_vga(param - 30) << 8;
-            break;
-        }
-    }
-}
-
-void VirtualConsole::escape$s(const Vector<unsigned>&)
-{
-    m_saved_cursor_row = m_cursor_row;
-    m_saved_cursor_column = m_cursor_column;
-}
-
-void VirtualConsole::escape$u(const Vector<unsigned>&)
-{
-    set_cursor(m_saved_cursor_row, m_saved_cursor_column);
-}
-
-void VirtualConsole::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];
-    set_cursor(row - 1, col - 1);
-}
-
-void VirtualConsole::escape$A(const Vector<unsigned>& params)
-{
-    int num = 1;
-    if (params.size() >= 1)
-        num = params[0];
-    int new_row = (int)m_cursor_row - num;
-    if (new_row < 0)
-        new_row = 0;
-    set_cursor(new_row, m_cursor_column);
-}
-
-void VirtualConsole::escape$D(const Vector<unsigned>& params)
-{
-    int num = 1;
-    if (params.size() >= 1)
-        num = params[0];
-    int new_column = (int)m_cursor_column - num;
-    if (new_column < 0)
-        new_column = 0;
-    set_cursor(m_cursor_row, new_column);
-}
-
-void VirtualConsole::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.
-        ASSERT_NOT_REACHED();
-        break;
-    case 1:
-        // FIXME: Clear from cursor to beginning of screen.
+    default:
         ASSERT_NOT_REACHED();
-        break;
-    case 2:
-        clear();
-        break;
-    case 3:
-        // FIXME: <esc>[3J should also clear the scrollback buffer.
-        clear();
-        break;
     }
 }
 
-void VirtualConsole::execute_escape_sequence(u8 final)
+static inline u8 xterm_color_to_vga(u32 color)
 {
-    auto paramparts = String::copy(m_parameters).split(';');
-    Vector<unsigned> params;
-    for (auto& parampart : paramparts) {
-        bool ok;
-        unsigned value = parampart.to_uint(ok);
-        if (!ok) {
-            // FIXME: Should we do something else?
-            return;
-        }
-        params.append(value);
+    for (u8 i = 0; i < (u8)ANSIColor::__Count; i++) {
+        if (xterm_colors[i] == color)
+            return (u8)ansi_color_to_vga((ANSIColor)i);
     }
-    switch (final) {
-    case 'A':
-        escape$A(params);
-        break;
-    case 'D':
-        escape$D(params);
-        break;
-    case 'H':
-        escape$H(params);
-        break;
-    case 'J':
-        escape$J(params);
-        break;
-    case 'm':
-        escape$m(params);
-        break;
-    case 's':
-        escape$s(params);
-        break;
-    case 'u':
-        escape$u(params);
-        break;
-    default:
-        break;
-    }
-
-    m_parameters.clear();
-    m_intermediates.clear();
+    return (u8)VGAColor::LightGray;
 }
 
 void VirtualConsole::clear_vga_row(u16 row)
@@ -412,173 +217,112 @@ void VirtualConsole::clear_vga_row(u16 row)
         linemem[i] = 0x0720;
 }
 
-void VirtualConsole::scroll_up()
+void VirtualConsole::on_key_pressed(KeyboardDevice::Event event)
 {
-    if (m_cursor_row == (rows() - 1)) {
-        if (m_active) {
-            if (m_vga_start_row >= 160) {
-                memcpy(s_vga_buffer, m_current_vga_window + 160, (rows() - 1) * columns() * 2);
-                set_vga_start_row(0);
-                clear_vga_row(24);
-            } else {
-                set_vga_start_row(m_vga_start_row + 1);
-                clear_vga_row(24);
-            }
-        } else {
-            memmove(m_buffer, m_buffer + 160, 160 * 24);
-            u16* linemem = (u16*)&m_buffer[24 * 160];
-            for (u16 i = 0; i < columns(); ++i)
-                linemem[i] = 0x0720;
-        }
-    } else {
-        ++m_cursor_row;
+    // Ignore keyboard in graphical mode.
+    if (m_graphical)
+        return;
+
+    if (!event.is_press())
+        return;
+
+    if (event.key == KeyCode::Key_PageUp && event.flags == Mod_Shift) {
+        // TODO: scroll up
+        return;
+    }
+    if (event.key == KeyCode::Key_PageDown && event.flags == Mod_Shift) {
+        // TODO: scroll down
+        return;
     }
-    m_cursor_column = 0;
+
+    m_terminal.handle_key_press(event.key, event.character, event.flags);
 }
 
-void VirtualConsole::set_cursor(unsigned row, unsigned column)
+ssize_t VirtualConsole::on_tty_write(const u8* data, ssize_t size)
 {
-    ASSERT(row < rows());
-    ASSERT(column < columns());
-    m_cursor_row = row;
-    m_cursor_column = column;
+    InterruptDisabler disabler;
+    for (ssize_t i = 0; i < size; ++i)
+        m_terminal.on_input(data[i]);
     if (m_active)
-        flush_vga_cursor();
+        flush_dirty_lines();
+    return size;
 }
 
-void VirtualConsole::put_character_at(unsigned row, unsigned column, u8 ch)
+void VirtualConsole::set_vga_start_row(u16 row)
 {
-    ASSERT(row < rows());
-    ASSERT(column < columns());
-    u16 cur = (row * 160) + (column * 2);
-    if (m_active) {
-        u16 cur = (row * 160) + (column * 2);
-        m_current_vga_window[cur] = ch;
-        m_current_vga_window[cur + 1] = m_current_attribute;
-    } else {
-        m_buffer[cur] = ch;
-        m_buffer[cur + 1] = m_current_attribute;
-    }
+    m_vga_start_row = row;
+    m_current_vga_start_address = row * columns();
+    m_current_vga_window = s_vga_buffer + row * 160;
+    IO::out8(0x3d4, 0x0c);
+    IO::out8(0x3d5, MSB(m_current_vga_start_address));
+    IO::out8(0x3d4, 0x0d);
+    IO::out8(0x3d5, LSB(m_current_vga_start_address));
 }
 
-void VirtualConsole::on_char(u8 ch)
+static inline u8 attribute_to_vga(const VT::Attribute& attribute)
 {
-    // ignore writes in graphical mode
-    if (m_graphical)
-        return;
+    u8 vga_attr = 0x07;
 
-    switch (m_escape_state) {
-    case ExpectBracket:
-        if (ch == '[')
-            m_escape_state = ExpectParameter;
-        else
-            m_escape_state = Normal;
-        return;
-    case ExpectParameter:
-        if (is_valid_parameter_character(ch)) {
-            m_parameters.append(ch);
-            return;
-        }
-        m_escape_state = ExpectIntermediate;
-        [[fallthrough]];
-    case ExpectIntermediate:
-        if (is_valid_intermediate_character(ch)) {
-            m_intermediates.append(ch);
-            return;
-        }
-        m_escape_state = ExpectFinal;
-        [[fallthrough]];
-    case ExpectFinal:
-        if (is_valid_final_character(ch)) {
-            m_escape_state = Normal;
-            execute_escape_sequence(ch);
-            return;
-        }
-        m_escape_state = Normal;
-        return;
-    case Normal:
-        break;
-    }
+    if (attribute.flags & VT::Attribute::Bold)
+        vga_attr |= 0x08;
 
-    switch (ch) {
-    case '\0':
-        return;
-    case '\033':
-        m_escape_state = ExpectBracket;
-        return;
-    case 8: // Backspace
-        if (m_cursor_column) {
-            set_cursor(m_cursor_row, m_cursor_column - 1);
-            put_character_at(m_cursor_row, m_cursor_column, ' ');
-            return;
-        }
-        break;
-    case '\a':
-        // FIXME: Bell!
-        return;
-    case '\t': {
-        for (unsigned i = m_cursor_column; i < columns(); ++i) {
-            if (m_horizontal_tabs[i]) {
-                set_cursor(m_cursor_row, i);
-                return;
-            }
-        }
-        return;
-    }
-    case '\n':
-        scroll_up();
-        set_cursor(m_cursor_row, m_cursor_column);
-        return;
-    }
+    // Background color
+    vga_attr &= ~0x70;
+    vga_attr |= xterm_color_to_vga(attribute.background_color) << 8;
 
-    put_character_at(m_cursor_row, m_cursor_column, ch);
+    // Foreground color
+    vga_attr &= ~0x7;
+    vga_attr |= xterm_color_to_vga(attribute.foreground_color);
 
-    ++m_cursor_column;
-    if (m_cursor_column >= columns())
-        scroll_up();
-    set_cursor(m_cursor_row, m_cursor_column);
+    return vga_attr;
 }
 
-void VirtualConsole::on_key_pressed(KeyboardDevice::Event key)
+void VirtualConsole::flush_dirty_lines()
 {
-    // ignore keyboard in graphical mode
-    if (m_graphical)
-        return;
-
-    if (!key.is_press())
-        return;
-    if (key.ctrl()) {
-        if (key.character >= 'a' && key.character <= 'z') {
-            emit(key.character - 'a' + 1);
-            return;
-        } else if (key.character == '\\') {
-            emit(0x1c);
-            return;
+    for (u16 visual_row = 0; visual_row < m_terminal.rows(); ++visual_row) {
+        auto& line = m_terminal.visible_line(visual_row);
+        if (!line.is_dirty() && !m_terminal.m_need_full_flush)
+            continue;
+        for (size_t column = 0; column < line.length(); ++column) {
+            u32 codepoint = line.codepoint(column);
+            auto attribute = line.attributes()[column];
+            u16 vga_index = (visual_row * 160) + (column * 2);
+            m_current_vga_window[vga_index] = codepoint < 128 ? codepoint : '?';
+            m_current_vga_window[vga_index + 1] = attribute_to_vga(attribute);
         }
+        line.set_dirty(false);
     }
-    emit(key.character);
+    flush_vga_cursor();
+    m_terminal.m_need_full_flush = false;
 }
 
-void VirtualConsole::on_sysconsole_receive(u8 ch)
+void VirtualConsole::beep()
 {
-    InterruptDisabler disabler;
-    auto old_attribute = m_current_attribute;
-    m_current_attribute = 0x03;
-    on_char(ch);
-    m_current_attribute = old_attribute;
+    // TODO
+    dbg() << "Beep!1";
 }
 
-ssize_t VirtualConsole::on_tty_write(const u8* data, ssize_t size)
+void VirtualConsole::set_window_title(const StringView&)
 {
-    InterruptDisabler disabler;
-    for (ssize_t i = 0; i < size; ++i)
-        on_char(data[i]);
-    return size;
+    // Do nothing.
 }
 
-StringView VirtualConsole::tty_name() const
+void VirtualConsole::terminal_did_resize(u16 columns, u16 rows)
 {
-    return m_tty_name;
+    ASSERT(columns == 80);
+    ASSERT(rows == 25);
+    set_size(columns, rows);
+}
+
+void VirtualConsole::terminal_history_changed()
+{
+    // Do nothing, I guess?
+}
+
+void VirtualConsole::emit(const u8* data, size_t size)
+{
+    for (size_t i = 0; i < size; i++)
+        TTY::emit(data[i]);
 }
 
 void VirtualConsole::echo(u8 ch)
@@ -588,15 +332,4 @@ void VirtualConsole::echo(u8 ch)
     }
 }
 
-void VirtualConsole::set_vga_start_row(u16 row)
-{
-    m_vga_start_row = row;
-    m_current_vga_start_address = row * columns();
-    m_current_vga_window = s_vga_buffer + row * 160;
-    IO::out8(0x3d4, 0x0c);
-    IO::out8(0x3d5, MSB(m_current_vga_start_address));
-    IO::out8(0x3d4, 0x0d);
-    IO::out8(0x3d5, LSB(m_current_vga_start_address));
-}
-
 }

+ 16 - 49
Kernel/TTY/VirtualConsole.h

@@ -26,23 +26,19 @@
 
 #pragma once
 
+#include <Kernel/Console.h>
 #include <Kernel/Devices/KeyboardDevice.h>
 #include <Kernel/TTY/TTY.h>
-#include <Kernel/Console.h>
+#include <LibVT/Terminal.h>
 
 namespace Kernel {
 
 class VirtualConsole final : public TTY
     , public KeyboardClient
-    , public ConsoleImplementation {
+    , public VT::TerminalClient {
     AK_MAKE_ETERNAL
 public:
-    enum InitialContents {
-        Cleared,
-        AdoptCurrentVGABuffer
-    };
-
-    VirtualConsole(unsigned index, InitialContents = Cleared);
+    VirtualConsole(unsigned index);
     virtual ~VirtualConsole() override;
 
     static void switch_to(unsigned);
@@ -55,68 +51,39 @@ private:
     // ^KeyboardClient
     virtual void on_key_pressed(KeyboardDevice::Event) override;
 
-    // ^ConsoleImplementation
-    virtual void on_sysconsole_receive(u8) override;
-
     // ^TTY
     virtual ssize_t on_tty_write(const u8*, ssize_t) override;
-    virtual StringView tty_name() const override;
+    virtual StringView tty_name() const override { return m_tty_name; }
     virtual void echo(u8) override;
 
+    // ^TerminalClient
+    virtual void beep() override;
+    virtual void set_window_title(const StringView&) override;
+    virtual void terminal_did_resize(u16 columns, u16 rows) override;
+    virtual void terminal_history_changed() override;
+    virtual void emit(const u8*, size_t) override;
+
     // ^CharacterDevice
     virtual const char* class_name() const override { return "VirtualConsole"; }
 
     void set_active(bool);
-    void on_char(u8);
 
-    void get_vga_cursor(u8& row, u8& column);
     void flush_vga_cursor();
+    void flush_dirty_lines();
 
-    u8* m_buffer;
     unsigned m_index;
     bool m_active { false };
     bool m_graphical { false };
 
-    void scroll_up();
-    void set_cursor(unsigned row, unsigned column);
-    void put_character_at(unsigned row, unsigned column, u8 ch);
-
-    void escape$A(const Vector<unsigned>&);
-    void escape$D(const Vector<unsigned>&);
-    void escape$H(const Vector<unsigned>&);
-    void escape$J(const Vector<unsigned>&);
-    void escape$m(const Vector<unsigned>&);
-    void escape$s(const Vector<unsigned>&);
-    void escape$u(const Vector<unsigned>&);
-
-    void clear();
-
-    u8 m_cursor_row { 0 };
-    u8 m_cursor_column { 0 };
-    u8 m_saved_cursor_row { 0 };
-    u8 m_saved_cursor_column { 0 };
-    u8 m_current_attribute { 0x07 };
-
     void clear_vga_row(u16 row);
     void set_vga_start_row(u16 row);
     u16 m_vga_start_row { 0 };
     u16 m_current_vga_start_address { 0 };
     u8* m_current_vga_window { nullptr };
 
-    void execute_escape_sequence(u8 final);
-
-    enum EscapeState {
-        Normal,
-        ExpectBracket,
-        ExpectParameter,
-        ExpectIntermediate,
-        ExpectFinal,
-    };
-    EscapeState m_escape_state { Normal };
-    Vector<u8> m_parameters;
-    Vector<u8> m_intermediates;
-    u8* m_horizontal_tabs { nullptr };
-    char m_tty_name[32];
+    VT::Terminal m_terminal;
+
+    String m_tty_name;
 };
 
 }

+ 1 - 1
Kernel/init.cpp

@@ -143,7 +143,7 @@ extern "C" [[noreturn]] void init()
     new SerialDevice(SERIAL_COM4_ADDR, 67);
 
     VirtualConsole::initialize();
-    tty0 = new VirtualConsole(0, VirtualConsole::AdoptCurrentVGABuffer);
+    tty0 = new VirtualConsole(0);
     new VirtualConsole(1);
     VirtualConsole::switch_to(0);