X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Fgui_terminal_src%2Fvt100.c;h=dc1902f873a6cb00f0a229571292fdd8aff021ca;hb=f8596a513cb7d05cb9b542f53416bedc244968a0;hp=c1d51777a1bb6977d19f6dd9de10e24b05355e72;hpb=77c5f08971d6354aee5d402d25adea8d82b6e67b;p=tpg%2Facess2.git diff --git a/Usermode/Applications/gui_terminal_src/vt100.c b/Usermode/Applications/gui_terminal_src/vt100.c index c1d51777..dc1902f8 100644 --- a/Usermode/Applications/gui_terminal_src/vt100.c +++ b/Usermode/Applications/gui_terminal_src/vt100.c @@ -15,27 +15,123 @@ # include // _SysDebug # include # include +# include // malloc/free #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_Short(tTerminal *Term, int Len, const char *Buf); int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buf); + int Term_HandleVT100_OSC(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) +{ + for( size_t ret = 0; ret < Len; ret ++ ) + { + 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 + _SysDebug("Ignore 1 '%c'", *Buf); + return 1; + } + else 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; + st->StringCache = tmp; + memcpy(tmp+st->StringLen, Buf, bytes); + tmp[st->StringLen+bytes] = 0; + st->StringLen += bytes; + + _SysDebug("pos=%i", pos); + _SysDebug("Buf[+%zi] = '%.*s'", bytes, 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; + } + else { + // fall through + } if( inc_len > 0 || *Buf == '\x1b' ) { @@ -46,6 +142,7 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf) 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; } @@ -56,30 +153,16 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *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; - case 'D': - Display_ScrollDown(Term, 1); - ret = 2; - break; - case 'M': - Display_ScrollDown(Term, -1); - 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); + // Check that we actually used the new data (as should have happened) + if( ret <= old_inc_len ) { + _SysDebug("Term_HandleVT100: ret(%i) <= old_inc_len(%i) '%.*s'\n", + ret, old_inc_len, inc_len, inc_buf); + 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 @@ -99,6 +182,7 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf) 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 @@ -106,13 +190,12 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf) return 1; case '\r': if( Len >= 2 && Buf[1] == '\n' ) { + // Fast case for \r\n Display_Newline(Term, 1); return 2; } - else { - Display_MoveCursor(Term, 0, INT_MIN); - return 1; - } + Display_MoveCursor(Term, 0, INT_MIN); + return 1; } int ret = 0; @@ -137,8 +220,68 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf) return -ret; } +int Term_HandleVT100_Short(tTerminal *Term, int Len, const char *Buf) +{ + 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 ']': + tmp = Term_HandleVT100_OSC(Term, Len-2, Buf+2); + assert(tmp >= 0); + if( tmp == 0 ) + return 0; + return tmp + 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}; @@ -188,12 +331,25 @@ 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 12: + _SysDebug("TODO: \\e[?25%c Start/Stop blinking cursor", 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; @@ -209,22 +365,37 @@ 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 ) { } else { - Display_SetCursor(Term, args[0], args[1]); + // Adjust 1-based cursor position to 0-based + Display_SetCursor(Term, args[0]-1, args[1]-1); } break; - case 'J': + case 'J': // Clear lines switch( args[0] ) { case 0: + Display_ClearLines(Term, 1); // Down + break; case 1: - _SysDebug("TODO: VT100 %i J", args[0]); + Display_ClearLines(Term, -1); // Up break; - case 2: // Everything - Display_ClearLines(Term, 0); + case 2: + Display_ClearLines(Term, 0); // All break; default: _SysDebug("Unknown VT100 %i J", args[0]); @@ -235,8 +406,10 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) switch( args[0] ) { case 0: // To EOL + Display_ClearLine(Term, 1); + break; case 1: // To SOL - _SysDebug("TODO: VT100 %i K", args[0]); + Display_ClearLine(Term, -1); break; case 2: Display_ClearLine(Term, 0); @@ -245,8 +418,11 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) _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 - Display_ScrollDown(Term, 1); + Display_ScrollDown(Term, (argc >= 1 ? args[0] : 1)); break; case 'm': if( argc == 0 ) @@ -261,15 +437,30 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) switch(args[i]) { 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: - // TODO: Bold/bright - Display_SetForeground( Term, caVT100Colours[ args[i]-30 ] ); + 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: - // TODO: Bold/bright - Display_SetBackground( Term, caVT100Colours[ args[i]-30 ] ); + 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]); @@ -280,7 +471,7 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) break; // Set scrolling region case 'r': - Display_SetScrollArea(Term, args[0], args[1] - args[0]); + Display_SetScrollArea(Term, args[0], (args[1] - args[0])); break; case 's': @@ -296,3 +487,61 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer) } return j; } + +int Term_HandleVT100_OSC(tTerminal *Term, int Len, const char *Buf) +{ + tVT100State *st = Display_GetTermState(Term); + + int ofs = 0; + // OSC Ps ; Pt [ST/BEL] + if(Len < 2) return 0; // Need moar + + int Ps = 0; + while( ofs < Len && isdigit(Buf[ofs]) ) { + Ps = Ps * 10 + (Buf[ofs] - '0'); + ofs ++; + } + + if( ofs == Len ) return 0; + if( Buf[ofs] != ';' ) { + // Error + st->Mode = MODE_STRING; + st->StringType = STRING_IGNORE; + return ofs; + } + ofs ++; + + switch(Ps) + { + case 0: // Icon Name + Window Title + case 1: // Icon Name + case 2: // Window Title + st->Mode = MODE_STRING; + st->StringType = STRING_TITLE; + break; + case 3: // Set X Property + _SysDebug("TODO: \\e]3; Support X properties"); + st->Mode = MODE_STRING; + st->StringType = STRING_IGNORE; + break; + case 4: // Change colour number + case 5: // Change special colour number + _SysDebug("TODO: \\e]%i;c; Support X properties", Ps); + st->Mode = MODE_STRING; + st->StringType = STRING_IGNORE; + break; + case 10: // Change foreground to Pt + case 11: // Change background to Pt + case 52: + // TODO: Can be Pt = [cps01234567]*; + // > Clipboard data in base-64, cut/primary/select buffers 0-7 + // > ='?' returns the clipbard in the same format + default: + _SysDebug("Unknown VT100 OSC \\e]%i;", Ps); + st->Mode = MODE_STRING; + st->StringType = STRING_IGNORE; + break; + } + return ofs; +} +