diff --git a/src/terminal/buffer.c b/src/terminal/buffer.c index 59c10209b0..fe93fc4b65 100644 --- a/src/terminal/buffer.c +++ b/src/terminal/buffer.c @@ -48,6 +48,7 @@ guac_terminal_buffer* guac_terminal_buffer_alloc(int rows, guac_terminal_char* d /* Allocate row */ row->available = 256; row->length = 0; + row->wrapped_row = false; row->characters = guac_mem_alloc(sizeof(guac_terminal_char), row->available); /* Next row */ @@ -166,6 +167,10 @@ void guac_terminal_buffer_copy_rows(guac_terminal_buffer* buffer, /* Copy data */ memcpy(dst_row->characters, src_row->characters, sizeof(guac_terminal_char) * src_row->length); dst_row->length = src_row->length; + dst_row->wrapped_row = src_row->wrapped_row; + + /* Reset src wrapped_row */ + src_row->wrapped_row = false; /* Next current_row */ current_row += step; diff --git a/src/terminal/select.c b/src/terminal/select.c index b0baeb0736..acc50f15f4 100644 --- a/src/terminal/select.c +++ b/src/terminal/select.c @@ -371,17 +371,31 @@ void guac_terminal_select_end(guac_terminal* terminal) { /* Otherwise, copy multiple rows */ else { - /* Store first row */ + /* Get the first selected row */ + guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, start_row, 0); + + /* Store first row from start_col to last available col */ guac_terminal_clipboard_append_row(terminal, start_row, start_col, -1); /* Store all middle rows */ for (int row = start_row + 1; row < end_row; row++) { - guac_common_clipboard_append(terminal->clipboard, "\n", 1); + + /* Add a new line only if the line was not wrapped */ + if (buffer_row->wrapped_row == false) + guac_common_clipboard_append(terminal->clipboard, "\n", 1); + + /* Store middle row */ guac_terminal_clipboard_append_row(terminal, row, 0, -1); + + /* Get next buffer row */ + buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); } - /* Store last row */ - guac_common_clipboard_append(terminal->clipboard, "\n", 1); + /* Add a new line only if the line was not wrapped */ + if (buffer_row->wrapped_row == false) + guac_common_clipboard_append(terminal->clipboard, "\n", 1); + + /* Store last row from col 0 to end_col */ guac_terminal_clipboard_append_row(terminal, end_row, 0, end_col); } diff --git a/src/terminal/terminal-handlers.c b/src/terminal/terminal-handlers.c index 7bec0f2765..5a2d134966 100644 --- a/src/terminal/terminal-handlers.c +++ b/src/terminal/terminal-handlers.c @@ -57,8 +57,16 @@ * * @param term * The guac_terminal whose cursor should be advanced to the next row. + * + * @param force_wrap + * True if the line wrap was forced, false otherwise */ -static void guac_terminal_linefeed(guac_terminal* term) { +static void guac_terminal_linefeed(guac_terminal* term, bool force_wrap) { + + /* Assign in wrapped_row: 1 to avoid \n in clipboard or 0 to add \n */ + guac_terminal_buffer_row* buffer_row = + guac_terminal_buffer_get_row(term->buffer, term->cursor_row, 0); + buffer_row->wrapped_row = force_wrap; /* Scroll up if necessary */ if (term->cursor_row == term->scroll_end) @@ -221,7 +229,7 @@ int guac_terminal_echo(guac_terminal* term, unsigned char c) { case 0x0C: /* FF */ /* Advance to next row */ - guac_terminal_linefeed(term); + guac_terminal_linefeed(term, false); /* If automatic carriage return, fall through to CR handler */ if (!term->automatic_carriage_return) @@ -269,8 +277,10 @@ int guac_terminal_echo(guac_terminal* term, unsigned char c) { /* Wrap if necessary */ if (term->cursor_col >= term->term_width) { + + /* New line */ term->cursor_col = 0; - guac_terminal_linefeed(term); + guac_terminal_linefeed(term, true); } /* If insert mode, shift other characters right by 1 */ @@ -340,14 +350,14 @@ int guac_terminal_escape(guac_terminal* term, unsigned char c) { /* Index (IND) */ case 'D': - guac_terminal_linefeed(term); + guac_terminal_linefeed(term, false); term->char_handler = guac_terminal_echo; break; /* Next Line (NEL) */ case 'E': guac_terminal_move_cursor(term, term->cursor_row, 0); - guac_terminal_linefeed(term); + guac_terminal_linefeed(term, false); term->char_handler = guac_terminal_echo; break; diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 192c85a193..15b9fea83c 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -241,9 +241,10 @@ void guac_terminal_reset(guac_terminal* term) { /* Reset display palette */ guac_terminal_display_reset_palette(term->display); - /* Clear terminal */ + /* Clear terminal with a row length of term_width-1 + * to avoid exceed the size of the display layer */ for (row=0; rowterm_height; row++) - guac_terminal_set_columns(term, row, 0, term->term_width, &(term->default_char)); + guac_terminal_set_columns(term, row, 0, term->term_width-1, &(term->default_char)); } diff --git a/src/terminal/terminal/buffer.h b/src/terminal/terminal/buffer.h index 7c7f29c5c0..cebb8e88eb 100644 --- a/src/terminal/terminal/buffer.h +++ b/src/terminal/terminal/buffer.h @@ -51,6 +51,12 @@ typedef struct guac_terminal_buffer_row { */ int available; + /** + * True if the current row has been wrapped to avoid going off the screen. + * False otherwise. + */ + bool wrapped_row; + } guac_terminal_buffer_row; /**