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

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