size_t input_enqueue(String keys) { char *ptr = keys.data; char *end = ptr + keys.size; while (rbuffer_space(input_buffer) >= 6 && ptr < end) { uint8_t buf[6] = { 0 }; unsigned int new_size = trans_special((const uint8_t **)&ptr, (size_t)(end - ptr), buf, true, true); if (new_size) { new_size = handle_mouse_event(&ptr, buf, new_size); rbuffer_write(input_buffer, (char *)buf, new_size); continue; } if (*ptr == '<') { char *old_ptr = ptr; // Invalid or incomplete key sequence, skip until the next '>' or *end. do { ptr++; } while (ptr < end && *ptr != '>'); if (*ptr != '>') { // Incomplete key sequence, return without consuming. ptr = old_ptr; break; } ptr++; continue; } // copy the character, escaping CSI and K_SPECIAL if ((uint8_t)*ptr == CSI) { rbuffer_write(input_buffer, (char *)&(uint8_t){K_SPECIAL}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KS_EXTRA}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KE_CSI}, 1); } else if ((uint8_t)*ptr == K_SPECIAL) { rbuffer_write(input_buffer, (char *)&(uint8_t){K_SPECIAL}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KS_SPECIAL}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KE_FILLER}, 1); } else { rbuffer_write(input_buffer, ptr, 1); } ptr++; } size_t rv = (size_t)(ptr - keys.data); process_interrupts(); return rv; }
static int replace_termcodes(char **to, char *from) { int len = strlen(from); char buf[len]; int i = 0; while (*from) { buf[i] = trans_special(&from); i++; from++; } *to = malloc((i)*sizeof(char*)); strncpy(*to, buf, i); return i; }
// Replace any terminal code strings in from[] with the equivalent internal // vim representation. This is used for the "from" and "to" part of a // mapping, and the "to" part of a menu command. // Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains // '<'. // K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER. // // The replacement is done in result[] and finally copied into allocated // memory. If this all works well *bufp is set to the allocated memory and a // pointer to it is returned. If something fails *bufp is set to NULL and from // is returned. // // CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V // is included, otherwise it is removed (for ":map xx ^V", maps xx to // nothing). When 'cpoptions' does not contain 'B', a backslash can be used // instead of a CTRL-V. char_u * replace_termcodes ( char_u *from, char_u **bufp, int from_part, int do_lt, // also translate <lt> int special // always accept <key> notation ) { ssize_t i; size_t slen; char_u key; size_t dlen = 0; char_u *src; int do_backslash; // backslash is a special character int do_special; // recognize <> key codes char_u *result; // buffer for resulting string do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL); do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL) || special; // Allocate space for the translation. Worst case a single character is // replaced by 6 bytes (shifted special key), plus a NUL at the end. result = xmalloc(STRLEN(from) * 6 + 1); src = from; // Check for #n at start only: function key n if (from_part && src[0] == '#' && VIM_ISDIGIT(src[1])) { // function key result[dlen++] = K_SPECIAL; result[dlen++] = 'k'; if (src[1] == '0') { result[dlen++] = ';'; // #0 is F10 is "k;" } else { result[dlen++] = src[1]; // #3 is F3 is "k3" } src += 2; } // Copy each byte from *from to result[dlen] while (*src != NUL) { // If 'cpoptions' does not contain '<', check for special key codes, // like "<C-S-LeftMouse>" if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0)) { // Replace <SID> by K_SNR <script-nr> _. // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) if (STRNICMP(src, "<SID>", 5) == 0) { if (current_SID <= 0) { EMSG(_(e_usingsid)); } else { src += 5; result[dlen++] = K_SPECIAL; result[dlen++] = (int)KS_EXTRA; result[dlen++] = (int)KE_SNR; sprintf((char *)result + dlen, "%" PRId64, (int64_t)current_SID); dlen += STRLEN(result + dlen); result[dlen++] = '_'; continue; } } slen = trans_special(&src, result + dlen, TRUE); if (slen) { dlen += slen; continue; } } if (do_special) { char_u *p, *s, len; // Replace <Leader> by the value of "mapleader". // Replace <LocalLeader> by the value of "maplocalleader". // If "mapleader" or "maplocalleader" isn't set use a backslash. if (STRNICMP(src, "<Leader>", 8) == 0) { len = 8; p = get_var_value((char_u *)"g:mapleader"); } else if (STRNICMP(src, "<LocalLeader>", 13) == 0) { len = 13; p = get_var_value((char_u *)"g:maplocalleader"); } else { len = 0; p = NULL; } if (len != 0) { // Allow up to 8 * 6 characters for "mapleader". if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6) { s = (char_u *)"\\"; } else { s = p; } while (*s != NUL) { result[dlen++] = *s++; } src += len; continue; } } // Remove CTRL-V and ignore the next character. // For "from" side the CTRL-V at the end is included, for the "to" // part it is removed. // If 'cpoptions' does not contain 'B', also accept a backslash. key = *src; if (key == Ctrl_V || (do_backslash && key == '\\')) { ++src; // skip CTRL-V or backslash if (*src == NUL) { if (from_part) { result[dlen++] = key; } break; } } // skip multibyte char correctly for (i = (*mb_ptr2len)(src); i > 0; --i) { // If the character is K_SPECIAL, replace it with K_SPECIAL // KS_SPECIAL KE_FILLER. // If compiled with the GUI replace CSI with K_CSI. if (*src == K_SPECIAL) { result[dlen++] = K_SPECIAL; result[dlen++] = KS_SPECIAL; result[dlen++] = KE_FILLER; } else { result[dlen++] = *src; } ++src; } } result[dlen] = NUL; *bufp = xrealloc(result, dlen + 1); return *bufp; }