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