#include <errno.h>
#include <semaphore.h>
-#define USE_CTRL_ALT 1
-
// === CONSTANTS ===
#define VERSION ((0<<8)|(50))
#define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4)
//#define DEFAULT_OUTPUT "BochsGA"
#define DEFAULT_OUTPUT "Vesa"
+#define FALLBACK_OUTPUT "x86_VGAText"
#define DEFAULT_INPUT "PS2Keyboard"
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define VT_FLAG_HIDECSR 0x01
#define VT_FLAG_ALTBUF 0x02 //!< Alternate screen buffer
+#define VT_FLAG_RAWIN 0x04 //!< Don't handle ^Z/^C/^V
#define VT_FLAG_HASFB 0x10 //!< Set if the VTerm has requested the Framebuffer
enum eVT_InModes {
};
// === GLOBALS ===
-MODULE_DEFINE(0, VERSION, VTerm, VT_Install, NULL, DEFAULT_OUTPUT, DEFAULT_INPUT, NULL);
+MODULE_DEFINE(0, VERSION, VTerm, VT_Install, NULL, FALLBACK_OUTPUT, DEFAULT_INPUT, NULL);
tDevFS_Driver gVT_DrvInfo = {
NULL, "VTerm",
{
Log_Debug("VTerm", "Argument '%s'", arg);
if( strcmp(opt, "Video") == 0 ) {
- if( !gsVT_OutputDevice && Modules_InitialiseBuiltin( val ) == 0 )
+ if( !gsVT_OutputDevice )
gsVT_OutputDevice = strdup(val);
}
else if( strcmp(opt, "Input") == 0 ) {
- if( !gsVT_InputDevice && Modules_InitialiseBuiltin( val ) == 0 )
+ if( !gsVT_InputDevice )
gsVT_InputDevice = strdup(val);
}
else if( strcmp(opt, "Width") == 0 ) {
}
// Apply Defaults
- if(!gsVT_OutputDevice) gsVT_OutputDevice = strdup(DEFAULT_OUTPUT);
- if(!gsVT_InputDevice) gsVT_InputDevice = strdup(DEFAULT_INPUT);
+ if(!gsVT_OutputDevice) gsVT_OutputDevice = (char*)DEFAULT_OUTPUT;
+ else if( Module_EnsureLoaded( gsVT_OutputDevice ) ) gsVT_OutputDevice = (char*)DEFAULT_OUTPUT;
+ if( Module_EnsureLoaded( gsVT_OutputDevice ) ) gsVT_OutputDevice = (char*)FALLBACK_OUTPUT;
+
+ if(!gsVT_InputDevice) gsVT_InputDevice = (char*)DEFAULT_INPUT;
+ else if( Module_EnsureLoaded( gsVT_InputDevice ) ) gsVT_InputDevice = (char*)DEFAULT_INPUT;
- // Create paths
+ // Create device paths
{
char *tmp;
tmp = malloc( 9 + strlen(gsVT_OutputDevice) + 1 );
strcpy(tmp, "/Devices/");
strcpy(&tmp[9], gsVT_OutputDevice);
gsVT_OutputDevice = tmp;
+
tmp = malloc( 9 + strlen(gsVT_InputDevice) + 1 );
strcpy(tmp, "/Devices/");
strcpy(&tmp[9], gsVT_InputDevice);
// Set kernel output to VT0
Debug_SetKTerminal("/Devices/VTerm/0");
- Log_Log("VTerm", "Returning %i", MODULE_ERR_OK);
return MODULE_ERR_OK;
}
// Resize the text terminals
giVT_RealWidth = mode.width;
giVT_RealHeight = mode.height;
+ Log_Debug("VTerm", "Resizing terminals to %ix%i",
+ giVT_RealWidth/giVT_CharWidth, giVT_RealHeight/giVT_CharHeight);
for( i = 0; i < NUM_VTS; i ++ )
{
if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue;
gVT_Terminals[i].TextWidth = giVT_RealWidth/giVT_CharWidth;
gVT_Terminals[i].TextHeight = giVT_RealHeight/giVT_CharHeight;
+ gVT_Terminals[i].ScrollHeight = gVT_Terminals[i].TextHeight;
gVT_Terminals[i].Text = realloc(
gVT_Terminals[i].Text,
}
/**
- * \fn Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
* \brief Read from a virtual terminal
*/
Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
// Other - UCS-4
default:
VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "VT_Read (UCS-4)");
-
+
avail = term->InputWrite - term->InputRead;
if(avail < 0)
avail += MAX_INPUT_CHARS32;
Codepoint &= 0x7FFFFFFF;
switch(Codepoint)
{
- #if !USE_CTRL_ALT
- case KEY_RSHIFT: gbVT_CtrlDown = 0; break;
- case KEY_LSHIFT: gbVT_AltDown = 0; break;
- #else
case KEY_LALT: gbVT_AltDown &= ~1; break;
case KEY_RALT: gbVT_AltDown &= ~2; break;
case KEY_LCTRL: gbVT_CtrlDown &= ~1; break;
case KEY_RCTRL: gbVT_CtrlDown &= ~2; break;
- #endif
}
return;
}
switch(Codepoint)
{
- #if !USE_CTRL_ALT // HACK: Use both shifts instead of Ctrl-Alt
- case KEY_RSHIFT: gbVT_CtrlDown = 1; break;
- case KEY_LSHIFT: gbVT_AltDown = 1; break;
- #else
case KEY_LALT: gbVT_AltDown |= 1; break;
case KEY_RALT: gbVT_AltDown |= 2; break;
case KEY_LCTRL: gbVT_CtrlDown |= 1; break;
case KEY_RCTRL: gbVT_CtrlDown |= 2; break;
- #endif
default:
if(!gbVT_AltDown || !gbVT_CtrlDown)
// Unprintable / Don't Pass
return;
}
+
+#if 0
+ // Handle meta characters
+ if( !(term->Flags & VT_FLAG_RAWIN) )
+ {
+ switch(buf[0])
+ {
+ case '\3': // ^C
+
+ break;
+ }
+ }
+#endif
// Write
if( MAX_INPUT_CHARS8 - term->InputWrite >= len )
break;
}
break;
+
+ // Erase in line
+ case 'K':
+ switch(args[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;
+ }
+ break;
+
// Set cursor position
case 'H':
if( Term->Flags & VT_FLAG_ALTBUF )
write_pos -= write_pos % Term->TextWidth;
break;
- case '\t':
+ case '\t': { int tmp = write_pos / Term->TextWidth;
+ write_pos %= Term->TextWidth;
do {
buffer[ write_pos ].Ch = '\0';
buffer[ write_pos ].Colour = Term->CurColour;
write_pos ++;
} while(write_pos & 7);
- break;
+ write_pos += tmp * Term->TextWidth;
+ break; }
case '\b':
// Backspace is invalid at Offset 0
tVT_Char *buf;
int height, init_write_pos;
int len, i;
+ int scroll_top, scroll_height;
if( Term->Flags & VT_FLAG_ALTBUF )
{
buf = Term->AltBuf;
height = Term->TextHeight;
init_write_pos = Term->AltWritePos;
+ scroll_top = Term->ScrollTop;
+ scroll_height = Term->ScrollHeight;
}
else
{
buf = Term->Text;
height = Term->TextHeight*giVT_Scrollback;
init_write_pos = Term->WritePos;
+ scroll_top = 0;
+ scroll_height = height;
}
if( Count > 0 )
{
int base;
- if(Count > Term->ScrollHeight) Count = Term->ScrollHeight;
- base = Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count);
- len = Term->TextWidth*(Term->ScrollHeight - Count);
+ if(Count > scroll_height) Count = scroll_height;
+// Debug("Scroll: Count = %i", Count);
+ base = Term->TextWidth*(scroll_top + scroll_height - Count);
+ len = Term->TextWidth*(scroll_height - Count);
// Scroll terminal cache
memcpy(
- &buf[Term->TextWidth*Term->ScrollTop],
- &buf[Term->TextWidth*(Term->ScrollTop+Count)],
+ &buf[Term->TextWidth*scroll_top],
+ &buf[Term->TextWidth*(scroll_top+Count)],
len*sizeof(tVT_Char)
);
// Clear last rows
for( i = 0; i < Term->TextWidth*Count; i ++ )
{
- Term->AltBuf[ base + i ].Ch = 0;
- Term->AltBuf[ base + i ].Colour = Term->CurColour;
+ buf[ base + i ].Ch = 0;
+ buf[ base + i ].Colour = Term->CurColour;
}
// Update Screen
VT_int_ScrollFramebuffer( Term, Count );
if( Term->Flags & VT_FLAG_ALTBUF )
- Term->AltWritePos = Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count);
+ Term->AltWritePos = base;
else
- Term->WritePos = Term->ViewPos + Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count);
-// Log_Debug("VTerm", "Term->WritePos = %i/%i = %i", Term->WritePos, Term->TextWidth, Term->WritePos/Term->TextWidth);
+ Term->WritePos = Term->ViewPos + Term->TextWidth*(Term->TextHeight - Count);
for( i = 0; i < Count; i ++ )
{
VT_int_UpdateScreen( Term, 0 );
else
{
Count = -Count;
- if(Count > Term->ScrollHeight) Count = Term->ScrollHeight;
+ if(Count > scroll_height) Count = scroll_height;
- len = Term->TextWidth*(Term->ScrollHeight - Count);
+ len = Term->TextWidth*(scroll_height - Count);
// Scroll terminal cache
memcpy(
- &buf[Term->TextWidth*(Term->ScrollTop+Count)],
- &buf[Term->TextWidth*Term->ScrollTop],
+ &buf[Term->TextWidth*(scroll_top+Count)],
+ &buf[Term->TextWidth*scroll_top],
len*sizeof(tVT_Char)
);
// Clear preceding rows
for( i = 0; i < Term->TextWidth*Count; i ++ )
{
- Term->AltBuf[ i ].Ch = 0;
- Term->AltBuf[ i ].Colour = Term->CurColour;
+ buf[ i ].Ch = 0;
+ buf[ i ].Colour = Term->CurColour;
}
VT_int_ScrollFramebuffer( Term, -Count );
if( Term->Flags & VT_FLAG_ALTBUF )
- Term->AltWritePos = Term->TextWidth*Term->ScrollTop;
+ Term->AltWritePos = Term->TextWidth*scroll_top;
else
- Term->WritePos = Term->ViewPos + Term->TextWidth*Term->ScrollTop;
+ Term->WritePos = Term->ViewPos;
for( i = 0; i < Count; i ++ )
{
VT_int_UpdateScreen( Term, 0 );
// BLIT to 0,0 from 0,giVT_CharHeight
buf.Op = VIDEO_2DOP_BLIT;
buf.SrcX = 0; buf.DstX = 0;
+ // TODO: Don't assume character dimensions
buf.W = Term->TextWidth * giVT_CharWidth;
if( Count > 0 )
{
Term->Flags |= VT_FLAG_ALTBUF;
else
Term->Flags &= ~VT_FLAG_ALTBUF;
+ VT_int_UpdateScreen(Term, 1);
}
// ---