Usermode/GUI Terminal - Reworking terminal code. Incomplete
authorJohn Hodge <[email protected]>
Sat, 7 Sep 2013 15:08:16 +0000 (23:08 +0800)
committerJohn Hodge <[email protected]>
Sat, 7 Sep 2013 15:08:16 +0000 (23:08 +0800)
- Works for basic usage, but backspace and more complex escape codes
  cause instant quit.

Usermode/Applications/gui_shell_src/display.c
Usermode/Applications/gui_shell_src/include/display.h
Usermode/Applications/gui_shell_src/include/vt100.h
Usermode/Applications/gui_shell_src/main.c
Usermode/Applications/gui_shell_src/vt100.c

index bb07e39..0049608 100644 (file)
 #include <stdio.h>
 #include <axwin3/axwin.h>
 #include <axwin3/richtext.h>
+#include <stdbool.h>
+#include <assert.h>
 
 #define UNIMPLIMENTED()        do{_SysDebug("UNIMPLIMENTED %s", __func__); exit(-1);}while(0)
 
 // === EXTERN ==
 extern tHWND   gMainWindow;
 
+typedef struct sLine   tLine;
+
+struct sLine {
+       char    *Data;
+       // TODO: Cache offsets to avoid scan-forward
+       size_t  Len;
+       size_t  Size;
+       bool    IsDirty;
+};
+
+struct sTerminal {
+        int    ViewCols;
+        int    ViewRows;
+
+        int    CursorRow;
+        int    CursorCol;
+
+       size_t  CursorByte;
+
+       bool    bUsingAltBuf;
+
+       size_t  ViewOffset;     
+       size_t  TotalLines;
+       struct sLine    *PriBuf;
+       
+       struct sLine    *AltBuf;
+};
+
 // === GLOBALS ===
- int   giDisplayCols;
- int   giDisplayLines;
- int   giDisplayTotalLines;
- int   giDisplayBufSize;
+tTerminal      gMainBuffer;
  int   giCurrentLine;
  int   giCurrentLinePos;       // byte offset, not column
  int   giCurrentCol;
@@ -34,147 +61,205 @@ char      **gasDisplayLines;
 char   *gabDisplayLinesDirty;
 
 // === CODE ===
-void Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
+tTerminal *Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
 {
-       giDisplayCols = Cols;
-       giDisplayLines = Lines;
-       giDisplayTotalLines = Lines + ExtraScrollbackLines;
-       gasDisplayLines = calloc( sizeof(char*), (Lines + ExtraScrollbackLines) );
-       gaiDisplayLineSizes = calloc( sizeof(int), (Lines + ExtraScrollbackLines) );
-       gabDisplayLinesDirty = calloc( sizeof(char), (Lines + ExtraScrollbackLines) );
+       tTerminal       *term = &gMainBuffer;
+       term->ViewCols = Cols;
+       term->ViewRows = Lines;
+       term->TotalLines = Lines + ExtraScrollbackLines;
+       term->PriBuf = calloc( sizeof(tLine), (Lines + ExtraScrollbackLines) );
        
        AxWin3_RichText_SetLineCount(gMainWindow, Lines+ExtraScrollbackLines);
        AxWin3_RichText_SetCursorType(gMainWindow, 1);  // TODO: enum
+       return term;
 }
 
