diff --git a/templates.cpp b/templates.cpp index 49a2ef5..d94069a 100644 --- a/templates.cpp +++ b/templates.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "terminal.hpp" @@ -9,6 +10,6 @@ namespace Parser { template class std::vector; template class std::vector; -template class std::vector; +template class std::deque; template class std::vector; template class std::vector; diff --git a/termemu.cpp b/termemu.cpp index fc0cd3c..a5af174 100644 --- a/termemu.cpp +++ b/termemu.cpp @@ -182,5 +182,7 @@ int termemu( int fd, Terminal::Emulator *terminal ) terminal->input( buf[ i ] ); } + terminal->debug_printout( stdout ); + return 0; } diff --git a/terminal.cpp b/terminal.cpp index cd3c3cb..83b495e 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -1,3 +1,5 @@ +#include + #include "terminal.hpp" using namespace Terminal; @@ -57,7 +59,72 @@ void Emulator::input( char c ) } } +void Emulator::scroll( int N ) +{ + if ( N == 0 ) { + return; + } else if ( N > 0 ) { + for ( int i = 0; i < N; i++ ) { + rows.pop_front(); + rows.push_back( Row( width ) ); + cursor_row--; + } + } +} + +void Emulator::newgrapheme( void ) +{ + combining_char_col = cursor_col; + combining_char_row = cursor_row; +} + void Emulator::print( Parser::Print *act ) { - fprintf( stderr, "print (%lc)!\r\n", act->ch ); + assert( act->char_present ); + + if ( (width == 0) || (height == 0) ) { + return; + } + + assert( cursor_row < height ); /* must be on screen */ + assert( cursor_row <= width ); /* one off is ok */ + + int chwidth = act->ch == L'\0' ? -1 : wcwidth( act->ch ); + + switch ( chwidth ) { + case 1: /* normal character */ + case 2: /* wide character */ + if ( cursor_col >= width ) { /* wrap */ + cursor_col = 0; + cursor_row++; + } + + if ( cursor_row >= height ) { /* scroll */ + scroll( cursor_row - height + 1 ); + } + + rows[ cursor_row ].cells[ cursor_col ].contents.clear(); + rows[ cursor_row ].cells[ cursor_col ].contents.push_back( act->ch ); + newgrapheme(); + cursor_col++; + } +} + +void Emulator::debug_printout( FILE *f ) +{ + fprintf( f, "\033[H\033[2J" ); + + for ( size_t y = 0; y < height; y++ ) { + for ( size_t x = 0; x < width; x++ ) { + fprintf( f, "\033[%d;%dH", y + 1, x + 1 ); + Cell *cell = &rows[ y ].cells[ x ]; + for ( std::vector::iterator i = cell->contents.begin(); + i != cell->contents.end(); + i++ ) { + fprintf( f, "%lc", *i ); + } + } + } + + fflush( NULL ); } diff --git a/terminal.hpp b/terminal.hpp index d5a0d70..078ece9 100644 --- a/terminal.hpp +++ b/terminal.hpp @@ -2,6 +2,10 @@ #define TERMINAL_CPP #include +#include +#include +#include + #include "parser.hpp" namespace Terminal { @@ -34,10 +38,14 @@ namespace Terminal { size_t cursor_col, cursor_row; size_t combining_char_col, combining_char_row; - std::vector rows; + std::deque rows; void print( Parser::Print *act ); + void scroll( int N ); + + void newgrapheme( void ); + public: Emulator( size_t s_width, size_t s_height ); ~Emulator(); @@ -48,6 +56,8 @@ namespace Terminal { size_t get_width( void ) { return width; } size_t get_height( void ) { return height; } + + void debug_printout( FILE *f ); }; }