Skip to content

Commit

Permalink
GUACAMOLE-287: Add constants for "magic numbers" in function __guac_t…
Browse files Browse the repository at this point in the history
…erminal_send_key.
  • Loading branch information
corentin-soriano committed Jun 17, 2024
1 parent 8f3b5d3 commit 47e04b8
Showing 1 changed file with 259 additions and 49 deletions.
308 changes: 259 additions & 49 deletions src/terminal/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,141 @@
#include <guacamole/string.h>
#include <guacamole/timestamp.h>

/**
* Keysym for movement keys (and keypad).
*/
#define GUAC_TERMINAL_KEY_UP 0xFF52
#define GUAC_TERMINAL_KEY_DOWN 0xFF54
#define GUAC_TERMINAL_KEY_LEFT 0xFF51
#define GUAC_TERMINAL_KEY_RIGHT 0xFF53
#define GUAC_TERMINAL_KEY_HOME 0xFF50
#define GUAC_TERMINAL_KEY_END 0xFF57
#define GUAC_TERMINAL_KEY_PAGEUP 0xFF55
#define GUAC_TERMINAL_KEY_PAGEDOWN 0xFF56

/**
* Keysym for keypad movement keys.
*/
#define GUAC_TERMINAL_KEY_KP_UP 0xFF97
#define GUAC_TERMINAL_KEY_KP_DOWN 0xFF99
#define GUAC_TERMINAL_KEY_KP_LEFT 0xFF96
#define GUAC_TERMINAL_KEY_KP_RIGHT 0xFF98
#define GUAC_TERMINAL_KEY_KP_HOME 0xFF95
#define GUAC_TERMINAL_KEY_KP_END 0xFF9C
#define GUAC_TERMINAL_KEY_KP_PAGEUP 0xFF9A
#define GUAC_TERMINAL_KEY_KP_PAGEDOWN 0xFF9B

/**
* Keysym for Control/Meta/ALT/Shift (left and right keys).
*/
#define GUAC_TERMINAL_KEY_CTRL_L 0xFFE3
#define GUAC_TERMINAL_KEY_CTRL_R 0xFFE4
#define GUAC_TERMINAL_KEY_META_L 0xFFE7
#define GUAC_TERMINAL_KEY_META_R 0xFFE8
#define GUAC_TERMINAL_KEY_ALT_L 0xFFE9
#define GUAC_TERMINAL_KEY_ALT_R 0xFFEA
#define GUAC_TERMINAL_KEY_SHIFT_L 0xFFE1
#define GUAC_TERMINAL_KEY_SHIFT_R 0xFFE2

/**
* Keysym for special keys.
*/
#define GUAC_TERMINAL_KEY_ESCAPE 0xFF1B
#define GUAC_TERMINAL_KEY_INSERT 0xFF63
#define GUAC_TERMINAL_KEY_ENTER 0xFF0D
#define GUAC_TERMINAL_KEY_TAB 0xFF09
#define GUAC_TERMINAL_KEY_BACKSPACE 0xFF08
#define GUAC_TERMINAL_KEY_DELETE 0xFFFF


/**
* Keysym for keypad special keys.
*/
#define GUAC_TERMINAL_KEY_KP_INSERT 0xFF9E
#define GUAC_TERMINAL_KEY_KP_ENTER 0xFF8D
#define GUAC_TERMINAL_KEY_KP_TAB 0xFF89
#define GUAC_TERMINAL_KEY_KP_DELETE 0xFF9F

/**
* Keysym for Function keys (1-12).
*/
#define GUAC_TERMINAL_KEY_F1 0xFFBE
#define GUAC_TERMINAL_KEY_F2 0xFFBF
#define GUAC_TERMINAL_KEY_F3 0xFFC0
#define GUAC_TERMINAL_KEY_F4 0xFFC1
#define GUAC_TERMINAL_KEY_F5 0xFFC2
#define GUAC_TERMINAL_KEY_F6 0xFFC3
#define GUAC_TERMINAL_KEY_F7 0xFFC4
#define GUAC_TERMINAL_KEY_F8 0xFFC5
#define GUAC_TERMINAL_KEY_F9 0xFFC6
#define GUAC_TERMINAL_KEY_F10 0xFFC7
#define GUAC_TERMINAL_KEY_F11 0xFFC8
#define GUAC_TERMINAL_KEY_F12 0xFFC9