-void Display_int_PushString(int Length, const char *Text)
+// Return the byte length of a single on-screen character
+size_t _GetCharLength(size_t AvailLength, const char *Text, uint32_t *BaseCodepoint)
 {
-       _SysDebug("Line %i += %i '%*C'", giCurrentLine, Length, Length, Text);
-       if( !gasDisplayLines[giCurrentLine] || giCurrentLinePos + Length >= gaiDisplayLineSizes[giCurrentLine] )
+       if( !AvailLength )
+               return 0;
+       
+       size_t  charlen = ReadUTF8(Text, BaseCodepoint);
+       
+       while(charlen < AvailLength)
        {
-                int    reqsize = giCurrentLinePos + Length;
-               gaiDisplayLineSizes[giCurrentLine] = (reqsize + 32-1) & ~(32-1);
-               void *tmp = realloc(gasDisplayLines[giCurrentLine], gaiDisplayLineSizes[giCurrentLine]);
-               if( !tmp )      perror("Display_AddText - realloc");
-               gasDisplayLines[giCurrentLine] = tmp;
+               uint32_t        cp;
+               size_t size = ReadUTF8(Text+charlen, &cp);
+               if( Unicode_IsPrinting(cp) )
+                       break;
+               charlen += size;
+       }
+       
+       return charlen;
+}
+
+tLine *Display_int_GetCurLine(tTerminal *Term)
+{
+        int    lineidx = Term->CursorRow + (Term->bUsingAltBuf ? 0 : Term->ViewOffset);
+       return (Term->bUsingAltBuf ? Term->AltBuf : Term->PriBuf) + lineidx;
+}
+
+size_t Display_int_PushCharacter(tTerminal *Term, size_t AvailLength, const char *Text)
+{
+       tLine   *lineptr = Display_int_GetCurLine(Term);
+       uint32_t        cp;
+       size_t  charlen = _GetCharLength(AvailLength, Text, &cp);
+       bool    bOverwrite = Unicode_IsPrinting(cp);
+       
+       _SysDebug("Line %b:%i += %i '%.*s'", Term->bUsingAltBuf, Term->CursorRow, charlen, charlen, Text);
+
+       // Figure out how much we need to shift the stream
+        int    shift;
+       if( bOverwrite ) {
+               size_t nextlen = _GetCharLength(
+                       lineptr->Len-Term->CursorByte,
+                       lineptr->Data+Term->CursorByte,
+                       NULL);
+               _SysDebug("Char at +%i is %i long (%.*s)", Term->CursorByte, nextlen,
+                               nextlen, lineptr->Data+Term->CursorByte);
+               shift = charlen - nextlen;
+       }
+       else {
+               shift = charlen;
+       }
+       _SysDebug("shift = %i", shift);
+       
+       // Ensure we have space enough
+       if( !lineptr->Data || shift > 0 ) {
+               const size_t    size_step = 64;
+               assert(shift > 0);
+               lineptr->Size = (lineptr->Len+shift+1 + size_step-1) & ~(size_step-1);
+               void *tmp = realloc(lineptr->Data, lineptr->Size);
+               if( !tmp )      perror("Display_int_PushCharacter - realloc");
+               lineptr->Data = tmp;
+       }
+       
+       // Insert into stream
+       char    *base = lineptr->Data + Term->CursorByte;
+       if( Term->CursorByte == lineptr->Len ) {
+               // No shifting needed
+       }
+       else if( shift >= 0 ) {
+               size_t  bytes = lineptr->Len - (Term->CursorByte+shift);
+               _SysDebug("memmove(base+%i, base, %i)", shift, bytes);
+               memmove(base+shift, base, bytes);
+       }
+       else {
+               shift = -shift;
+               size_t  bytes = lineptr->Len - (Term->CursorByte+shift);
+               _SysDebug("memmove(base, base+%i, %i)", shift, bytes);
+               memmove(base, base+shift, bytes);
        }
+       memcpy(base, Text, charlen);
+       lineptr->IsDirty = true;
+       lineptr->Len += shift;
+       lineptr->Data[lineptr->Len] = 0;        // NULL Terminate
 
-       memcpy(gasDisplayLines[giCurrentLine]+giCurrentLinePos, Text, Length);
-       gabDisplayLinesDirty[giCurrentLine] = 1;
-       gasDisplayLines[giCurrentLine][giCurrentLinePos+Length] = 0;
-       giCurrentLinePos += Length;
+       Term->CursorByte += charlen;
        
+       // HACKY: Prevents the CursorCol++ in Display_AddText from having an effect
+       if( !bOverwrite )
+               Term->CursorCol --;
+       
+       return charlen;
 }
 
