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

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