X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fdrv%2Fvterm_vt100.c;h=ccb0c520f5c76b174e7ea31ed28559b703546dc8;hb=07ed0e7479fc741a947579d4460a25a050fc9260;hp=8ebd9bfd7342b8367e31edc9e065bd3e49eca284;hpb=cc3501e20d89f5e9db13bd874310bfb9983a35a6;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/drv/vterm_vt100.c b/KernelLand/Kernel/drv/vterm_vt100.c index 8ebd9bfd..ccb0c520 100644 --- a/KernelLand/Kernel/drv/vterm_vt100.c +++ b/KernelLand/Kernel/drv/vterm_vt100.c @@ -5,372 +5,224 @@ * drv/vterm_vt100.c * - Virtual Terminal - VT100 (Kinda) Emulation */ +#define DEBUG 0 #include "vterm.h" -// === CONSTANTS === -const Uint16 caVT100Colours[] = { - // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray - // Same again, but bright - VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0xAAA, - VT_COL_GREY, 0xF00, 0x0F0, 0xFF0, 0x00F, 0xF0F, 0x0FF, VT_COL_WHITE - }; +#define sTerminal sVTerm +#include "../../../Usermode/Applications/gui_terminal_src/vt100.c" -// === CODE === -/** - * \brief Handle a standard large escape code - * - * Handles any escape code of the form \x1B[n,...A where n is an integer - * and A is any letter. - */ -void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int *args) +void *Display_GetTermState(tTerminal *Term) { + return Term->VT100Info; +} +void Display_SetTermState(tTerminal *Term, void *State) { + Term->VT100Info = State; +} + +void Display_SendInput(tTerminal *Term, const char *String) +{ + PTY_SendInput(Term->PTY, String, strlen(String)); +} + +void Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text) +{ + LOG("'%*C'", Length, UTF8Text); + VT_int_PutRawString(Term, (const void*)UTF8Text, Length); +} +void Display_Newline(tTerminal *Term, bool bCarriageReturn) +{ + LOG(""); + VT_int_PutChar(Term, '\n'); +} +void Display_SetScrollArea(tTerminal *Term, int Start, int Count) { - int tmp = 1; - switch(CmdChar) + LOG("(%i,+%i)", Start, Count); + Term->ScrollTop = Start; + Term->ScrollHeight = Count; +} +void Display_ScrollDown(tTerminal *Term, int CountDown) +{ + LOG("(%i)", CountDown); + VT_int_UpdateScreen(Term, 0); + if( Term->Flags & VT_FLAG_ALTBUF ) + VT_int_ScrollText(Term, CountDown); + else + { + if(Term->ViewPos/Term->TextWidth + CountDown < 0) + return ; + if(Term->ViewPos/Term->TextWidth + CountDown > Term->TextHeight * (giVT_Scrollback + 1)) + return ; + + Term->ViewPos += Term->TextWidth * CountDown; + } +} +void Display_SetCursor(tTerminal *Term, int Row, int Col) +{ + LOG("(R%i,C%i)", Row, Col); + VT_int_UpdateScreen(Term, 0); + int maxrows = ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight; + ASSERTCR( Row, >=, 0, ); + ASSERTCR( Row, <, maxrows, ); + ASSERTCR( Col, >=, 0, ); + ASSERTCR( Col, <, Term->TextWidth, ); + *(Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos) = Row*Term->TextWidth + Col; +} +void Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol) +{ + LOG("(R+%i,C+%i)", RelRow, RelCol); + int *wrpos = (Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos); + + // TODO: Support scrolling if cursor goes offscreen + // if( bScrollIfNeeded ) + // Display_ScrollDown(extra); + // else + // clip + + if( RelCol != 0 ) { - // Left - case 'D': - tmp = -1; - // Right - case 'C': - if(argc == 1) tmp *= args[0]; - if( Term->Flags & VT_FLAG_ALTBUF ) + // + if( RelCol < 0 ) { - if( (Term->AltWritePos + tmp) % Term->TextWidth == 0 ) { - Term->AltWritePos -= Term->AltWritePos % Term->TextWidth; - Term->AltWritePos += Term->TextWidth - 1; - } - else - Term->AltWritePos += tmp; + int avail = *wrpos % Term->TextWidth; + if( RelCol < -avail ) + RelCol = -avail; } else { - if( (Term->WritePos + tmp) % Term->TextWidth == 0 ) { - Term->WritePos -= Term->WritePos % Term->TextWidth; - Term->WritePos += Term->TextWidth - 1; - } - else - Term->WritePos += tmp; - } - break; - - // Erase - case 'J': - switch(args[0]) - { - case 0: // Erase below - break; - case 1: // Erase above - break; - case 2: // Erase all - if( Term->Flags & VT_FLAG_ALTBUF ) - { - int i = Term->TextHeight; - while( i-- ) VT_int_ClearLine(Term, i); - Term->AltWritePos = 0; - VT_int_UpdateScreen(Term, 1); - } - else - { - int i = Term->TextHeight * (giVT_Scrollback + 1); - while( i-- ) VT_int_ClearLine(Term, i); - Term->WritePos = 0; - Term->ViewPos = 0; - VT_int_UpdateScreen(Term, 1); - } - break; + size_t avail = Term->TextWidth - (*wrpos % Term->TextWidth); + if(RelCol > avail) + RelCol = avail; } - break; - - // Erase in line - case 'K': - switch(args[0]) + *wrpos += RelCol; + } + if( RelRow != 0 ) + { + int currow = *wrpos / Term->TextWidth; + int maxrows = ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight; + if( RelRow < 0 ) { - case 0: // Erase to right - if( Term->Flags & VT_FLAG_ALTBUF ) - { - int i, max; - max = Term->Width - Term->AltWritePos % Term->Width; - for( i = 0; i < max; i ++ ) - Term->AltBuf[Term->AltWritePos+i].Ch = 0; - } - else - { - int i, max; - max = Term->Width - Term->WritePos % Term->Width; - for( i = 0; i < max; i ++ ) - Term->Text[Term->WritePos+i].Ch = 0; - } - VT_int_UpdateScreen(Term, 0); - break; - case 1: // Erase to left - if( Term->Flags & VT_FLAG_ALTBUF ) - { - int i = Term->AltWritePos % Term->Width; - while( i -- ) - Term->AltBuf[Term->AltWritePos++].Ch = 0; - } - else - { - int i = Term->WritePos % Term->Width; - while( i -- ) - Term->Text[Term->WritePos++].Ch = 0; - } - VT_int_UpdateScreen(Term, 0); - break; - case 2: // Erase all - if( Term->Flags & VT_FLAG_ALTBUF ) - { - VT_int_ClearLine(Term, Term->AltWritePos / Term->Width); - } - else - { - VT_int_ClearLine(Term, Term->WritePos / Term->Width); - } - VT_int_UpdateScreen(Term, 0); - break; + if( RelRow < -currow ) + RelRow = -currow; } - break; - - // Set cursor position - case 'H': - if( Term->Flags & VT_FLAG_ALTBUF ) - Term->AltWritePos = args[0] + args[1]*Term->TextWidth; - else - Term->WritePos = args[0] + args[1]*Term->TextWidth; - //Log_Debug("VTerm", "args = {%i, %i}", args[0], args[1]); - break; - - // Scroll up `n` lines - case 'S': - tmp = -1; - // Scroll down `n` lines - case 'T': - if(argc == 1) tmp *= args[0]; - if( Term->Flags & VT_FLAG_ALTBUF ) - VT_int_ScrollText(Term, tmp); else { - if(Term->ViewPos/Term->TextWidth + tmp < 0) - break; - if(Term->ViewPos/Term->TextWidth + tmp > Term->TextHeight * (giVT_Scrollback + 1)) - break; - - Term->ViewPos += Term->TextWidth*tmp; + if( currow + RelRow > maxrows-1 ) + RelRow = maxrows-1 - currow; } - break; - // Set Mode (?) - case 'h': - if( argc >= 1 ) - { - switch(args[0]) - { - case 2: // Keyboard action mode - case 4: // Insert mode - case 12: // Send/receive - case 20: // Automatic newline - break; - default: // ? - break; - } - } - break; - - // Set Font flags - case 'm': - for( ; argc--; ) - { - int colour_idx; - // Flags - if( 0 <= args[argc] && args[argc] <= 8) - { - switch(args[argc]) - { - case 0: Term->CurColour = DEFAULT_COLOUR; break; // Reset - case 1: Term->CurColour |= 0x80000000; break; // Bright - case 2: Term->CurColour &= ~0x80000000; break; // Dim - } - } - // Foreground Colour - else if(30 <= args[argc] && args[argc] <= 37) { - // Get colour index, accounting for bright bit - colour_idx = args[argc]-30 + ((Term->CurColour>>28) & 8); - Term->CurColour &= 0x8000FFFF; - Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ] << 16; - } - // Background Colour - else if(40 <= args[argc] && args[argc] <= 47) { - // Get colour index, accounting for bright bit - colour_idx = args[argc]-40 + ((Term->CurColour>>12) & 8); - Term->CurColour &= 0xFFFF8000; - Term->CurColour |= caVT100Colours[ colour_idx ]; - } - // Foreground Colour - bright - else if(90 <= args[argc] && args[argc] <= 97 ) { - colour_idx = args[argc]-90 + 8; - Term->CurColour &= 0x8000FFFF; - Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ] << 16; - } - // Background Colour - bright - else if(100 <= args[argc] && args[argc] <= 107 ) { - colour_idx = args[argc]-100 + 8; - Term->CurColour &= 0xFFFF8000; - Term->CurColour |= (Uint32)caVT100Colours[ colour_idx ]; - } - else { - Log_Warning("VTerm", "Unknown font flag %i", args[argc]); - } - } - break; - - // Set scrolling region - case 'r': - if( argc != 2 ) break; - Term->ScrollTop = args[0]; - Term->ScrollHeight = args[1] - args[0]; - break; - - // Save cursor position - case 's': - if( argc != 0 ) break; - Term->SavedWritePos = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltWritePos : Term->WritePos; - break; - - // Restore saved cursor position - case 'u': - if( argc != 0 ) break; - *((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos) = Term->SavedWritePos; - break; - - default: - Log_Warning("VTerm", "Unknown control sequence '\\x1B[%c'", CmdChar); - break; + *wrpos += RelRow*Term->TextWidth; } + LOG("=(R%i,C%i)", *wrpos / Term->TextWidth, *wrpos % Term->TextWidth); } - -/** - * \fn int VT_int_ParseEscape(tVTerm *Term, const char *Buffer) - * \brief Parses a VT100 Escape code - */ -int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes) +void Display_SaveCursor(tTerminal *Term) { - char c; - int argc = 0, j = 0; - int args[6] = {0,0,0,0}; - int bQuestionMark = 0; - const int ofs = Term->EscapeCodeLen; - const int sparespace = sizeof(Term->EscapeCodeCache)-Term->EscapeCodeLen; - const int copysize = MIN(Bytes, sparespace); + Term->SavedWritePos = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltWritePos : Term->WritePos; + LOG("Saved = %i", Term->SavedWritePos); +} +void Display_RestoreCursor(tTerminal *Term) +{ + int max = ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight * Term->TextWidth; + int *wrpos = ((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos); + if( Term->SavedWritePos >= max ) + *wrpos = max-1; + else + *wrpos = Term->SavedWritePos; + LOG("Restored %i", *wrpos); +} +// 0: All, 1: Forward, -1: Reverse +void Display_ClearLine(tTerminal *Term, int Dir) +{ + const int wrpos = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltWritePos : Term->WritePos); + const int row = wrpos / Term->TextWidth; + const int col = wrpos % Term->TextWidth; - memcpy( Term->EscapeCodeCache + Term->EscapeCodeLen, Buffer, copysize ); - Term->EscapeCodeLen += copysize; - - Bytes = Term->EscapeCodeLen; - Buffer = Term->EscapeCodeCache; + LOG("(Dir=%i)", Dir); - if( Bytes == j ) return j-ofs; - c = Buffer[j++]; - if(c != '\x1b') { - Term->EscapeCodeLen = 0; - return 0; + // Erase all + if( Dir == 0 ) { + VT_int_ClearLine(Term, row); + VT_int_UpdateScreen(Term, 0); } - - if( Bytes == j ) return j-ofs; - c = Buffer[j++]; - - switch(c) - { - //Large Code - case '[': - // Get Arguments - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - if(c == '?') { - bQuestionMark = 1; - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - } - if( '0' <= c && c <= '9' ) - { - do { - if(c == ';') { - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - } - while('0' <= c && c <= '9') { - args[argc] *= 10; - args[argc] += c-'0'; - if(Bytes == j) return j-ofs; - c = Buffer[j++]; - } - argc ++; - } while(c == ';'); - } - - // Get Command - if( !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') ) - { - // Error - eat ESC only? - // > j : Entire code skipped - Term->EscapeCodeLen = 0; - return j-ofs; - } + // Erase to right + else if( Dir == 1 ) { + VT_int_ClearInLine(Term, row, col, Term->TextWidth); + VT_int_UpdateScreen(Term, 0); + } + // Erase to left + else if( Dir == -1 ) { + VT_int_ClearInLine(Term, row, 0, col); + VT_int_UpdateScreen(Term, 0); + } + else { + // ERROR! + ASSERTC(Dir, >=, -1); + ASSERTC(Dir, <=, 1); + } +} +void Display_ClearLines(tTerminal *Term, int Dir) +{ + LOG("(Dir=%i)", Dir); + int *wrpos = (Term->Flags & VT_FLAG_ALTBUF ? &Term->AltWritePos : &Term->WritePos); + int height = Term->TextHeight * (Term->Flags & VT_FLAG_ALTBUF ? 1 : giVT_Scrollback + 1); + + // All + if( Dir == 0 ) { - if( bQuestionMark ) - { - switch(c) - { - // DEC Private Mode Set - case 'h': - if(argc != 1) break; - switch(args[0]) - { - case 25: - Term->Flags &= ~VT_FLAG_HIDECSR; - break; - case 1047: - VT_int_ToggleAltBuffer(Term, 1); - break; - } - break; - case 'l': - if(argc != 1) break; - switch(args[0]) - { - case 25: - Term->Flags |= VT_FLAG_HIDECSR; - break; - case 1047: - VT_int_ToggleAltBuffer(Term, 0); - break; - } - break; - default: - Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c); - break; - } + if( !(Term->Flags & VT_FLAG_ALTBUF) ) { + Term->ViewPos = 0; } - else - { - VT_int_ParseEscape_StandardLarge(Term, c, argc, args); - } - break; - case '\0': - // Ignore \0 - break; - default: - //Log_Notice("VTerm", "TODO: Handle short escape codes"); - { - static volatile int tmp = 0; - if(tmp == 0) { - tmp = 1; - Debug("VTerm: Unknown short 0x%x", c); - tmp = 0; - } - } - break; + int count = height; + while( count -- ) + VT_int_ClearLine(Term, count); + *wrpos = 0; + VT_int_UpdateScreen(Term, 1); + } + // Downwards + else if( Dir == 1 ) { + for( int row = *wrpos / Term->TextWidth; row < height; row ++ ) + VT_int_ClearLine(Term, row); + VT_int_UpdateScreen(Term, 1); } + // Upwards + else if( Dir == -1 ) { + for( int row = 0; row < *wrpos / Term->TextWidth; row ++ ) + VT_int_ClearLine(Term, row); + VT_int_UpdateScreen(Term, 1); + } + else { + // ERROR! + ASSERTC(Dir, >=, -1); + ASSERTC(Dir, <=, 1); + } +} +void Display_ResetAttributes(tTerminal *Term) +{ + LOG(""); + Term->CurColour = DEFAULT_COLOUR; +} +void Display_SetForeground(tTerminal *Term, uint32_t RGB) +{ + LOG("(%06x)", RGB); + Term->CurColour &= 0x8000FFFF; + Term->CurColour |= (Uint32)VT_Colour24to12(RGB) << 16; - //Log_Debug("VTerm", "j = %i, Buffer = '%s'", j, Buffer); - Term->EscapeCodeLen = 0; - return j-ofs; } +void Display_SetBackground(tTerminal *Term, uint32_t RGB) +{ + LOG("(%06x)", RGB); + Term->CurColour &= 0xFFFF8000; + Term->CurColour |= (Uint32)VT_Colour24to12(RGB) << 0; +} +void Display_Flush(tTerminal *Term) +{ + LOG(""); + VT_int_UpdateScreen(Term, 0); +} +void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled) +{ + LOG("(%B)", AltBufEnabled); + VT_int_ToggleAltBuffer(Term, AltBufEnabled); +} +void Display_SetTitle(tTerminal *Term, const char *Title) +{ + // ignore +} +