/**
* Keysym for keypad Function keys (1-4).
*/
#define GUAC_TERMINAL_KEY_KP_F1 0xFF91
#define GUAC_TERMINAL_KEY_KP_F2 0xFF92
#define GUAC_TERMINAL_KEY_KP_F3 0xFF93
#define GUAC_TERMINAL_KEY_KP_F4 0xFF94

/**
* Hex ASCII codes.
*/
#define GUAC_TERMINAL_ASCII_TAB "\x09"
#define GUAC_TERMINAL_ASCII_CR "\x0D"
#define GUAC_TERMINAL_ASCII_ESCAPE "\x1B"

/**
* Escape sequence: special keys.
*/
#define GUAC_TERMINAL_ESC_SEQ_PAGEUP "\x1B[5~"
#define GUAC_TERMINAL_ESC_SEQ_PAGEDOWN "\x1B[6~"
#define GUAC_TERMINAL_ESC_SEQ_END "\x1B[4~"
#define GUAC_TERMINAL_ESC_SEQ_INSERT "\x1B[2~"
#define GUAC_TERMINAL_ESC_SEQ_HOME "\x1B[1~"
#define GUAC_TERMINAL_ESC_SEQ_CURSOR_LEFT "\x1B[D"
#define GUAC_TERMINAL_ESC_SEQ_CURSOR_RIGHT "\x1B[C"
#define GUAC_TERMINAL_ESC_SEQ_CURSOR_UP "\x1B[A"
#define GUAC_TERMINAL_ESC_SEQ_CURSOR_DOWN "\x1B[B"
#define GUAC_TERMINAL_ESC_SEQ_DELETE "\x1B[3~"

/**
* Escape sequence: application cursor.
*/
#define GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_LEFT "\x1BOD"
#define GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_RIGHT "\x1BOC"
#define GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_UP "\x1BOA"
#define GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_DOWN "\x1BOB"

/**
* Escape sequence: function keys.
*/
#define GUAC_TERMINAL_ESC_SEQ_F1 "\x1B[[A"
#define GUAC_TERMINAL_ESC_SEQ_F2 "\x1B[[B"
#define GUAC_TERMINAL_ESC_SEQ_F3 "\x1B[[C"
#define GUAC_TERMINAL_ESC_SEQ_F4 "\x1B[[D"
#define GUAC_TERMINAL_ESC_SEQ_F5 "\x1B[[E"
#define GUAC_TERMINAL_ESC_SEQ_F6 "\x1B[17~"
#define GUAC_TERMINAL_ESC_SEQ_F7 "\x1B[18~"
#define GUAC_TERMINAL_ESC_SEQ_F8 "\x1B[19~"
#define GUAC_TERMINAL_ESC_SEQ_F9 "\x1B[20~"
#define GUAC_TERMINAL_ESC_SEQ_F10 "\x1B[21~"
#define GUAC_TERMINAL_ESC_SEQ_F11 "\x1B[22~"
#define GUAC_TERMINAL_ESC_SEQ_F12 "\x1B[23~"

/**
* Escape sequence: go to previous/next word.
*/
#define GUAC_TERMINAL_ESC_SEQ_PREV_WORD "\033[1;5D"
#define GUAC_TERMINAL_ESC_SEQ_NEXT_WORD "\033[1;5C"

/**
* Escape sequence: delete word.
*/
#define GUAC_TERMINAL_ESC_SEQ_DELETE_WORD "\033D"

/**
* Sets the given range of columns to the given character.
*/
Expand Down Expand Up @@ -1583,13 +1718,13 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
}

