Cleanup the terminal system

This commit is contained in:
Baptiste Wicht 2016-09-24 19:45:58 +02:00
parent 565c364f6f
commit 321c6dcf5d
9 changed files with 307 additions and 124 deletions

View File

@ -16,30 +16,68 @@
namespace stdio { namespace stdio {
/*!
* \brief Init the console
*/
void init_console(); void init_console();
/*!
* \brief A console
*/
struct console { struct console {
/*!
* \brief Init the console
*/
void init(); void init();
size_t get_columns() const ; /*!
size_t get_rows() const ; * \brief Returns the number of columns of the console
*/
size_t get_columns() const;
/*!
* \brief Returns the number of rows of the console
*/
size_t get_rows() const;
/*!
* \brief Print the given char to the console
* \param c The character to print
*/
void print(char c); void print(char c);
/*!
* \brief Clear the console
*/
void wipeout(); void wipeout();
/*!
* \brief Set the active status of the console
* \param active The active status of the console
*/
void set_active(bool active); void set_active(bool active);
/*!
* \brief Save the state of the console
*/
void save(); void save();
/*!
* \brief Restore the state of the console
*/
void restore(); void restore();
private: private:
/*!
* \brief Move to the next line
*/
void next_line(); void next_line();
size_t current_line = 0; size_t current_line = 0; ///< The current line of the console
size_t current_column = 0; size_t current_column = 0; ///< The current column of the console
void* buffer = nullptr; void* buffer = nullptr; ///< The buffer to save the state
bool active = false; bool active = false; ///< The active status of the console
}; };
} // end of namespace stdio } // end of namespace stdio

View File

@ -14,14 +14,40 @@
namespace stdio { namespace stdio {
/*!
* \brief Initialize the terminals
*/
void init_terminals(); void init_terminals();
/*!
* \brief Register the devices into the devfs
*/
void register_devices(); void register_devices();
/*!
* \brief Finalize the terminals
*/
void finalize(); void finalize();
/*!
* \brief Switch the active terminal to the terminal with the given id
* \param id The terminal to activate
*/
void switch_terminal(size_t id); void switch_terminal(size_t id);
/*!
* \brief Returns the number of terminals
*/
size_t terminals_count(); size_t terminals_count();
/*!
* \brief Returns the active terminal
*/
virtual_terminal& get_active_terminal(); virtual_terminal& get_active_terminal();
/*!
* \brief Returns the terminal with the given id
*/
virtual_terminal& get_terminal(size_t id); virtual_terminal& get_terminal(size_t id);
} //end of namespace stdio } //end of namespace stdio

View File

@ -23,7 +23,13 @@ namespace stdio {
constexpr const size_t INPUT_BUFFER_SIZE = 256; constexpr const size_t INPUT_BUFFER_SIZE = 256;
/*!
* \brief A virtual terminal
*/
struct virtual_terminal { struct virtual_terminal {
/*!
* \brief Construct a new virtual_terminal
*/
virtual_terminal(){} virtual_terminal(){}
virtual_terminal(const virtual_terminal& rhs) = delete; virtual_terminal(const virtual_terminal& rhs) = delete;
@ -32,6 +38,10 @@ struct virtual_terminal {
virtual_terminal(virtual_terminal&& rhs) = delete; virtual_terminal(virtual_terminal&& rhs) = delete;
virtual_terminal& operator=(virtual_terminal&& rhs) = delete; virtual_terminal& operator=(virtual_terminal&& rhs) = delete;
/*!
* \brief Print the given char to the terminal
* \param c The character to print
*/
void print(char c); void print(char c);
/*! /*!
@ -76,13 +86,36 @@ struct virtual_terminal {
*/ */
size_t read_input_raw(size_t ms); size_t read_input_raw(size_t ms);
/*!
* \brief Set the canonical mode of the terminal
* \param can The canonical mode of the terminal
*/
void set_canonical(bool can); void set_canonical(bool can);
/*!
* \brief Set the mouse mode of the terminal
* \param can The mouse mode of the terminal
*/
void set_mouse(bool m); void set_mouse(bool m);
/*!
* \brief Returns true if the terminal is in canonical mode, false otherwise
*/
bool is_canonical() const; bool is_canonical() const;
/*!
* \brief Returns true if the terminal is in mouse mode, false otherwise
*/
bool is_mouse() const;
/*!
* \brief Set the active mode of the terminal
*/
void set_active(bool); void set_active(bool);
/*!
* \brief Returns the console linked to this terminal
*/
console& get_console(); console& get_console();
size_t id; size_t id;

View File

@ -10,12 +10,41 @@
#include <types.hpp> #include <types.hpp>
/*!
* \brief A textual console
*/
struct text_console { struct text_console {
/*!
* \brief Initialize the console
*/
void init(); void init();
/*!
* \brief Returns the number of lines of the console
*/
size_t lines(); size_t lines();
/*!
* \brief Returns the number of columns of the console
*/
size_t columns(); size_t columns();
/*!
* \brief Clear the text console
*/
void clear(); void clear();
/*!
* \brief Scroll up one line
*/
void scroll_up(); void scroll_up();
/*!
* \brief Print a char at the given line and column
* \param line The line at which to print the char
* \param column The column at which to print the char
* \param c The char to print
*/
void print_char(size_t line, size_t column, char c); void print_char(size_t line, size_t column, char c);
}; };

View File

@ -10,22 +10,75 @@
#include <types.hpp> #include <types.hpp>
/*!
* \brief A VESA console
*/
struct vesa_console { struct vesa_console {
/*!
* \brief Initialize the console
*/
void init(); void init();
size_t lines() const ; /*!
size_t columns() const ; * \brief Returns the number of lines of the console
*/
size_t lines() const;
/*!
* \brief Returns the number of columns of the console
*/
size_t columns() const;
/*!
* \brief Clear the vesa console
*/
void clear(); void clear();
/*!
* \brief Clear the given vesa console state
* \param buffer The VESA console state
*/
void clear(void* buffer); void clear(void* buffer);
/*!
* \brief Scroll up one line
*/
void scroll_up(); void scroll_up();
/*!
* \brief Scroll up one line on the given vesa console state
* \param buffer The VESA console state
*/
void scroll_up(void* buffer); void scroll_up(void* buffer);
/*!
* \brief Print a char at the given line and column
* \param line The line at which to print the char
* \param column The column at which to print the char
* \param c The char to print
*/
void print_char(size_t line, size_t column, char c); void print_char(size_t line, size_t column, char c);
/*!
* \brief Print a char at the given line and column on the given vesa console state
* \param buffer The VESA console state
* \param line The line at which to print the char
* \param column The column at which to print the char
* \param c The char to print
*/
void print_char(void* buffer, size_t line, size_t column, char c); void print_char(void* buffer, size_t line, size_t column, char c);
/*!
* \brief Save the state of the console
* \param buffer The buffer to save to
* \return the buffer the state was saved to
*/
void* save(void* buffer); void* save(void* buffer);
/*!
* \brief Restore the state of the console
* \param buffer The buffer to restore from
*/
void restore(void* buffer); void restore(void* buffer);
}; };

View File

@ -26,24 +26,24 @@ bool text = true;
} //end of anonymous namespace } //end of anonymous namespace
void stdio::init_console(){ void stdio::init_console() {
text = !vesa::enabled(); text = !vesa::enabled();
if(text){ if (text) {
t_console.init(); t_console.init();
} else { } else {
v_console.init(); v_console.init();
} }
} }
void stdio::console::init(){ void stdio::console::init() {
if(!text){ if (!text) {
buffer = vesa::create_buffer(); buffer = vesa::create_buffer();
} }
} }
size_t stdio::console::get_rows() const { size_t stdio::console::get_rows() const {
if(text){ if (text) {
return t_console.lines(); return t_console.lines();
} else { } else {
return v_console.lines(); return v_console.lines();
@ -51,30 +51,30 @@ size_t stdio::console::get_rows() const {
} }
size_t stdio::console::get_columns() const { size_t stdio::console::get_columns() const {
if(text){ if (text) {
return t_console.columns(); return t_console.columns();
} else { } else {
return v_console.columns(); return v_console.columns();
} }
} }
void stdio::console::print(char key){ void stdio::console::print(char key) {
if(key == '\n'){ if (key == '\n') {
next_line(); next_line();
} else if(key == '\r'){ } else if (key == '\r') {
// Ignore \r for now // Ignore \r for now
} else if(key == '\b'){ } else if (key == '\b') {
--current_column; --current_column;
print(' '); print(' ');
--current_column; --current_column;
} else if(key == '\t'){ } else if (key == '\t') {
print(' '); print(' ');
print(' '); print(' ');
} else { } else {
if(text){ if (text) {
t_console.print_char(current_line, current_column, key); t_console.print_char(current_line, current_column, key);
} else { } else {
if(active){ if (active) {
v_console.print_char(current_line, current_column, key); v_console.print_char(current_line, current_column, key);
} else { } else {
v_console.print_char(buffer, current_line, current_column, key); v_console.print_char(buffer, current_line, current_column, key);
@ -83,51 +83,51 @@ void stdio::console::print(char key){
++current_column; ++current_column;
if(current_column == console::get_columns()){ if (current_column == console::get_columns()) {
next_line(); next_line();
} }
} }
} }
void stdio::console::wipeout(){ void stdio::console::wipeout() {
if(text){ if (text) {
t_console.clear(); t_console.clear();
} else { } else {
if(active){ if (active) {
v_console.clear(); v_console.clear();
} else { } else {
v_console.clear(buffer); v_console.clear(buffer);
} }
} }
current_line = 0; current_line = 0;
current_column = 0; current_column = 0;
} }
void stdio::console::save(){ void stdio::console::save() {
thor_assert(!text, "save/restore of the text console is not yet supported"); thor_assert(!text, "save/restore of the text console is not yet supported");
buffer = v_console.save(buffer); buffer = v_console.save(buffer);
} }
void stdio::console::restore(){ void stdio::console::restore() {
thor_assert(!text, "save/restore of the text console is not yet supported"); thor_assert(!text, "save/restore of the text console is not yet supported");
v_console.restore(buffer); v_console.restore(buffer);
} }
void stdio::console::set_active(bool active){ void stdio::console::set_active(bool active) {
this->active = active; this->active = active;
} }
void stdio::console::next_line(){ void stdio::console::next_line() {
++current_line; ++current_line;
if(current_line == console::get_rows()){ if (current_line == console::get_rows()) {
if(text){ if (text) {
t_console.scroll_up(); t_console.scroll_up();
} else { } else {
if(active){ if (active) {
v_console.scroll_up(); v_console.scroll_up();
} else { } else {
v_console.scroll_up(buffer); v_console.scroll_up(buffer);

View File

@ -27,7 +27,7 @@ size_t active_terminal;
std::array<stdio::virtual_terminal, MAX_TERMINALS> terminals; std::array<stdio::virtual_terminal, MAX_TERMINALS> terminals;
void input_thread(void* data){ void input_thread(void* data) {
auto& terminal = *reinterpret_cast<stdio::virtual_terminal*>(data); auto& terminal = *reinterpret_cast<stdio::virtual_terminal*>(data);
auto pid = scheduler::get_pid(); auto pid = scheduler::get_pid();
@ -35,62 +35,62 @@ void input_thread(void* data){
logging::logf(logging::log_level::TRACE, "stdio: Input Thread for terminal %u started (pid:%u)\n", terminal.id, pid); logging::logf(logging::log_level::TRACE, "stdio: Input Thread for terminal %u started (pid:%u)\n", terminal.id, pid);
bool shift = false; bool shift = false;
bool alt = false; bool alt = false;
while(true){ while (true) {
// Wait for some input // Wait for some input
scheduler::block_process(pid); scheduler::block_process(pid);
// Handle keyboard input // Handle keyboard input
while(!terminal.keyboard_buffer.empty()){ while (!terminal.keyboard_buffer.empty()) {
auto key = terminal.keyboard_buffer.pop(); auto key = terminal.keyboard_buffer.pop();
if(terminal.canonical){ if (terminal.canonical) {
//Key released //Key released
if(key & 0x80){ if (key & 0x80) {
key &= ~(0x80); key &= ~(0x80);
if(alt && key == keyboard::KEY_F1){ if (alt && key == keyboard::KEY_F1) {
stdio::switch_terminal(0); stdio::switch_terminal(0);
} else if(alt && key == keyboard::KEY_F2){ } else if (alt && key == keyboard::KEY_F2) {
stdio::switch_terminal(1); stdio::switch_terminal(1);
} else if(alt && key == keyboard::KEY_F3){ } else if (alt && key == keyboard::KEY_F3) {
stdio::switch_terminal(2); stdio::switch_terminal(2);
} }
if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){ if (key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT) {
shift = false; shift = false;
} }
if(key == keyboard::KEY_ALT){ if (key == keyboard::KEY_ALT) {
alt = false; alt = false;
} }
} }
//Key pressed //Key pressed
else { else {
if(key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT){ if (key == keyboard::KEY_LEFT_SHIFT || key == keyboard::KEY_RIGHT_SHIFT) {
shift = true; shift = true;
} else if(key == keyboard::KEY_ALT){ } else if (key == keyboard::KEY_ALT) {
alt = true; alt = true;
} else if(key == keyboard::KEY_BACKSPACE){ } else if (key == keyboard::KEY_BACKSPACE) {
if(!terminal.input_buffer.empty()){ if (!terminal.input_buffer.empty()) {
terminal.input_buffer.pop_last(); terminal.input_buffer.pop_last();
terminal.print('\b'); terminal.print('\b');
} }
} else { } else {
auto qwertz_key = auto qwertz_key =
shift shift
? keyboard::shift_key_to_ascii(key) ? keyboard::shift_key_to_ascii(key)
: keyboard::key_to_ascii(key); : keyboard::key_to_ascii(key);
if(qwertz_key){ if (qwertz_key) {
terminal.input_buffer.push(qwertz_key); terminal.input_buffer.push(qwertz_key);
terminal.print(qwertz_key); terminal.print(qwertz_key);
if(qwertz_key == '\n'){ if (qwertz_key == '\n') {
// Transfer current line to the canonical buffer // Transfer current line to the canonical buffer
while(!terminal.input_buffer.empty()){ while (!terminal.input_buffer.empty()) {
terminal.canonical_buffer.push(terminal.input_buffer.pop()); terminal.canonical_buffer.push(terminal.input_buffer.pop());
} }
@ -112,10 +112,10 @@ void input_thread(void* data){
} }
// Handle mouse input // Handle mouse input
while(!terminal.mouse_buffer.empty()){ while (!terminal.mouse_buffer.empty()) {
auto key = terminal.mouse_buffer.pop(); auto key = terminal.mouse_buffer.pop();
if(!terminal.canonical && terminal.mouse){ if (!terminal.canonical && terminal.is_mouse()) {
terminal.raw_buffer.push(key); terminal.raw_buffer.push(key);
terminal.input_queue.notify_one(); terminal.input_queue.notify_one();
@ -128,10 +128,10 @@ void input_thread(void* data){
} //end of anonymous namespace } //end of anonymous namespace
void stdio::init_terminals(){ void stdio::init_terminals() {
size_t id = 0; size_t id = 0;
for(auto& terminal : terminals){ for (auto& terminal : terminals) {
terminal.id = id++; terminal.id = id++;
terminal.active = false; terminal.active = false;
terminal.canonical = true; terminal.canonical = true;
@ -140,25 +140,25 @@ void stdio::init_terminals(){
// Initialize the active terminal // Initialize the active terminal
active_terminal = 0; active_terminal = 0;
terminals[active_terminal].active = true; terminals[active_terminal].active = true;
terminals[active_terminal].get_console().set_active(true); terminals[active_terminal].get_console().set_active(true);
} }
void stdio::register_devices(){ void stdio::register_devices() {
for(auto& terminal : terminals){ for (auto& terminal : terminals) {
std::string name = std::string("tty") + std::to_string(terminal.id); std::string name = std::string("tty") + std::to_string(terminal.id);
devfs::register_device("/dev/", name, devfs::device_type::CHAR_DEVICE, tty_driver, &terminal); devfs::register_device("/dev/", name, devfs::device_type::CHAR_DEVICE, tty_driver, &terminal);
} }
} }
void stdio::finalize(){ void stdio::finalize() {
for(auto& terminal : terminals){ for (auto& terminal : terminals) {
auto* user_stack = new char[scheduler::user_stack_size]; auto* user_stack = new char[scheduler::user_stack_size];
auto* kernel_stack = new char[scheduler::kernel_stack_size]; auto* kernel_stack = new char[scheduler::kernel_stack_size];
auto& input_process = scheduler::create_kernel_task_args("tty_input", user_stack, kernel_stack, &input_thread, &terminal); auto& input_process = scheduler::create_kernel_task_args("tty_input", user_stack, kernel_stack, &input_thread, &terminal);
input_process.ppid = 1; input_process.ppid = 1;
input_process.priority = scheduler::DEFAULT_PRIORITY; input_process.priority = scheduler::DEFAULT_PRIORITY;
@ -172,22 +172,22 @@ void stdio::finalize(){
} }
} }
size_t stdio::terminals_count(){ size_t stdio::terminals_count() {
return MAX_TERMINALS; return MAX_TERMINALS;
} }
stdio::virtual_terminal& stdio::get_active_terminal(){ stdio::virtual_terminal& stdio::get_active_terminal() {
return terminals[active_terminal]; return terminals[active_terminal];
} }
stdio::virtual_terminal& stdio::get_terminal(size_t id){ stdio::virtual_terminal& stdio::get_terminal(size_t id) {
thor_assert(id < MAX_TERMINALS, "Out of bound tty"); thor_assert(id < MAX_TERMINALS, "Out of bound tty");
return terminals[id]; return terminals[id];
} }
void stdio::switch_terminal(size_t id){ void stdio::switch_terminal(size_t id) {
if(active_terminal != id){ if (active_terminal != id) {
logging::logf(logging::log_level::TRACE, "stdio: Switch activate virtual terminal %u\n", id); logging::logf(logging::log_level::TRACE, "stdio: Switch activate virtual terminal %u\n", id);
// Effectively switch the terminal // Effectively switch the terminal

View File

@ -17,12 +17,12 @@
#include "print.hpp" #include "print.hpp"
void stdio::virtual_terminal::print(char key){ void stdio::virtual_terminal::print(char key) {
cons.print(key); cons.print(key);
} }
void stdio::virtual_terminal::send_input(char key){ void stdio::virtual_terminal::send_input(char key) {
if(!input_thread_pid){ if (!input_thread_pid) {
return; return;
} }
@ -34,8 +34,8 @@ void stdio::virtual_terminal::send_input(char key){
scheduler::unblock_process_hint(input_thread_pid); scheduler::unblock_process_hint(input_thread_pid);
} }
void stdio::virtual_terminal::send_mouse_input(std::keycode key){ void stdio::virtual_terminal::send_mouse_input(std::keycode key) {
if(!input_thread_pid){ if (!input_thread_pid) {
return; return;
} }
@ -47,16 +47,16 @@ void stdio::virtual_terminal::send_mouse_input(std::keycode key){
scheduler::unblock_process_hint(input_thread_pid); scheduler::unblock_process_hint(input_thread_pid);
} }
size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max){ size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max) {
size_t read = 0; size_t read = 0;
while(true){ while (true) {
while(!canonical_buffer.empty()){ while (!canonical_buffer.empty()) {
auto c = canonical_buffer.pop(); auto c = canonical_buffer.pop();
buffer[read++] = c; buffer[read++] = c;
if(read >= max || c == '\n'){ if (read >= max || c == '\n') {
return read; return read;
} }
} }
@ -66,45 +66,45 @@ size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max){
} }
// TODO In case of max < read, the timeout is not respected // TODO In case of max < read, the timeout is not respected
size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max, size_t ms){ size_t stdio::virtual_terminal::read_input_can(char* buffer, size_t max, size_t ms) {
size_t read = 0; size_t read = 0;
while(true){ while (true) {
while(!canonical_buffer.empty()){ while (!canonical_buffer.empty()) {
auto c = canonical_buffer.pop(); auto c = canonical_buffer.pop();
buffer[read++] = c; buffer[read++] = c;
if(read >= max || c == '\n'){ if (read >= max || c == '\n') {
return read; return read;
} }
} }
if(!ms){ if (!ms) {
return read; return read;
} }
if(!input_queue.wait_for(ms)){ if (!input_queue.wait_for(ms)) {
return read; return read;
} }
} }
} }
size_t stdio::virtual_terminal::read_input_raw(){ size_t stdio::virtual_terminal::read_input_raw() {
if(raw_buffer.empty()){ if (raw_buffer.empty()) {
input_queue.wait(); input_queue.wait();
} }
return raw_buffer.pop(); return raw_buffer.pop();
} }
size_t stdio::virtual_terminal::read_input_raw(size_t ms){ size_t stdio::virtual_terminal::read_input_raw(size_t ms) {
if(raw_buffer.empty()){ if (raw_buffer.empty()) {
if(!ms){ if (!ms) {
return static_cast<size_t>(std::keycode::TIMEOUT); return static_cast<size_t>(std::keycode::TIMEOUT);
} }
if(!input_queue.wait_for(ms)){ if (!input_queue.wait_for(ms)) {
return static_cast<size_t>(std::keycode::TIMEOUT); return static_cast<size_t>(std::keycode::TIMEOUT);
} }
} }
@ -114,13 +114,13 @@ size_t stdio::virtual_terminal::read_input_raw(size_t ms){
return raw_buffer.pop(); return raw_buffer.pop();
} }
void stdio::virtual_terminal::set_canonical(bool can){ void stdio::virtual_terminal::set_canonical(bool can) {
logging::logf(logging::log_level::TRACE, "Switched terminal %u canonical mode from %u to %u\n", id, uint64_t(canonical), uint64_t(can)); logging::logf(logging::log_level::TRACE, "Switched terminal %u canonical mode from %u to %u\n", id, uint64_t(canonical), uint64_t(can));
canonical = can; canonical = can;
} }
void stdio::virtual_terminal::set_mouse(bool m){ void stdio::virtual_terminal::set_mouse(bool m) {
logging::logf(logging::log_level::TRACE, "Switched terminal %u mouse handling mode from %u to %u\n", id, uint64_t(mouse), uint64_t(m)); logging::logf(logging::log_level::TRACE, "Switched terminal %u mouse handling mode from %u to %u\n", id, uint64_t(mouse), uint64_t(m));
mouse = m; mouse = m;
@ -130,8 +130,12 @@ bool stdio::virtual_terminal::is_canonical() const {
return canonical; return canonical;
} }
void stdio::virtual_terminal::set_active(bool active){ bool stdio::virtual_terminal::is_mouse() const {
if(this->active == active){ return mouse;
}
void stdio::virtual_terminal::set_active(bool active) {
if (this->active == active) {
return; return;
} }
@ -139,13 +143,13 @@ void stdio::virtual_terminal::set_active(bool active){
cons.set_active(active); cons.set_active(active);
if(active){ if (active) {
cons.restore(); cons.restore();
} else { } else {
cons.save(); cons.save();
} }
} }
stdio::console& stdio::virtual_terminal::get_console(){ stdio::console& stdio::virtual_terminal::get_console() {
return cons; return cons;
} }

View File

@ -12,70 +12,70 @@
namespace { namespace {
enum vga_color { enum vga_color {
BLACK = 0, BLACK = 0,
BLUE = 1, BLUE = 1,
GREEN = 2, GREEN = 2,
CYAN = 3, CYAN = 3,
RED = 4, RED = 4,
MAGENTA = 5, MAGENTA = 5,
BROWN = 6, BROWN = 6,
LIGHT_GREY = 7, LIGHT_GREY = 7,
DARK_GREY = 8, DARK_GREY = 8,
LIGHT_BLUE = 9, LIGHT_BLUE = 9,
LIGHT_GREEN = 10, LIGHT_GREEN = 10,
LIGHT_CYAN = 11, LIGHT_CYAN = 11,
LIGHT_RED = 12, LIGHT_RED = 12,
LIGHT_MAGENTA = 13, LIGHT_MAGENTA = 13,
LIGHT_BROWN = 14, LIGHT_BROWN = 14,
WHITE = 15, WHITE = 15,
}; };
uint8_t make_color(vga_color fg, vga_color bg){ uint8_t make_color(vga_color fg, vga_color bg) {
return fg | bg << 4; return fg | bg << 4;
} }
uint16_t make_vga_entry(char c, uint8_t color){ uint16_t make_vga_entry(char c, uint8_t color) {
uint16_t c16 = c; uint16_t c16 = c;
uint16_t color16 = color; uint16_t color16 = color;
return c16 | color16 << 8; return c16 | color16 << 8;
} }
} //end of anonymous namespace } //end of anonymous namespace
void text_console::init(){ void text_console::init() {
//Nothing special to init //Nothing special to init
} }
size_t text_console::lines(){ size_t text_console::lines() {
return 25; return 25;
} }
size_t text_console::columns(){ size_t text_console::columns() {
return 80; return 80;
} }
void text_console::clear(){ void text_console::clear() {
for(int line = 0; line < 25; ++line){ for (int line = 0; line < 25; ++line) {
for(uint64_t column = 0; column < 80; ++column){ for (uint64_t column = 0; column < 80; ++column) {
print_char(line, column, ' '); print_char(line, column, ' ');
} }
} }
} }
void text_console::scroll_up(){ void text_console::scroll_up() {
auto vga_buffer_fast = reinterpret_cast<uint64_t*>(0x0B8000); auto vga_buffer_fast = reinterpret_cast<uint64_t*>(0x0B8000);
auto destination = vga_buffer_fast; auto destination = vga_buffer_fast;
auto source = &vga_buffer_fast[20]; auto source = &vga_buffer_fast[20];
std::copy_n(source, 24 * 20, destination); std::copy_n(source, 24 * 20, destination);
auto vga_buffer = reinterpret_cast<uint16_t*>(0x0B8000); auto vga_buffer = reinterpret_cast<uint16_t*>(0x0B8000);
for(uint64_t i = 0; i < 80; ++i){ for (uint64_t i = 0; i < 80; ++i) {
vga_buffer[24 * 80 + i] = make_vga_entry(' ', make_color(WHITE, BLACK)); vga_buffer[24 * 80 + i] = make_vga_entry(' ', make_color(WHITE, BLACK));
} }
} }
void text_console::print_char(size_t line, size_t column, char c){ void text_console::print_char(size_t line, size_t column, char c) {
uint16_t* vga_buffer = reinterpret_cast<uint16_t*>(0x0B8000); uint16_t* vga_buffer = reinterpret_cast<uint16_t*>(0x0B8000);
vga_buffer[line * 80 + column] = make_vga_entry(c, make_color(WHITE, BLACK)); vga_buffer[line * 80 + column] = make_vga_entry(c, make_color(WHITE, BLACK));