Copied some code from the console driver: we now understand cursor movements,

and even color changes :-)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13898 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-08-04 14:55:11 +00:00
parent 6b9018bf1c
commit 67f207164b
1 changed files with 331 additions and 16 deletions

View File

@ -6,6 +6,7 @@
#include "blue_screen.h"
#include <KernelExport.h>
#include <frame_buffer_console.h>
#include <console.h>
#include <arch/debug_console.h>
@ -17,11 +18,31 @@
#define USE_SCROLLING 0
#define NO_CLEAR 1
#define MAX_ARGS 8
#define FMASK 0x0f
#define BMASK 0x70
typedef enum {
CONSOLE_STATE_NORMAL = 0,
CONSOLE_STATE_GOT_ESCAPE,
CONSOLE_STATE_SEEN_BRACKET,
CONSOLE_STATE_NEW_ARG,
CONSOLE_STATE_PARSING_ARG,
} console_state;
struct screen_info {
int32 columns;
int32 rows;
int32 x, y;
uint8 attr;
bool bright_attr;
bool reverse_attr;
// state machine
console_state state;
int32 arg_count;
int32 args[MAX_ARGS];
} sScreen;
console_module_info *sModule;
@ -41,6 +62,15 @@ update_cursor(int32 x, int32 y)
}
static inline void
move_cursor(int32 x, int32 y)
{
sScreen.x = x;
sScreen.y = y;
update_cursor(x, y);
}
#if USE_SCROLLING
/** scroll from the cursor line up to the top of the scroll region up one line */
@ -100,27 +130,311 @@ put_character(char c)
}
static void
set_vt100_attributes(int32 *args, int32 argCount)
{
if (argCount == 0) {
// that's the default (attributes off)
argCount++;
args[0] = 0;
}
for (int32 i = 0; i < argCount; i++) {
switch (args[i]) {
case 0: // reset
sScreen.attr = 0x0f;
sScreen.bright_attr = true;
sScreen.reverse_attr = false;
break;
case 1: // bright
sScreen.bright_attr = true;
sScreen.attr |= 0x08; // set the bright bit
break;
case 2: // dim
sScreen.bright_attr = false;
sScreen.attr &= ~0x08; // unset the bright bit
break;
case 4: // underscore we can't do
break;
case 5: // blink
sScreen.attr |= 0x80; // set the blink bit
break;
case 7: // reverse
sScreen.reverse_attr = true;
sScreen.attr = ((sScreen.attr & BMASK) >> 4) | ((sScreen.attr & FMASK) << 4);
if (sScreen.bright_attr)
sScreen.attr |= 0x08;
break;
case 8: // hidden?
break;
/* foreground colors */
case 30: sScreen.attr = (sScreen.attr & ~FMASK) | 0 | (sScreen.bright_attr ? 0x08 : 0); break; // black
case 31: sScreen.attr = (sScreen.attr & ~FMASK) | 4 | (sScreen.bright_attr ? 0x08 : 0); break; // red
case 32: sScreen.attr = (sScreen.attr & ~FMASK) | 2 | (sScreen.bright_attr ? 0x08 : 0); break; // green
case 33: sScreen.attr = (sScreen.attr & ~FMASK) | 6 | (sScreen.bright_attr ? 0x08 : 0); break; // yellow
case 34: sScreen.attr = (sScreen.attr & ~FMASK) | 1 | (sScreen.bright_attr ? 0x08 : 0); break; // blue
case 35: sScreen.attr = (sScreen.attr & ~FMASK) | 5 | (sScreen.bright_attr ? 0x08 : 0); break; // magenta
case 36: sScreen.attr = (sScreen.attr & ~FMASK) | 3 | (sScreen.bright_attr ? 0x08 : 0); break; // cyan
case 37: sScreen.attr = (sScreen.attr & ~FMASK) | 7 | (sScreen.bright_attr ? 0x08 : 0); break; // white
/* background colors */
case 40: sScreen.attr = (sScreen.attr & ~BMASK) | (0 << 4); break; // black
case 41: sScreen.attr = (sScreen.attr & ~BMASK) | (4 << 4); break; // red
case 42: sScreen.attr = (sScreen.attr & ~BMASK) | (2 << 4); break; // green
case 43: sScreen.attr = (sScreen.attr & ~BMASK) | (6 << 4); break; // yellow
case 44: sScreen.attr = (sScreen.attr & ~BMASK) | (1 << 4); break; // blue
case 45: sScreen.attr = (sScreen.attr & ~BMASK) | (5 << 4); break; // magenta
case 46: sScreen.attr = (sScreen.attr & ~BMASK) | (3 << 4); break; // cyan
case 47: sScreen.attr = (sScreen.attr & ~BMASK) | (7 << 4); break; // white
}
}
}
static bool
process_vt100_command(const char c, bool seenBracket, int32 *args, int32 argCount)
{
bool ret = true;
// kprintf("process_vt100_command: c '%c', argCount %ld, arg[0] %ld, arg[1] %ld, seenBracket %d\n",
// c, argCount, args[0], args[1], seenBracket);
if (seenBracket) {
switch (c) {
case 'H': /* set cursor position */
case 'f': {
int32 row = argCount > 0 ? args[0] : 1;
int32 col = argCount > 1 ? args[1] : 1;
if (row > 0)
row--;
if (col > 0)
col--;
move_cursor(col, row);
break;
}
case 'A': { /* move up */
int32 deltay = argCount > 0 ? -args[0] : -1;
if (deltay == 0)
deltay = -1;
move_cursor(sScreen.x, sScreen.y + deltay);
break;
}
case 'e':
case 'B': { /* move down */
int32 deltay = argCount > 0 ? args[0] : 1;
if (deltay == 0)
deltay = 1;
move_cursor(sScreen.x, sScreen.y + deltay);
break;
}
case 'D': { /* move left */
int32 deltax = argCount > 0 ? -args[0] : -1;
if (deltax == 0)
deltax = -1;
move_cursor(sScreen.x + deltax, sScreen.y);
break;
}
case 'a':
case 'C': { /* move right */
int32 deltax = argCount > 0 ? args[0] : 1;
if (deltax == 0)
deltax = 1;
move_cursor(sScreen.x + deltax, sScreen.y);
break;
}
case '`':
case 'G': { /* set X position */
int32 newx = argCount > 0 ? args[0] : 1;
if (newx > 0)
newx--;
move_cursor(newx, sScreen.y);
break;
}
case 'd': { /* set y position */
int32 newy = argCount > 0 ? args[0] : 1;
if (newy > 0)
newy--;
move_cursor(sScreen.x, newy);
break;
}
#if 0
case 's': /* save current cursor */
save_cur(console, false);
break;
case 'u': /* restore cursor */
restore_cur(console, false);
break;
case 'r': { /* set scroll region */
int32 low = argCount > 0 ? args[0] : 1;
int32 high = argCount > 1 ? args[1] : sScreen.lines;
if (low <= high)
set_scroll_region(console, low - 1, high - 1);
break;
}
case 'L': { /* scroll virtual down at cursor */
int32 lines = argCount > 0 ? args[0] : 1;
while (lines > 0) {
scrdown(console);
lines--;
}
break;
}
case 'M': { /* scroll virtual up at cursor */
int32 lines = argCount > 0 ? args[0] : 1;
while (lines > 0) {
scrup(console);
lines--;
}
break;
}
case 'K':
if (argCount == 0 || args[0] == 0) {
// erase to end of line
erase_line(console, LINE_ERASE_RIGHT);
} else if (argCount > 0) {
if (args[0] == 1)
erase_line(console, LINE_ERASE_LEFT);
else if (args[0] == 2)
erase_line(console, LINE_ERASE_WHOLE);
}
break;
case 'J':
if (argCount == 0 || args[0] == 0) {
// erase to end of screen
erase_screen(console, SCREEN_ERASE_DOWN);
} else {
if (args[0] == 1)
erase_screen(console, SCREEN_ERASE_UP);
else if (args[0] == 2)
erase_screen(console, SCREEN_ERASE_WHOLE);
}
break;
#endif
case 'm':
if (argCount >= 0)
set_vt100_attributes(args, argCount);
break;
default:
ret = false;
}
} else {
switch (c) {
#if 0
case 'c':
reset_console(console);
break;
case 'D':
rlf(console);
break;
case 'M':
lf(console);
break;
case '7':
save_cur(console, true);
break;
case '8':
restore_cur(console, true);
break;
#endif
default:
ret = false;
}
}
return ret;
}
static void
parse_character(char c)
{
// just output the stuff
switch (c) {
case '\n':
next_line();
break;
case 0x8:
back_space();
break;
case '\t':
put_character(' ');
break;
switch (sScreen.state) {
case CONSOLE_STATE_NORMAL:
// just output the stuff
switch (c) {
case '\n':
next_line();
break;
case 0x8:
back_space();
break;
case '\t':
// ToDo: real tab...
put_character(' ');
break;
case '\r':
case '\0':
break;
case '\r':
case '\0':
case '\a': // beep
break;
default:
put_character(c);
case 0x1b:
// escape character
sScreen.arg_count = -1;
sScreen.state = CONSOLE_STATE_GOT_ESCAPE;
break;
default:
put_character(c);
}
break;
case CONSOLE_STATE_GOT_ESCAPE:
// look for either commands with no argument, or the '[' character
switch (c) {
case '[':
sScreen.state = CONSOLE_STATE_SEEN_BRACKET;
break;
default:
sScreen.args[sScreen.arg_count] = 0;
process_vt100_command(c, false, sScreen.args, sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
break;
case CONSOLE_STATE_SEEN_BRACKET:
switch (c) {
case '0'...'9':
sScreen.arg_count = 0;
sScreen.args[sScreen.arg_count] = c - '0';
sScreen.state = CONSOLE_STATE_PARSING_ARG;
break;
case '?':
// private DEC mode parameter follows - we ignore those anyway
break;
default:
process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
break;
case CONSOLE_STATE_NEW_ARG:
switch (c) {
case '0'...'9':
sScreen.arg_count++;
if (sScreen.arg_count == MAX_ARGS) {
sScreen.state = CONSOLE_STATE_NORMAL;
break;
}
sScreen.args[sScreen.arg_count] = c - '0';
sScreen.state = CONSOLE_STATE_PARSING_ARG;
break;
default:
process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
break;
case CONSOLE_STATE_PARSING_ARG:
// parse args
switch (c) {
case '0'...'9':
sScreen.args[sScreen.arg_count] *= 10;
sScreen.args[sScreen.arg_count] += c - '0';
break;
case ';':
sScreen.state = CONSOLE_STATE_NEW_ARG;
break;
default:
process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
}
}
@ -148,6 +462,7 @@ blue_screen_enter(void)
{
sScreen.attr = 0x0f; // black on white
sScreen.x = sScreen.y = 0;
sScreen.state = CONSOLE_STATE_NORMAL;
sModule->get_size(&sScreen.columns, &sScreen.rows);
#if !NO_CLEAR