Fix bug involving wraparound copy-and-paste to a blank line.

Identified by Anders Kaseorg.

Test case:

( reset; seq 100; printf 'Hello, world!'; sleep 1;
printf '\t\t\t\t\t\t\t\t\t\t   \r\e[K'; sleep 1; printf '\n' )
> /dev/pts/16 2>&1

(replace /dev/pts/16 with mosh or termemu terminal)
This commit is contained in:
Keith Winstein
2012-04-11 02:40:18 -04:00
parent 4144f2e4f0
commit b4c47b77cf
2 changed files with 18 additions and 4 deletions
+16 -4
View File
@@ -180,6 +180,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
/* next write will wrap */ /* next write will wrap */
frame.cursor_x = 0; frame.cursor_x = 0;
frame.cursor_y++; frame.cursor_y++;
frame.force_next_put = true;
} }
} }
@@ -196,6 +197,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
frame.append( tmp ); frame.append( tmp );
frame.cursor_x = frame.x; frame.cursor_x = frame.x;
frame.force_next_put = true;
put_cell( initialized, frame, f ); put_cell( initialized, frame, f );
} }
} }
@@ -237,10 +239,12 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
const Cell *cell = f.get_cell( frame.y, frame.x ); const Cell *cell = f.get_cell( frame.y, frame.x );
if ( initialized if ( !frame.force_next_put ) {
&& ( *cell == *(frame.last_frame.get_cell( frame.y, frame.x )) ) ) { if ( initialized
frame.x += cell->width; && ( *cell == *(frame.last_frame.get_cell( frame.y, frame.x )) ) ) {
return; frame.x += cell->width;
return;
}
} }
if ( (frame.x != frame.cursor_x) || (frame.y != frame.cursor_y) ) { if ( (frame.x != frame.cursor_x) || (frame.y != frame.cursor_y) ) {
@@ -270,6 +274,12 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
bool can_use_erase = has_bce || (cell->renditions == initial_rendition()); bool can_use_erase = has_bce || (cell->renditions == initial_rendition());
if ( frame.force_next_put ) {
frame.append( " " );
frame.append_silent_move( frame.y, frame.x );
frame.force_next_put = false;
}
/* can we go to the end of the line? */ /* can we go to the end of the line? */
if ( (frame.x + clear_count == f.ds.get_width()) if ( (frame.x + clear_count == f.ds.get_width())
&& can_use_erase ) { && can_use_erase ) {
@@ -309,6 +319,8 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
frame.x += cell->width; frame.x += cell->width;
frame.cursor_x += cell->width; frame.cursor_x += cell->width;
frame.force_next_put = false;
} }
void FrameState::append_silent_move( int y, int x ) void FrameState::append_silent_move( int y, int x )
+2
View File
@@ -26,6 +26,7 @@ namespace Terminal {
class FrameState { class FrameState {
public: public:
int x, y; int x, y;
bool force_next_put;
std::string str; std::string str;
int cursor_x, cursor_y; int cursor_x, cursor_y;
@@ -35,6 +36,7 @@ namespace Terminal {
FrameState( const Framebuffer &s_last ) FrameState( const Framebuffer &s_last )
: x(0), y(0), : x(0), y(0),
force_next_put( false ),
str(), cursor_x(0), cursor_y(0), current_rendition( 0 ), str(), cursor_x(0), cursor_y(0), current_rendition( 0 ),
last_frame( s_last ) last_frame( s_last )
{ {