diff --git a/protocols/ssh/include/display.h b/protocols/ssh/include/display.h index 0aa94528..8b368b0f 100644 --- a/protocols/ssh/include/display.h +++ b/protocols/ssh/include/display.h @@ -181,6 +181,11 @@ typedef struct guac_terminal_display { */ int glyph_background; + /** + * Layer above default layer which highlights selected text. + */ + guac_layer* select_layer; + /** * A single wide layer holding each glyph, with each glyph only * colored with foreground color (background remains transparent). @@ -237,5 +242,11 @@ void guac_terminal_display_resize(guac_terminal_display* display, int width, int */ void guac_terminal_display_flush(guac_terminal_display* display); +/** + * Draws the text selection rectangle from the given coordinates to the given end coordinates. + */ +void guac_terminal_display_select(guac_terminal_display* display, + int start_row, int start_col, int end_row, int end_col); + #endif diff --git a/protocols/ssh/src/display.c b/protocols/ssh/src/display.c index 5e220276..bfdfd8d2 100644 --- a/protocols/ssh/src/display.c +++ b/protocols/ssh/src/display.c @@ -353,6 +353,8 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client, int fore display->glyph_stroke = guac_client_alloc_buffer(client); display->filled_glyphs = guac_client_alloc_buffer(client); + display->select_layer = guac_client_alloc_layer(client); + /* Get font */ display->font_desc = pango_font_description_new(); pango_font_description_set_family(display->font_desc, "monospace"); @@ -573,6 +575,11 @@ void guac_terminal_display_resize(guac_terminal_display* display, int width, int display->char_width * width, display->char_height * height); + guac_protocol_send_size(display->client->socket, + display->select_layer, + display->char_width * width, + display->char_height * height); + } void __guac_terminal_display_flush_copy(guac_terminal_display* display) { @@ -880,3 +887,87 @@ void guac_terminal_display_flush(guac_terminal_display* display) { } +void guac_terminal_display_select(guac_terminal_display* display, + int start_row, int start_col, int end_row, int end_col) { + + guac_socket* socket = display->client->socket; + guac_layer* select_layer = display->select_layer; + + guac_client_log_info(display->client, "START_COL=%i", start_col); + + /* If single row, just need one rectangle */ + if (start_row == end_row) { + + /* Ensure proper ordering of columns */ + if (start_col > end_col) { + int temp = start_col; + start_col = end_col; + end_col = temp; + } + + /* Select characters between columns */ + guac_protocol_send_rect(socket, select_layer, + + start_col * display->char_width, + start_row * display->char_height, + + (end_col - start_col + 1) * display->char_width, + display->char_height); + + } + + /* Otherwise, need three */ + else { + + /* Ensure proper ordering of start and end coords */ + if (start_row > end_row) { + + int temp; + + temp = start_row; + start_row = end_row; + end_row = temp; + + temp = start_col; + start_col = end_col; + end_col = temp; + + } + + /* First row */ + guac_protocol_send_rect(socket, select_layer, + + start_col * display->char_width, + start_row * display->char_height, + + display->width * display->char_width, + display->char_height); + + /* Middle */ + guac_protocol_send_rect(socket, select_layer, + + 0, + (start_row + 1) * display->char_height, + + display->width * display->char_width, + (end_row - start_row - 1) * display->char_height); + + /* Last row */ + guac_protocol_send_rect(socket, select_layer, + + 0, + end_row * display->char_height, + + (end_col + 1) * display->char_width, + display->char_height); + + } + + /* Draw new selection, erasing old */ + guac_protocol_send_cfill(socket, GUAC_COMP_SRC, select_layer, + 0x00, 0xFF, 0x00, 0x80); + + guac_socket_flush(socket); + +} + diff --git a/protocols/ssh/src/terminal.c b/protocols/ssh/src/terminal.c index 30c5f333..30373678 100644 --- a/protocols/ssh/src/terminal.c +++ b/protocols/ssh/src/terminal.c @@ -374,16 +374,44 @@ void guac_terminal_scroll_display_up(guac_terminal* terminal, } +void guac_terminal_select_redraw(guac_terminal* terminal) { + + guac_terminal_display_select(terminal->display, + terminal->selection_start_row + terminal->scroll_offset, + terminal->selection_start_column, + terminal->selection_end_row + terminal->scroll_offset, + terminal->selection_end_column); + +} + void guac_terminal_select_start(guac_terminal* terminal, int row, int column) { - /* STUB */ + + terminal->selection_start_row = + terminal->selection_end_row = row; + + terminal->selection_start_column = + terminal->selection_end_column = column; + + terminal->text_selected = true; + + guac_terminal_select_redraw(terminal); + } void guac_terminal_select_update(guac_terminal* terminal, int row, int column) { - /* STUB */ + + if (row != terminal->selection_end_row || column != terminal->selection_end_column) { + terminal->selection_end_row = row; + terminal->selection_end_column = column; + + guac_terminal_select_redraw(terminal); + } + } void guac_terminal_select_end(guac_terminal* terminal) { /* STUB */ + terminal->text_selected = false; } void guac_terminal_copy_columns(guac_terminal* terminal, int row,