/* Track modifiers */
if (keysym == 0xFFE3 || keysym == 0xFFE4)
if (keysym == GUAC_TERMINAL_KEY_CTRL_L || keysym == GUAC_TERMINAL_KEY_CTRL_R)
term->mod_ctrl = pressed;
else if (keysym == 0xFFE7 || keysym == 0xFFE8)
else if (keysym == GUAC_TERMINAL_KEY_META_L || keysym == GUAC_TERMINAL_KEY_META_R)
term->mod_meta = pressed;
else if (keysym == 0xFFE9 || keysym == 0xFFEA)
else if (keysym == GUAC_TERMINAL_KEY_ALT_L || keysym == GUAC_TERMINAL_KEY_ALT_R)
term->mod_alt = pressed;
else if (keysym == 0xFFE1 || keysym == 0xFFE2)
else if (keysym == GUAC_TERMINAL_KEY_SHIFT_L || keysym == GUAC_TERMINAL_KEY_SHIFT_R)
term->mod_shift = pressed;

/* If key pressed */
Expand All @@ -1612,37 +1747,37 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
if (term->mod_shift) {

/* Home */
if (keysym == 0xFF50 || keysym == 0xFF95) {
if (keysym == GUAC_TERMINAL_KEY_HOME || keysym == GUAC_TERMINAL_KEY_KP_HOME) {
guac_terminal_scroll_display_up(term, term->max_scrollback);
return 0;
}

/* End */
if (keysym == 0xFF57 || keysym == 0xFF9C) {
if (keysym == GUAC_TERMINAL_KEY_END || keysym == GUAC_TERMINAL_KEY_KP_END) {
guac_terminal_scroll_display_down(term, term->max_scrollback);
return 0;
}

/* Page up */
if (keysym == 0xFF55) {
if (keysym == GUAC_TERMINAL_KEY_PAGEUP || keysym == GUAC_TERMINAL_KEY_KP_PAGEUP) {
guac_terminal_scroll_display_up(term, term->term_height);
return 0;
}

/* Page down */
if (keysym == 0xFF56) {
if (keysym == GUAC_TERMINAL_KEY_PAGEDOWN || keysym == GUAC_TERMINAL_KEY_KP_PAGEDOWN) {
guac_terminal_scroll_display_down(term, term->term_height);
return 0;
}

/* Up */
if (keysym == 0xFF52 || keysym == 0xFF97) {
if (keysym == GUAC_TERMINAL_KEY_UP || keysym == GUAC_TERMINAL_KEY_KP_UP) {
guac_terminal_scroll_display_up(term, 1);
return 0;
}

/* Down */
if (keysym == 0xFF54 || keysym == 0xFF99) {
if (keysym == GUAC_TERMINAL_KEY_DOWN || keysym == GUAC_TERMINAL_KEY_KP_DOWN) {
guac_terminal_scroll_display_down(term, 1);
return 0;
}
Expand All @@ -1655,7 +1790,7 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed

/* If alt being held, also send escape character */
if (term->mod_alt)
guac_terminal_send_string(term, "\x1B");
guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_ESCAPE);

/* Translate Ctrl+letter to control code */
if (term->mod_ctrl) {
Expand Down Expand Up @@ -1683,20 +1818,20 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
data = (char) (keysym - '3' + 0x1B);

/* CTRL+Left: return to previous word */
else if (keysym == 0xFF51 || keysym == 0xFF96)
return guac_terminal_send_string(term, "\033[1;5D");
else if (keysym == GUAC_TERMINAL_KEY_LEFT || keysym == GUAC_TERMINAL_KEY_KP_LEFT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_PREV_WORD);

/* CTRL+Right: go to next word */
else if (keysym == 0xFF53 || keysym == 0xFF98)
return guac_terminal_send_string(term, "\033[1;5C");
else if (keysym == GUAC_TERMINAL_KEY_RIGHT || keysym == GUAC_TERMINAL_KEY_KP_RIGHT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_NEXT_WORD);

/* CTRL+Backspace: remove word (map to CTRL+w) */
else if (keysym == 0xFF08)
else if (keysym == GUAC_TERMINAL_KEY_BACKSPACE)
data = (char) 23;

/* CTRL+Supr: remove word to right */
else if (keysym == 0xFFFF)
return guac_terminal_send_string(term, "\033D");
else if (keysym == GUAC_TERMINAL_KEY_DELETE || keysym == GUAC_TERMINAL_KEY_KP_DELETE)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_DELETE_WORD);

/* Otherwise ignore */
else
Expand Down Expand Up @@ -1727,51 +1862,126 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
else {

/* Backspace can vary based on configuration of terminal by client. */
if (keysym == 0xFF08) {
if (keysym == GUAC_TERMINAL_KEY_BACKSPACE) {
char backspace_str[] = { term->backspace, '\0' };
return guac_terminal_send_string(term, backspace_str);
}
if (keysym == 0xFF09 || keysym == 0xFF89) return guac_terminal_send_string(term, "\x09"); /* Tab */
if (keysym == 0xFF0D || keysym == 0xFF8D) return guac_terminal_send_string(term, "\x0D"); /* Enter */
if (keysym == 0xFF1B) return guac_terminal_send_string(term, "\x1B"); /* Esc */

if (keysym == 0xFF50 || keysym == 0xFF95) return guac_terminal_send_string(term, "\x1B[1~"); /* Home */
/* Tab */
if (keysym == GUAC_TERMINAL_KEY_TAB || keysym == GUAC_TERMINAL_KEY_KP_TAB)
return guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_TAB);

/* Enter */
if (keysym == GUAC_TERMINAL_KEY_ENTER || keysym == GUAC_TERMINAL_KEY_KP_ENTER)
return guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_CR);

/* Esc */
if (keysym == GUAC_TERMINAL_KEY_ESCAPE)
return guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_ESCAPE);

/* Home */
if (keysym == GUAC_TERMINAL_KEY_HOME || keysym == GUAC_TERMINAL_KEY_KP_HOME)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_HOME);

/* Arrow keys w/ application cursor */
if (term->application_cursor_keys) {
if (keysym == 0xFF51 || keysym == 0xFF96) return guac_terminal_send_string(term, "\x1BOD"); /* Left */
if (keysym == 0xFF52 || keysym == 0xFF97) return guac_terminal_send_string(term, "\x1BOA"); /* Up */
if (keysym == 0xFF53 || keysym == 0xFF98) return guac_terminal_send_string(term, "\x1BOC"); /* Right */
if (keysym == 0xFF54 || keysym == 0xFF99) return guac_terminal_send_string(term, "\x1BOB"); /* Down */

/* Left */
if (keysym == GUAC_TERMINAL_KEY_LEFT || keysym == GUAC_TERMINAL_KEY_KP_LEFT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_LEFT);

/* Up */
if (keysym == GUAC_TERMINAL_KEY_UP || keysym == GUAC_TERMINAL_KEY_KP_UP)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_UP);

/* Right */
if (keysym == GUAC_TERMINAL_KEY_RIGHT || keysym == GUAC_TERMINAL_KEY_KP_RIGHT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_RIGHT);

/* Down */
if (keysym == GUAC_TERMINAL_KEY_DOWN || keysym == GUAC_TERMINAL_KEY_KP_DOWN)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_DOWN);
}
else {
if (keysym == 0xFF51 || keysym == 0xFF96) return guac_terminal_send_string(term, "\x1B[D"); /* Left */
if (keysym == 0xFF52 || keysym == 0xFF97) return guac_terminal_send_string(term, "\x1B[A"); /* Up */
if (keysym == 0xFF53 || keysym == 0xFF98) return guac_terminal_send_string(term, "\x1B[C"); /* Right */
if (keysym == 0xFF54 || keysym == 0xFF99) return guac_terminal_send_string(term, "\x1B[B"); /* Down */
}

if (keysym == 0xFF55 || keysym == 0xFF9A) return guac_terminal_send_string(term, "\x1B[5~"); /* Page up */
if (keysym == 0xFF56 || keysym == 0xFF9B) return guac_terminal_send_string(term, "\x1B[6~"); /* Page down */
if (keysym == 0xFF57 || keysym == 0xFF9C) return guac_terminal_send_string(term, "\x1B[4~"); /* End */
/* Left */
if (keysym == GUAC_TERMINAL_KEY_LEFT || keysym == GUAC_TERMINAL_KEY_KP_LEFT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_LEFT);

if (keysym == 0xFF63 || keysym == 0xFF9E) return guac_terminal_send_string(term, "\x1B[2~"); /* Insert */
/* Up */
if (keysym == GUAC_TERMINAL_KEY_UP || keysym == GUAC_TERMINAL_KEY_KP_UP)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_UP);

if (keysym == 0xFFBE || keysym == 0xFF91) return guac_terminal_send_string(term, "\x1B[[A"); /* F1 */
if (keysym == 0xFFBF || keysym == 0xFF92) return guac_terminal_send_string(term, "\x1B[[B"); /* F2 */
if (keysym == 0xFFC0 || keysym == 0xFF93) return guac_terminal_send_string(term, "\x1B[[C"); /* F3 */
if (keysym == 0xFFC1 || keysym == 0xFF94) return guac_terminal_send_string(term, "\x1B[[D"); /* F4 */
if (keysym == 0xFFC2) return guac_terminal_send_string(term, "\x1B[[E"); /* F5 */
/* Right */
if (keysym == GUAC_TERMINAL_KEY_RIGHT || keysym == GUAC_TERMINAL_KEY_KP_RIGHT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_RIGHT);

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 */
/* Down */
if (keysym == GUAC_TERMINAL_KEY_DOWN || keysym == GUAC_TERMINAL_KEY_KP_DOWN)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_DOWN);
}

