X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Fgui_terminal_src%2Fvt100.c;h=4af6403da3f52c4944684cd1ba056ecc08631b6d;hb=ac3028884d3c109359bc20369391adba7dab4ba9;hp=cad4119494d3f705d7c705b5868cd59a0212df29;hpb=3a6a04204acae8bc2ccfce7d0be1f1ba75744bb5;p=tpg%2Facess2.git diff --git a/Usermode/Applications/gui_terminal_src/vt100.c b/Usermode/Applications/gui_terminal_src/vt100.c index cad41194..4af6403d 100644 --- a/Usermode/Applications/gui_terminal_src/vt100.c +++ b/Usermode/Applications/gui_terminal_src/vt100.c @@ -5,81 +5,184 @@ * vt100.c * - VT100/xterm Emulation */ -#include #include #include "include/vt100.h" #include "include/display.h" #include // isalpha -#include // _SysDebug +#ifdef KERNEL_VERSION +# define _SysDebug(v...) Debug("VT100 "v) +#else +# include // _SysDebug +# include +# include +#endif + +enum eExcapeMode { + MODE_NORMAL, + MODE_IGNORE, + MODE_STRING +}; +enum eStringType { + STRING_IGNORE, + STRING_TITLE +}; + +#define FLAG_BOLD 0x01 +#define FLAG_REVERSE 0x02 + +typedef struct { + uint32_t Flags; + int CurFG, CurBG; + + enum eExcapeMode Mode; + + enum eStringType StringType; + size_t StringLen; + char *StringCache; +} tVT100State; const uint32_t caVT100Colours[] = { - // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray + // Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray // Same again, but bright - 0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA, - 0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF + 0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAA, + 0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF, }; + int _locate_eos(size_t Len, const char *Buf); int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buf); + int Term_HandleVT100_Short(tTerminal *Term, int Len, const char *Buf); static inline int min(int a, int b) { return a < b ? a : b; } +int _locate_eos(size_t Len, const char *Buf) +{ + size_t ret = 0; + while( ret < Len ) + { + if( Buf[ret] == '\007' ) + return ret; + if( Buf[ret] == '\x9c' ) + return ret; + if( ret+1 < Len && Buf[ret] == '\x1b' && Buf[ret+1] == '\\' ) + return ret; + } + return -1; +} + int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf) { #define MAX_VT100_ESCAPE_LEN 16 static char inc_buf[MAX_VT100_ESCAPE_LEN]; static int inc_len = 0; + tVT100State *st = Display_GetTermState(Term); + + if( st == NULL ) { + st = malloc( sizeof(*st) ); + memset(st, 0, sizeof(*st)); + Display_SetTermState(Term, st); + } + + if( st->Mode == MODE_IGNORE ) { + st->Mode = MODE_NORMAL; + // Used for multi-byte EOS + return 1; + } + if( st->Mode == MODE_STRING ) + { + // We're in a string mode + int pos = _locate_eos(Len, Buf); + size_t bytes = (pos >= 0 ? pos : Len); + char *tmp = realloc(st->StringCache, st->StringLen + bytes+1); + if(!tmp) return bytes; + memcpy(tmp+st->StringLen, Buf, bytes); + tmp[st->StringLen+bytes] = 0; + + _SysDebug("pos=%i", pos); + _SysDebug("'%.*s'", bytes, Buf); + // Only apply when we hit EOS at the start + if( pos != 0 ) + return bytes; + switch(st->StringType) + { + case STRING_TITLE: + Display_SetTitle(Term, st->StringCache); + break; + case STRING_IGNORE: + break; + } + free(st->StringCache); + st->StringCache = 0; + st->StringLen = 0; + + if( *Buf == '\x1b' ) { + st->Mode = MODE_IGNORE; + // skip the '\\' + } + else + st->Mode = MODE_NORMAL; + return 1; + } if( inc_len > 0 || *Buf == '\x1b' ) { // Handle VT100 (like) escape sequence int new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len); - int ret = 0, old_inc_len = inc_len; + int ret = 0; + int old_inc_len = inc_len; memcpy(inc_buf + inc_len, Buf, new_bytes); + if( new_bytes == 0 ) { + _SysDebug("Term_HandleVT100: Hit max? (Len=%i) Flushing cache", Len); + inc_len = 0; + return 0; + } + inc_len += new_bytes; + //_SysDebug("inc_buf = %i '%.*s'", inc_len, inc_len, inc_buf); if( inc_len <= 1 ) return 1; // Skip 1 character (the '\x1b') - switch(inc_buf[1]) - { - case '[': // Multibyte, funtime starts - ret = Term_HandleVT100_Long(Term, inc_len-2, inc_buf+2); - if( ret > 0 ) { - ret += 2; - } - break; - default: - ret = 2; - break; - } + ret = Term_HandleVT100_Short(Term, inc_len, inc_buf); if( ret != 0 ) { inc_len = 0; + assert(ret > old_inc_len); + //_SysDebug("%i bytes of escape code '%.*s' (return %i)", + // ret, ret, inc_buf, ret-old_inc_len); ret -= old_inc_len; // counter cached bytes } + else + ret = new_bytes; return ret; } switch( *Buf ) { + // TODO: Need to handle \t and ^A-Z case '\b': - Display_MoveCursor(Term, -1, 0); + Display_MoveCursor(Term, 0, -1); Display_AddText(Term, 1, " "); - Display_MoveCursor(Term, -1, 0); - // TODO: Need to handle \t and ^A-Z + Display_MoveCursor(Term, 0, -1); return 1; case '\t': // TODO: tab (get current cursor pos, space until multiple of 8) + _SysDebug("TODO: VT100 Support \\t tab"); return 1; case '\n': + // TODO: Support disabling CR after NL Display_Newline(Term, 1); return 1; case '\r': - Display_MoveCursor(Term, INT_MIN, 0); + if( Len >= 2 && Buf[1] == '\n' ) { + // Fast case for \r\n + Display_Newline(Term, 1); + return 2; + } + Display_MoveCursor(Term, 0, INT_MIN); return 1; } @@ -105,8 +208,68 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf) return -ret; } +int Term_HandleVT100_Short(tTerminal *Term, int Len, const char *Buf) +{ + tVT100State *st = Display_GetTermState(Term); + int tmp; + switch(Buf[1]) + { + case '[': // Multibyte, funtime starts + tmp = Term_HandleVT100_Long(Term, Len-2, Buf+2); + assert(tmp >= 0); + if( tmp == 0 ) + return 0; + return tmp + 2; + case ']': + st->Mode = MODE_STRING; + st->StringType = STRING_IGNORE; + _SysDebug("TODO: \\e] Support title changes"); + return 2; + case '=': + _SysDebug("TODO: \\e= Application Keypad"); + return 2; + case '>': + _SysDebug("TODO: \\e= Normal Keypad"); + return 2; + + case '(': // Update G0 charset + tmp = 0; if(0) + case ')': // Update G1 charset + tmp = 1; if(0) + case '*': + tmp = 2; if(0) + case '+': + tmp = 3; + + if( Len <= 2 ) + return 0; // We need more + switch(Buf[2]) + { + case '0': // DEC Special Character/Linedrawing set + case 'A': // UK + case 'B': // US ASCII + break; + } + return 3; + // xterm C1 \eD and \eM are 'Index' and 'Reverse Index' + // - Aparently scroll? + //case 'D': + // Display_ScrollDown(Term, 1); + // ret = 2; + // break; + //case 'M': + // Display_ScrollDown(Term, -1); + // ret = 2; + // break; + default: + _SysDebug("Unknown VT100 \\e%c", Buf[1]); + return 2; + } +} + int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) { + tVT100State *st = Display_GetTermState(Term); char c; int argc = 0, j = 0; int args[6] = {0,0,0,0,0,0}; @@ -140,8 +303,9 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) // Get Command if( !isalpha(c) ) { // Bother. - _SysDebug("Unexpected char 0x%x in VT100 escape code", c); - return 1; + _SysDebug("Unexpected char 0x%x in VT100 escape code '\\e[%.*s'", c, + Len, Buffer); + return j; } if( bQuestionMark ) @@ -155,12 +319,22 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) case 'l': // unset switch(args[0]) { + case 1: // Aplication cursor keys + _SysDebug("TODO: \\e[?1%c Application cursor keys", c); + break; case 25: // Hide cursor _SysDebug("TODO: \\e[?25%c Show/Hide cursor", c); break; case 1047: // Alternate buffer Display_ShowAltBuffer(Term, set); break; + case 1048: // Save/restore cursor in DECSC + _SysDebug("TODO: \\e[?1048%c Save/Restore cursor", c); + break; + case 1049: // Save/restore cursor in DECSC and use alternate buffer + _SysDebug("TODO: \\e[?1049%c Save/Restore cursor", c); + Display_ShowAltBuffer(Term, set); + break; default: _SysDebug("TODO: \\e[?%i%c Unknow DEC private mode", args[0], c); break; @@ -176,6 +350,18 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) // Standard commands switch( c ) { + case 'A': + Display_MoveCursor(Term, -(argc >= 1 ? args[0] : 1), 0); + break; + case 'B': + Display_MoveCursor(Term, (argc >= 1 ? args[0] : 1), 0); + break; + case 'C': + Display_MoveCursor(Term, 0, (argc >= 1 ? args[0] : 1)); + break; + case 'D': + Display_MoveCursor(Term, 0, -(argc >= 1 ? args[0] : 1)); + break; case 'H': if( argc != 2 ) { } @@ -183,48 +369,100 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) Display_SetCursor(Term, args[0], args[1]); } break; - case 'J': - if( argc == 0 ) + case 'J': // Clear lines + switch( args[0] ) + { + case 0: + Display_ClearLines(Term, 1); // Down + break; + case 1: + Display_ClearLines(Term, -1); // Up + break; + case 2: + Display_ClearLines(Term, 0); // All + break; + default: + _SysDebug("Unknown VT100 %i J", args[0]); + break; + } + break; + case 'K': + switch( args[0] ) + { + case 0: // To EOL + Display_ClearLine(Term, 1); + break; + case 1: // To SOL + Display_ClearLine(Term, -1); + break; + case 2: Display_ClearLine(Term, 0); - else if( args[0] == 2 ) - Display_ClearLines(Term, 0); // Entire screen! - else - _SysDebug("TODO: VT100 %i J", args[0]); + break; + default: + _SysDebug("Unknown VT100 %i K", args[0]); + break; + } + case 'S': // Scroll up n=1 + Display_ScrollDown(Term, -(argc >= 1 ? args[0] : 1)); break; case 'T': // Scroll down n=1 - _SysDebug("TODO: \\x1B[nT - Scroll down"); + Display_ScrollDown(Term, (argc >= 1 ? args[0] : 1)); break; case 'm': if( argc == 0 ) { // Reset + Display_ResetAttributes(Term); } else { - int i; - for( i = 0; i < argc; i ++ ) + for( int i = 0; i < argc; i ++ ) { - if( args[i] < 8 ) - { - // TODO: Flags? - } - else if( 30 <= args[i] && args[i] <= 37 ) + switch(args[i]) { - // TODO: Bold/bright - Display_SetForeground( Term, caVT100Colours[ args[i]-30 ] ); - } - else if( 40 <= args[i] && args[i] <= 47 ) - { - // TODO: Bold/bright - Display_SetBackground( Term, caVT100Colours[ args[i]-30 ] ); + case 0: + st->Flags = 0; + Display_ResetAttributes(Term); + break; + case 1: + st->Flags |= FLAG_BOLD; + Display_SetForeground( Term, caVT100Colours[st->CurFG + 8] ); + break; + case 2: + _SysDebug("TODO: VT100 \\e[1m - Reverse"); + break; + case 30 ... 37: + st->CurFG = args[i]-30; + if(0) + case 39: + st->CurFG = 7; + Display_SetForeground( Term, + caVT100Colours[ st->CurFG + (st->Flags&FLAG_BOLD?8:0) ] ); + break; + case 40 ... 47: + st->CurBG = args[i]-40; + if(0) + case 49: + st->CurBG = 0; + Display_SetBackground( Term, caVT100Colours[ st->CurBG ] ); + break; + default: + _SysDebug("TODO: VT100 \\e[%im", args[i]); + break; } } } break; // Set scrolling region case 'r': - _SysDebug("TODO: \\x1B[%i;%ir - Set Scroll Region", - args[0], args[1]); + Display_SetScrollArea(Term, args[0], (args[1] - args[0])); + break; + + case 's': + Display_SaveCursor(Term); + break; + case 'u': + Display_RestoreCursor(Term); break; default: _SysDebug("Unknown VT100 long escape char 0x%x '%c'", c, c);