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