Log_Debug("VTerm", "Initialising nodes (and creating buffers)");
for( i = 0; i < NUM_VTS; i++ )
{
- gVT_Terminals[i].Mode = TERM_MODE_TEXT;
- gVT_Terminals[i].Flags = 0;
// gVT_Terminals[i].Flags = VT_FLAG_HIDECSR; //HACK - Stop all those memcpy calls
gVT_Terminals[i].CurColour = DEFAULT_COLOUR;
- gVT_Terminals[i].WritePos = 0;
- gVT_Terminals[i].AltWritePos = 0;
- gVT_Terminals[i].ViewPos = 0;
- gVT_Terminals[i].ScrollHeight = 0;
+ gVT_Terminals[i].Mode = PTYBUFFMT_TEXT;
// Initialise
VT_int_Resize( &gVT_Terminals[i], giVT_RealWidth, giVT_RealHeight );
- gVT_Terminals[i].Mode = PTYBUFFMT_TEXT;
char name[] = {'v','t','0'+i,'\0'};
struct ptydims dims = {
.W = giVT_RealWidth / giVT_CharWidth,
typedef struct sVTerm tVTerm;
// === STRUCTURES ===
+typedef struct
+{
+ unsigned short Row;
+ unsigned short Col;
+} tVT_Pos;
+
struct sVTerm
{
int Mode; //!< Current Mode (see ::eTplTerminal_Modes)
Uint32 CurColour; //!< Current Text Colour
- size_t ViewPos; //!< View Buffer Offset (Text Only)
- size_t WritePos; //!< Write Buffer Offset (Text Only)
+ size_t ViewTopRow; //!< View Buffer Offset (Text Only)
+ tVT_Pos WritePos; //!< Write Buffer Offset (Text Only)
tVT_Char *Text;
+ tVT_Pos AltWritePos; //!< Alternate write position
tVT_Char *AltBuf; //!< Alternate Screen Buffer
- size_t AltWritePos; //!< Alternate write position
short ScrollTop; //!< Top of scrolling region (smallest)
short ScrollHeight; //!< Length of scrolling region
- size_t SavedWritePos; //!< Saved cursor position (\e[s and \e[u)
+ tVT_Pos SavedWritePos; //!< Saved cursor position (\e[s and \e[u)
char EscapeCodeCache[16];
size_t EscapeCodeLen;
extern void VT_int_Resize(tVTerm *Term, int NewWidth, int NewHeight);
extern void VT_int_ToggleAltBuffer(tVTerm *Term, int Enabled);
-extern size_t *VT_int_GetWritePosPtr(tVTerm *Term);
+extern tVT_Pos *VT_int_GetWritePosPtr(tVTerm *Term);
extern size_t VT_int_GetBufferRows(tVTerm *Term);
#endif
{
if( Term->Mode == PTYBUFFMT_TEXT )
{
- if(Term->Flags & VT_FLAG_ALTBUF)
- Term->AltWritePos = X + Y * Term->TextWidth;
- else
- Term->WritePos = X + Y * Term->TextWidth + Term->ViewPos;
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
+ wrpos->Row = X;
+ wrpos->Col = Y + (Term->Flags & VT_FLAG_ALTBUF ? 0 : Term->ViewTopRow);
VT_int_UpdateCursor(Term, 0);
}
else
case KEYSYM_PGUP:
if( term->Flags & VT_FLAG_ALTBUF )
return ;
- term->ViewPos = MAX( 0, term->ViewPos - term->Width );
+ term->ViewTopRow = MAX(0, term->ViewTopRow - 1);
VT_int_UpdateScreen(term, 1);
return;
case KEYSYM_PGDN:
if( term->Flags & VT_FLAG_ALTBUF )
return ;
- term->ViewPos = MIN(
- term->ViewPos + term->Width,
- term->Width * term->Height * giVT_Scrollback
- );
+ // Note the lack of giVT_Scrollback+1, view top can't go above size-onescreen
+ term->ViewTopRow = MIN(term->ViewTopRow + 1, term->Height * giVT_Scrollback);
VT_int_UpdateScreen(term, 1);
return;
}
}
else if( Term->Mode == TERM_MODE_TEXT )
{
- int offset;
-
// if( !(Term->Flags & VT_FLAG_SHOWCSR)
// && ( (Term->Flags & VT_FLAG_HIDECSR) || !Term->Node.ReadThreads)
// )
}
else
{
- if(Term->Flags & VT_FLAG_ALTBUF)
- offset = Term->AltWritePos;
- else
- offset = Term->WritePos - Term->ViewPos;
-
- csr_pos.x = offset % Term->TextWidth;
- csr_pos.y = offset / Term->TextWidth;
+ const tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
+ csr_pos.x = wrpos->Col;
+ csr_pos.y = wrpos->Row - (Term->Flags & VT_FLAG_ALTBUF ? 0 : Term->ViewTopRow);
if( 0 > csr_pos.y || csr_pos.y >= Term->TextHeight )
csr_pos.y = -1, csr_pos.x = -1;
}
switch( Term->Mode )
{
case TERM_MODE_TEXT: {
- size_t view_pos = (Term->Flags & VT_FLAG_ALTBUF) ? 0 : Term->ViewPos;
- size_t write_pos = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltWritePos : Term->WritePos;
+ size_t view_pos = (Term->Flags & VT_FLAG_ALTBUF) ? 0 : Term->ViewTopRow*Term->TextWidth;
+ const tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
const tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF) ? Term->AltBuf : Term->Text;
// Re copy the entire screen?
if(UpdateAll) {
}
// Only copy the current line
else {
- int ofs = write_pos - write_pos % Term->TextWidth;
+ size_t ofs = wrpos->Row * Term->TextWidth;
VFS_WriteAt(
giVT_OutputDevHandle,
(ofs - view_pos)*sizeof(tVT_Char),
* drv/vterm_termbuf.c
* - Virtual Terminal - Terminal buffer manipulation
*/
-#define DEBUG 0
+#define DEBUG 1
#define DEBUG_CHECKHEAP 0
#include "vterm.h"
HEAP_VALIDATE();
- size_t limit = VT_int_GetBufferRows(Term) * Term->TextWidth;
- size_t write_pos = *VT_int_GetWritePosPtr(Term);
+ const size_t maxrows = VT_int_GetBufferRows(Term);
+ const size_t limit = maxrows * Term->TextWidth;
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text);
- ASSERTC(write_pos, >=, 0);
+ // If writing with the cursor on righthand edge, wrap down to next line
+ // TODO: Wrap to same line?
+ if( wrpos->Col >= Term->TextWidth )
+ {
+ ASSERTC(wrpos->Col, <=, Term->TextWidth);
+ VT_int_UpdateScreen( Term, 0 );
+ //wrpos->Row ++;
+ wrpos->Col = 0;
+ }
// Scroll entire buffer (about to write outside limit)
- if( write_pos >= limit )
+ if( wrpos->Row >= maxrows )
{
- ASSERTC(write_pos, <, limit + Term->TextWidth);
+ ASSERTC(wrpos->Row, <, maxrows + 1);
VT_int_ScrollText(Term, 1);
- write_pos -= Term->TextWidth;
+ wrpos->Row --;
}
// Bring written cell into view
if( !(Term->Flags & VT_FLAG_ALTBUF) )
{
- size_t onescreen = Term->TextWidth*Term->TextHeight;
- if( write_pos >= Term->ViewPos + onescreen )
+ if( wrpos->Row >= Term->ViewTopRow + Term->TextHeight )
{
- size_t new_pos = write_pos - (write_pos % Term->TextWidth) - onescreen + Term->TextWidth;
- size_t count = (new_pos - Term->ViewPos) / Term->TextWidth;
+ size_t new_pos = wrpos->Row - (Term->TextHeight - 1);
+ size_t count = new_pos - Term->ViewTopRow;
VT_int_ScrollFramebuffer(Term, count);
- //Debug("VT_int_PutChar: VScroll down to %i", new_pos/Term->TextWidth);
- Term->ViewPos = new_pos;
+ //Debug("VT_int_PutChar: VScroll down to %i", new_pos);
+ Term->ViewTopRow = new_pos;
}
- else if( write_pos < Term->ViewPos )
+ else if( wrpos->Row < Term->ViewTopRow )
{
- size_t new_pos = write_pos - (write_pos % Term->TextWidth);
- size_t count = (Term->ViewPos - new_pos) / Term->TextWidth;
+ size_t new_pos = wrpos->Row;
+ size_t count = Term->ViewTopRow - new_pos;
VT_int_ScrollFramebuffer(Term, -count);
- //Debug("VT_int_PutChar: VScroll up to %i", new_pos/Term->TextWidth);
- Term->ViewPos = new_pos;
+ //Debug("VT_int_PutChar: VScroll up to %i", new_pos);
+ Term->ViewTopRow = new_pos;
}
else
{
// no action, cell is visible
}
}
-
+
+ size_t write_pos = wrpos->Row * Term->TextWidth + wrpos->Col;
+ ASSERTC(write_pos, <, limit);
+
switch(Ch)
{
case '\0': // Ignore NULL byte
return;
case '\n':
VT_int_UpdateScreen( Term, 0 ); // Update the line before newlining
- write_pos += Term->TextWidth;
- // TODO: Scroll display down if needed
+ wrpos->Row ++;
+ // TODO: Force scroll?
case '\r':
- write_pos -= write_pos % Term->TextWidth;
+ wrpos->Col = 0;
break;
case '\t': {
- size_t col = write_pos % Term->TextWidth;
+ size_t col = wrpos->Col;
do {
buffer[ write_pos ].Ch = '\0';
buffer[ write_pos ].Colour = Term->CurColour;
} while(write_pos && i-- && buffer[ write_pos ].Ch == '\0');
if(buffer[ write_pos ].Ch != '\0')
write_pos ++;
+ wrpos->Col = write_pos % Term->TextWidth;
break;
default:
if( (write_pos + 1) % Term->TextWidth == 0 )
VT_int_UpdateScreen( Term, 0 );
write_pos ++;
+ wrpos->Col ++;
break;
}
ASSERTC(write_pos, <=, limit);
- *VT_int_GetWritePosPtr(Term) = write_pos;
HEAP_VALIDATE();
// Get buffer pointer and attributes
size_t height = VT_int_GetBufferRows(Term);
- size_t *write_pos_ptr = VT_int_GetWritePosPtr(Term);
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
if( Term->Flags & VT_FLAG_ALTBUF )
{
scroll_height = height;
}
- const int init_write_pos = *write_pos_ptr;
+ const tVT_Pos init_wrpos = *wrpos;
// Scroll text upwards (more space at bottom)
if( Count > 0 )
// Update Screen
VT_int_ScrollFramebuffer( Term, Count );
if( Term->Flags & VT_FLAG_ALTBUF )
- Term->AltWritePos = base;
+ wrpos->Row = scroll_top;
else
- Term->WritePos = Term->ViewPos + Term->TextWidth*(Term->TextHeight - Count);
+ wrpos->Row = Term->ViewTopRow + (Term->TextHeight - Count);
for( int i = 0; i < Count; i ++ )
{
VT_int_UpdateScreen( Term, 0 );
- *write_pos_ptr += Term->TextWidth;
+ wrpos->Row ++;
}
}
else
// Update screen (shift framebuffer, re-render revealed lines)
VT_int_ScrollFramebuffer( Term, -Count );
if( Term->Flags & VT_FLAG_ALTBUF )
- Term->AltWritePos = Term->TextWidth*scroll_top;
+ wrpos->Row = scroll_top;
else
- Term->WritePos = Term->ViewPos;
+ wrpos->Row = Term->ViewTopRow;
for( int i = 0; i < Count; i ++ )
{
VT_int_UpdateScreen( Term, 0 );
+ // Increment?
}
}
- *write_pos_ptr = init_write_pos;
+ *wrpos = init_wrpos;
HEAP_VALIDATE();
}
VT_int_UpdateScreen(Term, 1);
}
-size_t *VT_int_GetWritePosPtr(tVTerm *Term)
+tVT_Pos *VT_int_GetWritePosPtr(tVTerm *Term)
{
return ((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos);
}
* drv/vterm_vt100.c
* - Virtual Terminal - VT100 (Kinda) Emulation
*/
-#define DEBUG 0
+#define DEBUG 1
#include "vterm.h"
#define sTerminal sVTerm
VT_int_ScrollText(Term, CountDown);
else
{
- if(Term->ViewPos/Term->TextWidth + CountDown < 0)
+ if(Term->ViewTopRow + CountDown < 0)
return ;
- if(Term->ViewPos/Term->TextWidth + CountDown > Term->TextHeight * (giVT_Scrollback + 1))
+ if(Term->ViewTopRow + CountDown > Term->TextHeight * (giVT_Scrollback + 1))
return ;
- Term->ViewPos += Term->TextWidth * CountDown;
+ Term->ViewTopRow += CountDown;
}
}
void Display_SetCursor(tTerminal *Term, int Row, int Col)
ASSERTCR( Row, <, maxrows, );
ASSERTCR( Col, >=, 0, );
ASSERTCR( Col, <, Term->TextWidth, );
- *VT_int_GetWritePosPtr(Term) = Row*Term->TextWidth + Col;
+ VT_int_GetWritePosPtr(Term)->Row = Row;
+ VT_int_GetWritePosPtr(Term)->Col = Col;
}
void Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol)
{
LOG("(R+%i,C+%i)", RelRow, RelCol);
- size_t *wrpos = VT_int_GetWritePosPtr(Term);
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
// TODO: Support scrolling if cursor goes offscreen
// if( bScrollIfNeeded )
//
if( RelCol < 0 )
{
- int max = *wrpos % Term->TextWidth;
+ int max = wrpos->Col;
if( RelCol < -max )
RelCol = -max;
}
else
{
- size_t max = Term->TextWidth - (*wrpos % Term->TextWidth) - 1;
+ size_t max = Term->TextWidth - wrpos->Col - 1;
if(RelCol > max)
RelCol = max;
}
- *wrpos += RelCol;
+ wrpos->Col += RelCol;
}
if( RelRow != 0 )
{
- int currow = *wrpos / Term->TextWidth;
+ int currow = wrpos->Row;
int maxrows = VT_int_GetBufferRows(Term);
if( RelRow < 0 )
{
if( currow + RelRow > maxrows-1 )
RelRow = maxrows-1 - currow;
}
- *wrpos += RelRow*Term->TextWidth;
+ wrpos->Row += RelRow;
}
- LOG("=(R%i,C%i)", *wrpos / Term->TextWidth, *wrpos % Term->TextWidth);
+ LOG("=(R%i,C%i)", wrpos->Row, wrpos->Col);
}
void Display_SaveCursor(tTerminal *Term)
{
}
void Display_RestoreCursor(tTerminal *Term)
{
- size_t max = VT_int_GetBufferRows(Term) * Term->TextWidth;
- size_t *wrpos = VT_int_GetWritePosPtr(Term);
- *wrpos = MIN(Term->SavedWritePos, max-1);
- LOG("Restored %i", *wrpos);
+ size_t maxrow = VT_int_GetBufferRows(Term);
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
+ *wrpos = Term->SavedWritePos;
+ if(wrpos->Row >= maxrow)
+ wrpos->Row = maxrow-1;
+ if(wrpos->Col >= Term->TextWidth )
+ wrpos->Col = Term->TextWidth-1;
+ LOG("Restored (R%i,C%i)", wrpos->Row, wrpos->Col);
}
// 0: All, 1: Forward, -1: Reverse
void Display_ClearLine(tTerminal *Term, int Dir)
{
- const size_t wrpos = *VT_int_GetWritePosPtr(Term);
- const int row = wrpos / Term->TextWidth;
- const int col = wrpos % Term->TextWidth;
+ const tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
LOG("(Dir=%i)", Dir);
// Erase all
if( Dir == 0 ) {
- VT_int_ClearLine(Term, row);
+ VT_int_ClearLine(Term, wrpos->Row);
VT_int_UpdateScreen(Term, 0);
}
// Erase to right
else if( Dir == 1 ) {
- VT_int_ClearInLine(Term, row, col, Term->TextWidth);
+ VT_int_ClearInLine(Term, wrpos->Row, wrpos->Col, Term->TextWidth);
VT_int_UpdateScreen(Term, 0);
}
// Erase to left
else if( Dir == -1 ) {
- VT_int_ClearInLine(Term, row, 0, col);
+ VT_int_ClearInLine(Term, wrpos->Row, 0, wrpos->Col);
VT_int_UpdateScreen(Term, 0);
}
else {
void Display_ClearLines(tTerminal *Term, int Dir)
{
LOG("(Dir=%i)", Dir);
- size_t *wrpos = VT_int_GetWritePosPtr(Term);
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
size_t height = VT_int_GetBufferRows(Term);
// All
if( Dir == 0 ) {
if( !(Term->Flags & VT_FLAG_ALTBUF) ) {
- Term->ViewPos = 0;
+ Term->ViewTopRow = 0;
}
int count = height;
while( count -- )
VT_int_ClearLine(Term, count);
- *wrpos = 0;
+ wrpos->Col = 0;
+ wrpos->Row = 0;
VT_int_UpdateScreen(Term, 1);
}
// Downwards
else if( Dir == 1 ) {
- for( int row = *wrpos / Term->TextWidth; row < height; row ++ )
+ for( int row = wrpos->Row; 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 ++ )
+ for( int row = 0; row < wrpos->Row; row ++ )
VT_int_ClearLine(Term, row);
VT_int_UpdateScreen(Term, 1);
}