3 * - By John Hodge (thePowersGang)
6 * - Virtual Terminal - VT100 (Kinda) Emulation
11 const Uint16 caVT100Colours[] = {
12 // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
13 // Same again, but bright
14 VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0xAAA,
15 VT_COL_GREY, 0xF00, 0x0F0, 0xFF0, 0x00F, 0xF0F, 0x0FF, VT_COL_WHITE
20 * \brief Handle a standard large escape code
22 * Handles any escape code of the form \x1B[n,...A where n is an integer
23 * and A is any letter.
25 void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int *args)
35 if(argc == 1) tmp *= args[0];
36 if( Term->Flags & VT_FLAG_ALTBUF )
38 if( (Term->AltWritePos + tmp) % Term->TextWidth == 0 ) {
39 Term->AltWritePos -= Term->AltWritePos % Term->TextWidth;
40 Term->AltWritePos += Term->TextWidth - 1;
43 Term->AltWritePos += tmp;
47 if( (Term->WritePos + tmp) % Term->TextWidth == 0 ) {
48 Term->WritePos -= Term->WritePos % Term->TextWidth;
49 Term->WritePos += Term->TextWidth - 1;
52 Term->WritePos += tmp;
60 case 0: // Erase below
62 case 1: // Erase above
65 if( Term->Flags & VT_FLAG_ALTBUF )
67 int i = Term->TextHeight;
68 while( i-- ) VT_int_ClearLine(Term, i);
69 Term->AltWritePos = 0;
70 VT_int_UpdateScreen(Term, 1);
74 int i = Term->TextHeight * (giVT_Scrollback + 1);
75 while( i-- ) VT_int_ClearLine(Term, i);
78 VT_int_UpdateScreen(Term, 1);
88 case 0: // Erase to right
89 if( Term->Flags & VT_FLAG_ALTBUF )
92 max = Term->Width - Term->AltWritePos % Term->Width;
93 for( i = 0; i < max; i ++ )
94 Term->AltBuf[Term->AltWritePos+i].Ch = 0;
99 max = Term->Width - Term->WritePos % Term->Width;
100 for( i = 0; i < max; i ++ )
101 Term->Text[Term->WritePos+i].Ch = 0;
103 VT_int_UpdateScreen(Term, 0);
105 case 1: // Erase to left
106 if( Term->Flags & VT_FLAG_ALTBUF )
108 int i = Term->AltWritePos % Term->Width;
110 Term->AltBuf[Term->AltWritePos++].Ch = 0;
114 int i = Term->WritePos % Term->Width;
116 Term->Text[Term->WritePos++].Ch = 0;
118 VT_int_UpdateScreen(Term, 0);
121 if( Term->Flags & VT_FLAG_ALTBUF )
123 VT_int_ClearLine(Term, Term->AltWritePos / Term->Width);
127 VT_int_ClearLine(Term, Term->WritePos / Term->Width);
129 VT_int_UpdateScreen(Term, 0);
134 // Set cursor position
136 if( Term->Flags & VT_FLAG_ALTBUF )
137 Term->AltWritePos = args[1] + args[0]*Term->TextWidth;
139 Term->WritePos = args[1] + args[0]*Term->TextWidth;
140 //Log_Debug("VTerm", "args = {%i, %i}", args[0], args[1]);
142 // Scroll up `n` lines
145 // Scroll down `n` lines
147 if(argc == 1) tmp *= args[0];
148 if( Term->Flags & VT_FLAG_ALTBUF )
149 VT_int_ScrollText(Term, tmp);
152 if(Term->ViewPos/Term->TextWidth + tmp < 0)
154 if(Term->ViewPos/Term->TextWidth + tmp > Term->TextHeight * (giVT_Scrollback + 1))
157 Term->ViewPos += Term->TextWidth*tmp;
166 case 2: // Keyboard action mode
167 case 4: // Insert mode
168 case 12: // Send/receive
169 case 20: // Automatic newline
183 if( 0 <= args[argc] && args[argc] <= 8)
187 case 0: Term->CurColour = DEFAULT_COLOUR; break; // Reset
188 case 1: Term->CurColour |= 0x80000000; break; // Bright
189 case 2: Term->CurColour &= ~0x80000000; break; // Dim
193 else if(30 <= args[argc] && args[argc] <= 37) {
194 // Get colour index, accounting for bright bit
195 colour_idx = args[argc]-30 + ((Term->CurColour>>28) & 8);
196 Term->CurColour &= 0x8000FFFF;
197 Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ] << 16;
200 else if(40 <= args[argc] && args[argc] <= 47) {
201 // Get colour index, accounting for bright bit
202 colour_idx = args[argc]-40 + ((Term->CurColour>>12) & 8);
203 Term->CurColour &= 0xFFFF8000;
204 Term->CurColour |= caVT100Colours[ colour_idx ];
206 // Foreground Colour - bright
207 else if(90 <= args[argc] && args[argc] <= 97 ) {
208 colour_idx = args[argc]-90 + 8;
209 Term->CurColour &= 0x8000FFFF;
210 Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ] << 16;
212 // Background Colour - bright
213 else if(100 <= args[argc] && args[argc] <= 107 ) {
214 colour_idx = args[argc]-100 + 8;
215 Term->CurColour &= 0xFFFF8000;
216 Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ];
219 Log_Warning("VTerm", "Unknown font flag %i", args[argc]);
224 // Set scrolling region
226 if( argc != 2 ) break;
227 Term->ScrollTop = args[0];
228 Term->ScrollHeight = args[1] - args[0];
231 // Save cursor position
233 if( argc != 0 ) break;
234 Term->SavedWritePos = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltWritePos : Term->WritePos;
237 // Restore saved cursor position
239 if( argc != 0 ) break;
240 *((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos) = Term->SavedWritePos;
244 Log_Warning("VTerm", "Unknown control sequence '\\x1B[%c'", CmdChar);
250 * \fn int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
251 * \brief Parses a VT100 Escape code
253 int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes)
257 int args[6] = {0,0,0,0};
258 int bQuestionMark = 0;
259 const int ofs = Term->EscapeCodeLen;
260 const int sparespace = sizeof(Term->EscapeCodeCache)-Term->EscapeCodeLen;
261 const int copysize = MIN(Bytes, sparespace);
263 memcpy( Term->EscapeCodeCache + Term->EscapeCodeLen, Buffer, copysize );
264 Term->EscapeCodeLen += copysize;
266 Bytes = Term->EscapeCodeLen;
267 Buffer = Term->EscapeCodeCache;
269 if( Bytes == j ) return j-ofs;
272 Term->EscapeCodeLen = 0;
276 if( Bytes == j ) return j-ofs;
284 if(Bytes == j) return j-ofs;
288 if(Bytes == j) return j-ofs;
291 if( '0' <= c && c <= '9' )
295 if(Bytes == j) return j-ofs;
298 while('0' <= c && c <= '9') {
301 if(Bytes == j) return j-ofs;
309 if( !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') )
311 // Error - eat ESC only?
312 // > j : Entire code skipped
313 Term->EscapeCodeLen = 0;
321 // DEC Private Mode Set
327 Term->Flags &= ~VT_FLAG_HIDECSR;
330 VT_int_ToggleAltBuffer(Term, 1);
339 Term->Flags |= VT_FLAG_HIDECSR;
342 VT_int_ToggleAltBuffer(Term, 0);
347 Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
353 VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
359 // Reset all attributes
361 Term->CurColour = DEFAULT_COLOUR;
363 Term->ScrollHeight = 0;
366 //Log_Notice("VTerm", "TODO: Handle short escape codes");
368 static volatile int tmp = 0;
371 Debug("VTerm: Unknown short 0x%x", c);
378 //Log_Debug("VTerm", "j = %i, Buffer = '%s'", j, Buffer);
379 Term->EscapeCodeLen = 0;