diff --git a/protocols/ssh/include/ssh_terminal.h b/protocols/ssh/include/ssh_terminal.h index e7e3bf80..e3f7c54c 100644 --- a/protocols/ssh/include/ssh_terminal.h +++ b/protocols/ssh/include/ssh_terminal.h @@ -146,6 +146,11 @@ struct ssh_guac_terminal { */ int cursor_col; + /** + * Simple cursor layer until scrollback, etc. is implemented. + */ + guac_layer* cursor_layer; + int foreground; int background; int reverse; @@ -172,6 +177,8 @@ void ssh_guac_terminal_free(ssh_guac_terminal* term); int ssh_guac_terminal_write(ssh_guac_terminal* term, const char* c, int size); +int ssh_guac_terminal_redraw_cursor(ssh_guac_terminal* term); + int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col, char c, int foreground, int background); @@ -185,6 +192,9 @@ int ssh_guac_terminal_clear(ssh_guac_terminal* term, int ssh_guac_terminal_scroll_up(ssh_guac_terminal* term, int start_row, int end_row, int amount); +int ssh_guac_terminal_scroll_down(ssh_guac_terminal* term, + int start_row, int end_row, int amount); + int ssh_guac_terminal_clear_range(ssh_guac_terminal* term, int start_row, int start_col, int end_row, int end_col, int background_color); diff --git a/protocols/ssh/src/ssh_client.c b/protocols/ssh/src/ssh_client.c index 81e0c174..8715da2d 100644 --- a/protocols/ssh/src/ssh_client.c +++ b/protocols/ssh/src/ssh_client.c @@ -69,6 +69,7 @@ int ssh_guac_client_password_key_handler(guac_client* client, int keysym, int pr /* Add to password */ client_data->password[client_data->password_length++] = keysym; ssh_guac_terminal_write(client_data->term, "*", 1); + ssh_guac_terminal_redraw_cursor(client_data->term); guac_flush(client->io); } else if (keysym == 0xFF08) { @@ -78,6 +79,7 @@ int ssh_guac_client_password_key_handler(guac_client* client, int keysym, int pr /* Backspace */ ssh_guac_terminal_write(client_data->term, "\x08\x1B[K", 4); + ssh_guac_terminal_redraw_cursor(client_data->term); guac_flush(client->io); } @@ -89,6 +91,7 @@ int ssh_guac_client_password_key_handler(guac_client* client, int keysym, int pr /* Clear screen */ ssh_guac_terminal_write(client_data->term, "\x1B[2J\x1B[1;1H", 10); + ssh_guac_terminal_redraw_cursor(client_data->term); guac_flush(client->io); return ssh_guac_client_auth(client, client_data->password); @@ -148,6 +151,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { client_data->password_length = 0; ssh_guac_terminal_write(client_data->term, "Password: ", 10); + ssh_guac_terminal_redraw_cursor(client_data->term); guac_flush(client->io); client->key_handler = ssh_guac_client_password_key_handler; diff --git a/protocols/ssh/src/ssh_handlers.c b/protocols/ssh/src/ssh_handlers.c index dce3f44f..a5ec6d58 100644 --- a/protocols/ssh/src/ssh_handlers.c +++ b/protocols/ssh/src/ssh_handlers.c @@ -60,6 +60,8 @@ int ssh_guac_client_handle_messages(guac_client* client) { ssh_channel read_channels[2]; struct timeval timeout; + guac_log_info("ENTER HANDLE MESSAGES..."); + /* Channels to read */ read_channels[0] = client_data->term_channel; read_channels[1] = NULL; @@ -73,13 +75,17 @@ int ssh_guac_client_handle_messages(guac_client* client) { int bytes_read = 0; + guac_log_info("DONE WAITING (%i)", GUAC_SYNC_FREQUENCY); + /* While data available, write to terminal */ while (channel_is_open(client_data->term_channel) && !channel_is_eof(client_data->term_channel) && (bytes_read = channel_read_nonblocking(client_data->term_channel, buffer, sizeof(buffer), 0)) > 0) { - ssh_guac_terminal_write(client_data->term, buffer, bytes_read); - guac_flush(io); + if (ssh_guac_terminal_write(client_data->term, buffer, bytes_read) + || ssh_guac_terminal_redraw_cursor(client_data->term) + || guac_flush(io)) + return 1; } @@ -91,6 +97,7 @@ int ssh_guac_client_handle_messages(guac_client* client) { } } + guac_log_info("LEAVE HANDLE MESSAGES"); return 0; } diff --git a/protocols/ssh/src/ssh_terminal.c b/protocols/ssh/src/ssh_terminal.c index c005148f..5431569e 100644 --- a/protocols/ssh/src/ssh_terminal.c +++ b/protocols/ssh/src/ssh_terminal.c @@ -93,6 +93,7 @@ ssh_guac_terminal* ssh_guac_terminal_create(guac_client* client) { term->cursor_row = 0; term->cursor_col = 0; + term->cursor_layer = guac_client_alloc_layer(client, 1); term->term_width = 80; term->term_height = 24; @@ -220,6 +221,33 @@ guac_layer* __ssh_guac_terminal_get_glyph(ssh_guac_terminal* term, char c) { } +int ssh_guac_terminal_redraw_cursor(ssh_guac_terminal* term) { + + GUACIO* io = term->client->io; + + /* Erase old cursor */ + return + guac_send_rect(io, + GUAC_COMP_SRC, term->cursor_layer, + + 0, 0, + term->char_width * term->term_width, + term->char_height * term->term_height, + + 0, 0, 0, 0) + + || guac_send_rect(io, + GUAC_COMP_SRC, term->cursor_layer, + + term->char_width * term->cursor_col, + term->char_height * term->cursor_row, + term->char_width, term->char_height, + + 0x40, 0xFF, 0x80, + 0x80); + +} + int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col, char c, int foreground, int background) { @@ -342,6 +370,26 @@ int ssh_guac_terminal_scroll_up(ssh_guac_terminal* term, } +int ssh_guac_terminal_scroll_down(ssh_guac_terminal* term, + int start_row, int end_row, int amount) { + + /* Calculate height of scroll region */ + int height = end_row - start_row + 1; + + return + + /* Move rows within scroll region down by the given amount */ + ssh_guac_terminal_copy(term, + start_row, 0, + height - amount, term->term_width, + start_row + amount, 0) + + /* Fill new rows with background */ + || ssh_guac_terminal_clear(term, + start_row, 0, amount, term->term_width, + term->background); + +} int ssh_guac_terminal_clear_range(ssh_guac_terminal* term, int start_row, int start_col, diff --git a/protocols/ssh/src/ssh_terminal_handlers.c b/protocols/ssh/src/ssh_terminal_handlers.c index 4ee4f44d..f3dc497d 100644 --- a/protocols/ssh/src/ssh_terminal_handlers.c +++ b/protocols/ssh/src/ssh_terminal_handlers.c @@ -407,6 +407,17 @@ int ssh_guac_terminal_csi(ssh_guac_terminal* term, char c) { break; + /* L: Insert blank lines (scroll down) */ + case 'L': + + amount = argv[0]; + if (amount == 0) amount = 1; + + ssh_guac_terminal_scroll_down(term, + term->cursor_row, term->scroll_end, amount); + + break; + /* Warn of unhandled codes */ default: if (c != ';')