serenity/Kernel/Devices/TTY/VirtualConsole.h
Ali Mohammad Pur 54ab6fe5b9 LibVT+Everywhere: Introduce 'automarks' and 'clear previous command'
Automarks are similar to bookmarks placed by the terminal, allowing the
user to selectively remove a single command and its output from the
terminal scrollback.
This commit implements a single way to add marks: automatically placing
them when the shell becomes interactive.

To make sure the shell behaves correctly after its expected prompt
position changes, the terminal layer forces a resize event to be passed
to the shell on such (possibly) partial clears; this also has the nice
side effect of fixing the disappearing prompt on the preexisting "clear
including history" action: Fixes #4192.
2024-02-07 00:43:11 +01:00

145 lines
4.4 KiB
C++

/*
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Noncopyable.h>
#include <AK/Vector.h>
#include <Kernel/API/KeyCode.h>
#include <Kernel/Devices/GPU/Console/Console.h>
#include <Kernel/Devices/Generic/ConsoleDevice.h>
#include <Kernel/Devices/HID/Management.h>
#include <Kernel/Devices/TTY/TTY.h>
#include <LibVT/Attribute.h>
#include <LibVT/Color.h>
#include <LibVT/Position.h>
#include <LibVT/Terminal.h>
namespace Kernel {
class ConsoleManagement;
class VirtualConsole;
// FIXME: This implementation has no knowledge about keeping terminal history...
class ConsoleImpl final : public VT::Terminal {
public:
explicit ConsoleImpl(VirtualConsole&);
virtual void set_size(u16 columns, u16 rows) override;
private:
virtual void invalidate_cursor() override;
virtual void clear() override;
virtual void clear_history() override;
virtual void scroll_up(u16 region_top, u16 region_bottom, size_t count) override;
virtual void scroll_down(u16 region_top, u16 region_bottom, size_t count) override;
virtual void scroll_left(u16 row, u16 column, size_t count) override;
virtual void scroll_right(u16 row, u16 column, size_t count) override;
virtual void put_character_at(unsigned row, unsigned column, u32 ch) override;
virtual void clear_in_line(u16 row, u16 first_column, u16 last_column) override;
};
class VirtualConsole final : public TTY
, public KeyboardClient
, public VT::TerminalClient {
friend class ConsoleManagement;
friend class DeviceManagement;
friend class ConsoleImpl;
friend class VT::Terminal;
public:
struct Line {
bool dirty;
size_t length;
};
struct Cell {
void clear()
{
ch = ' ';
attribute.reset();
}
char ch;
VT::Attribute attribute;
};
public:
static NonnullLockRefPtr<VirtualConsole> create(size_t index);
static NonnullLockRefPtr<VirtualConsole> create_with_preset_log(size_t index, CircularQueue<char, 16384> const&);
virtual ~VirtualConsole() override;
size_t index() const { return m_index; }
void refresh_after_resolution_change();
bool is_graphical() const { return m_graphical; }
void set_graphical(bool graphical);
void emit_char(char);
private:
explicit VirtualConsole(unsigned const index);
// ^KeyboardClient
virtual void on_key_pressed(KeyEvent) override;
// ^TTY
virtual ErrorOr<NonnullOwnPtr<KString>> pseudo_name() const override;
virtual ErrorOr<size_t> on_tty_write(UserOrKernelBuffer const&, size_t) override;
virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
virtual void echo(u8) override;
// ^TerminalClient
virtual void beep() override;
virtual void set_window_title(StringView) override;
virtual void set_window_progress(int, int) override;
virtual void terminal_did_resize(u16 columns, u16 rows) override;
virtual void terminal_history_changed(int) override;
virtual void terminal_did_perform_possibly_partial_clear() override;
virtual void emit(u8 const*, size_t) override;
virtual void set_cursor_shape(VT::CursorShape) override;
virtual void set_cursor_blinking(bool) override;
// ^CharacterDevice
virtual StringView class_name() const override { return "VirtualConsole"sv; }
void set_active(bool);
void flush_dirty_lines();
unsigned m_index;
bool m_active { false };
bool m_graphical { false };
private:
void initialize();
void invalidate_cursor(size_t row);
void clear();
Cell& cell_at(size_t column, size_t row);
using ParamVector = Vector<unsigned, 4>;
void scroll_down(u16 region_top, u16 region_bottom, size_t count);
void scroll_up(u16 region_top, u16 region_bottom, size_t count);
void scroll_left(u16 row, u16 column, size_t count);
void scroll_right(u16 row, u16 column, size_t count);
void clear_line(size_t index)
{
clear_in_line(index, 0, m_console_impl.columns() - 1);
}
void clear_in_line(u16 row, u16 first_column, u16 last_column);
void put_character_at(unsigned row, unsigned column, u32 ch, const VT::Attribute&);
OwnPtr<Memory::Region> m_cells;
Vector<VirtualConsole::Line> m_lines;
ConsoleImpl m_console_impl;
};
}