diff --git a/protocols/ssh/include/terminal.h b/protocols/ssh/include/terminal.h index 650b7226..dc80d156 100644 --- a/protocols/ssh/include/terminal.h +++ b/protocols/ssh/include/terminal.h @@ -348,28 +348,46 @@ void guac_terminal_free(guac_terminal* term); */ int guac_terminal_write(guac_terminal* term, const char* c, int size); -int guac_terminal_set_colors(guac_terminal* term, - int foreground, int background); - +/** + * Sets the character at the given row and column to the specified value. + */ int guac_terminal_set(guac_terminal* term, int row, int col, char c); +/** + * Copies a rectangular region of characters which may overlap with the + * destination. + */ int guac_terminal_copy(guac_terminal* term, int src_row, int src_col, int rows, int cols, int dst_row, int dst_col); +/** + * Clears a rectangular region of characters, replacing them with the + * given background color. + */ int guac_terminal_clear(guac_terminal* term, int row, int col, int rows, int cols, int background_color); -int guac_terminal_scroll_up(guac_terminal* term, - int start_row, int end_row, int amount); - -int guac_terminal_scroll_down(guac_terminal* term, - int start_row, int end_row, int amount); - +/** + * Clears the given region from right-to-left, top-to-bottom, replacing + * all characters with the given background color. + */ int guac_terminal_clear_range(guac_terminal* term, int start_row, int start_col, int end_row, int end_col, int background_color); +/** + * Scrolls the terminal's current scroll region up by one row. + */ +int guac_terminal_scroll_up(guac_terminal* term, + int start_row, int end_row, int amount); + +/** + * Scrolls the terminal's current scroll region down by one row. + */ +int guac_terminal_scroll_down(guac_terminal* term, + int start_row, int end_row, int amount); + /** * Allocates a new guac_terminal_delta. */ diff --git a/protocols/ssh/src/terminal.c b/protocols/ssh/src/terminal.c index 231bcb54..46e4658b 100644 --- a/protocols/ssh/src/terminal.c +++ b/protocols/ssh/src/terminal.c @@ -189,6 +189,12 @@ void guac_terminal_free(guac_terminal* term) { } +/** + * Returns the location of the given character in the glyph cache layer, + * sending it first if necessary. The location returned is in characters, + * and thus must be multiplied by the glyph width to obtain the actual + * location within the glyph cache layer. + */ int __guac_terminal_get_glyph(guac_terminal* term, char c) { guac_socket* socket = term->client->socket; @@ -264,11 +270,30 @@ int __guac_terminal_get_glyph(guac_terminal* term, char c) { } -int guac_terminal_set_colors(guac_terminal* term, - int foreground, int background) { +/** + * Sets the attributes of the glyph cache layer such that future copies from + * this layer will display as expected. + */ +int __guac_terminal_set_colors(guac_terminal* term, + guac_terminal_attributes* attributes) { guac_socket* socket = term->client->socket; const guac_terminal_color* background_color; + int background, foreground; + + /* Handle reverse video */ + if (attributes->reverse) { + background = attributes->foreground; + foreground = attributes->background; + } + else { + foreground = attributes->foreground; + background = attributes->background; + } + + /* Handle bold */ + if (attributes->bold && foreground <= 7) + foreground += 8; /* Get background color */ background_color = &guac_terminal_palette[background]; @@ -294,7 +319,8 @@ int guac_terminal_set_colors(guac_terminal* term, } /* If any color change at all, update filled */ - if (foreground != term->glyph_foreground || background != term->glyph_background) { + if (foreground != term->glyph_foreground + || background != term->glyph_background) { /* Set background */ guac_protocol_send_rect(socket, term->filled_glyphs, @@ -325,7 +351,12 @@ int guac_terminal_set_colors(guac_terminal* term, } -int guac_terminal_set(guac_terminal* term, int row, int col, char c) { +/** + * Sends the given character to the terminal at the given row and column, + * rendering the charater immediately. This bypasses the guac_terminal_delta + * mechanism and is intended for flushing of updates only. + */ +int __guac_terminal_set(guac_terminal* term, int row, int col, char c) { guac_socket* socket = term->client->socket; int location = __guac_terminal_get_glyph(term, c); @@ -339,6 +370,19 @@ int guac_terminal_set(guac_terminal* term, int row, int col, char c) { } +int guac_terminal_set(guac_terminal* term, int row, int col, char c) { + + /* Build character with current attributes */ + guac_terminal_char guac_char; + guac_char.value = c; + guac_char.attributes = term->current_attributes; + + /* Set delta */ + guac_terminal_delta_set(term->delta, row, col, &guac_char); + return 0; + +} + int guac_terminal_write(guac_terminal* term, const char* c, int size) { while (size > 0) { @@ -354,17 +398,13 @@ int guac_terminal_copy(guac_terminal* term, int src_row, int src_col, int rows, int cols, int dst_row, int dst_col) { - guac_socket* socket = term->client->socket; + /* Update delta */ + guac_terminal_delta_copy(term->delta, + dst_row, dst_col, + src_row, src_col, + cols, rows); - /* Send copy instruction */ - return guac_protocol_send_copy(socket, - - GUAC_DEFAULT_LAYER, - src_col * term->char_width, src_row * term->char_height, - cols * term->char_width, rows * term->char_height, - - GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, - dst_col * term->char_width, dst_row * term->char_height); + return 0; } diff --git a/protocols/ssh/src/terminal_handlers.c b/protocols/ssh/src/terminal_handlers.c index 54e93eae..02082068 100644 --- a/protocols/ssh/src/terminal_handlers.c +++ b/protocols/ssh/src/terminal_handlers.c @@ -42,9 +42,6 @@ int guac_terminal_echo(guac_terminal* term, char c) { - int foreground = term->current_attributes.foreground; - int background = term->current_attributes.background; - switch (c) { /* Bell */ @@ -71,7 +68,8 @@ int guac_terminal_echo(guac_terminal* term, char c) { term->cursor_row = term->scroll_end; /* Scroll up by one row */ - guac_terminal_scroll_up(term, term->scroll_start, term->scroll_end, 1); + guac_terminal_scroll_up(term, term->scroll_start, + term->scroll_end, 1); } break; @@ -95,24 +93,12 @@ int guac_terminal_echo(guac_terminal* term, char c) { term->cursor_row = term->scroll_end; /* Scroll up by one row */ - guac_terminal_scroll_up(term, term->scroll_start, term->scroll_end, 1); + guac_terminal_scroll_up(term, term->scroll_start, + term->scroll_end, 1); } - /* Handle reverse video */ - if (term->current_attributes.reverse) { - int swap = background; - background = foreground; - foreground = swap; - } - - /* Handle bold */ - if (term->current_attributes.bold && foreground <= 7) - foreground += 8; - - guac_terminal_set_colors(term, - foreground, background); - + /* Write character */ guac_terminal_set(term, term->cursor_row, term->cursor_col,