hos/kernel/char/vconsole.cpp

275 lines
6.3 KiB
C++

// vconsole.cpp
// Author: Josh Holtrop
// Date: 08/02/04
// Modified: 05/11/05
extern "C"
{
#include "hos_defines.h"
#include "mm/vmm.h"
#include "lang/lang.h"
#include "display/display.h"
#include "functions.h"
}
#include "devices.h"
#include "char/vconsole.h"
VConsole *vconsoles[VCONSOLE_MAX]; // pointer to virtual console structs
char ansi2vgaAttr[8] = {0, 4, 2, 6, 1, 5, 3, 7};
void vconsole_setup(int width, int height)
{
for (int i = 0; i < VCONSOLE_MAX; i++)
vconsoles[i] = new VConsole(width, height);
}
int vconsole_activate(u32_t id)
{
if (id >= VCONSOLE_MAX)
return -1;
vconsoles[id]->activate();
return 0;
}
int vconsole_deactivate(u32_t id)
{
if (id >= VCONSOLE_MAX)
return -1;
vconsoles[id]->deactivate();
return 0;
}
VConsoleDriver::~VConsoleDriver()
{
for (int i = 0; i < VCONSOLE_MAX; i++)
if (vconsoles[i])
delete vconsoles[i];
}
int VConsoleDriver::char_write(minor_t minor, int c)
{
if (minor < 0 || minor >= VCONSOLE_MAX)
return -1;
if (!vconsoles[minor])
return -2;
return vconsoles[minor]->char_write(c);
}
VConsole::VConsole(int width, int height)
{
myBuffer = new u16_t[width * height];
myBuffer2 = NULL;
myWidth = width;
myHeight = height;
myAttribute = myForeground = 0x07;
memsetw(myBuffer, 0x0720, width * height);
myCursorPosition = 0;
myCursorStackPosition = myEscapeLevel = myEscapePosition = myBackground =
myBold = myReverse = myBlink = myConcealed = myActive = 0;
}
VConsole::~VConsole()
{
delete[] myBuffer;
}
void VConsole::activate()
{
if (myActive) // don't activate if already active
return;
myActive = 1;
myBuffer2 = myBuffer;
myBuffer = (u16_t *)CONSOLE_MEMORY;
memcpyd(myBuffer, myBuffer2, (myWidth * myHeight) >> 1);
writeCursorPosition(myCursorPosition);
}
void VConsole::deactivate()
{
if (!myActive) // don't deactivate non-active console
return;
myActive = 0;
myBuffer = myBuffer2;
myBuffer2 = NULL;
memcpyd(myBuffer, (u16_t *)CONSOLE_MEMORY, (myWidth * myHeight) >> 1);
}
int VConsole::char_write(int c)
{
int cursorY = myCursorPosition / myWidth;
int cursorX = myCursorPosition % myWidth;
switch (myEscapeLevel)
{
case 2:
if (c >= '0' && c <= '9') // c is part of an escape value
{
myEscapeValue[myEscapePosition] *= 10;
myEscapeValue[myEscapePosition] += c - '0';
return 0;
}
else if (c == ';')
{
if (myEscapePosition < 7)
myEscapePosition++;
return 0;
}
switch (c)
{
case 'A': // move cursor up n rows
update_cursor_coord(cursorY - myEscapeValue[0], cursorX);
break;
case 'B': // move cursor down n rows
update_cursor_coord(cursorY + myEscapeValue[0], cursorX);
break;
case 'C': // move cursor left n columns
update_cursor_coord(cursorY, cursorX - myEscapeValue[0]);
break;
case 'D': // move cursor right n columns
update_cursor_coord(cursorY, cursorX + myEscapeValue[0]);
break;
case 'H':
case 'f': // move cursor to position (x,y) upper left is (1,1)
update_cursor_coord(myEscapeValue[1] - 1, myEscapeValue[0] - 1);
break;
case 'J': // clear screen, home cursor
memsetw(myBuffer, 0x0720, myWidth * myHeight);
update_cursor_coord(0, 0);
break;
case 'K': // erase line from cursor position (including char. under cursor) to end of line
memsetw(myBuffer + myCursorPosition, 0x0720, myWidth - cursorX);
break;
case 's': // push cursor position on an internal stack
if (myCursorStackPosition < 16)
myCursorStack[myCursorStackPosition++] = myCursorPosition;
break;
case 'u': // pop cursor position from stack
if (myCursorStackPosition > 0)
update_cursor(myCursorStack[--myCursorStackPosition]);
break;
case 'm': // set text attributes
for (int evalEscapePosition = 0; evalEscapePosition <= myEscapePosition; evalEscapePosition++)
{
switch (myEscapeValue[evalEscapePosition])
{
case 0:
myForeground = 0x07;
myBackground = myConcealed = myReverse = myBlink = myBold = 0;
update_attribute();
break;
case 1:
myBold = 1;
update_attribute();
break;
case 5:
myBlink = 1;
update_attribute();
break;
case 7:
myReverse = 1;
update_attribute();
break;
case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
myForeground = ansi2vgaAttr[myEscapeValue[evalEscapePosition] - 30];
update_attribute();
break;
case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
myBackground = ansi2vgaAttr[myEscapeValue[evalEscapePosition] - 40];
update_attribute();
break;
}
}
myEscapePosition = 0;
break;
}
memsetd(myEscapeValue, 0, 8);
myEscapePosition = 0;
myEscapeLevel = 0;
return 0;
case 1:
if (c == '[')
myEscapeLevel = 2;
break;
myEscapeLevel = 0;
return 0; // invalid escape sequence
default:
if (c == '\e')
{
myEscapeLevel = 1;
return 0;
}
put_char(c);
}
return 0;
}
void VConsole::put_char(int c)
{
if (!myConcealed)
{
switch (c)
{
case '\t':
if (myCursorPosition % 8)
update_cursor(myCursorPosition + (8 - (myCursorPosition % 8)));
else
update_cursor(myCursorPosition + 8);
break;
case '\n':
if (myCursorPosition % myWidth)
update_cursor(myCursorPosition + (myWidth - (myCursorPosition % myWidth)));
else
update_cursor(myCursorPosition + myWidth);
break;
default:
myBuffer[myCursorPosition] = c | (myAttribute << 8);
update_cursor(myCursorPosition + 1);
}
}
}
void VConsole::update_cursor_coord(int y, int x)
{
if (y < 0)
y = 0;
else if (y >= myHeight)
y = myHeight - 1;
if (x < 0)
x = 0;
else if (x >= myWidth)
x = myWidth - 1;
update_cursor(myWidth * y + x);
}
void VConsole::update_cursor(u16_t position)
{
myCursorPosition = position;
if (position >= (myWidth * myHeight)) // time to scroll console
{
int i;
for (i = 0; i < myCursorStackPosition; i++)
{
myCursorStack[i] -= myWidth;
if (myCursorStack[i] < 0)
myCursorStack[i] = 0;
}
myCursorPosition -= myWidth;
memcpyw(myBuffer, myBuffer + myWidth, myWidth * (myHeight - 1));
memsetw(myBuffer + (myWidth * (myHeight - 1)), 0x0720, myWidth);
}
if (myActive)
writeCursorPosition(position);
}
void VConsole::update_attribute()
{
if (myReverse)
myAttribute = myBlink << 7 | myForeground << 4 | myBold << 3 | myBackground;
else
myAttribute = myBlink << 7 | myBackground << 4 | myBold << 3 | myForeground;
}