diff --git a/protocols/ssh/Makefile.am b/protocols/ssh/Makefile.am index a3c36d50..4411fb4f 100644 --- a/protocols/ssh/Makefile.am +++ b/protocols/ssh/Makefile.am @@ -43,6 +43,7 @@ lib_LTLIBRARIES = libguac-client-ssh.la libguac_client_ssh_la_SOURCES = \ src/blank.c \ src/buffer.c \ + src/common.c \ src/cursor.c \ src/display.c \ src/ibar.c \ @@ -54,6 +55,7 @@ libguac_client_ssh_la_SOURCES = \ noinst_HEADERS = \ include/blank.h \ include/buffer.h \ + include/common.h \ include/cursor.h \ include/display.h \ include/ibar.h \ diff --git a/protocols/ssh/include/common.h b/protocols/ssh/include/common.h new file mode 100644 index 00000000..eedbeb89 --- /dev/null +++ b/protocols/ssh/include/common.h @@ -0,0 +1,48 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-ssh. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _SSH_GUAC_COMMON_H +#define _SSH_GUAC_COMMON_H + +/** + * Returns the closest value to the value given that is also + * within the given range. + */ +int guac_terminal_fit_to_range(int value, int min, int max); + +#endif + diff --git a/protocols/ssh/src/common.c b/protocols/ssh/src/common.c new file mode 100644 index 00000000..ca664666 --- /dev/null +++ b/protocols/ssh/src/common.c @@ -0,0 +1,46 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-ssh. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +int guac_terminal_fit_to_range(int value, int min, int max) { + + if (value < min) return min; + if (value > max) return max; + + return value; + +} + diff --git a/protocols/ssh/src/display.c b/protocols/ssh/src/display.c index ede7f16e..f972e31f 100644 --- a/protocols/ssh/src/display.c +++ b/protocols/ssh/src/display.c @@ -40,6 +40,7 @@ #include #include +#include "common.h" #include "types.h" #include "display.h" @@ -318,11 +319,21 @@ void guac_terminal_display_copy_columns(guac_terminal_display* display, int row, int start_column, int end_column, int offset) { int i; - guac_terminal_operation* src_current = - &(display->operations[row * display->width + start_column]); + guac_terminal_operation* src_current; + guac_terminal_operation* current; - guac_terminal_operation* current = - &(display->operations[row * display->width + start_column + offset]); + /* Ignore operations outside display bounds */ + if (row < 0 || row >= display->height) + return; + + /* Fit range within bounds */ + start_column = guac_terminal_fit_to_range(start_column, 0, display->width - 1); + end_column = guac_terminal_fit_to_range(end_column, 0, display->width - 1); + start_column = guac_terminal_fit_to_range(start_column + offset, 0, display->width - 1) - offset; + end_column = guac_terminal_fit_to_range(end_column + offset, 0, display->width - 1) - offset; + + src_current = &(display->operations[row * display->width + start_column]); + current = &(display->operations[row * display->width + start_column + offset]); /* Move data */ memmove(current, src_current, @@ -349,12 +360,17 @@ void guac_terminal_display_copy_rows(guac_terminal_display* display, int start_row, int end_row, int offset) { int row, col; + guac_terminal_operation* src_current_row; + guac_terminal_operation* current_row; - guac_terminal_operation* src_current_row = - &(display->operations[start_row * display->width]); + /* Fit range within bounds */ + start_row = guac_terminal_fit_to_range(start_row, 0, display->height - 1); + end_row = guac_terminal_fit_to_range(end_row, 0, display->height - 1); + start_row = guac_terminal_fit_to_range(start_row + offset, 0, display->height - 1) - offset; + end_row = guac_terminal_fit_to_range(end_row + offset, 0, display->height - 1) - offset; - guac_terminal_operation* current_row = - &(display->operations[(start_row + offset) * display->width]); + src_current_row = &(display->operations[start_row * display->width]); + current_row = &(display->operations[(start_row + offset) * display->width]); /* Move data */ memmove(current_row, src_current_row, @@ -389,8 +405,17 @@ void guac_terminal_display_set_columns(guac_terminal_display* display, int row, int start_column, int end_column, guac_terminal_char* character) { int i; - guac_terminal_operation* current = - &(display->operations[row * display->width + start_column]); + guac_terminal_operation* current; + + /* Ignore operations outside display bounds */ + if (row < 0 || row >= display->height) + return; + + /* Fit range within bounds */ + start_column = guac_terminal_fit_to_range(start_column, 0, display->width - 1); + end_column = guac_terminal_fit_to_range(end_column, 0, display->width - 1); + + current = &(display->operations[row * display->width + start_column]); /* For each column in range */ for (i=start_column; i<=end_column; i++) { diff --git a/protocols/ssh/src/terminal.c b/protocols/ssh/src/terminal.c index dc146a70..c950449a 100644 --- a/protocols/ssh/src/terminal.c +++ b/protocols/ssh/src/terminal.c @@ -131,7 +131,6 @@ int guac_terminal_set(guac_terminal* term, int row, int col, char c) { int guac_terminal_toggle_reverse(guac_terminal* term, int row, int col) { guac_terminal_char* guac_char; - int scrolled_row = row + term->scroll_offset; /* Get character from buffer */ guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(term->buffer, row, col+1); @@ -141,8 +140,7 @@ int guac_terminal_toggle_reverse(guac_terminal* term, int row, int col) { guac_char->attributes.reverse = !(guac_char->attributes.reverse); /* Set display */ - if (scrolled_row < term->display->height) - guac_terminal_display_set_columns(term->display, scrolled_row, col, col, guac_char); + guac_terminal_display_set_columns(term->display, row + term->scroll_offset, col, col, guac_char); return 0; @@ -387,7 +385,7 @@ void guac_terminal_copy_columns(guac_terminal* terminal, int row, int start_column, int end_column, int offset) { /* STUB */ - guac_terminal_display_copy_columns(terminal->display, row, + guac_terminal_display_copy_columns(terminal->display, row + terminal->scroll_offset, start_column, end_column, offset); guac_terminal_buffer_copy_columns(terminal->buffer, row, @@ -400,7 +398,7 @@ void guac_terminal_copy_rows(guac_terminal* terminal, /* STUB */ guac_terminal_display_copy_rows(terminal->display, - start_row, end_row, offset); + start_row + terminal->scroll_offset, end_row + terminal->scroll_offset, offset); guac_terminal_buffer_copy_rows(terminal->buffer, start_row, end_row, offset); @@ -411,7 +409,7 @@ void guac_terminal_set_columns(guac_terminal* terminal, int row, int start_column, int end_column, guac_terminal_char* character) { /* STUB */ - guac_terminal_display_set_columns(terminal->display, row, + guac_terminal_display_set_columns(terminal->display, row + terminal->scroll_offset, start_column, end_column, character); guac_terminal_buffer_set_columns(terminal->buffer, row,