From b54e750a3187bc9e4dcba82050125461f56e9613 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 4 Jun 2014 15:52:50 -0700 Subject: [PATCH] GUAC-717: Clear up to character end when setting characters. Handle character overwrite as part of copy. --- src/terminal/buffer.c | 4 +- src/terminal/terminal.c | 124 ++++++++++++++++++++++++++++------------ 2 files changed, 89 insertions(+), 39 deletions(-) diff --git a/src/terminal/buffer.c b/src/terminal/buffer.c index 98bd029c..e2f66c28 100644 --- a/src/terminal/buffer.c +++ b/src/terminal/buffer.c @@ -195,12 +195,12 @@ void guac_terminal_buffer_set_columns(guac_terminal_buffer* buffer, int row, /* Set values */ current = &(buffer_row->characters[start_column]); - for (i=start_column; i<=end_column; i++) { + for (i = start_column; i <= end_column; i += character->width) { *(current++) = *character; /* Store any required continuation characters */ - for (j=1; jwidth; j++) + for (j=1; j < character->width; j++) *(current++) = continuation_char; } diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index bfac5bab..e73f7ccf 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -48,6 +48,88 @@ #include #include +/** + * Sets the given range of columns to the given character. + */ +static void __guac_terminal_set_columns(guac_terminal* terminal, int row, + int start_column, int end_column, guac_terminal_char* character) { + + guac_terminal_display_set_columns(terminal->display, row + terminal->scroll_offset, + start_column, end_column, character); + + guac_terminal_buffer_set_columns(terminal->buffer, row, + start_column, end_column, character); + +} + +/** + * Declares that the given range of columns within the given row is about to be + * overwritten, and should be updated as necessary. + */ +static void __guac_terminal_overwrite_columns(guac_terminal* terminal, int row, int start_column, int end_column) { + + guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); + + /* Clear out initial character */ + if (start_column > 0) { + + int aligned_start_column = start_column; + guac_terminal_char* start_char = &(buffer_row->characters[aligned_start_column]); + + /* Determine nearest aligned boundary */ + while (aligned_start_column > 0 && start_char->value == GUAC_CHAR_CONTINUATION) { + start_char--; + aligned_start_column--; + } + + /* Clear up to character start */ + if (aligned_start_column != start_column) { + + guac_terminal_char cleared_char; + cleared_char.value = ' '; + cleared_char.attributes = start_char->attributes; + cleared_char.width = 1; + + __guac_terminal_set_columns(terminal, row, aligned_start_column, start_column-1, &cleared_char); + + } + + } + + /* Clear out final character */ + if (end_column >= 0 && end_column < buffer_row->length) { + + int aligned_end_column = end_column; + guac_terminal_char* end_char = &(buffer_row->characters[aligned_end_column]); + + /* If we're lucky enough to end on the beginning of a character, just use its defined width */ + if (end_char->value != GUAC_CHAR_CONTINUATION) + aligned_end_column += end_char->width - 1; + + /* Otherwise, search for nearest aligned boundary */ + else { + while (aligned_end_column+1 < buffer_row->length && (end_char+1)->value == GUAC_CHAR_CONTINUATION) { + end_char++; + aligned_end_column++; + } + } + + /* Clear up to true character end */ + if (aligned_end_column != end_column) { + + guac_terminal_char cleared_char; + cleared_char.value = ' '; + cleared_char.attributes = end_char->attributes; + cleared_char.width = 1; + + __guac_terminal_set_columns(terminal, row, end_column+1, aligned_end_column, &cleared_char); + + } + + } + +} + void guac_terminal_reset(guac_terminal* term) { int row; @@ -763,6 +845,8 @@ void guac_terminal_select_end(guac_terminal* terminal, char* string) { void guac_terminal_copy_columns(guac_terminal* terminal, int row, int start_column, int end_column, int offset) { + __guac_terminal_overwrite_columns(terminal, row, start_column + offset, end_column + offset); + guac_terminal_display_copy_columns(terminal->display, row + terminal->scroll_offset, start_column, end_column, offset); @@ -796,39 +880,8 @@ void guac_terminal_copy_rows(guac_terminal* terminal, void guac_terminal_set_columns(guac_terminal* terminal, int row, int start_column, int end_column, guac_terminal_char* character) { - guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, end_column+1); - - /* Reset initial character, if starting on non-char boundary */ - if (start_column > 0) { - - int aligned_start_column = start_column; - guac_terminal_char* start_char = &(buffer_row->characters[aligned_start_column]); - - /* Determine nearest aligned boundary */ - while (aligned_start_column > 0 && start_char->value == GUAC_CHAR_CONTINUATION) { - start_char--; - aligned_start_column--; - } - - /* Clear up to character start */ - if (aligned_start_column != start_column) { - - guac_terminal_char cleared_char; - cleared_char.value = ' '; - cleared_char.attributes = start_char->attributes; - cleared_char.width = 1; - - guac_terminal_set_columns(terminal, row, aligned_start_column, start_column-1, &cleared_char); - - } - - } - - guac_terminal_display_set_columns(terminal->display, row + terminal->scroll_offset, - start_column, end_column, character); - - guac_terminal_buffer_set_columns(terminal->buffer, row, - start_column, end_column, character); + __guac_terminal_overwrite_columns(terminal, row, start_column, end_column); + __guac_terminal_set_columns(terminal, row, start_column, end_column, character); /* If visible cursor in current row, preserve state */ if (row == terminal->visible_cursor_row @@ -839,10 +892,7 @@ void guac_terminal_set_columns(guac_terminal* terminal, int row, guac_terminal_char cursor_character = *character; cursor_character.attributes.cursor = true; - guac_terminal_display_set_columns(terminal->display, row + terminal->scroll_offset, - terminal->visible_cursor_col, terminal->visible_cursor_col, &cursor_character); - - guac_terminal_buffer_set_columns(terminal->buffer, row, + __guac_terminal_set_columns(terminal, row, terminal->visible_cursor_col, terminal->visible_cursor_col, &cursor_character); }