Add remaining keys, fix backspace. Add insert flag.

This commit is contained in:
Michael Jumper 2013-05-25 22:45:26 -07:00
parent 88ca59a5b3
commit 763ed37179
6 changed files with 110 additions and 68 deletions

View File

@ -69,6 +69,11 @@ typedef struct ssh_guac_client_data {
*/
char* clipboard_data;
/**
* Whether the alt key is currently being held down.
*/
int mod_alt;
/**
* Whether the control key is currently being held down.
*/

View File

@ -228,6 +228,11 @@ struct guac_terminal {
*/
bool automatic_carriage_return;
/**
* Whether insert mode is enabled (DECIM).
*/
bool insert_mode;
};
/**
@ -352,5 +357,21 @@ void guac_terminal_resize(guac_terminal* term, int width, int height);
*/
void guac_terminal_flush(guac_terminal* terminal);
/**
* Sends the given string as if typed by the user.
*/
int guac_terminal_send_data(guac_terminal* term, const char* data, int length);
/**
* Sends the given string as if typed by the user.
*/
int guac_terminal_send_string(guac_terminal* term, const char* data);
/**
* Sends data through STDIN as if typed by the user, using the format
* string given and any args (similar to printf).
*/
int guac_terminal_sendf(guac_terminal* term, const char* format, ...);
#endif

View File

@ -72,6 +72,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
/* Init client data */
client->data = client_data;
client_data->term = term;
client_data->mod_alt = 0;
client_data->mod_ctrl = 0;
client_data->clipboard_data = NULL;
client_data->term_channel = NULL;

View File

@ -158,7 +158,7 @@ int ssh_guac_client_mouse_handler(guac_client* client, int x, int y, int mask) {
int length = strlen(client_data->clipboard_data);
if (length)
return write(term->stdin_pipe_fd[1],
return guac_terminal_send_data(term,
client_data->clipboard_data, length);
}
@ -228,9 +228,6 @@ int ssh_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
guac_terminal* term = client_data->term;
/* Get write end of STDIN pipe */
int fd = term->stdin_pipe_fd[1];
/* Hide mouse cursor if not already hidden */
if (client_data->current_cursor != client_data->blank_cursor) {
pthread_mutex_lock(&(term->lock));
@ -243,9 +240,10 @@ int ssh_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
}
/* Track modifiers */
if (keysym == 0xFFE3) {
if (keysym == 0xFFE3)
client_data->mod_ctrl = pressed;
}
else if (keysym == 0xFFE9)
client_data->mod_alt = pressed;
/* If key pressed */
else if (pressed) {
@ -257,6 +255,10 @@ int ssh_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
pthread_mutex_unlock(&(term->lock));
}
/* If alt being held, also send escape character */
if (client_data->mod_alt)
return guac_terminal_send_string(term, "\x1B");
/* Translate Ctrl+letter to control code */
if (client_data->mod_ctrl) {
@ -272,7 +274,7 @@ int ssh_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
else
return 0;
return write(fd, &data, 1);
return guac_terminal_send_data(term, &data, 1);
}
@ -283,50 +285,57 @@ int ssh_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
char data[5];
length = guac_terminal_encode_utf8(keysym & 0xFFFF, data);
return write(fd, data, length);
return guac_terminal_send_data(term, data, length);
}
/* Non-printable keys */
else {
int length = 0;
const char* data = NULL;
if (keysym == 0xFF08) return guac_terminal_send_string(term, "\x7F"); /* Backspace */
if (keysym == 0xFF09) return guac_terminal_send_string(term, "\x09"); /* Tab */
if (keysym == 0xFF0D) return guac_terminal_send_string(term, "\x0D"); /* Enter */
if (keysym == 0xFF1B) return guac_terminal_send_string(term, "\x1B"); /* Esc */
if (keysym == 0xFF08) { data = "\x08"; length = 1; }
else if (keysym == 0xFF09) { data = "\x09"; length = 1; }
else if (keysym == 0xFF0D) { data = "\x0D"; length = 1; }
else if (keysym == 0xFF1B) { data = "\x1B"; length = 1; }
if (keysym == 0xFF50) return guac_terminal_send_string(term, "\x1BOH"); /* Home */
/* Arrow keys */
else if (keysym == 0xFF52) {
if (term->application_cursor_keys) data = "\x1BOA";
else data = "\x1B[A";
length = 3;
/* Arrow keys w/ application cursor */
if (term->application_cursor_keys) {
if (keysym == 0xFF51) return guac_terminal_send_string(term, "\x1BOD"); /* Left */
if (keysym == 0xFF52) return guac_terminal_send_string(term, "\x1BOA"); /* Up */
if (keysym == 0xFF53) return guac_terminal_send_string(term, "\x1BOC"); /* Right */
if (keysym == 0xFF54) return guac_terminal_send_string(term, "\x1BOB"); /* Down */
}
else {
if (keysym == 0xFF51) return guac_terminal_send_string(term, "\x1B[D"); /* Left */
if (keysym == 0xFF52) return guac_terminal_send_string(term, "\x1B[A"); /* Up */
if (keysym == 0xFF53) return guac_terminal_send_string(term, "\x1B[C"); /* Right */
if (keysym == 0xFF54) return guac_terminal_send_string(term, "\x1B[B"); /* Down */
}
else if (keysym == 0xFF54) {
if (term->application_cursor_keys) data = "\x1BOB";
else data = "\x1B[B";
length = 3;
}
if (keysym == 0xFF55) return guac_terminal_send_string(term, "\x1B[5;3~"); /* Page up */
if (keysym == 0xFF56) return guac_terminal_send_string(term, "\x1B[6;3~"); /* Page down */
if (keysym == 0xFF57) return guac_terminal_send_string(term, "\x1BOF"); /* End */
else if (keysym == 0xFF53) {
if (term->application_cursor_keys) data = "\x1BOC";
else data = "\x1B[C";
length = 3;
}
if (keysym == 0xFF63) return guac_terminal_send_string(term, "\x1B[2~"); /* Insert */
else if (keysym == 0xFF51) {
if (term->application_cursor_keys) data = "\x1BOD";
else data = "\x1B[D";
length = 3;
}
if (keysym == 0xFFBE) return guac_terminal_send_string(term, "\x1BOP"); /* F1 */
if (keysym == 0xFFBF) return guac_terminal_send_string(term, "\x1BOQ"); /* F2 */
if (keysym == 0xFFC0) return guac_terminal_send_string(term, "\x1BOR"); /* F3 */
if (keysym == 0xFFC1) return guac_terminal_send_string(term, "\x1BOS"); /* F4 */
if (keysym == 0xFFC2) return guac_terminal_send_string(term, "\x1B[15~"); /* F5 */
if (keysym == 0xFFC3) return guac_terminal_send_string(term, "\x1B[17~"); /* F6 */
if (keysym == 0xFFC4) return guac_terminal_send_string(term, "\x1B[18~"); /* F7 */
if (keysym == 0xFFC5) return guac_terminal_send_string(term, "\x1B[19~"); /* F8 */
if (keysym == 0xFFC6) return guac_terminal_send_string(term, "\x1B[20~"); /* F9 */
if (keysym == 0xFFC7) return guac_terminal_send_string(term, "\x1B[21~"); /* F10 */
if (keysym == 0xFFC8) return guac_terminal_send_string(term, "\x1B[22~"); /* F11 */
if (keysym == 0xFFC9) return guac_terminal_send_string(term, "\x1B[23~"); /* F12 */
/* Ignore other keys */
else return 0;
if (keysym == 0xFFFF) return guac_terminal_send_string(term, "\x1B[3~"); /* Delete */
return write(fd, data, length);
/* Ignore unknown keys */
}
}

View File

@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <pthread.h>
@ -80,6 +81,7 @@ void guac_terminal_reset(guac_terminal* term) {
term->text_selected = false;
term->application_cursor_keys = false;
term->automatic_carriage_return = false;
term->insert_mode = false;
/* Clear terminal */
for (row=0; row<term->term_height; row++)
@ -755,3 +757,32 @@ void guac_terminal_resize(guac_terminal* term, int width, int height) {
}
int guac_terminal_send_data(guac_terminal* term, const char* data, int length) {
return guac_terminal_write_all(term->stdin_pipe_fd[1], data, length);
}
int guac_terminal_send_string(guac_terminal* term, const char* data) {
return guac_terminal_write_all(term->stdin_pipe_fd[1], data, strlen(data));
}
int guac_terminal_sendf(guac_terminal* term, const char* format, ...) {
int written;
va_list ap;
char buffer[1024];
/* Print to buffer */
va_start(ap, format);
written = vsnprintf(buffer, sizeof(buffer)-1, format, ap);
va_end(ap);
if (written < 0)
return written;
/* Write to STDIN */
return guac_terminal_write_all(term->stdin_pipe_fd[1], buffer, written);
}

View File

@ -36,7 +36,6 @@
* ***** END LICENSE BLOCK ***** */
#include <stdlib.h>
#include <stdarg.h>
#include "common.h"
#include "terminal.h"
@ -58,31 +57,6 @@
*/
#define GUAC_TERMINAL_OK "\x1B[0n"
/**
* Sends data through STDIN as if typed by the user, using the format
* string given and any args (similar to printf).
*/
static int guac_terminal_respond(guac_terminal* term, const char* format, ...) {
int written;
va_list ap;
char buffer[1024];
/* Print to buffer */
va_start(ap, format);
written = vsnprintf(buffer, sizeof(buffer)-1, format, ap);
va_end(ap);
if (written < 0)
return written;
/* Write to STDIN */
return guac_terminal_write_all(term->stdin_pipe_fd[1], buffer, written);
}
int guac_terminal_echo(guac_terminal* term, char c) {
static int bytes_remaining = 0;
@ -140,7 +114,7 @@ int guac_terminal_echo(guac_terminal* term, char c) {
/* Enquiry */
case 0x05:
guac_terminal_respond(term, "%s", GUAC_TERMINAL_ANSWERBACK);
guac_terminal_send_string(term, GUAC_TERMINAL_ANSWERBACK);
break;
/* Bell */
@ -345,7 +319,7 @@ int guac_terminal_escape(guac_terminal* term, char c) {
/* DEC Identify */
case 'Z':
guac_terminal_respond(term, "%s", GUAC_TERMINAL_VT102_ID);
guac_terminal_send_string(term, GUAC_TERMINAL_VT102_ID);
term->char_handler = guac_terminal_echo;
break;
@ -413,6 +387,7 @@ static bool* __guac_terminal_get_flag(guac_terminal* term, int num, char private
else if (private_mode == 0) {
switch (num) {
case 4: return &(term->insert_mode); /* DECIM */
case 20: return &(term->automatic_carriage_return); /* LF/NL */
}
}
@ -696,7 +671,7 @@ int guac_terminal_csi(guac_terminal* term, char c) {
/* c: Identify */
case 'c':
if (argv[0] == 0 && private_mode_character == 0)
guac_terminal_respond(term, "%s", GUAC_TERMINAL_VT102_ID);
guac_terminal_send_string(term, GUAC_TERMINAL_VT102_ID);
break;
/* d: Move cursor, current col */
@ -810,11 +785,11 @@ int guac_terminal_csi(guac_terminal* term, char c) {
/* Device status report */
if (argv[0] == 5 && private_mode_character == 0)
guac_terminal_respond(term, "%s", GUAC_TERMINAL_OK);
guac_terminal_send_string(term, GUAC_TERMINAL_OK);
/* Cursor position report */
else if (argv[0] == 6 && private_mode_character == 0)
guac_terminal_respond(term, "\x1B[%i;%iR", term->cursor_row+1, term->cursor_col+1);
guac_terminal_sendf(term, "\x1B[%i;%iR", term->cursor_row+1, term->cursor_col+1);
break;