refactor console code for better ansi escape-code handling

This commit is contained in:
Dave Murphy 2025-06-24 16:16:47 +01:00
parent 2680749e8c
commit b82bc6c97a
No known key found for this signature in database
GPG Key ID: F7FD5492264BB9D0
3 changed files with 436 additions and 413 deletions

View File

@ -121,6 +121,8 @@ struct PrintConsole
#define CONSOLE_CROSSED_OUT (1<<8) ///< Crossed out text #define CONSOLE_CROSSED_OUT (1<<8) ///< Crossed out text
#define CONSOLE_FG_CUSTOM (1<<9) ///< Foreground custom color #define CONSOLE_FG_CUSTOM (1<<9) ///< Foreground custom color
#define CONSOLE_BG_CUSTOM (1<<10) ///< Background custom color #define CONSOLE_BG_CUSTOM (1<<10) ///< Background custom color
#define CONSOLE_COLOR_FG_BRIGHT (1<<11) ///< Bright foreground color
#define CONSOLE_COLOR_BG_BRIGHT (1<<12) ///< Bright background color
/// Console debug devices supported by libnx. /// Console debug devices supported by libnx.
typedef enum { typedef enum {

View File

@ -28,12 +28,12 @@ static PrintConsole defaultConsole =
16, //tile height 16, //tile height
}, },
NULL, //renderer NULL, //renderer
0,0, //cursorX cursorY 1,1, //cursorX cursorY
0,0, //prevcursorX prevcursorY 1,1, //prevcursorX prevcursorY
80, //console width 80, //console width
45, //console height 45, //console height
0, //window x 1, //window x
0, //window y 1, //window y
80, //window width 80, //window width
45, //window height 45, //window height
3, //tab size 3, //tab size
@ -43,64 +43,6 @@ static PrintConsole defaultConsole =
false //console initialized false //console initialized
}; };
static bool parseColor (char **esc, int *escLen, u16 *color, bool *custom)
{
unsigned int p;
unsigned int n;
unsigned int r;
unsigned int g;
unsigned int b;
int consumed;
if (sscanf (*esc, "%d;%n", &p, &consumed) != 1)
return false;
*esc += consumed;
*escLen -= consumed;
if (p == 5) {
if (sscanf (*esc, "%u%n", &n, &consumed) != 1)
return false;
*esc += consumed;
*escLen -= consumed;
if (n <= 15) {
*color = n;
*custom = false;
} else if (n <= 231) {
n -= 16;
r = n / 36;
g = (n - r * 36) / 6;
b = n - r * 36 - g * 6;
*color = RGB565_FROM_RGB8 (colorCube[r], colorCube[g], colorCube[b]);
*custom = true;
} else if (n <= 255) {
n -= 232;
*color = RGB565_FROM_RGB8 (grayScale[n], grayScale[n], grayScale[n]);
*custom = true;
} else {
return false;
}
return true;
} else if (p == 2) {
if (sscanf (*esc, "%u;%u;%u%n", &r, &g, &b, &consumed) != 3)
return false;
*esc += consumed;
*escLen -= consumed;
*color = RGB565_FROM_RGB8 (r, g, b);
*custom = true;
return true;
}
return false;
}
static PrintConsole currentCopy; static PrintConsole currentCopy;
@ -113,7 +55,7 @@ static void consolePrintChar(int c);
static void consoleDrawChar(int c); static void consoleDrawChar(int c);
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
static void consoleCls(char mode) { static void consoleCls(int mode) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
int i = 0; int i = 0;
@ -121,26 +63,25 @@ static void consoleCls(char mode) {
switch (mode) switch (mode)
{ {
case '[': case 0:
case '0':
{ {
colTemp = currentConsole->cursorX ; colTemp = currentConsole->cursorX ;
rowTemp = currentConsole->cursorY ; rowTemp = currentConsole->cursorY ;
while(i++ < ((currentConsole->windowHeight * currentConsole->windowWidth) - (rowTemp * currentConsole->consoleWidth + colTemp))) while(i++ < ((currentConsole->windowHeight * currentConsole->windowWidth) - (rowTemp * currentConsole->windowWidth + colTemp)))
consolePrintChar(' '); consolePrintChar(' ');
currentConsole->cursorX = colTemp; currentConsole->cursorX = colTemp;
currentConsole->cursorY = rowTemp; currentConsole->cursorY = rowTemp;
break; break;
} }
case '1': case 1:
{ {
colTemp = currentConsole->cursorX ; colTemp = currentConsole->cursorX ;
rowTemp = currentConsole->cursorY ; rowTemp = currentConsole->cursorY ;
currentConsole->cursorY = 0; currentConsole->cursorY = 1;
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
while (i++ < (rowTemp * currentConsole->windowWidth + colTemp)) while (i++ < (rowTemp * currentConsole->windowWidth + colTemp))
consolePrintChar(' '); consolePrintChar(' ');
@ -149,22 +90,22 @@ static void consoleCls(char mode) {
currentConsole->cursorY = rowTemp; currentConsole->cursorY = rowTemp;
break; break;
} }
case '2': case 2:
{ {
currentConsole->cursorY = 0; currentConsole->cursorY = 1;
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
while(i++ < currentConsole->windowHeight * currentConsole->windowWidth) while(i++ < currentConsole->windowHeight * currentConsole->windowWidth)
consolePrintChar(' '); consolePrintChar(' ');
currentConsole->cursorY = 0; currentConsole->cursorY = 1;
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
break; break;
} }
} }
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
static void consoleClearLine(char mode) { static void consoleClearLine(int mode) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
int i = 0; int i = 0;
@ -172,40 +113,34 @@ static void consoleClearLine(char mode) {
switch (mode) switch (mode)
{ {
case '[': case 0:
case '0':
{
colTemp = currentConsole->cursorX; colTemp = currentConsole->cursorX;
while(i++ < (currentConsole->windowWidth - colTemp)) { for (i=0; i < currentConsole->windowWidth - colTemp + 1; i++) {
consolePrintChar(' '); consolePrintChar(' ');
} }
currentConsole->cursorX = colTemp; currentConsole->cursorX = colTemp;
break; break;
} case 1:
case '1':
{
colTemp = currentConsole->cursorX ; colTemp = currentConsole->cursorX ;
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
while(i++ < ((currentConsole->windowWidth - colTemp)-2)) { for(i=0; i < colTemp - 1; i++) {
consolePrintChar(' '); consolePrintChar(' ');
} }
currentConsole->cursorX = colTemp; currentConsole->cursorX = colTemp;
break; break;
} case 2:
case '2':
{
colTemp = currentConsole->cursorX ; colTemp = currentConsole->cursorX ;
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
while(i++ < currentConsole->windowWidth) { for(i=0; i < currentConsole->windowWidth; i++) {
consolePrintChar(' '); consolePrintChar(' ');
} }
@ -214,8 +149,6 @@ static void consoleClearLine(char mode) {
break; break;
} }
} }
}
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
static inline void consolePosition(int x, int y) { static inline void consolePosition(int x, int y) {
@ -236,9 +169,251 @@ static inline void consolePosition(int x, int y) {
if(y > currentConsole->windowHeight) if(y > currentConsole->windowHeight)
y = currentConsole->windowHeight; y = currentConsole->windowHeight;
// 1-based adjustment currentConsole->cursorX = x;
currentConsole->cursorX = x - 1; currentConsole->cursorY = y;
currentConsole->cursorY = y - 1; }
#define _ANSI_MAXARGS 16
static struct
{
struct
{
int flags;
u32 fg;
u32 bg;
} color;
int argIdx;
int args[_ANSI_MAXARGS];
int colorArgCount;
unsigned int colorArgs[3];
bool hasArg;
enum
{
ESC_NONE,
ESC_START,
ESC_BUILDING_UNKNOWN,
ESC_BUILDING_FORMAT_FG,
ESC_BUILDING_FORMAT_BG,
ESC_BUILDING_FORMAT_FG_NONRGB,
ESC_BUILDING_FORMAT_BG_NONRGB,
ESC_BUILDING_FORMAT_FG_RGB,
ESC_BUILDING_FORMAT_BG_RGB,
} state;
} escapeSeq;
static void consoleSetColorState(int code)
{
switch(code)
{
case 0: // reset
escapeSeq.color.flags = 0;
escapeSeq.color.bg = 0;
escapeSeq.color.fg = 7;
break;
case 1: // bold
escapeSeq.color.flags &= ~CONSOLE_COLOR_FAINT;
escapeSeq.color.flags |= CONSOLE_COLOR_BOLD;
break;
case 2: // faint
escapeSeq.color.flags &= ~CONSOLE_COLOR_BOLD;
escapeSeq.color.flags |= CONSOLE_COLOR_FAINT;
break;
case 3: // italic
escapeSeq.color.flags |= CONSOLE_ITALIC;
break;
case 4: // underline
escapeSeq.color.flags |= CONSOLE_UNDERLINE;
break;
case 5: // blink slow
escapeSeq.color.flags &= ~CONSOLE_BLINK_FAST;
escapeSeq.color.flags |= CONSOLE_BLINK_SLOW;
break;
case 6: // blink fast
escapeSeq.color.flags &= ~CONSOLE_BLINK_SLOW;
escapeSeq.color.flags |= CONSOLE_BLINK_FAST;
break;
case 7: // reverse video
escapeSeq.color.flags |= CONSOLE_COLOR_REVERSE;
break;
case 8: // conceal
escapeSeq.color.flags |= CONSOLE_CONCEAL;
break;
case 9: // crossed-out
escapeSeq.color.flags |= CONSOLE_CROSSED_OUT;
break;
case 21: // bold off
escapeSeq.color.flags &= ~CONSOLE_COLOR_BOLD;
break;
case 22: // normal color
escapeSeq.color.flags &= ~CONSOLE_COLOR_BOLD;
escapeSeq.color.flags &= ~CONSOLE_COLOR_FAINT;
break;
case 23: // italic off
escapeSeq.color.flags &= ~CONSOLE_ITALIC;
break;
case 24: // underline off
escapeSeq.color.flags &= ~CONSOLE_UNDERLINE;
break;
case 25: // blink off
escapeSeq.color.flags &= ~CONSOLE_BLINK_SLOW;
escapeSeq.color.flags &= ~CONSOLE_BLINK_FAST;
break;
case 27: // reverse off
escapeSeq.color.flags &= ~CONSOLE_COLOR_REVERSE;
break;
case 29: // crossed-out off
escapeSeq.color.flags &= ~CONSOLE_CROSSED_OUT;
break;
case 30 ... 37: // writing color
escapeSeq.color.flags &= ~CONSOLE_FG_CUSTOM;
escapeSeq.color.fg = code - 30;
break;
case 38: // custom foreground color
escapeSeq.state = ESC_BUILDING_FORMAT_FG;
escapeSeq.colorArgCount = 0;
break;
case 39: // reset foreground color
escapeSeq.color.flags &= ~CONSOLE_FG_CUSTOM;
escapeSeq.color.fg = 7;
break;
case 40 ... 47: // screen color
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
escapeSeq.color.bg = code - 40;
break;
case 48: // custom background color
escapeSeq.state = ESC_BUILDING_FORMAT_BG;
escapeSeq.colorArgCount = 0;
break;
case 49: // reset background color
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
escapeSeq.color.bg = 0;
break;
case 90 ... 97: // bright foreground
escapeSeq.color.flags &= ~CONSOLE_COLOR_FAINT;
escapeSeq.color.flags |= CONSOLE_COLOR_FG_BRIGHT;
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
escapeSeq.color.fg = code - 90;
break;
case 100 ... 107: // bright background
escapeSeq.color.flags &= ~CONSOLE_COLOR_FAINT;
escapeSeq.color.flags |= CONSOLE_COLOR_BG_BRIGHT;
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
escapeSeq.color.bg = code - 100;
break;
}
}
static void consoleHandleColorEsc(int argCount)
{
escapeSeq.color.bg = currentConsole->bg;
escapeSeq.color.fg = currentConsole->fg;
escapeSeq.color.flags = currentConsole->flags;
for (int arg = 0; arg < argCount; arg++)
{
int code = escapeSeq.args[arg];
switch (escapeSeq.state)
{
case ESC_BUILDING_UNKNOWN:
consoleSetColorState(code);
break;
case ESC_BUILDING_FORMAT_FG:
if (code == 5)
escapeSeq.state = ESC_BUILDING_FORMAT_FG_NONRGB;
else if (code == 2)
escapeSeq.state = ESC_BUILDING_FORMAT_FG_RGB;
else
escapeSeq.state = ESC_BUILDING_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_BG:
if (code == 5)
escapeSeq.state = ESC_BUILDING_FORMAT_BG_NONRGB;
else if (code == 2)
escapeSeq.state = ESC_BUILDING_FORMAT_BG_RGB;
else
escapeSeq.state = ESC_BUILDING_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_FG_NONRGB:
if (code <= 15) {
escapeSeq.color.fg = code;
escapeSeq.color.flags &= ~CONSOLE_FG_CUSTOM;
} else if (code <= 231) {
code -= 16;
unsigned int r = code / 36;
unsigned int g = (code - r * 36) / 6;
unsigned int b = code - r * 36 - g * 6;
escapeSeq.color.fg = RGB565_FROM_RGB8 (colorCube[r], colorCube[g], colorCube[b]);
escapeSeq.color.flags |= CONSOLE_FG_CUSTOM;
} else if (code <= 255) {
code -= 232;
escapeSeq.color.fg = RGB565_FROM_RGB8 (grayScale[code], grayScale[code], grayScale[code]);
escapeSeq.color.flags |= CONSOLE_FG_CUSTOM;
}
escapeSeq.state = ESC_BUILDING_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_BG_NONRGB:
if (code <= 15) {
escapeSeq.color.bg = code;
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
} else if (code <= 231) {
code -= 16;
unsigned int r = code / 36;
unsigned int g = (code - r * 36) / 6;
unsigned int b = code - r * 36 - g * 6;
escapeSeq.color.bg = RGB565_FROM_RGB8 (colorCube[r], colorCube[g], colorCube[b]);
escapeSeq.color.flags |= CONSOLE_BG_CUSTOM;
} else if (code <= 255) {
code -= 232;
escapeSeq.color.bg = RGB565_FROM_RGB8 (grayScale[code], grayScale[code], grayScale[code]);
escapeSeq.color.flags |= CONSOLE_BG_CUSTOM;
}
escapeSeq.state = ESC_BUILDING_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_FG_RGB:
escapeSeq.colorArgs[escapeSeq.colorArgCount++] = code;
if(escapeSeq.colorArgCount == 3)
{
escapeSeq.color.fg = RGB565_FROM_RGB8(escapeSeq.colorArgs[0], escapeSeq.colorArgs[1], escapeSeq.colorArgs[2]);
escapeSeq.color.flags |= CONSOLE_FG_CUSTOM;
escapeSeq.state = ESC_BUILDING_UNKNOWN;
}
break;
case ESC_BUILDING_FORMAT_BG_RGB:
escapeSeq.colorArgs[escapeSeq.colorArgCount++] = code;
if(escapeSeq.colorArgCount == 3)
{
escapeSeq.color.bg = RGB565_FROM_RGB8(escapeSeq.colorArgs[0], escapeSeq.colorArgs[1], escapeSeq.colorArgs[2]);
escapeSeq.color.flags |= CONSOLE_BG_CUSTOM;
escapeSeq.state = ESC_BUILDING_UNKNOWN;
}
default:
break;
}
}
escapeSeq.argIdx = 0;
currentConsole->bg = escapeSeq.color.bg;
currentConsole->fg = escapeSeq.color.fg;
currentConsole->flags = escapeSeq.color.flags;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -258,306 +433,151 @@ static ssize_t con_write(struct _reent *r,void *fd,const char *ptr, size_t len)
chr = *(tmp++); chr = *(tmp++);
i++; count++; i++; count++;
switch (escapeSeq.state)
if ( chr == 0x1b && len > 1 && *tmp == '[' ) { {
bool escaping = true; case ESC_NONE:
char *escapeseq = tmp++; if (chr == 0x1b)
int escapelen = 1; escapeSeq.state = ESC_START;
i++; count++; else
consolePrintChar(chr);
do { break;
chr = *(tmp++); case ESC_START:
i++; count++; escapelen++; if (chr == '[')
int parameter, assigned, consumed; {
escapeSeq.state = ESC_BUILDING_UNKNOWN;
// make sure parameters are positive values and delimited by semicolon escapeSeq.hasArg = false;
if((chr >= '0' && chr <= '9') || chr == ';') memset(escapeSeq.args, 0, sizeof(escapeSeq.args));
continue; escapeSeq.color.bg = currentConsole->bg;
escapeSeq.color.fg = currentConsole->fg;
switch (chr) { escapeSeq.color.flags = currentConsole->flags;
//--------------------------------------- escapeSeq.argIdx = 0;
// Cursor directional movement }
else
{
consolePrintChar(0x1b);
consolePrintChar(chr);
escapeSeq.state = ESC_NONE;
}
break;
case ESC_BUILDING_UNKNOWN:
switch (chr)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
escapeSeq.hasArg = true;
escapeSeq.args[escapeSeq.argIdx] = escapeSeq.args[escapeSeq.argIdx] * 10 + (chr - '0');
break;
case ';':
if (escapeSeq.hasArg) {
if (escapeSeq.argIdx < _ANSI_MAXARGS) {
escapeSeq.argIdx++;
}
}
escapeSeq.hasArg = false;
break;
//--------------------------------------- // Cursor directional movement
//--------------------------------------- //---------------------------------------
case 'A': case 'A':
consumed = 0; if (!escapeSeq.hasArg && !escapeSeq.argIdx)
assigned = sscanf(escapeseq,"[%dA%n", &parameter, &consumed); escapeSeq.args[0] = 1;
if (assigned==0) parameter = 1; currentConsole->cursorY = currentConsole->cursorY - escapeSeq.args[0];
if (consumed) if (currentConsole->cursorY < 1)
currentConsole->cursorY = (currentConsole->cursorY - parameter) < 0 ? 0 : currentConsole->cursorY - parameter; currentConsole->cursorY = 1;
escaping = false; escapeSeq.state = ESC_NONE;
break; break;
case 'B': case 'B':
consumed = 0; if (!escapeSeq.hasArg && !escapeSeq.argIdx)
assigned = sscanf(escapeseq,"[%dB%n", &parameter, &consumed); escapeSeq.args[0] = 1;
if (assigned==0) parameter = 1; currentConsole->cursorY = currentConsole->cursorY + escapeSeq.args[0];
if (consumed) if (currentConsole->cursorY > currentConsole->windowHeight)
currentConsole->cursorY = (currentConsole->cursorY + parameter) > currentConsole->windowHeight - 1 ? currentConsole->windowHeight - 1 : currentConsole->cursorY + parameter; currentConsole->cursorY = currentConsole->windowHeight;
escaping = false; escapeSeq.state = ESC_NONE;
break; break;
case 'C': case 'C':
consumed = 0; if (!escapeSeq.hasArg && !escapeSeq.argIdx)
assigned = sscanf(escapeseq,"[%dC%n", &parameter, &consumed); escapeSeq.args[0] = 1;
if (assigned==0) parameter = 1; currentConsole->cursorX = currentConsole->cursorX + escapeSeq.args[0];
if (consumed) if (currentConsole->cursorX > currentConsole->windowWidth)
currentConsole->cursorX = (currentConsole->cursorX + parameter) > currentConsole->windowWidth - 1 ? currentConsole->windowWidth - 1 : currentConsole->cursorX + parameter; currentConsole->cursorX = currentConsole->windowWidth;
escaping = false; escapeSeq.state = ESC_NONE;
break; break;
case 'D': case 'D':
consumed = 0; if (!escapeSeq.hasArg && !escapeSeq.argIdx)
assigned = sscanf(escapeseq,"[%dD%n", &parameter, &consumed); escapeSeq.args[0] = 1;
if (assigned==0) parameter = 1; currentConsole->cursorX = currentConsole->cursorX - escapeSeq.args[0];
if (consumed) if (currentConsole->cursorX < 1)
currentConsole->cursorX = (currentConsole->cursorX - parameter) < 0 ? 0 : currentConsole->cursorX - parameter; currentConsole->cursorX = 1;
escaping = false; escapeSeq.state = ESC_NONE;
break; break;
//--------------------------------------- //---------------------------------------
// Cursor position movement // Cursor position movement
//--------------------------------------- //---------------------------------------
case 'H': case 'H':
case 'f': case 'f':
{ consolePosition(escapeSeq.args[1], escapeSeq.args[0]);
int x, y; escapeSeq.state = ESC_NONE;
char c;
if(sscanf(escapeseq,"[%d;%d%c", &y, &x, &c) == 3 && (c == 'f' || c == 'H')) {
consolePosition(x, y);
escaping = false;
break; break;
}
x = y = 1;
if(sscanf(escapeseq,"[%d;%c", &y, &c) == 2 && (c == 'f' || c == 'H')) {
consolePosition(x, y);
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[;%d%c", &x, &c) == 2 && (c == 'f' || c == 'H')) {
consolePosition(x, y);
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[;%c", &c) == 1 && (c == 'f' || c == 'H')) {
consolePosition(x, y);
escaping = false;
break;
}
// invalid format
escaping = false;
break;
}
//--------------------------------------- //---------------------------------------
// Screen clear // Screen clear
//--------------------------------------- //---------------------------------------
case 'J': case 'J':
if(escapelen <= 3) if (escapeSeq.argIdx == 0 && !escapeSeq.hasArg) {
consoleCls(escapeseq[escapelen-2]); escapeSeq.args[0] = 0;
escaping = false; }
consoleCls(escapeSeq.args[0]);
escapeSeq.state = ESC_NONE;
break; break;
//--------------------------------------- //---------------------------------------
// Line clear // Line clear
//--------------------------------------- //---------------------------------------
case 'K': case 'K':
if(escapelen <= 3) if (escapeSeq.argIdx == 0 && !escapeSeq.hasArg) {
consoleClearLine(escapeseq[escapelen-2]); escapeSeq.args[0] = 0;
escaping = false; }
consoleClearLine(escapeSeq.args[0]);
escapeSeq.state = ESC_NONE;
break; break;
//--------------------------------------- //---------------------------------------
// Save cursor position // Save cursor position
//--------------------------------------- //---------------------------------------
case 's': case 's':
if(escapelen == 2) {
currentConsole->prevCursorX = currentConsole->cursorX ; currentConsole->prevCursorX = currentConsole->cursorX ;
currentConsole->prevCursorY = currentConsole->cursorY ; currentConsole->prevCursorY = currentConsole->cursorY ;
} escapeSeq.state = ESC_NONE;
escaping = false;
break; break;
//--------------------------------------- //---------------------------------------
// Load cursor position // Load cursor position
//--------------------------------------- //---------------------------------------
case 'u': case 'u':
if(escapelen == 2) {
currentConsole->cursorX = currentConsole->prevCursorX ; currentConsole->cursorX = currentConsole->prevCursorX ;
currentConsole->cursorY = currentConsole->prevCursorY ; currentConsole->cursorY = currentConsole->prevCursorY ;
} escapeSeq.state = ESC_NONE;
escaping = false;
break; break;
//--------------------------------------- //---------------------------------------
// Color scan codes // Color scan codes
//--------------------------------------- //---------------------------------------
case 'm': case 'm':
escapeseq++; if (escapeSeq.argIdx == 0 && !escapeSeq.hasArg) escapeSeq.args[escapeSeq.argIdx++] = 0;
escapelen--; if (escapeSeq.hasArg) escapeSeq.argIdx++;
consoleHandleColorEsc(escapeSeq.argIdx);
do { escapeSeq.state = ESC_NONE;
bool custom;
parameter = 0;
if (escapelen == 1) {
consumed = 1;
} else if (memchr(escapeseq,';',escapelen)) {
sscanf(escapeseq,"%d;%n", &parameter, &consumed);
} else {
sscanf(escapeseq,"%dm%n", &parameter, &consumed);
}
escapeseq += consumed;
escapelen -= consumed;
switch(parameter) {
case 0: // reset
currentConsole->flags = 0;
currentConsole->bg = 0;
currentConsole->fg = 7;
break; break;
case 1: // bold
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
currentConsole->flags |= CONSOLE_COLOR_BOLD;
break;
case 2: // faint
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
currentConsole->flags |= CONSOLE_COLOR_FAINT;
break;
case 3: // italic
currentConsole->flags |= CONSOLE_ITALIC;
break;
case 4: // underline
currentConsole->flags |= CONSOLE_UNDERLINE;
break;
case 5: // blink slow
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
currentConsole->flags |= CONSOLE_BLINK_SLOW;
break;
case 6: // blink fast
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
currentConsole->flags |= CONSOLE_BLINK_FAST;
break;
case 7: // reverse video
currentConsole->flags |= CONSOLE_COLOR_REVERSE;
break;
case 8: // conceal
currentConsole->flags |= CONSOLE_CONCEAL;
break;
case 9: // crossed-out
currentConsole->flags |= CONSOLE_CROSSED_OUT;
break;
case 21: // bold off
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
break;
case 22: // normal color
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
break;
case 23: // italic off
currentConsole->flags &= ~CONSOLE_ITALIC;
break;
case 24: // underline off
currentConsole->flags &= ~CONSOLE_UNDERLINE;
break;
case 25: // blink off
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
break;
case 27: // reverse off
currentConsole->flags &= ~CONSOLE_COLOR_REVERSE;
break;
case 29: // crossed-out off
currentConsole->flags &= ~CONSOLE_CROSSED_OUT;
break;
case 30 ... 37: // writing color
currentConsole->flags &= ~CONSOLE_FG_CUSTOM;
currentConsole->fg = parameter - 30;
break;
case 38: // custom foreground color
if (parseColor (&escapeseq, &escapelen, &currentConsole->fg, &custom)) {
if (custom)
currentConsole->flags |= CONSOLE_FG_CUSTOM;
else
currentConsole->flags &= ~CONSOLE_FG_CUSTOM;
if (!custom && currentConsole->fg < 16) {
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
if (currentConsole->fg < 8)
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
else
currentConsole->flags |= CONSOLE_COLOR_BOLD;
}
// consume next ; or m
++escapeseq;
--escapelen;
} else {
// stop processing
escapelen = 0;
}
break;
case 39: // reset foreground color
currentConsole->flags &= ~CONSOLE_FG_CUSTOM;
currentConsole->fg = 7;
break;
case 40 ... 47: // screen color
currentConsole->flags &= ~CONSOLE_BG_CUSTOM;
currentConsole->bg = parameter - 40;
break;
case 48: // custom background color
if (parseColor (&escapeseq, &escapelen, &currentConsole->bg, &custom)) {
if (custom)
currentConsole->flags |= CONSOLE_BG_CUSTOM;
else
currentConsole->flags &= ~CONSOLE_BG_CUSTOM;
// consume next ; or m
++escapeseq;
--escapelen;
} else {
// stop processing
escapelen = 0;
}
break;
case 49: // reset background color
currentConsole->flags &= ~CONSOLE_BG_CUSTOM;
currentConsole->bg = 0;
break;
}
} while (escapelen > 0);
escaping = false;
break;
default: default:
// some sort of unsupported escape; just gloss over it // some sort of unsupported escape; just gloss over it
escaping = false; escapeSeq.state = ESC_NONE;
break; break;
} }
} while (escaping); default:
continue; break;
} }
consolePrintChar(chr);
} }
return count; return count;
@ -652,10 +672,10 @@ void consoleNewRow(void) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
currentConsole->cursorY++; currentConsole->cursorY++;
if(currentConsole->cursorY >= currentConsole->windowHeight) { if(currentConsole->cursorY > currentConsole->windowHeight) {
currentConsole->cursorY --;
currentConsole->renderer->scrollWindow(currentConsole); currentConsole->renderer->scrollWindow(currentConsole);
consoleClearLine('2'); currentConsole->cursorY = currentConsole->windowHeight;
consoleClearLine(2);
} }
} }
@ -667,8 +687,8 @@ void consoleDrawChar(int c) {
currentConsole->renderer->drawChar( currentConsole->renderer->drawChar(
currentConsole, currentConsole,
currentConsole->cursorX + currentConsole->windowX, currentConsole->cursorX - 1 + currentConsole->windowX - 1,
currentConsole->cursorY + currentConsole->windowY, currentConsole->cursorY - 1 + currentConsole->windowY - 1,
c); c);
} }
@ -677,12 +697,6 @@ void consolePrintChar(int c) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
if (c==0) return; if (c==0) return;
if(currentConsole->cursorX >= currentConsole->windowWidth) {
currentConsole->cursorX = 0;
consoleNewRow();
}
switch(c) { switch(c) {
/* /*
The only special characters we will handle are tab (\t), carriage return (\r), line feed (\n) The only special characters we will handle are tab (\t), carriage return (\r), line feed (\n)
@ -696,12 +710,12 @@ void consolePrintChar(int c) {
case '\b': case '\b':
currentConsole->cursorX--; currentConsole->cursorX--;
if(currentConsole->cursorX < 0) { if(currentConsole->cursorX < 1) {
if(currentConsole->cursorY > 0) { if(currentConsole->cursorY > 1) {
currentConsole->cursorX = currentConsole->windowX - 1; currentConsole->cursorX = currentConsole->windowWidth;
currentConsole->cursorY--; currentConsole->cursorY--;
} else { } else {
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
} }
} }
@ -714,9 +728,13 @@ void consolePrintChar(int c) {
case '\n': case '\n':
consoleNewRow(); consoleNewRow();
case '\r': case '\r':
currentConsole->cursorX = 0; currentConsole->cursorX = 1;
break; break;
default: default:
if(currentConsole->cursorX > currentConsole->windowWidth) {
currentConsole->cursorX = 1;
consoleNewRow();
}
consoleDrawChar(c); consoleDrawChar(c);
++currentConsole->cursorX ; ++currentConsole->cursorX ;
break; break;
@ -735,12 +753,15 @@ void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height
if(!console) console = currentConsole; if(!console) console = currentConsole;
if (x < 1) x = 1;
if (y < 1) y = 1;
console->windowWidth = width; console->windowWidth = width;
console->windowHeight = height; console->windowHeight = height;
console->windowX = x; console->windowX = x;
console->windowY = y; console->windowY = y;
console->cursorX = 0; console->cursorX = 1;
console->cursorY = 0; console->cursorY = 1;
} }

View File

@ -172,8 +172,8 @@ static void ConsoleSwRenderer_scrollWindow(PrintConsole* con)
int i,j; int i,j;
u32 x, y; u32 x, y;
x = con->windowX * 16; x = (con->windowX - 1) * 16;
y = con->windowY * 16; y = (con->windowY - 1) * 16;
for (i=0; i<con->windowWidth*16; i+=sizeof(u128)/sizeof(u16)) { for (i=0; i<con->windowWidth*16; i+=sizeof(u128)/sizeof(u16)) {
u128 *from; u128 *from;