Terminal - Adding some (slightly buggy) xterm features
authorJohn Hodge <[email protected]>
Fri, 22 Nov 2013 09:43:51 +0000 (17:43 +0800)
committerJohn Hodge <[email protected]>
Fri, 22 Nov 2013 09:43:51 +0000 (17:43 +0800)
KernelLand/Kernel/drv/vterm.h
KernelLand/Kernel/drv/vterm_termbuf.c
KernelLand/Kernel/drv/vterm_vt100.c
Usermode/Applications/gui_terminal_src/display.c
Usermode/Applications/gui_terminal_src/include/display.h
Usermode/Applications/gui_terminal_src/vt100.c

index 8526426..4ca241b 100644 (file)
@@ -46,6 +46,8 @@ struct sVTerm
 {
         int    Mode;   //!< Current Mode (see ::eTplTerminal_Modes)
         int    Flags;  //!< Flags (see VT_FLAG_*)
+
+       void    *VT100Info;
        
        short   Width;  //!< Virtual Width
        short   Height; //!< Virtual Height
index 1ce8051..abf9897 100644 (file)
@@ -5,7 +5,7 @@
  * drv/vterm_termbuf.c
  * - Virtual Terminal - Terminal buffer manipulation
  */
-#define DEBUG  1
+#define DEBUG  0
 #include "vterm.h"
 
 extern int     Term_HandleVT100(tVTerm *Term, int Len, const char *Buf);
@@ -24,7 +24,7 @@ void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count)
                int esc_len = Term_HandleVT100(Term, Count - ofs, (const void*)(Buffer + ofs));
                if( esc_len < 0 ) {
                        esc_len = -esc_len;
-                       LOG("%i '%*c'", esc_len, esc_len, Buffer+ofs);
+                       LOG("%i '%*C'", esc_len, esc_len, Buffer+ofs);
                        VT_int_PutRawString(Term, Buffer + ofs, esc_len);
                        //Debug("Raw string '%.*s'", esc_len, Buffer+ofs);
                }
index 5c2e35d..1f635a1 100644 (file)
@@ -5,15 +5,22 @@
  * drv/vterm_vt100.c
  * - Virtual Terminal - VT100 (Kinda) Emulation
  */
-#define DEBUG  1
+#define DEBUG  0
 #include "vterm.h"
 
 #define sTerminal      sVTerm
 #include "../../../Usermode/Applications/gui_terminal_src/vt100.c"
 
+void *Display_GetTermState(tTerminal *Term) {
+       return Term->VT100Info;;
+}
+void Display_SetTermState(tTerminal *Term, void *State) {
+       Term->VT100Info = State;
+}
+
 void Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text)
 {
-       LOG("'%.*s'", Length, UTF8Text);
+       LOG("'%*C'", Length, UTF8Text);
        VT_int_PutRawString(Term, (const void*)UTF8Text, Length);
 }
 void Display_Newline(tTerminal *Term, bool bCarriageReturn)
@@ -146,7 +153,6 @@ void Display_ClearLines(tTerminal *Term, int Dir)
 {
        LOG("(Dir=%i)", Dir);   
         int    *wrpos = (Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos);
-       tVT_Char        *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text);
        
        // All
        if( Dir == 0 ) {
@@ -206,4 +212,8 @@ void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled)
        LOG("(%B)", AltBufEnabled);
        VT_int_ToggleAltBuffer(Term, AltBufEnabled);
 }
+void Display_SetTitle(tTerminal *Term, const char *Title)
+{
+       // ignore
+}
 
index 901e967..1b026d5 100644 (file)
@@ -42,6 +42,8 @@ struct sLine {
 };
 
 struct sTerminal {
+       void    *TermState;
+       
         int    ViewCols;
         int    ViewRows;
 
@@ -97,6 +99,13 @@ tTerminal *Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
        return term;
 }
 
+void *Display_GetTermState(tTerminal *Term) {
+       return Term->TermState;
+}
+void Display_SetTermState(tTerminal *Term, void *State) {
+       Term->TermState = State;
+}
+
 // Return the byte length of a single on-screen character
 size_t _GetCharLength(size_t AvailLength, const char *Text, uint32_t *BaseCodepoint)
 {
@@ -527,3 +536,8 @@ void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled)
        Display_int_SetCursor(Term, row, col);
 }
 
+void Display_SetTitle(tTerminal *Term, const char *Title)
+{
+       _SysDebug("TODO: Set window title to '%s'", Title);
+}
+
index 2e24487..59abfba 100644 (file)
@@ -16,6 +16,10 @@ typedef struct sTerminal     tTerminal;
 
 extern tTerminal       *Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
 
+// TermState is a variable used by the terminal emulation code
+extern void    *Display_GetTermState(tTerminal *Term);
+extern void    Display_SetTermState(tTerminal *Term, void *State);
+
 extern void    Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text);
 extern void    Display_Newline(tTerminal *Term, bool bCarriageReturn);
 extern void    Display_SetScrollArea(tTerminal *Term, int Start, int Count);   // Only valid in AltBuffer
@@ -40,5 +44,7 @@ extern void   Display_Flush(tTerminal *Term);
  */
 extern void    Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled);
 
+extern void    Display_SetTitle(tTerminal *Term, const char *Title);
+
 #endif
 
index 1c47381..4af6403 100644 (file)
 # include <assert.h>
 #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,  Magenta,     Cyan,      Gray
        // Same again, but bright
@@ -24,18 +48,83 @@ const uint32_t      caVT100Colours[] = {
        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' )
        {
@@ -46,7 +135,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)", Len);
+                       _SysDebug("Term_HandleVT100: Hit max? (Len=%i) Flushing cache", Len);
                        inc_len = 0;
                        return 0;
                }
@@ -57,26 +146,7 @@ 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;
@@ -100,6 +170,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
@@ -107,13 +178,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;
@@ -138,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};
@@ -198,6 +328,13 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                        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;
@@ -253,10 +390,10 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                        switch( args[0] )
                        {
                        case 0: // To EOL
-                               Display_ClearLine(Term, -1);
+                               Display_ClearLine(Term, 1);
                                break;
                        case 1: // To SOL
-                               Display_ClearLine(Term, 1);
+                               Display_ClearLine(Term, -1);
                                break;
                        case 2:
                                Display_ClearLine(Term, 0);
@@ -265,7 +402,7 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                                _SysDebug("Unknown VT100 %i K", args[0]);
                                break;
                        }
-               case 'S':       // Scroll down n=1
+               case 'S':       // Scroll up n=1
                        Display_ScrollDown(Term, -(argc >= 1 ? args[0] : 1));
                        break;
                case 'T':       // Scroll down n=1
@@ -284,21 +421,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:
-                                               _SysDebug("TODO: VT100 \\e[1m - Bold");
+                                               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]-40 ] );
+                                               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]);

UCC git Repository :: git.ucc.asn.au