From 67f207164b759ef6e03dae8cba79800ef142df04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 4 Aug 2005 14:55:11 +0000 Subject: [PATCH] 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 --- src/system/kernel/debug/blue_screen.cpp | 347 ++++++++++++++++++++++-- 1 file changed, 331 insertions(+), 16 deletions(-) diff --git a/src/system/kernel/debug/blue_screen.cpp b/src/system/kernel/debug/blue_screen.cpp index 8fa09a89f5..b06e14a565 100644 --- a/src/system/kernel/debug/blue_screen.cpp +++ b/src/system/kernel/debug/blue_screen.cpp @@ -6,6 +6,7 @@ #include "blue_screen.h" +#include #include #include #include @@ -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