Usermode/GUI Terminal - Fixed some characters not triggering end of normal text
[tpg/acess2.git] / Usermode / Applications / gui_shell_src / vt100.c
1 /*
2  * Acess GUI Terminal
3  * - By John Hodge (thePowersGang)
4  *
5  * vt100.c
6  * - VT100/xterm Emulation
7  */
8 #include <string.h>
9 #include <limits.h>
10 #include "include/vt100.h"
11 #include "include/display.h"
12 #include <ctype.h>      // isalpha
13 #include <acess/sys.h>  // _SysDebug
14
15 const uint32_t  caVT100Colours[] = {
16         // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
17         // Same again, but bright
18         0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA,
19         0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
20 };
21
22  int    Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buf);
23
24 static inline int min(int a, int b)
25 {
26         return a < b ? a : b;
27 }
28
29 int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
30 {
31         #define MAX_VT100_ESCAPE_LEN    16
32         static char     inc_buf[MAX_VT100_ESCAPE_LEN];
33         static int      inc_len = 0;
34
35         if( inc_len > 0 || *Buf == '\x1b' )
36         {
37                 // Handle VT100 (like) escape sequence
38                  int    new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len);
39                  int    ret = 0, old_inc_len = inc_len;
40                 memcpy(inc_buf + inc_len, Buf, new_bytes);
41
42                 inc_len += new_bytes;
43
44                 if( inc_len <= 1 )
45                         return 1;       // Skip 1 character (the '\x1b')
46
47                 switch(inc_buf[1])
48                 {
49                 case '[':       // Multibyte, funtime starts    
50                         ret = Term_HandleVT100_Long(Term, inc_len-2, inc_buf+2);
51                         if( ret > 0 ) {
52                                 ret += 2;
53                         }
54                         break;
55                 default:
56                         ret = 2;
57                         break;
58                 }       
59
60                 if( ret != 0 ) {
61                         inc_len = 0;
62                         ret -= old_inc_len;     // counter cached bytes
63                 }
64                 return ret;
65         }
66
67         switch( *Buf )
68         {
69         case '\b':
70                 Display_MoveCursor(Term, -1, 0);
71                 Display_AddText(Term, 1, " ");
72                 Display_MoveCursor(Term, -1, 0);
73                 // TODO: Need to handle \t and ^A-Z
74                 return 1;
75         case '\t':
76                 // TODO: tab (get current cursor pos, space until multiple of 8)
77                 return 1;
78         case '\n':
79                 Display_Newline(Term, 1);
80                 return 1;
81         case '\r':
82                 Display_MoveCursor(Term, INT_MIN, 0);
83                 return 1;
84         }
85
86          int    ret = 0;
87         while( ret < Len )
88         {
89                 switch(*Buf)
90                 {
91                 case '\x1b':
92                 case '\b':
93                 case '\t':
94                 case '\n':
95                 case '\r':
96                         // Force an exit right now
97                         Len = ret;
98                         break;
99                 default:
100                         ret ++;
101                         Buf ++;
102                         break;
103                 }
104         }
105         return -ret;
106 }
107
108 int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
109 {
110         char    c;
111          int    argc = 0, j = 0;
112          int    args[6] = {0,0,0,0,0,0};
113          int    bQuestionMark = 0;
114         
115         // Get Arguments
116         if(j == Len)    return 0;
117         c = Buffer[j++];
118         if(c == '?') {
119                 bQuestionMark = 1;
120                 if(j == Len)    return 0;
121                 c = Buffer[j++];
122         }
123         if( '0' <= c && c <= '9' )
124         {
125                 do {
126                         if(c == ';') {
127                                 if(j == Len)    return 0;
128                                 c = Buffer[j++];
129                         }
130                         while('0' <= c && c <= '9') {
131                                 args[argc] *= 10;
132                                 args[argc] += c-'0';
133                                 if(j == Len)    return 0;
134                                 c = Buffer[j++];
135                         }
136                         argc ++;
137                 } while(c == ';');
138         }
139         
140         // Get Command
141         if( !isalpha(c) ) {
142                 // Bother.
143                 _SysDebug("Unexpected char 0x%x in VT100 escape code", c);
144                 return 1;
145         }
146
147         if( bQuestionMark )
148         {
149                  int    set = 0;
150                 // Special commands
151                 switch( c )
152                 {
153                 case 'h':       // set
154                         set = 1;
155                 case 'l':       // unset
156                         switch(args[0])
157                         {
158                         case 25:        // Hide cursor
159                                 _SysDebug("TODO: \\e[?25%c Show/Hide cursor", c);
160                                 break;
161                         case 1047:      // Alternate buffer
162                                 Display_ShowAltBuffer(Term, set);
163                                 break;
164                         default:
165                                 _SysDebug("TODO: \\e[?%i%c Unknow DEC private mode", args[0], c);
166                                 break;
167                         }
168                         break;
169                 default:
170                         _SysDebug("Unknown VT100 extended escape char 0x%x", c);
171                         break;
172                 }
173         }
174         else
175         {
176                 // Standard commands
177                 switch( c )
178                 {
179                 case 'H':
180                         if( argc != 2 ) {
181                         }
182                         else {
183                                 Display_SetCursor(Term, args[0], args[1]);
184                         }
185                         break;
186                 case 'J':
187                         if( argc == 0 )
188                                 Display_ClearLine(Term, 0);
189                         else if( args[0] == 2 )
190                                 Display_ClearLines(Term, 0);    // Entire screen!
191                         else
192                                 _SysDebug("TODO: VT100 %i J", args[0]);
193                         break;
194                 case 'T':       // Scroll down n=1
195                         _SysDebug("TODO: \\x1B[nT - Scroll down");
196                         break;
197                 case 'm':
198                         if( argc == 0 )
199                         {
200                                 // Reset
201                         }
202                         else
203                         {
204                                 int i;
205                                 for( i = 0; i < argc; i ++ )
206                                 {
207                                         if( args[i] < 8 )
208                                         {
209                                                 // TODO: Flags?
210                                         }
211                                         else if( 30 <= args[i] && args[i] <= 37 )
212                                         {
213                                                 // TODO: Bold/bright
214                                                 Display_SetForeground( Term, caVT100Colours[ args[i]-30 ] );
215                                         } 
216                                         else if( 40 <= args[i] && args[i] <= 47 )
217                                         {
218                                                 // TODO: Bold/bright
219                                                 Display_SetBackground( Term, caVT100Colours[ args[i]-30 ] );
220                                         } 
221                                 }
222                         }
223                         break;
224                 // Set scrolling region
225                 case 'r':
226                         _SysDebug("TODO: \\x1B[%i;%ir - Set Scroll Region",
227                                 args[0], args[1]);
228                         break;
229                 default:
230                         _SysDebug("Unknown VT100 long escape char 0x%x '%c'", c, c);
231                         break;
232                 }
233         }
234         return j;
235 }

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