-void Display_AddText(int Length, const char *UTF8Text)
+void Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text)
 {
        _SysDebug("%i '%.*s'", Length, Length, UTF8Text);
-       // Copy as many characters (not bytes, have to trim off the last char) as we can to the current line
-       // - then roll over to the next line
        while( Length > 0 )
        {
-                int    space = giDisplayCols - giCurrentCol;
-                int    bytes = 0;
-               while( space && bytes < Length )
-               {
-                       uint32_t        cp;
-                       bytes += ReadUTF8(UTF8Text+bytes, &cp);
-                       if( Unicode_IsPrinting(cp) ) {
-                               space --;
-                               giCurrentCol ++;
-                       }
-               }
+               size_t used = Display_int_PushCharacter(Term, Length, UTF8Text);
        
-               Display_int_PushString(bytes, UTF8Text);
-
-               UTF8Text += bytes;
-               Length -= bytes;
-               if( Length != 0 )
-               {
-                       // Next line
-                       giCurrentLinePos = 0;
-                       giCurrentCol = 0;
-                       giCurrentLine ++;
+               Length -= used;
+               UTF8Text += used;
+               
+               Term->CursorCol ++;
+               if( Term->CursorCol == Term->ViewCols ) {
+                       Display_Newline(Term, 1);
                }
        }
 }
 
-void Display_Newline(int bCarriageReturn)
+void Display_Newline(tTerminal *Term, bool bCarriageReturn)
 {
 //     Display_Flush();
 
        // Going down!
-       giCurrentLine ++;
-       if( giCurrentLine == giDisplayLines )
-               giCurrentLine = 0;
-       if( giCurrentLine == giFirstLine )
-       {
-               giFirstLine ++;
-               if(giFirstLine == giDisplayLines)
-                       giFirstLine = 0;
+       Term->CursorRow ++;
+       if( Term->CursorRow == Term->TotalLines ) {
+               // TODO: Scrolling
        }
        
        if( bCarriageReturn ) {
-               giCurrentLinePos = 0;
-               giCurrentCol = 0;
+               Term->CursorByte = 0;
+               Term->CursorCol = 0;
+               return ;
        }
-       else {
-               giCurrentLinePos = 0;
-                int    i = giCurrentCol;
-               if( !gasDisplayLines[giCurrentLine] )
-               {
-                       giCurrentCol = 0;
-                       while(i--)
-                               Display_AddText(1, " ");
-               }
-               else
-               {
-                       while( i -- )
-                       {
-                               uint32_t        cp;
-                               giCurrentLinePos += ReadUTF8(gasDisplayLines[giCurrentLine]+giCurrentLinePos, &cp);
-                               if( !Unicode_IsPrinting(cp) )
-                                       i ++;
-                       }
-               }
+
+       tLine   *line = Display_int_GetCurLine(Term);
+       
+       Term->CursorByte = 0;
+        int    old_col = Term->CursorCol;
+       Term->CursorCol = 0;
+
+       size_t  ofs = 0;
+       while( Term->CursorCol < old_col && ofs < line->Len ) {
+               ofs += _GetCharLength(line->Len-ofs, line->Data+ofs, NULL);
+               Term->CursorCol ++;
        }
+       Term->CursorByte = ofs;
+
+       while( Term->CursorCol < old_col )
+               Display_AddText(Term, 1, " ");
 }
 
-void Display_SetCursor(int Row, int Col)
+void Display_SetCursor(tTerminal *Term, int Row, int Col)
 {
        UNIMPLIMENTED();
 }
 
-void Display_MoveCursor(int RelRow, int RelCol)
+void Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol)
 {
-       if( RelRow < 0 )
+       if( RelRow != 0 )
        {
-               for( ; RelRow < 0; RelRow ++ )
-               {
-                       uint32_t        cp;
-                       int delta = ReadUTF8Rev(gasDisplayLines[giCurrentLine], giCurrentLinePos, &cp);
-                       if( !Unicode_IsPrinting(cp) )
-                               RelRow --;
-                       else
-                               giCurrentCol --;
-                       giCurrentLinePos -= delta;
-               }
+               UNIMPLIMENTED();
        }
-       else
+       
+       if( RelCol != 0 )
        {
-               UNIMPLIMENTED();
+               int req_col = Term->CursorCol + RelCol;
+               if( req_col < 0 )       req_col = 0;
+               if( req_col > Term->ViewCols )  req_col = Term->ViewCols;
+
+               tLine   *line = Display_int_GetCurLine(Term);
+               size_t  ofs = 0;
+               for( int i = 0; i < req_col; i ++ )
+               {
+                       size_t clen = _GetCharLength(line->Len-ofs, line->Data+ofs, NULL);
+                       if( clen == 0 ) {
+                               req_col = i;
+                               break;
+                       }
+                       ofs += clen;
+               }
+
+               Term->CursorCol = req_col;
+               Term->CursorByte = ofs;
        }
 }
 
-void Display_ClearLine(int Dir)        // 0: All, 1: Forward, -1: Reverse
+void Display_ClearLine(tTerminal *Term, int Dir)       // 0: All, 1: Forward, -1: Reverse
 {
        if( Dir == 0 )
        {
+               tLine   *line = Display_int_GetCurLine(Term);
                // Completely clear line
-               if( gasDisplayLines[giCurrentLine] )
-                       free(gasDisplayLines[giCurrentLine]);
-               gasDisplayLines[giCurrentLine] = NULL;
-               gabDisplayLinesDirty[giCurrentLine] = 1;
+               if( line->Data )
+                       free(line->Data);
+               line->Data = NULL;
+               line->IsDirty = true;
        }
        else if( Dir == 1 )
        {
@@ -190,7 +275,7 @@ void Display_ClearLine(int Dir)     // 0: All, 1: Forward, -1: Reverse
        }
 }
 
-void Display_ClearLines(int Dir)       // 0: All, 1: Forward, -1: Reverse
+void Display_ClearLines(tTerminal *Term, int Dir)      // 0: All, 1: Forward, -1: Reverse
 {
        if( Dir == 0 )
        {
@@ -211,36 +296,36 @@ void Display_ClearLines(int Dir)  // 0: All, 1: Forward, -1: Reverse
        }
 }
 
-void Display_SetForeground(uint32_t RGB)
+void Display_SetForeground(tTerminal *Term, uint32_t RGB)
 {
        char    buf[7+1];
        sprintf(buf, "\1%06x", RGB&0xFFFFFF);
-       Display_int_PushString(7, buf);
+       Display_AddText(Term, 7, buf);
 }
 
-void Display_SetBackground(uint32_t RGB)
+void Display_SetBackground(tTerminal *Term, uint32_t RGB)
 {
        char    buf[7+1];
        sprintf(buf, "\2%06x", RGB&0xFFFFFF);
-       Display_int_PushString(7, buf);
+       Display_AddText(Term, 7, buf);
 }
 
-void Display_Flush(void)
+void Display_Flush(tTerminal *Term)
 {
-        int    i;
-       for( i = 0; i < giDisplayCols; i ++ )
+       for( int i = 0; i < Term->ViewRows; i ++ )
        {
-                int    line = (giFirstLine + i) % giDisplayTotalLines;
-               if( !gabDisplayLinesDirty[line] )
+                int    line = (Term->ViewOffset + i) % Term->TotalLines;
+               tLine   *lineptr = &Term->PriBuf[line];
+               if( !lineptr->IsDirty )
                        continue;
-               _SysDebug("Line %i+%i '%s'", giFirstLine, i, gasDisplayLines[line]);
-               AxWin3_RichText_SendLine(gMainWindow, giFirstLine + i, gasDisplayLines[line] );
-               gabDisplayLinesDirty[line] = 0;
+               _SysDebug("Line %i+%i '%.*s'", Term->ViewOffset, i, lineptr->Len, lineptr->Data);
+               AxWin3_RichText_SendLine(gMainWindow, Term->ViewOffset + i, lineptr->Data );
+               lineptr->IsDirty = 0;
        }
-       AxWin3_RichText_SetCursorPos(gMainWindow, giCurrentLine, giCurrentCol);
+       AxWin3_RichText_SetCursorPos(gMainWindow, Term->CursorRow, Term->CursorCol);
 }
 
-void Display_ShowAltBuffer(int AltBufEnabled)
+void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled)
 {
        UNIMPLIMENTED();
 }
index 4feaf35..26601fe 100644 (file)
@@ -9,27 +9,31 @@
 #define _DISPLAY_H_
 
 #include <stdint.h>
+#include <stddef.h>    // size_t
+#include <stdbool.h>
 
-extern void    Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
+typedef struct sTerminal       tTerminal;
 
-extern void    Display_AddText(int Length, const char *UTF8Text);
-extern void    Display_Newline(int bCarriageReturn);
-extern void    Display_SetCursor(int Row, int Col);
-extern void    Display_MoveCursor(int RelRow, int RelCol);
-extern void    Display_ClearLine(int Dir);     // 0: All, 1: Forward, -1: Reverse
-extern void    Display_ClearLines(int Dir);    // 0: All, 1: Forward, -1: Reverse
-extern void    Display_SetForeground(uint32_t RGB);
-extern void    Display_SetBackground(uint32_t RGB);
+extern tTerminal       *Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
+
+extern void    Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text);
+extern void    Display_Newline(tTerminal *Term, bool bCarriageReturn);
+extern void    Display_SetCursor(tTerminal *Term, int Row, int Col);
+extern void    Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol);
+extern void    Display_ClearLine(tTerminal *Term, int Dir);    // 0: All, 1: Forward, -1: Reverse
+extern void    Display_ClearLines(tTerminal *Term, int Dir);   // 0: All, 1: Forward, -1: Reverse
+extern void    Display_SetForeground(tTerminal *Term, uint32_t RGB);
+extern void    Display_SetBackground(tTerminal *Term, uint32_t RGB);
 /**
  * \brief Ensure that recent updates are flushed to the server
  * \note Called at the end of an "input" buffer
  */
