input.c revision 5b78a3aa7741c3f44b676ccffa765cecee1cbd4c
1#include "vterm_internal.h" 2 3#include <stdio.h> 4 5#include "utf8.h" 6 7void vterm_input_push_char(VTerm *vt, VTermModifier mod, uint32_t c) 8{ 9 /* The shift modifier is never important for Unicode characters 10 * apart from Space 11 */ 12 if(c != ' ') 13 mod &= ~VTERM_MOD_SHIFT; 14 /* However, since Shift-Space is too easy to mistype accidentally, remove 15 * shift if it's the only modifier 16 */ 17 else if(mod == VTERM_MOD_SHIFT) 18 mod = 0; 19 20 if(mod == 0) { 21 // Normal text - ignore just shift 22 char str[6]; 23 int seqlen = fill_utf8(c, str); 24 vterm_push_output_bytes(vt, str, seqlen); 25 return; 26 } 27 28 int needs_CSIu; 29 switch(c) { 30 /* Special Ctrl- letters that can't be represented elsewise */ 31 case 'h': case 'i': case 'j': case 'm': case '[': 32 needs_CSIu = 1; 33 break; 34 /* Ctrl-\ ] ^ _ don't need CSUu */ 35 case '\\': case ']': case '^': case '_': 36 needs_CSIu = 0; 37 break; 38 /* All other characters needs CSIu except for letters a-z */ 39 default: 40 needs_CSIu = (c < 'a' || c > 'z'); 41 } 42 43 /* ALT we can just prefix with ESC; anything else requires CSI u */ 44 if(needs_CSIu && (mod & ~VTERM_MOD_ALT)) { 45 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", c, mod+1); 46 return; 47 } 48 49 if(mod & VTERM_MOD_CTRL) 50 c &= 0x1f; 51 52 vterm_push_output_sprintf(vt, "%s%c", mod & VTERM_MOD_ALT ? "\e" : "", c); 53} 54 55typedef struct { 56 enum { 57 KEYCODE_NONE, 58 KEYCODE_LITERAL, 59 KEYCODE_TAB, 60 KEYCODE_ENTER, 61 KEYCODE_SS3, 62 KEYCODE_CSI, 63 KEYCODE_CSI_CURSOR, 64 KEYCODE_CSINUM, 65 KEYCODE_KEYPAD, 66 } type; 67 char literal; 68 int csinum; 69} keycodes_s; 70 71static keycodes_s keycodes[] = { 72 { KEYCODE_NONE }, // NONE 73 74 { KEYCODE_ENTER, '\r' }, // ENTER 75 { KEYCODE_TAB, '\t' }, // TAB 76 { KEYCODE_LITERAL, '\x7f' }, // BACKSPACE == ASCII DEL 77 { KEYCODE_LITERAL, '\e' }, // ESCAPE 78 79 { KEYCODE_CSI_CURSOR, 'A' }, // UP 80 { KEYCODE_CSI_CURSOR, 'B' }, // DOWN 81 { KEYCODE_CSI_CURSOR, 'D' }, // LEFT 82 { KEYCODE_CSI_CURSOR, 'C' }, // RIGHT 83 84 { KEYCODE_CSINUM, '~', 2 }, // INS 85 { KEYCODE_CSINUM, '~', 3 }, // DEL 86 { KEYCODE_CSI_CURSOR, 'H' }, // HOME 87 { KEYCODE_CSI_CURSOR, 'F' }, // END 88 { KEYCODE_CSINUM, '~', 5 }, // PAGEUP 89 { KEYCODE_CSINUM, '~', 6 }, // PAGEDOWN 90}; 91 92static keycodes_s keycodes_fn[] = { 93 { KEYCODE_NONE }, // F0 - shouldn't happen 94 { KEYCODE_CSI_CURSOR, 'P' }, // F1 95 { KEYCODE_CSI_CURSOR, 'Q' }, // F2 96 { KEYCODE_CSI_CURSOR, 'R' }, // F3 97 { KEYCODE_CSI_CURSOR, 'S' }, // F4 98 { KEYCODE_CSINUM, '~', 15 }, // F5 99 { KEYCODE_CSINUM, '~', 17 }, // F6 100 { KEYCODE_CSINUM, '~', 18 }, // F7 101 { KEYCODE_CSINUM, '~', 19 }, // F8 102 { KEYCODE_CSINUM, '~', 20 }, // F9 103 { KEYCODE_CSINUM, '~', 21 }, // F10 104 { KEYCODE_CSINUM, '~', 23 }, // F11 105 { KEYCODE_CSINUM, '~', 24 }, // F12 106}; 107 108static keycodes_s keycodes_kp[] = { 109 { KEYCODE_KEYPAD, '0', 'p' }, // KP_0 110 { KEYCODE_KEYPAD, '1', 'q' }, // KP_1 111 { KEYCODE_KEYPAD, '2', 'r' }, // KP_2 112 { KEYCODE_KEYPAD, '3', 's' }, // KP_3 113 { KEYCODE_KEYPAD, '4', 't' }, // KP_4 114 { KEYCODE_KEYPAD, '5', 'u' }, // KP_5 115 { KEYCODE_KEYPAD, '6', 'v' }, // KP_6 116 { KEYCODE_KEYPAD, '7', 'w' }, // KP_7 117 { KEYCODE_KEYPAD, '8', 'x' }, // KP_8 118 { KEYCODE_KEYPAD, '9', 'y' }, // KP_9 119 { KEYCODE_KEYPAD, '*', 'j' }, // KP_MULT 120 { KEYCODE_KEYPAD, '+', 'k' }, // KP_PLUS 121 { KEYCODE_KEYPAD, ',', 'l' }, // KP_COMMA 122 { KEYCODE_KEYPAD, '-', 'm' }, // KP_MINUS 123 { KEYCODE_KEYPAD, '.', 'n' }, // KP_PERIOD 124 { KEYCODE_KEYPAD, '/', 'o' }, // KP_DIVIDE 125 { KEYCODE_KEYPAD, '\n', 'M' }, // KP_ENTER 126 { KEYCODE_KEYPAD, '=', 'X' }, // KP_EQUAL 127}; 128 129void vterm_input_push_key(VTerm *vt, VTermModifier mod, VTermKey key) 130{ 131 /* Since Shift-Enter and Shift-Backspace are too easy to mistype 132 * accidentally, remove shift if it's the only modifier 133 */ 134 if((key == VTERM_KEY_ENTER || key == VTERM_KEY_BACKSPACE) && mod == VTERM_MOD_SHIFT) 135 mod = 0; 136 137 if(key == VTERM_KEY_NONE) 138 return; 139 140 keycodes_s k; 141 if(key < VTERM_KEY_FUNCTION_0) { 142 if(key >= sizeof(keycodes)/sizeof(keycodes[0])) 143 return; 144 k = keycodes[key]; 145 } 146 else if(key >= VTERM_KEY_FUNCTION_0 && key <= VTERM_KEY_FUNCTION_MAX) { 147 if((key - VTERM_KEY_FUNCTION_0) >= sizeof(keycodes_fn)/sizeof(keycodes_fn[0])) 148 return; 149 k = keycodes_fn[key - VTERM_KEY_FUNCTION_0]; 150 } 151 else if(key >= VTERM_KEY_KP_0) { 152 if((key - VTERM_KEY_KP_0) >= sizeof(keycodes_kp)/sizeof(keycodes_kp[0])) 153 return; 154 k = keycodes_kp[key - VTERM_KEY_KP_0]; 155 } 156 157 switch(k.type) { 158 case KEYCODE_NONE: 159 break; 160 161 case KEYCODE_TAB: 162 /* Shift-Tab is CSI Z but plain Tab is 0x09 */ 163 if(mod == VTERM_MOD_SHIFT) 164 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "Z"); 165 else if(mod & VTERM_MOD_SHIFT) 166 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%dZ", mod+1); 167 else 168 goto case_LITERAL; 169 break; 170 171 case KEYCODE_ENTER: 172 /* Enter is CRLF in newline mode, but just LF in linefeed */ 173 if(vt->state->mode.newline) 174 vterm_push_output_sprintf(vt, "\r\n"); 175 else 176 goto case_LITERAL; 177 break; 178 179 case KEYCODE_LITERAL: case_LITERAL: 180 if(mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL)) 181 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", k.literal, mod+1); 182 else 183 vterm_push_output_sprintf(vt, mod & VTERM_MOD_ALT ? "\e%c" : "%c", k.literal); 184 break; 185 186 case KEYCODE_SS3: case_SS3: 187 if(mod == 0) 188 vterm_push_output_sprintf_ctrl(vt, C1_SS3, "%c", k.literal); 189 else 190 goto case_CSI; 191 break; 192 193 case KEYCODE_CSI: case_CSI: 194 if(mod == 0) 195 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%c", k.literal); 196 else 197 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%d%c", mod + 1, k.literal); 198 break; 199 200 case KEYCODE_CSINUM: 201 if(mod == 0) 202 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d%c", k.csinum, k.literal); 203 else 204 vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%d%c", k.csinum, mod + 1, k.literal); 205 break; 206 207 case KEYCODE_CSI_CURSOR: 208 if(vt->state->mode.cursor) 209 goto case_SS3; 210 else 211 goto case_CSI; 212 213 case KEYCODE_KEYPAD: 214 if(vt->state->mode.keypad) { 215 k.literal = k.csinum; 216 goto case_SS3; 217 } 218 else 219 goto case_LITERAL; 220 } 221} 222