275 lines
6.3 KiB
C++
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;
|
|
}
|
|
|
|
|