-extern void    Display_Flush(void);
+extern void    Display_Flush(tTerminal *Term);
 
 /**
  * \brief Switch the display to the alternate buffer (no scrollback)
  */
-extern void    Display_ShowAltBuffer(int AltBufEnabled);
+extern void    Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled);
 
 #endif
 
index 13f830e..162991b 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _VT100_H_
 #define _VT100_H_
 
+#include "display.h"
+
 /**
  * Returns either a positive or negative byte count.
  * Positive means that many bytes were used as part of the escape sequence
@@ -15,7 +17,7 @@
  * Negative means that there were that many bytes before the next escape
  * sequence (and hence those should be displayed).
  */
-extern int     Term_HandleVT100(int Len, const char *Buf);
+extern int     Term_HandleVT100(tTerminal *Term, int Len, const char *Buf);
 
 
 #endif
index 3f9a656..344bba0 100644 (file)
@@ -22,7 +22,7 @@
  int   main(int argc, char *argv[], const char **envp);
  int   Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
  int   Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
-void   Term_HandleOutput(int Len, const char *Buf);
+void   Term_HandleOutput(tTerminal *Term, int Len, const char *Buf);
 
 // === GLOBALS ===
 tHWND  gMainWindow;
@@ -55,7 +55,7 @@ int main(int argc, char *argv[], const char **envp)
        AxWin3_RichText_SetCursorType   (gMainWindow, AXWIN3_RICHTEXT_CURSOR_INV);
        AxWin3_RichText_SetCursorBlink  (gMainWindow, 1);
 
