mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge pull request #4593 from ZyX-I/length-functions
Make some function accept strings with length in place of just strings
This commit is contained in:
		| @@ -116,8 +116,14 @@ String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char *ptr = NULL; |   char *ptr = NULL; | ||||||
|   replace_termcodes((char_u *)str.data, (char_u **)&ptr, |   // Set 'cpoptions' the way we want it. | ||||||
|                                             from_part, do_lt, special); |   //    FLAG_CPO_BSLASH  set - backslashes are *not* treated specially | ||||||
|  |   //    FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered | ||||||
|  |   //    FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted | ||||||
|  |   //  The third from end parameter of replace_termcodes() is true so that the | ||||||
|  |   //  <lt> sequence is recognised - needed for a real backslash. | ||||||
|  |   replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, | ||||||
|  |                     from_part, do_lt, special, CPO_TO_CPO_FLAGS); | ||||||
|   return cstr_as_string(ptr); |   return cstr_as_string(ptr); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1794,10 +1794,11 @@ bool vim_isblankline(char_u *lbuf) | |||||||
| /// @param nptr Returns the signed result. | /// @param nptr Returns the signed result. | ||||||
| /// @param unptr Returns the unsigned result. | /// @param unptr Returns the unsigned result. | ||||||
| /// @param maxlen Max length of string to check. | /// @param maxlen Max length of string to check. | ||||||
| void vim_str2nr(char_u *start, int *prep, int *len, int what, | void vim_str2nr(const char_u *const start, int *const prep, int *const len, | ||||||
|                 long *nptr, unsigned long *unptr, int maxlen) |                 const int what, long *const nptr, unsigned long *const unptr, | ||||||
|  |                 const int maxlen) | ||||||
| { | { | ||||||
|   char_u *ptr = start; |   const char_u *ptr = start; | ||||||
|   int pre = 0;  // default is decimal |   int pre = 0;  // default is decimal | ||||||
|   bool negative = false; |   bool negative = false; | ||||||
|   unsigned long un = 0; |   unsigned long un = 0; | ||||||
|   | |||||||
| @@ -4740,13 +4740,14 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) | |||||||
|         ++name; |         ++name; | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|       /* Special key, e.g.: "\<C-W>" */ |       // Special key, e.g.: "\<C-W>" | ||||||
|       case '<': extra = trans_special(&p, name, TRUE); |       case '<': | ||||||
|  |         extra = trans_special((const char_u **) &p, STRLEN(p), name, true); | ||||||
|         if (extra != 0) { |         if (extra != 0) { | ||||||
|           name += extra; |           name += extra; | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|       /* FALLTHROUGH */ |         // FALLTHROUGH | ||||||
|  |  | ||||||
|       default:  MB_COPY_CHAR(p, name); |       default:  MB_COPY_CHAR(p, name); | ||||||
|         break; |         break; | ||||||
| @@ -10866,21 +10867,22 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv) | |||||||
|  */ |  */ | ||||||
| static void f_histadd(typval_T *argvars, typval_T *rettv) | static void f_histadd(typval_T *argvars, typval_T *rettv) | ||||||
| { | { | ||||||
|   int histype; |   HistoryType histype; | ||||||
|   char_u      *str; |   char_u      *str; | ||||||
|   char_u buf[NUMBUFLEN]; |   char_u buf[NUMBUFLEN]; | ||||||
|  |  | ||||||
|   rettv->vval.v_number = FALSE; |   rettv->vval.v_number = false; | ||||||
|   if (check_restricted() || check_secure()) |   if (check_restricted() || check_secure()) { | ||||||
|     return; |     return; | ||||||
|   str = get_tv_string_chk(&argvars[0]);         /* NULL on type error */ |   } | ||||||
|   histype = str != NULL ? get_histtype(str) : -1; |   str = get_tv_string_chk(&argvars[0]);  // NULL on type error | ||||||
|   if (histype >= 0) { |   histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID; | ||||||
|  |   if (histype != HIST_INVALID) { | ||||||
|     str = get_tv_string_buf(&argvars[1], buf); |     str = get_tv_string_buf(&argvars[1], buf); | ||||||
|     if (*str != NUL) { |     if (*str != NUL) { | ||||||
|       init_history(); |       init_history(); | ||||||
|       add_to_history(histype, str, FALSE, NUL); |       add_to_history(histype, str, false, NUL); | ||||||
|       rettv->vval.v_number = TRUE; |       rettv->vval.v_number = true; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -10895,20 +10897,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) | |||||||
|   char_u buf[NUMBUFLEN]; |   char_u buf[NUMBUFLEN]; | ||||||
|   char_u      *str; |   char_u      *str; | ||||||
|  |  | ||||||
|   str = get_tv_string_chk(&argvars[0]);         /* NULL on type error */ |   str = get_tv_string_chk(&argvars[0]);  // NULL on type error | ||||||
|   if (str == NULL) |   if (str == NULL) { | ||||||
|     n = 0; |     n = 0; | ||||||
|   else if (argvars[1].v_type == VAR_UNKNOWN) |   } else if (argvars[1].v_type == VAR_UNKNOWN) { | ||||||
|     /* only one argument: clear entire history */ |     // only one argument: clear entire history | ||||||
|     n = clr_history(get_histtype(str)); |     n = clr_history(get_histtype(str, STRLEN(str), false)); | ||||||
|   else if (argvars[1].v_type == VAR_NUMBER) |   } else if (argvars[1].v_type == VAR_NUMBER) { | ||||||
|     /* index given: remove that entry */ |     // index given: remove that entry | ||||||
|     n = del_history_idx(get_histtype(str), |     n = del_history_idx(get_histtype(str, STRLEN(str), false), | ||||||
|         (int)get_tv_number(&argvars[1])); |                         (int) get_tv_number(&argvars[1])); | ||||||
|   else |   } else { | ||||||
|     /* string given: remove all matching entries */ |     // string given: remove all matching entries | ||||||
|     n = del_history_entry(get_histtype(str), |     n = del_history_entry(get_histtype(str, STRLEN(str), false), | ||||||
|         get_tv_string_buf(&argvars[1], buf)); |                           get_tv_string_buf(&argvars[1], buf)); | ||||||
|  |   } | ||||||
|   rettv->vval.v_number = n; |   rettv->vval.v_number = n; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -10917,20 +10920,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) | |||||||
|  */ |  */ | ||||||
| static void f_histget(typval_T *argvars, typval_T *rettv) | static void f_histget(typval_T *argvars, typval_T *rettv) | ||||||
| { | { | ||||||
|   int type; |   HistoryType type; | ||||||
|   int idx; |   int idx; | ||||||
|   char_u      *str; |   char_u      *str; | ||||||
|  |  | ||||||
|   str = get_tv_string_chk(&argvars[0]);         /* NULL on type error */ |   str = get_tv_string_chk(&argvars[0]);  // NULL on type error | ||||||
|   if (str == NULL) |   if (str == NULL) { | ||||||
|     rettv->vval.v_string = NULL; |     rettv->vval.v_string = NULL; | ||||||
|   else { |   } else { | ||||||
|     type = get_histtype(str); |     type = get_histtype(str, STRLEN(str), false); | ||||||
|     if (argvars[1].v_type == VAR_UNKNOWN) |     if (argvars[1].v_type == VAR_UNKNOWN) { | ||||||
|       idx = get_history_idx(type); |       idx = get_history_idx(type); | ||||||
|     else |     } else { | ||||||
|       idx = (int)get_tv_number_chk(&argvars[1], NULL); |       idx = (int)get_tv_number_chk(&argvars[1], NULL); | ||||||
|     /* -1 on type error */ |     } | ||||||
|  |     // -1 on type error | ||||||
|     rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); |     rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); | ||||||
|   } |   } | ||||||
|   rettv->v_type = VAR_STRING; |   rettv->v_type = VAR_STRING; | ||||||
| @@ -10945,11 +10949,13 @@ static void f_histnr(typval_T *argvars, typval_T *rettv) | |||||||
|  |  | ||||||
|   char_u      *history = get_tv_string_chk(&argvars[0]); |   char_u      *history = get_tv_string_chk(&argvars[0]); | ||||||
|  |  | ||||||
|   i = history == NULL ? HIST_CMD - 1 : get_histtype(history); |   i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history), | ||||||
|   if (i >= HIST_CMD && i < HIST_COUNT) |                                                     false); | ||||||
|  |   if (i != HIST_INVALID) { | ||||||
|     i = get_history_idx(i); |     i = get_history_idx(i); | ||||||
|   else |   } else { | ||||||
|     i = -1; |     i = -1; | ||||||
|  |   } | ||||||
|   rettv->vval.v_number = i; |   rettv->vval.v_number = i; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -12086,8 +12092,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) | |||||||
|  |  | ||||||
|   mode = get_map_mode(&which, 0); |   mode = get_map_mode(&which, 0); | ||||||
|  |  | ||||||
|   keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); |   keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false, | ||||||
|   rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local); |                            CPO_TO_CPO_FLAGS); | ||||||
|  |   rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local); | ||||||
|   xfree(keys_buf); |   xfree(keys_buf); | ||||||
|  |  | ||||||
|   if (!get_dict) { |   if (!get_dict) { | ||||||
|   | |||||||
| @@ -4556,7 +4556,8 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep, | |||||||
|   char_u      *rep_buf = NULL; |   char_u      *rep_buf = NULL; | ||||||
|   garray_T    *gap; |   garray_T    *gap; | ||||||
|  |  | ||||||
|   replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE); |   replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, false, | ||||||
|  |                     CPO_TO_CPO_FLAGS); | ||||||
|   if (rep_buf == NULL) { |   if (rep_buf == NULL) { | ||||||
|     /* Can't replace termcodes - try using the string as is */ |     /* Can't replace termcodes - try using the string as is */ | ||||||
|     rep_buf = vim_strsave(rep); |     rep_buf = vim_strsave(rep); | ||||||
|   | |||||||
| @@ -4272,20 +4272,33 @@ void globpath(char_u *path, char_u *file, garray_T *ga, int expand_options) | |||||||
| *  Command line history stuff	 * | *  Command line history stuff	 * | ||||||
| *********************************/ | *********************************/ | ||||||
|  |  | ||||||
| /* | /// Translate a history character to the associated type number | ||||||
|  * Translate a history character to the associated type number. | static HistoryType hist_char2type(const int c) | ||||||
|  */ |   FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT | ||||||
| static int hist_char2type(int c) |  | ||||||
| { | { | ||||||
|   if (c == ':') |   switch (c) { | ||||||
|     return HIST_CMD; |     case ':': { | ||||||
|   if (c == '=') |       return HIST_CMD; | ||||||
|     return HIST_EXPR; |     } | ||||||
|   if (c == '@') |     case '=': { | ||||||
|     return HIST_INPUT; |       return HIST_EXPR; | ||||||
|   if (c == '>') |     } | ||||||
|     return HIST_DEBUG; |     case '@': { | ||||||
|   return HIST_SEARCH;       /* must be '?' or '/' */ |       return HIST_INPUT; | ||||||
|  |     } | ||||||
|  |     case '>': { | ||||||
|  |       return HIST_DEBUG; | ||||||
|  |     } | ||||||
|  |     case '/': | ||||||
|  |     case '?': { | ||||||
|  |       return HIST_SEARCH; | ||||||
|  |     } | ||||||
|  |     default: { | ||||||
|  |       assert(false); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   // Silence -Wreturn-type | ||||||
|  |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -4454,28 +4467,38 @@ in_history ( | |||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /// Convert history name to its HIST_ equivalent | ||||||
|  * Convert history name (from table above) to its HIST_ equivalent. | /// | ||||||
|  * When "name" is empty, return "cmd" history. | /// Names are taken from the table above. When `name` is empty returns currently | ||||||
|  * Returns -1 for unknown history name. | /// active history or HIST_DEFAULT, depending on `return_default` argument. | ||||||
|  */ | /// | ||||||
| int get_histtype(char_u *name) | /// @param[in]  name            Converted name. | ||||||
|  | /// @param[in]  len             Name length. | ||||||
|  | /// @param[in]  return_default  Determines whether HIST_DEFAULT should be | ||||||
|  | ///                             returned or value based on `ccline.cmdfirstc`. | ||||||
|  | /// | ||||||
|  | /// @return Any value from HistoryType enum, including HIST_INVALID. May not | ||||||
|  | ///         return HIST_DEFAULT unless return_default is true. | ||||||
|  | HistoryType get_histtype(const char_u *const name, const size_t len, | ||||||
|  |                          const bool return_default) | ||||||
|  |   FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT | ||||||
| { | { | ||||||
|   int i; |   // No argument: use current history. | ||||||
|   int len = (int)STRLEN(name); |   if (len == 0) { | ||||||
|  |     return return_default ? HIST_DEFAULT :hist_char2type(ccline.cmdfirstc); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* No argument: use current history. */ |   for (HistoryType i = 0; history_names[i] != NULL; i++) { | ||||||
|   if (len == 0) |     if (STRNICMP(name, history_names[i], len) == 0) { | ||||||
|     return hist_char2type(ccline.cmdfirstc); |  | ||||||
|  |  | ||||||
|   for (i = 0; history_names[i] != NULL; ++i) |  | ||||||
|     if (STRNICMP(name, history_names[i], len) == 0) |  | ||||||
|       return i; |       return i; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   if (vim_strchr((char_u *)":=@>?/", name[0]) != NULL && name[1] == NUL) |   if (vim_strchr((char_u *)":=@>?/", name[0]) != NULL && len == 1) { | ||||||
|     return hist_char2type(name[0]); |     return hist_char2type(name[0]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   return -1; |   return HIST_INVALID; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int last_maptick = -1;           /* last seen maptick */ | static int last_maptick = -1;           /* last seen maptick */ | ||||||
| @@ -4847,23 +4870,20 @@ void ex_history(exarg_T *eap) | |||||||
|     while (ASCII_ISALPHA(*end) |     while (ASCII_ISALPHA(*end) | ||||||
|            || vim_strchr((char_u *)":=@>/?", *end) != NULL) |            || vim_strchr((char_u *)":=@>/?", *end) != NULL) | ||||||
|       end++; |       end++; | ||||||
|     i = *end; |     histype1 = get_histtype(arg, end - arg, false); | ||||||
|     *end = NUL; |     if (histype1 == HIST_INVALID) { | ||||||
|     histype1 = get_histtype(arg); |       if (STRNICMP(arg, "all", end - arg) == 0) { | ||||||
|     if (histype1 == -1) { |  | ||||||
|       if (STRNICMP(arg, "all", STRLEN(arg)) == 0) { |  | ||||||
|         histype1 = 0; |         histype1 = 0; | ||||||
|         histype2 = HIST_COUNT-1; |         histype2 = HIST_COUNT-1; | ||||||
|       } else { |       } else { | ||||||
|         *end = i; |  | ||||||
|         EMSG(_(e_trailing)); |         EMSG(_(e_trailing)); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|     } else |     } else | ||||||
|       histype2 = histype1; |       histype2 = histype1; | ||||||
|     *end = i; |   } else { | ||||||
|   } else |  | ||||||
|     end = arg; |     end = arg; | ||||||
|  |   } | ||||||
|   if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) { |   if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) { | ||||||
|     EMSG(_(e_trailing)); |     EMSG(_(e_trailing)); | ||||||
|     return; |     return; | ||||||
|   | |||||||
| @@ -27,11 +27,13 @@ | |||||||
|  |  | ||||||
| /// Present history tables | /// Present history tables | ||||||
| typedef enum { | typedef enum { | ||||||
|   HIST_CMD,     ///< Colon commands. |   HIST_DEFAULT = -2,  ///< Default (current) history. | ||||||
|   HIST_SEARCH,  ///< Search commands. |   HIST_INVALID = -1,  ///< Unknown history. | ||||||
|   HIST_EXPR,    ///< Expressions (e.g. from entering = register). |   HIST_CMD = 0,       ///< Colon commands. | ||||||
|   HIST_INPUT,   ///< input() lines. |   HIST_SEARCH,        ///< Search commands. | ||||||
|   HIST_DEBUG,   ///< Debug commands. |   HIST_EXPR,          ///< Expressions (e.g. from entering = register). | ||||||
|  |   HIST_INPUT,         ///< input() lines. | ||||||
|  |   HIST_DEBUG,         ///< Debug commands. | ||||||
| } HistoryType; | } HistoryType; | ||||||
|  |  | ||||||
| /// Number of history tables | /// Number of history tables | ||||||
|   | |||||||
| @@ -2688,22 +2688,24 @@ do_map ( | |||||||
|     goto theend; |     goto theend; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* |   // If mapping has been given as ^V<C_UP> say, then replace the term codes | ||||||
|    * If mapping has been given as ^V<C_UP> say, then replace the term codes |   // with the appropriate two bytes. If it is a shifted special key, unshift | ||||||
|    * with the appropriate two bytes. If it is a shifted special key, unshift |   // it too, giving another two bytes. | ||||||
|    * it too, giving another two bytes. |   // replace_termcodes() may move the result to allocated memory, which | ||||||
|    * replace_termcodes() may move the result to allocated memory, which |   // needs to be freed later (*keys_buf and *arg_buf). | ||||||
|    * needs to be freed later (*keys_buf and *arg_buf). |   // replace_termcodes() also removes CTRL-Vs and sometimes backslashes. | ||||||
|    * replace_termcodes() also removes CTRL-Vs and sometimes backslashes. |   if (haskey) { | ||||||
|    */ |     keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, special, | ||||||
|   if (haskey) |                              CPO_TO_CPO_FLAGS); | ||||||
|     keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special); |   } | ||||||
|   orig_rhs = rhs; |   orig_rhs = rhs; | ||||||
|   if (hasarg) { |   if (hasarg) { | ||||||
|     if (STRICMP(rhs, "<nop>") == 0)         /* "<Nop>" means nothing */ |     if (STRICMP(rhs, "<nop>") == 0) {  // "<Nop>" means nothing | ||||||
|       rhs = (char_u *)""; |       rhs = (char_u *)""; | ||||||
|     else |     } else { | ||||||
|       rhs = replace_termcodes(rhs, &arg_buf, FALSE, TRUE, special); |       rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, special, | ||||||
|  |                               CPO_TO_CPO_FLAGS); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
| @@ -3270,7 +3272,8 @@ int map_to_exists(char_u *str, char_u *modechars, int abbr) | |||||||
|   char_u      *buf; |   char_u      *buf; | ||||||
|   int retval; |   int retval; | ||||||
|  |  | ||||||
|   rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE); |   rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false, | ||||||
|  |                           CPO_TO_CPO_FLAGS); | ||||||
|  |  | ||||||
|   if (vim_strchr(modechars, 'n') != NULL) |   if (vim_strchr(modechars, 'n') != NULL) | ||||||
|     mode |= NORMAL; |     mode |= NORMAL; | ||||||
| @@ -3465,7 +3468,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file) | |||||||
|         mp = maphash[hash]; |         mp = maphash[hash]; | ||||||
|       for (; mp; mp = mp->m_next) { |       for (; mp; mp = mp->m_next) { | ||||||
|         if (mp->m_mode & expand_mapmodes) { |         if (mp->m_mode & expand_mapmodes) { | ||||||
|           p = translate_mapping(mp->m_keys, TRUE); |           p = translate_mapping(mp->m_keys, true, CPO_TO_CPO_FLAGS); | ||||||
|           if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) { |           if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) { | ||||||
|             if (round == 1) |             if (round == 1) | ||||||
|               ++count; |               ++count; | ||||||
| @@ -4190,14 +4193,15 @@ void add_map(char_u *map, int mode) | |||||||
| // Returns NULL when there is a problem. | // Returns NULL when there is a problem. | ||||||
| static char_u * translate_mapping ( | static char_u * translate_mapping ( | ||||||
|     char_u *str, |     char_u *str, | ||||||
|     int expmap  // TRUE when expanding mappings on command-line |     int expmap,   // True when expanding mappings on command-line | ||||||
|  |     int cpo_flags  // Value of various flags present in &cpo | ||||||
| ) | ) | ||||||
| { | { | ||||||
|   garray_T ga; |   garray_T ga; | ||||||
|   ga_init(&ga, 1, 40); |   ga_init(&ga, 1, 40); | ||||||
|  |  | ||||||
|   int cpo_bslash = (vim_strchr(p_cpo, CPO_BSLASH) != NULL); |   bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH); | ||||||
|   int cpo_special = (vim_strchr(p_cpo, CPO_SPECI) != NULL); |   bool cpo_special = !(cpo_flags&FLAG_CPO_SPECI); | ||||||
|  |  | ||||||
|   for (; *str; ++str) { |   for (; *str; ++str) { | ||||||
|     int c = *str; |     int c = *str; | ||||||
|   | |||||||
| @@ -482,26 +482,28 @@ char_u *get_special_key_name(int c, int modifiers) | |||||||
|   return string; |   return string; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /// Try translating a <> name | ||||||
|  * Try translating a <> name at (*srcp)[] to dst[]. | /// | ||||||
|  * Return the number of characters added to dst[], zero for no match. | /// @param[in,out]  srcp  Source from which <> are translated. Is advanced to | ||||||
|  * If there is a match, srcp is advanced to after the <> name. | ///                       after the <> name if there is a match. | ||||||
|  * dst[] must be big enough to hold the result (up to six characters)! | /// @param[in]  src_len  Length of the srcp. | ||||||
|  */ | /// @param[out]  dst  Location where translation result will be kept. Must have | ||||||
| unsigned int  | ///                   at least six bytes. | ||||||
| trans_special ( | /// @param[in]  keycode  Prefer key code, e.g. K_DEL in place of DEL. | ||||||
|     char_u **srcp, | /// | ||||||
|     char_u *dst, | /// @return Number of characters added to dst, zero for no match. | ||||||
|     int keycode             /* prefer key code, e.g. K_DEL instead of DEL */ | unsigned int trans_special(const char_u **srcp, const size_t src_len, | ||||||
| ) |                            char_u *const dst, const bool keycode) | ||||||
|  |   FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT | ||||||
| { | { | ||||||
|   int modifiers = 0; |   int modifiers = 0; | ||||||
|   int key; |   int key; | ||||||
|   unsigned int dlen = 0; |   unsigned int dlen = 0; | ||||||
|  |  | ||||||
|   key = find_special_key(srcp, &modifiers, keycode, FALSE); |   key = find_special_key(srcp, src_len, &modifiers, keycode, false); | ||||||
|   if (key == 0) |   if (key == 0) { | ||||||
|     return 0; |     return 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* Put the appropriate modifier in a string */ |   /* Put the appropriate modifier in a string */ | ||||||
|   if (modifiers != 0) { |   if (modifiers != 0) { | ||||||
| @@ -514,69 +516,78 @@ trans_special ( | |||||||
|     dst[dlen++] = K_SPECIAL; |     dst[dlen++] = K_SPECIAL; | ||||||
|     dst[dlen++] = (char_u)KEY2TERMCAP0(key); |     dst[dlen++] = (char_u)KEY2TERMCAP0(key); | ||||||
|     dst[dlen++] = KEY2TERMCAP1(key); |     dst[dlen++] = KEY2TERMCAP1(key); | ||||||
|   } else if (has_mbyte && !keycode) |   } else if (has_mbyte && !keycode) { | ||||||
|     dlen += (unsigned int)(*mb_char2bytes)(key, dst + dlen); |     dlen += (unsigned int)(*mb_char2bytes)(key, dst + dlen); | ||||||
|   else if (keycode) { |   } else if (keycode) { | ||||||
|     char_u *after = add_char2buf(key, dst + dlen); |     char_u *after = add_char2buf(key, dst + dlen); | ||||||
|     assert(after >= dst && (uintmax_t)(after - dst) <= UINT_MAX); |     assert(after >= dst && (uintmax_t)(after - dst) <= UINT_MAX); | ||||||
|     dlen = (unsigned int)(after - dst); |     dlen = (unsigned int)(after - dst); | ||||||
|   } |   } else { | ||||||
|   else |  | ||||||
|     dst[dlen++] = (char_u)key; |     dst[dlen++] = (char_u)key; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   return dlen; |   return dlen; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Try translating a <> name at (*srcp)[], return the key and modifiers. | /// Try translating a <> name | ||||||
| // srcp is advanced to after the <> name. | /// | ||||||
| // returns 0 if there is no match. | /// @param[in,out]  srcp  Translated <> name. Is advanced to after the <> name. | ||||||
| int find_special_key( | /// @param[in]  src_len  srcp length. | ||||||
|     char_u **srcp, | /// @param[out]  modp  Location where information about modifiers is saved. | ||||||
|     int *modp, | /// @param[in]  keycode  Prefer key code, e.g. K_DEL in place of DEL. | ||||||
|     int keycode,                // prefer key code, e.g. K_DEL instead of DEL | /// @param[in]  keep_x_key  Don’t translate xHome to Home key. | ||||||
|     int keep_x_key              // don't translate xHome to Home key | /// | ||||||
| ) | /// @return Key and modifiers or 0 if there is no match. | ||||||
|  | int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, | ||||||
|  |                      const bool keycode, const bool keep_x_key) | ||||||
|  |   FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
|   char_u      *last_dash; |   const char_u *last_dash; | ||||||
|   char_u      *end_of_name; |   const char_u *end_of_name; | ||||||
|   char_u      *src; |   const char_u *src; | ||||||
|   char_u      *bp; |   const char_u *bp; | ||||||
|  |   const char_u *const end = *srcp + src_len - 1; | ||||||
|   int modifiers; |   int modifiers; | ||||||
|   int bit; |   int bit; | ||||||
|   int key; |   int key; | ||||||
|   unsigned long n; |   unsigned long n; | ||||||
|   int l; |   int l; | ||||||
|  |  | ||||||
|   src = *srcp; |   if (src_len == 0) { | ||||||
|   if (src[0] != '<') |  | ||||||
|     return 0; |     return 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   src = *srcp; | ||||||
|  |   if (src[0] != '<') { | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Find end of modifier list |   // Find end of modifier list | ||||||
|   last_dash = src; |   last_dash = src; | ||||||
|   for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++) { |   for (bp = src + 1; bp <= end && (*bp == '-' || vim_isIDc(*bp)); bp++) { | ||||||
|     if (*bp == '-') { |     if (*bp == '-') { | ||||||
|       last_dash = bp; |       last_dash = bp; | ||||||
|       if (bp[1] != NUL) { |       if (bp + 1 <= end) { | ||||||
|         if (has_mbyte) { |         if (has_mbyte) { | ||||||
|           l = mb_ptr2len(bp + 1); |           l = mb_ptr2len_len(bp + 1, (int) (end - bp) + 1); | ||||||
|         } else { |         } else { | ||||||
|           l = 1; |           l = 1; | ||||||
|         } |         } | ||||||
|         if (bp[l + 1] == '>') { |         if (end - bp > l && bp[l + 1] == '>') { | ||||||
|           bp += l;              // anything accepted, like <C-?> |           bp += l;  // anything accepted, like <C-?> | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) { |     if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { | ||||||
|       bp += 3;          // skip t_xx, xx may be '-' or '>' |       bp += 3;  // skip t_xx, xx may be '-' or '>' | ||||||
|     } else if (STRNICMP(bp, "char-", 5) == 0) { |     } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { | ||||||
|       vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0); |       vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0); | ||||||
|       bp += l + 5; |       bp += l + 5; | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (*bp == '>') {     /* found matching '>' */ |   if (bp <= end && *bp == '>') {  // found matching '>' | ||||||
|     end_of_name = bp + 1; |     end_of_name = bp + 1; | ||||||
|  |  | ||||||
|     /* Which modifiers are given? */ |     /* Which modifiers are given? */ | ||||||
| @@ -696,7 +707,7 @@ int find_special_key_in_table(int c) | |||||||
|  * termcap name. |  * termcap name. | ||||||
|  * Return the key code, or 0 if not found. |  * Return the key code, or 0 if not found. | ||||||
|  */ |  */ | ||||||
| int get_special_key_code(char_u *name) | int get_special_key_code(const char_u *name) | ||||||
| { | { | ||||||
|   char_u  *table_name; |   char_u  *table_name; | ||||||
|   int i, j; |   int i, j; | ||||||
| @@ -730,50 +741,58 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) | |||||||
|   return 0;         /* Shouldn't get here */ |   return 0;         /* Shouldn't get here */ | ||||||
| } | } | ||||||
|  |  | ||||||
| // Replace any terminal code strings in from[] with the equivalent internal | /// Replace any terminal code strings with the equivalent internal | ||||||
| // vim representation.	This is used for the "from" and "to" part of a | /// representation | ||||||
| // mapping, and the "to" part of a menu command. | /// | ||||||
| // Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains | /// 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 | ||||||
| // K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER. | /// '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 | /// @param[in]  from  What characters to replace. | ||||||
| // pointer to it is returned. If something fails *bufp is set to NULL and from | /// @param[in]  from_len  Length of the "from" argument. | ||||||
| // is returned. | /// @param[out]  bufp  Location where results were saved in case of success | ||||||
| // | ///                    (allocated). Will be set to NULL in case of failure. | ||||||
| // CTRL-V characters are removed.  When "from_part" is TRUE, a trailing CTRL-V | /// @param[in]  do_lt  If true, also translate <lt>. | ||||||
| // is included, otherwise it is removed (for ":map xx ^V", maps xx to | /// @param[in]  from_part  If true, trailing <C-v> is included, otherwise it is | ||||||
| // nothing).  When 'cpoptions' does not contain 'B', a backslash can be used | ///                        removed (to make ":map xx ^V" map xx to nothing). | ||||||
| // instead of a CTRL-V. | ///                        When cpo_flags contains #FLAG_CPO_BSLASH, a backslash | ||||||
| char_u * replace_termcodes ( | ///                        can be used in place of <C-v>. All other <C-v> | ||||||
|     char_u *from, | ///                        characters are removed. | ||||||
|     char_u **bufp, | /// @param[in]  special  If true, always accept <key> notation. | ||||||
|     int from_part, | /// @param[in]  cpo_flags  Relevant flags derived from p_cpo, see | ||||||
|     int do_lt,                     // also translate <lt> | ///                        #CPO_TO_CPO_FLAGS. | ||||||
|     int special                    // always accept <key> notation | /// | ||||||
| ) | /// @return Pointer to an allocated memory in case of success, "from" in case of | ||||||
|  | ///         failure. In case of success returned pointer is also saved to | ||||||
|  | ///         "bufp". | ||||||
|  | char_u *replace_termcodes(const char_u *from, const size_t from_len, | ||||||
|  |                           char_u **bufp, const bool from_part, const bool do_lt, | ||||||
|  |                           const bool special, int cpo_flags) | ||||||
|  |   FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
|   ssize_t i; |   ssize_t i; | ||||||
|   size_t slen; |   size_t slen; | ||||||
|   char_u key; |   char_u key; | ||||||
|   size_t dlen = 0; |   size_t dlen = 0; | ||||||
|   char_u      *src; |   const char_u *src; | ||||||
|  |   const char_u *const end = from + from_len - 1; | ||||||
|   int do_backslash;             // backslash is a special character |   int do_backslash;             // backslash is a special character | ||||||
|   int do_special;               // recognize <> key codes |   int do_special;               // recognize <> key codes | ||||||
|   char_u      *result;          // buffer for resulting string |   char_u      *result;          // buffer for resulting string | ||||||
|  |  | ||||||
|   do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL); |   do_backslash = !(cpo_flags&FLAG_CPO_BSLASH); | ||||||
|   do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL) || special; |   do_special = !(cpo_flags&FLAG_CPO_SPECI) || special; | ||||||
|  |  | ||||||
|   // Allocate space for the translation.  Worst case a single character is |   // Allocate space for the translation.  Worst case a single character is | ||||||
|   // replaced by 6 bytes (shifted special key), plus a NUL at the end. |   // replaced by 6 bytes (shifted special key), plus a NUL at the end. | ||||||
|   result = xmalloc(STRLEN(from) * 6 + 1); |   result = xmalloc(from_len * 6 + 1); | ||||||
|  |  | ||||||
|   src = from; |   src = from; | ||||||
|  |  | ||||||
|   // Check for #n at start only: function key n |   // Check for #n at start only: function key n | ||||||
|   if (from_part && src[0] == '#' && ascii_isdigit(src[1])) {  // function key |   if (from_part && from_len > 1 && src[0] == '#' | ||||||
|  |       && ascii_isdigit(src[1])) {  // function key | ||||||
|     result[dlen++] = K_SPECIAL; |     result[dlen++] = K_SPECIAL; | ||||||
|     result[dlen++] = 'k'; |     result[dlen++] = 'k'; | ||||||
|     if (src[1] == '0') { |     if (src[1] == '0') { | ||||||
| @@ -785,13 +804,14 @@ char_u * replace_termcodes ( | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Copy each byte from *from to result[dlen] |   // Copy each byte from *from to result[dlen] | ||||||
|   while (*src != NUL) { |   while (src <= end) { | ||||||
|     // If 'cpoptions' does not contain '<', check for special key codes, |     // If 'cpoptions' does not contain '<', check for special key codes, | ||||||
|     // like "<C-S-LeftMouse>" |     // like "<C-S-LeftMouse>" | ||||||
|     if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0)) { |     if (do_special && (do_lt || ((end - src) >= 3 | ||||||
|  |                                  && STRNCMP(src, "<lt>", 4) != 0))) { | ||||||
|       // Replace <SID> by K_SNR <script-nr> _. |       // Replace <SID> by K_SNR <script-nr> _. | ||||||
|       // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) |       // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) | ||||||
|       if (STRNICMP(src, "<SID>", 5) == 0) { |       if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) { | ||||||
|         if (current_SID <= 0) { |         if (current_SID <= 0) { | ||||||
|           EMSG(_(e_usingsid)); |           EMSG(_(e_usingsid)); | ||||||
|         } else { |         } else { | ||||||
| @@ -806,7 +826,7 @@ char_u * replace_termcodes ( | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       slen = trans_special(&src, result + dlen, TRUE); |       slen = trans_special(&src, (size_t) (end - src) + 1, result + dlen, true); | ||||||
|       if (slen) { |       if (slen) { | ||||||
|         dlen += slen; |         dlen += slen; | ||||||
|         continue; |         continue; | ||||||
| @@ -819,10 +839,10 @@ char_u * replace_termcodes ( | |||||||
|       // Replace <Leader> by the value of "mapleader". |       // Replace <Leader> by the value of "mapleader". | ||||||
|       // Replace <LocalLeader> by the value of "maplocalleader". |       // Replace <LocalLeader> by the value of "maplocalleader". | ||||||
|       // If "mapleader" or "maplocalleader" isn't set use a backslash. |       // If "mapleader" or "maplocalleader" isn't set use a backslash. | ||||||
|       if (STRNICMP(src, "<Leader>", 8) == 0) { |       if (end - src >= 7 && STRNICMP(src, "<Leader>", 8) == 0) { | ||||||
|         len = 8; |         len = 8; | ||||||
|         p = get_var_value((char_u *)"g:mapleader"); |         p = get_var_value((char_u *)"g:mapleader"); | ||||||
|       } else if (STRNICMP(src, "<LocalLeader>", 13) == 0)   { |       } else if (end - src >= 12 && STRNICMP(src, "<LocalLeader>", 13) == 0) { | ||||||
|         len = 13; |         len = 13; | ||||||
|         p = get_var_value((char_u *)"g:maplocalleader"); |         p = get_var_value((char_u *)"g:maplocalleader"); | ||||||
|       } else { |       } else { | ||||||
| @@ -851,8 +871,8 @@ char_u * replace_termcodes ( | |||||||
|     // If 'cpoptions' does not contain 'B', also accept a backslash. |     // If 'cpoptions' does not contain 'B', also accept a backslash. | ||||||
|     key = *src; |     key = *src; | ||||||
|     if (key == Ctrl_V || (do_backslash && key == '\\')) { |     if (key == Ctrl_V || (do_backslash && key == '\\')) { | ||||||
|       ++src;  // skip CTRL-V or backslash |       src++;  // skip CTRL-V or backslash | ||||||
|       if (*src == NUL) { |       if (src > end) { | ||||||
|         if (from_part) { |         if (from_part) { | ||||||
|           result[dlen++] = key; |           result[dlen++] = key; | ||||||
|         } |         } | ||||||
| @@ -861,7 +881,7 @@ char_u * replace_termcodes ( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // skip multibyte char correctly |     // skip multibyte char correctly | ||||||
|     for (i = (*mb_ptr2len)(src); i > 0; --i) { |     for (i = (*mb_ptr2len_len)(src, (int) (end - src) + 1); i > 0; i--) { | ||||||
|       // If the character is K_SPECIAL, replace it with K_SPECIAL |       // If the character is K_SPECIAL, replace it with K_SPECIAL | ||||||
|       // KS_SPECIAL KE_FILLER. |       // KS_SPECIAL KE_FILLER. | ||||||
|       // If compiled with the GUI replace CSI with K_CSI. |       // If compiled with the GUI replace CSI with K_CSI. | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| #ifndef NVIM_KEYMAP_H | #ifndef NVIM_KEYMAP_H | ||||||
| #define NVIM_KEYMAP_H | #define NVIM_KEYMAP_H | ||||||
|  |  | ||||||
|  | #include "nvim/strings.h" | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Keycode definitions for special keys. |  * Keycode definitions for special keys. | ||||||
|  * |  * | ||||||
| @@ -461,6 +463,14 @@ enum key_extra { | |||||||
| // This is a total of 6 tokens, and is currently the longest one possible. | // This is a total of 6 tokens, and is currently the longest one possible. | ||||||
| #define MAX_KEY_CODE_LEN    6 | #define MAX_KEY_CODE_LEN    6 | ||||||
|  |  | ||||||
|  | #define FLAG_CPO_BSLASH    0x01 | ||||||
|  | #define FLAG_CPO_SPECI     0x02 | ||||||
|  | #define CPO_TO_CPO_FLAGS   (((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ | ||||||
|  |                              ? 0 \ | ||||||
|  |                              : FLAG_CPO_BSLASH)| \ | ||||||
|  |                             (vim_strchr(p_cpo, CPO_SPECI) == NULL \ | ||||||
|  |                              ? 0 \ | ||||||
|  |                              : FLAG_CPO_SPECI)) | ||||||
|  |  | ||||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||||
| # include "keymap.h.generated.h" | # include "keymap.h.generated.h" | ||||||
|   | |||||||
| @@ -215,10 +215,12 @@ ex_menu ( | |||||||
|     if (STRICMP(map_to, "<nop>") == 0) {        /* "<Nop>" means nothing */ |     if (STRICMP(map_to, "<nop>") == 0) {        /* "<Nop>" means nothing */ | ||||||
|       map_to = (char_u *)""; |       map_to = (char_u *)""; | ||||||
|       map_buf = NULL; |       map_buf = NULL; | ||||||
|     } else if (modes & MENU_TIP_MODE) |     } else if (modes & MENU_TIP_MODE) { | ||||||
|       map_buf = NULL;           /* Menu tips are plain text. */ |       map_buf = NULL;  // Menu tips are plain text. | ||||||
|     else |     } else { | ||||||
|       map_to = replace_termcodes(map_to, &map_buf, FALSE, TRUE, special); |       map_to = replace_termcodes(map_to, STRLEN(map_to), &map_buf, false, true, | ||||||
|  |                                  special, CPO_TO_CPO_FLAGS); | ||||||
|  |     } | ||||||
|     menuarg.modes = modes; |     menuarg.modes = modes; | ||||||
|     menuarg.noremap[0] = noremap; |     menuarg.noremap[0] = noremap; | ||||||
|     menuarg.silent[0] = silent; |     menuarg.silent[0] = silent; | ||||||
|   | |||||||
| @@ -1177,28 +1177,27 @@ do_set ( | |||||||
|           errmsg = e_invarg; |           errmsg = e_invarg; | ||||||
|           goto skip; |           goto skip; | ||||||
|         } |         } | ||||||
|         arg[len] = NUL;                             /* put NUL after name */ |         if (arg[1] == 't' && arg[2] == '_') {  // could be term code | ||||||
|         if (arg[1] == 't' && arg[2] == '_')         /* could be term code */ |           opt_idx = findoption_len(arg + 1, (size_t) (len - 1)); | ||||||
|           opt_idx = findoption(arg + 1); |         } | ||||||
|         arg[len++] = '>';                           /* restore '>' */ |         len++; | ||||||
|         if (opt_idx == -1) |         if (opt_idx == -1) { | ||||||
|           key = find_key_option(arg + 1); |           key = find_key_option(arg + 1); | ||||||
|  |         } | ||||||
|       } else { |       } else { | ||||||
|         len = 0; |         len = 0; | ||||||
|         /* |         // The two characters after "t_" may not be alphanumeric. | ||||||
|          * The two characters after "t_" may not be alphanumeric. |         if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { | ||||||
|          */ |  | ||||||
|         if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) |  | ||||||
|           len = 4; |           len = 4; | ||||||
|         else |         } else { | ||||||
|           while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') |           while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { | ||||||
|             ++len; |             len++; | ||||||
|         nextchar = arg[len]; |           } | ||||||
|         arg[len] = NUL;                             /* put NUL after name */ |         } | ||||||
|         opt_idx = findoption(arg); |         opt_idx = findoption_len(arg, (size_t) len); | ||||||
|         arg[len] = nextchar;                        /* restore nextchar */ |         if (opt_idx == -1) { | ||||||
|         if (opt_idx == -1) |  | ||||||
|           key = find_key_option(arg); |           key = find_key_option(arg); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       /* remember character after option name */ |       /* remember character after option name */ | ||||||
| @@ -2965,7 +2964,8 @@ did_set_string_option ( | |||||||
|   /* 'pastetoggle': translate key codes like in a mapping */ |   /* 'pastetoggle': translate key codes like in a mapping */ | ||||||
|   else if (varp == &p_pt) { |   else if (varp == &p_pt) { | ||||||
|     if (*p_pt) { |     if (*p_pt) { | ||||||
|       (void)replace_termcodes(p_pt, &p, TRUE, TRUE, FALSE); |       (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, false, | ||||||
|  |                               CPO_TO_CPO_FLAGS); | ||||||
|       if (p != NULL) { |       if (p != NULL) { | ||||||
|         if (new_value_alloced) |         if (new_value_alloced) | ||||||
|           free_string_option(p_pt); |           free_string_option(p_pt); | ||||||
| @@ -4303,14 +4303,16 @@ static void check_redraw(uint32_t flags) | |||||||
|     redraw_all_later(NOT_VALID); |     redraw_all_later(NOT_VALID); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /// Find index for named option | ||||||
|  * Find index for option 'arg'. | /// | ||||||
|  * Return -1 if not found. | /// @param[in]  arg  Option to find index for. | ||||||
|  */ | /// @param[in]  len  Length of the option. | ||||||
| static int findoption(char_u *arg) | /// | ||||||
|  | /// @return Index of the option or -1 if option was not found. | ||||||
|  | int findoption_len(const char_u *const arg, const size_t len) | ||||||
| { | { | ||||||
|   char            *s, *p; |   char *s, *p; | ||||||
|   static short quick_tab[27] = {0, 0};          /* quick access table */ |   static int quick_tab[27] = { 0, 0 };  // quick access table | ||||||
|   int is_term_opt; |   int is_term_opt; | ||||||
|  |  | ||||||
|   /* |   /* | ||||||
| @@ -4334,25 +4336,31 @@ static int findoption(char_u *arg) | |||||||
|   /* |   /* | ||||||
|    * Check for name starting with an illegal character. |    * Check for name starting with an illegal character. | ||||||
|    */ |    */ | ||||||
|   if (arg[0] < 'a' || arg[0] > 'z') |   if (len == 0 || arg[0] < 'a' || arg[0] > 'z') { | ||||||
|     return -1; |     return -1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   int opt_idx; |   int opt_idx; | ||||||
|   is_term_opt = (arg[0] == 't' && arg[1] == '_'); |   is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_'); | ||||||
|   if (is_term_opt) |   if (is_term_opt) { | ||||||
|     opt_idx = quick_tab[26]; |     opt_idx = quick_tab[26]; | ||||||
|   else |   } else { | ||||||
|     opt_idx = quick_tab[CharOrdLow(arg[0])]; |     opt_idx = quick_tab[CharOrdLow(arg[0])]; | ||||||
|  |   } | ||||||
|  |   // Match full name | ||||||
|   for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) { |   for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) { | ||||||
|     if (STRCMP(arg, s) == 0)                        /* match full name */ |     if (STRNCMP(arg, s, len) == 0 && s[len] == NUL) { | ||||||
|       break; |       break; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   if (s == NULL && !is_term_opt) { |   if (s == NULL && !is_term_opt) { | ||||||
|     opt_idx = quick_tab[CharOrdLow(arg[0])]; |     opt_idx = quick_tab[CharOrdLow(arg[0])]; | ||||||
|  |     // Match short name | ||||||
|     for (; options[opt_idx].fullname != NULL; opt_idx++) { |     for (; options[opt_idx].fullname != NULL; opt_idx++) { | ||||||
|       s = options[opt_idx].shortname; |       s = options[opt_idx].shortname; | ||||||
|       if (s != NULL && STRCMP(arg, s) == 0)         /* match short name */ |       if (s != NULL && STRNCMP(arg, s, len) == 0 && s[len] == NUL) { | ||||||
|         break; |         break; | ||||||
|  |       } | ||||||
|       s = NULL; |       s = NULL; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -4419,6 +4427,15 @@ bool set_tty_option(char *name, char *value) | |||||||
|     || !strcmp(name, "ttytype"); |     || !strcmp(name, "ttytype"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Find index for option 'arg'. | ||||||
|  |  * Return -1 if not found. | ||||||
|  |  */ | ||||||
|  | static int findoption(char_u *arg) | ||||||
|  | { | ||||||
|  |   return findoption_len(arg, STRLEN(arg)); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Get the value for an option. |  * Get the value for an option. | ||||||
|  * |  * | ||||||
| @@ -4675,27 +4692,32 @@ char_u *get_highlight_default(void) | |||||||
| /* | /* | ||||||
|  * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number. |  * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number. | ||||||
|  */ |  */ | ||||||
| static int find_key_option(char_u *arg) | int find_key_option_len(const char_u *arg, size_t len) | ||||||
| { | { | ||||||
|   int key; |   int key; | ||||||
|   int modifiers; |   int modifiers; | ||||||
|  |  | ||||||
|   /* |   // Don't use get_special_key_code() for t_xx, we don't want it to call | ||||||
|    * Don't use get_special_key_code() for t_xx, we don't want it to call |   // add_termcap_entry(). | ||||||
|    * add_termcap_entry(). |   if (len >= 4 && arg[0] == 't' && arg[1] == '_') { | ||||||
|    */ |  | ||||||
|   if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) |  | ||||||
|     key = TERMCAP2KEY(arg[2], arg[3]); |     key = TERMCAP2KEY(arg[2], arg[3]); | ||||||
|   else { |   } else { | ||||||
|     --arg;                          /* put arg at the '<' */ |     arg--;  // put arg at the '<' | ||||||
|     modifiers = 0; |     modifiers = 0; | ||||||
|     key = find_special_key(&arg, &modifiers, TRUE, TRUE); |     key = find_special_key(&arg, len + 1, &modifiers, true, true); | ||||||
|     if (modifiers)                  /* can't handle modifiers here */ |     if (modifiers) {  // can't handle modifiers here | ||||||
|       key = 0; |       key = 0; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   return key; |   return key; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int find_key_option(const char_u *arg) | ||||||
|  | { | ||||||
|  |   return find_key_option_len(arg, STRLEN(arg)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * if 'all' == 0: show changed options |  * if 'all' == 0: show changed options | ||||||
|  * if 'all' == 1: show all normal options |  * if 'all' == 1: show all normal options | ||||||
|   | |||||||
| @@ -175,8 +175,9 @@ size_t input_enqueue(String keys) | |||||||
|   char *ptr = keys.data, *end = ptr + keys.size; |   char *ptr = keys.data, *end = ptr + keys.size; | ||||||
|  |  | ||||||
|   while (rbuffer_space(input_buffer) >= 6 && ptr < end) { |   while (rbuffer_space(input_buffer) >= 6 && ptr < end) { | ||||||
|     uint8_t buf[6] = {0}; |     uint8_t buf[6] = { 0 }; | ||||||
|     unsigned int new_size = trans_special((uint8_t **)&ptr, buf, true); |     unsigned int new_size = trans_special((const uint8_t **)&ptr, keys.size, | ||||||
|  |                                           buf, true); | ||||||
|  |  | ||||||
|     if (new_size) { |     if (new_size) { | ||||||
|       new_size = handle_mouse_event(&ptr, buf, new_size); |       new_size = handle_mouse_event(&ptr, buf, new_size); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes