void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
{
int i;
- tVT_Char *buffer;
- int write_pos;
- int limit;
HEAP_VALIDATE();
- if(Term->Flags & VT_FLAG_ALTBUF) {
- buffer = Term->AltBuf;
- write_pos = Term->AltWritePos;
- limit = Term->TextHeight * Term->TextWidth;
+ 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);
+
+ // 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;
}
- else {
- buffer = Term->Text;
- write_pos = Term->WritePos;
- limit = Term->TextHeight*(giVT_Scrollback+1) * Term->TextWidth;
+
+ // Scroll entire buffer (about to write outside limit)
+ if( wrpos->Row >= maxrows )
+ {
+ ASSERTC(wrpos->Row, <, maxrows + 1);
+ VT_int_ScrollText(Term, 1);
+ wrpos->Row --;
}
-
- // TODO: Can the write position be equal to the end of screen?
+
+ // Bring written cell into view
+ if( !(Term->Flags & VT_FLAG_ALTBUF) )
+ {
+ if( wrpos->Row >= Term->ViewTopRow + Term->TextHeight )
+ {
+ 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->ViewTopRow = new_pos;
+ }
+ else if( wrpos->Row < Term->ViewTopRow )
+ {
+ 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->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;
+ 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;
}
- if(Term->Flags & VT_FLAG_ALTBUF)
- {
- Term->AltWritePos = write_pos;
-
- if(Term->AltWritePos >= limit)
- {
- Term->AltWritePos -= Term->TextWidth;
- VT_int_ScrollText(Term, 1);
- }
- }
- else
- {
- Term->WritePos = write_pos;
- // Move Screen
- // - Check if we need to scroll the entire scrollback buffer
- if(Term->WritePos >= limit)
- {
- int base;
-
- // Update view position
- base = Term->TextWidth*Term->TextHeight*(giVT_Scrollback);
- if(Term->ViewPos < base)
- Term->ViewPos += Term->Width;
- if(Term->ViewPos > base)
- Term->ViewPos = base;
-
- VT_int_ScrollText(Term, 1);
- Term->WritePos -= Term->TextWidth;
- }
- // Ok, so we only need to scroll the screen
- else if(Term->WritePos >= Term->ViewPos + Term->TextWidth*Term->TextHeight)
- {
- VT_int_ScrollFramebuffer( Term, 1 );
-
- Term->ViewPos += Term->TextWidth;
- }
- }
+ ASSERTC(write_pos, <=, limit);
HEAP_VALIDATE();
void VT_int_ScrollText(tVTerm *Term, int Count)
{
tVT_Char *buf;
- int *write_pos_ptr;
- int height;
int scroll_top, scroll_height;
HEAP_VALIDATE();
// Get buffer pointer and attributes
+ size_t height = VT_int_GetBufferRows(Term);
+ tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term);
+
if( Term->Flags & VT_FLAG_ALTBUF )
{
buf = Term->AltBuf;
- height = Term->TextHeight;
- write_pos_ptr = &Term->AltWritePos;
scroll_top = Term->ScrollTop;
scroll_height = Term->ScrollHeight;
}
else
{
buf = Term->Text;
- height = Term->TextHeight*(giVT_Scrollback+1);
- write_pos_ptr = &Term->WritePos;
scroll_top = 0;
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();
}
{
HEAP_VALIDATE();
- size_t height = Term->TextHeight * (Term->Flags & VT_FLAG_ALTBUF ? 1 : giVT_Scrollback + 1);
+ size_t height = VT_int_GetBufferRows(Term);
tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text);
ASSERTCR(Row, >=, 0, );
ASSERTCR(Row, <, height, );
{
HEAP_VALIDATE();
- size_t height = Term->TextHeight * (Term->Flags & VT_FLAG_ALTBUF ? 1 : giVT_Scrollback + 1);
+ size_t height = VT_int_GetBufferRows(Term);
tVT_Char *buffer = (Term->Flags & VT_FLAG_ALTBUF ? Term->AltBuf : Term->Text);
ASSERTCR(Row, >=, 0, );
ASSERTCR(Row, <, height, );
VT_int_UpdateScreen(Term, 1);
}
+tVT_Pos *VT_int_GetWritePosPtr(tVTerm *Term)
+{
+ return ((Term->Flags & VT_FLAG_ALTBUF) ? &Term->AltWritePos : &Term->WritePos);
+}
+
+size_t VT_int_GetBufferRows(tVTerm *Term)
+{
+ return ((Term->Flags & VT_FLAG_ALTBUF) ? 1 : (giVT_Scrollback+1))*Term->TextHeight;
+}
+