/* Page up */
if (keysym == GUAC_TERMINAL_KEY_PAGEUP || keysym == GUAC_TERMINAL_KEY_KP_PAGEUP)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_PAGEUP);

if (keysym == 0xFFFF || keysym == 0xFF9F) return guac_terminal_send_string(term, "\x1B[3~"); /* Delete */
/* Page down */
if (keysym == GUAC_TERMINAL_KEY_PAGEDOWN || keysym == GUAC_TERMINAL_KEY_KP_PAGEDOWN)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_PAGEDOWN);

/* End */
if (keysym == GUAC_TERMINAL_KEY_END || keysym == GUAC_TERMINAL_KEY_KP_END)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_END);

/* Insert */
if (keysym == GUAC_TERMINAL_KEY_INSERT || keysym == GUAC_TERMINAL_KEY_KP_INSERT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_INSERT);

/* F1 */
if (keysym == GUAC_TERMINAL_KEY_F1 || keysym == GUAC_TERMINAL_KEY_KP_F1)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F1);

/* F2 */
if (keysym == GUAC_TERMINAL_KEY_F2 || keysym == GUAC_TERMINAL_KEY_KP_F2)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F2);

/* F3 */
if (keysym == GUAC_TERMINAL_KEY_F3 || keysym == GUAC_TERMINAL_KEY_KP_F3)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F3);

/* F4 */
if (keysym == GUAC_TERMINAL_KEY_F4 || keysym == GUAC_TERMINAL_KEY_KP_F4)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F4);

/* F5 */
if (keysym == GUAC_TERMINAL_KEY_F5)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F5);

/* F6 */
if (keysym == GUAC_TERMINAL_KEY_F6)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F6);
/* F7 */
if (keysym == GUAC_TERMINAL_KEY_F7)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F7);
/* F8 */
if (keysym == GUAC_TERMINAL_KEY_F8)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F8);
/* F9 */
if (keysym == GUAC_TERMINAL_KEY_F9)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F9);
/* F10 */
if (keysym == GUAC_TERMINAL_KEY_F10)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F10);
/* F11 */
if (keysym == GUAC_TERMINAL_KEY_F11)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F11);
/* F12 */
if (keysym == GUAC_TERMINAL_KEY_F12)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F12);

/* Delete */
if (keysym == GUAC_TERMINAL_KEY_DELETE || keysym == GUAC_TERMINAL_KEY_KP_DELETE)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_DELETE);

/* Ignore unknown keys */
guac_client_log(term->client, GUAC_LOG_DEBUG,
Expand Down

0 comments on commit 47e04b8

Please sign in to comment.