-       Display_Init(80, 25, 100);
+       tTerminal *term = Display_Init(80, 25, 100);
        AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16);
        AxWin3_MoveWindow(gMainWindow, 20, 50);
        AxWin3_ShowWindow(gMainWindow, 1);
@@ -105,7 +105,7 @@ int main(int argc, char *argv[], const char **envp)
                        int len = _SysRead(giPTYHandle, buf, sizeof(buf));
                        if( len <= 0 )  break;
                        
-                       Term_HandleOutput(len, buf);
+                       Term_HandleOutput(term, len, buf);
                }
        }
 
@@ -184,7 +184,7 @@ int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
        return 0;
 }
 
-void Term_HandleOutput(int Len, const char *Buf)
+void Term_HandleOutput(tTerminal *Term, int Len, const char *Buf)
 {
        // TODO: Handle graphical / accelerated modes
 
@@ -193,15 +193,15 @@ void Term_HandleOutput(int Len, const char *Buf)
 
        while( ofs < Len )
        {
-               esc_len = Term_HandleVT100(Len - ofs, Buf + ofs);
+               esc_len = Term_HandleVT100(Term, Len - ofs, Buf + ofs);
                if( esc_len < 0 ) {
-                       Display_AddText(-esc_len, Buf + ofs);
+                       Display_AddText(Term, -esc_len, Buf + ofs);
                        esc_len = -esc_len;
                }
                ofs += esc_len;
                //_SysDebug("Len = %i, ofs = %i", Len, ofs);
        }
        
-       Display_Flush();
+       Display_Flush(Term);
 }
 
index 09a96d9..0a62ba9 100644 (file)
@@ -19,14 +19,14 @@ const uint32_t      caVT100Colours[] = {
        0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
 };
 
- int   Term_HandleVT100_Long(int Len, const char *Buf);
+ int   Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buf);
 
 static inline int min(int a, int b)
 {
        return a < b ? a : b;
 }
 
