1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 08:48:11 +00:00

Virtual consoles kinda work!

We now make three VirtualConsoles at boot: tty0, tty1, and tty2.
We launch an instance of /bin/sh in each one.
You switch between them with Alt+1/2/3

How very very cool :^)
This commit is contained in:
Andreas Kling 2018-10-30 15:33:37 +01:00
parent 68739dc43e
commit 7a7956a595
24 changed files with 251 additions and 103 deletions

View file

@ -3,16 +3,17 @@
#include "kmalloc.h"
#include "i386.h"
#include "StdLib.h"
#include "Keyboard.h"
#include <AK/String.h>
static byte* s_vgaBuffer = (byte*)0xb8000;
static VirtualConsole* s_consoles[6];
static unsigned s_activeConsole;
static int s_activeConsole;
void VirtualConsole::initialize()
{
memset(s_consoles, 0, sizeof(s_consoles));
s_activeConsole = 0;
s_activeConsole = -1;
}
VirtualConsole::VirtualConsole(unsigned index, InitialContents initialContents)
@ -40,7 +41,7 @@ VirtualConsole::~VirtualConsole()
void VirtualConsole::switchTo(unsigned index)
{
if (index == s_activeConsole)
if ((int)index == s_activeConsole)
return;
dbgprintf("[VC] Switch to %u\n", index);
ASSERT(index < 6);
@ -49,6 +50,7 @@ void VirtualConsole::switchTo(unsigned index)
s_consoles[s_activeConsole]->setActive(false);
s_activeConsole = index;
s_consoles[s_activeConsole]->setActive(true);
Console::the().setImplementation(s_consoles[s_activeConsole]);
}
void VirtualConsole::setActive(bool b)
@ -60,14 +62,14 @@ void VirtualConsole::setActive(bool b)
m_active = b;
if (!m_active) {
dbgprintf("%u becomes inactive, copying to buffer\n", m_index);
memcpy(m_buffer, s_vgaBuffer, 80 * 25 * 2);
return;
}
dbgprintf("%u becomes active, copying from buffer, set cursor %u,%u\n", m_index, m_cursorRow, m_cursorColumn);
memcpy(s_vgaBuffer, m_buffer, 80 * 25 * 2);
vga_set_cursor(m_cursorRow, m_cursorColumn);
Keyboard::the().setClient(this);
}
inline bool isParameter(byte ch)
@ -205,7 +207,6 @@ void VirtualConsole::escape$m(const Vector<unsigned>& params)
break;
}
}
vga_set_attr(m_currentAttribute);
}
void VirtualConsole::escape$s(const Vector<unsigned>&)
@ -216,9 +217,7 @@ void VirtualConsole::escape$s(const Vector<unsigned>&)
void VirtualConsole::escape$u(const Vector<unsigned>&)
{
m_cursorRow = m_savedCursorRow;
m_cursorColumn = m_savedCursorColumn;
vga_set_cursor(m_cursorRow, m_cursorColumn);
setCursor(m_savedCursorRow, m_savedCursorColumn);
}
void VirtualConsole::escape$H(const Vector<unsigned>& params)
@ -229,9 +228,7 @@ void VirtualConsole::escape$H(const Vector<unsigned>& params)
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);
setCursor(row - 1, col - 1);
}
void VirtualConsole::escape$J(const Vector<unsigned>& params)
@ -284,16 +281,42 @@ void VirtualConsole::executeEscapeSequence(byte final)
m_intermediates.clear();
}
void VirtualConsole::onChar(byte ch)
void VirtualConsole::scrollUp()
{
auto scrollup = [&] {
if (m_cursorRow == (m_rows - 1)) {
if (m_cursorRow == (m_rows - 1)) {
memcpy(m_buffer, m_buffer + 160, 160 * 24);
word* linemem = (word*)&m_buffer[24 * 160];
for (word i = 0; i < 80; ++i)
linemem[i] = 0x0720;
if (m_active)
vga_scroll_up();
} else {
++m_cursorRow;
}
m_cursorColumn = 0;
};
} else {
++m_cursorRow;
}
m_cursorColumn = 0;
}
void VirtualConsole::setCursor(unsigned row, unsigned column)
{
m_cursorRow = row;
m_cursorColumn = column;
if (m_active)
vga_set_cursor(m_cursorRow, m_cursorColumn);
}
void VirtualConsole::putCharacterAt(unsigned row, unsigned column, byte ch)
{
word cur = (row * 160) + (column * 2);
m_buffer[cur] = ch;
m_buffer[cur + 1] = m_currentAttribute;
if (m_active)
vga_putch_at(row, column, ch, m_currentAttribute);
}
void VirtualConsole::onChar(byte ch, bool shouldEmit)
{
if (shouldEmit)
emit(ch);
switch (m_escState) {
case ExpectBracket:
@ -336,32 +359,43 @@ void VirtualConsole::onChar(byte ch)
return;
case 8: // Backspace
if (m_cursorColumn) {
--m_cursorColumn;\
vga_set_cursor(m_cursorRow, m_cursorColumn);
vga_putch_at(m_cursorRow, m_cursorColumn, ' ');
setCursor(m_cursorRow, m_cursorColumn - 1);
putCharacterAt(m_cursorRow, m_cursorColumn, ' ');
return;
}
break;
case '\n':
scrollup();
vga_set_cursor(m_cursorRow, m_cursorColumn);
scrollUp();
setCursor(m_cursorRow, m_cursorColumn);
return;
}
vga_putch_at(m_cursorRow, m_cursorColumn, ch);
putCharacterAt(m_cursorRow, m_cursorColumn, ch);
++m_cursorColumn;
if (m_cursorColumn >= m_columns)
scrollup();
vga_set_cursor(m_cursorRow, m_cursorColumn);
scrollUp();
setCursor(m_cursorRow, m_cursorColumn);
}
void VirtualConsole::onKeyPress(byte ch)
{
onChar(ch);
emit(ch);
}
void VirtualConsole::onConsoleReceive(byte ch)
{
onChar(ch);
onChar(ch, false);
}
void VirtualConsole::onTTYWrite(byte ch)
{
onChar(ch, false);
}
String VirtualConsole::ttyName() const
{
char buf[8];
ksprintf(buf, "tty%u", m_index);
return String(buf);
}