-int Term_HandleVT100(int Len, const char *Buf)
+int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
 {
        #define MAX_VT100_ESCAPE_LEN    16
        static char     inc_buf[MAX_VT100_ESCAPE_LEN];
@@ -47,7 +47,7 @@ int Term_HandleVT100(int Len, const char *Buf)
                switch(inc_buf[1])
                {
                case '[':       // Multibyte, funtime starts    
-                       ret = Term_HandleVT100_Long(inc_len-2, inc_buf+2);
+                       ret = Term_HandleVT100_Long(Term, inc_len-2, inc_buf+2);
                        if( ret > 0 ) {
                                ret += 2;
                        }
@@ -67,19 +67,19 @@ int Term_HandleVT100(int Len, const char *Buf)
        switch( *Buf )
        {
        case '\b':
-               Display_MoveCursor(-1, 0);
-               Display_AddText(1, " ");
-               Display_MoveCursor(-1, 0);
+               Display_MoveCursor(Term, -1, 0);
+               Display_AddText(Term, 1, " ");
+               Display_MoveCursor(Term, -1, 0);
                // TODO: Need to handle \t and ^A-Z
                return 1;
        case '\t':
                // TODO: tab (get current cursor pos, space until multiple of 8)
                return 1;
        case '\n':
-               Display_Newline(1);
+               Display_Newline(Term, 1);
                return 1;
        case '\r':
-               Display_MoveCursor(INT_MIN, 0);
+               Display_MoveCursor(Term, INT_MIN, 0);
                return 1;
        }
 
@@ -96,7 +96,7 @@ int Term_HandleVT100(int Len, const char *Buf)
        return -ret;
 }
 
-int Term_HandleVT100_Long(int Len, const char *Buffer)
+int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
 {
        char    c;
         int    argc = 0, j = 0;
@@ -137,9 +137,26 @@ int Term_HandleVT100_Long(int Len, const char *Buffer)
 
        if( bQuestionMark )
        {
+                int    set = 0;
                // Special commands
                switch( c )
                {
+               case 'h':       // set
+                       set = 1;
+               case 'l':       // unset
+                       switch(args[0])
+                       {
+                       case 25:        // Hide cursor
+                               _SysDebug("TODO: \\e[?25%c Show/Hide cursor", c);
+                               break;
+                       case 1047:      // Alternate buffer
+                               Display_ShowAltBuffer(Term, set);
+                               break;
+                       default:
+                               _SysDebug("TODO: \\e[?%i%c Unknow DEC private mode", args[0], c);
+                               break;
+                       }
+                       break;
                default:
                        _SysDebug("Unknown VT100 extended escape char 0x%x", c);
                        break;
@@ -150,14 +167,24 @@ int Term_HandleVT100_Long(int Len, const char *Buffer)
                // Standard commands
                switch( c )
                {
+               case 'H':
+                       if( argc != 2 ) {
+                       }
+                       else {
+                               Display_SetCursor(Term, args[0], args[1]);
+                       }
+                       break;
                case 'J':
                        if( argc == 0 )
-                               Display_ClearLine(0);
+                               Display_ClearLine(Term, 0);
                        else if( args[0] == 2 )
-                               Display_ClearLines(0);  // Entire screen!
+                               Display_ClearLines(Term, 0);    // Entire screen!
                        else
                                _SysDebug("TODO: VT100 %i J", args[0]);
                        break;
+               case 'T':       // Scroll down n=1
+                       _SysDebug("TODO: \\x1B[nT - Scroll down");
+                       break;
                case 'm':
                        if( argc == 0 )
                        {
@@ -175,18 +202,23 @@ int Term_HandleVT100_Long(int Len, const char *Buffer)
                                        else if( 30 <= args[i] && args[i] <= 37 )
                                        {
                                                // TODO: Bold/bright
-                                               Display_SetForeground( caVT100Colours[ args[i]-30 ] );
+                                               Display_SetForeground( Term, caVT100Colours[ args[i]-30 ] );
                                        } 
                                        else if( 40 <= args[i] && args[i] <= 47 )
                                        {
                                                // TODO: Bold/bright
-                                               Display_SetBackground( caVT100Colours[ args[i]-30 ] );
+                                               Display_SetBackground( Term, caVT100Colours[ args[i]-30 ] );
                                        } 
                                }
                        }
                        break;
+               // Set scrolling region
+               case 'r':
+                       _SysDebug("TODO: \\x1B[%i;%ir - Set Scroll Region",
+                               args[0], args[1]);
+                       break;
                default:
-                       _SysDebug("Unknown VT100 escape char 0x%x", c);
+                       _SysDebug("Unknown VT100 long escape char 0x%x '%c'", c, c);
                        break;
                }
        }

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