diff options
| author | Justin M. Keyes <justinkz@gmail.com> | 2017-07-03 23:33:08 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-03 23:33:08 +0200 | 
| commit | 008b604bacbbeeaf0e04f94b1d331b11ebec631a (patch) | |
| tree | 45a004c00c61f0bbe84cbf291093b6dffcf0bfb1 /src | |
| parent | e333957a1a9ae64b7daa36e08fd1df583114d4ba (diff) | |
| parent | 35898cff5d1d6dc60e0d7b87bfe106539453b031 (diff) | |
| download | rneovim-008b604bacbbeeaf0e04f94b1d331b11ebec631a.tar.gz rneovim-008b604bacbbeeaf0e04f94b1d331b11ebec631a.tar.bz2 rneovim-008b604bacbbeeaf0e04f94b1d331b11ebec631a.zip | |
Merge #6947 from ZyX-I/consistent-get_keymap
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/eval.c | 26 | ||||
| -rw-r--r-- | src/nvim/eval/typval.c | 23 | ||||
| -rw-r--r-- | src/nvim/getchar.c | 12 | ||||
| -rw-r--r-- | src/nvim/mbyte.c | 85 | ||||
| -rw-r--r-- | src/nvim/message.c | 159 | ||||
| -rw-r--r-- | src/nvim/option.c | 23 | 
6 files changed, 189 insertions, 139 deletions
| diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 18aa5bf763..662270e788 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -12117,9 +12117,11 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)    xfree(keys_buf);    if (!get_dict) { -    /* Return a string. */ -    if (rhs != NULL) -      rettv->vval.v_string = str2special_save(rhs, FALSE); +    // Return a string. +    if (rhs != NULL) { +      rettv->vval.v_string = (char_u *)str2special_save( +          (const char *)rhs, false, false); +    }    } else {      tv_dict_alloc_ret(rettv); @@ -12154,7 +12156,8 @@ void mapblock_fill_dict(dict_T *const dict,                          bool compatible)    FUNC_ATTR_NONNULL_ALL  { -  char_u *lhs = str2special_save(mp->m_keys, true); +  char *const lhs = str2special_save((const char *)mp->m_keys, +                                     compatible, !compatible);    char *const mapmode = map_mode_to_chars(mp->m_mode);    varnumber_T noremap_value; @@ -12168,18 +12171,21 @@ void mapblock_fill_dict(dict_T *const dict,      noremap_value = mp->m_noremap == REMAP_SCRIPT ? 2 : !!mp->m_noremap;    } -  tv_dict_add_str(dict, S_LEN("lhs"), (const char *)lhs); -  tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str); +  if (compatible) { +    tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str); +  } else { +    tv_dict_add_allocated_str(dict, S_LEN("rhs"), +                              str2special_save((const char *)mp->m_str, false, +                                               true)); +  } +  tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs);    tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value);    tv_dict_add_nr(dict, S_LEN("expr"),  mp->m_expr ? 1 : 0);    tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0);    tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ID);    tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value);    tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0); -  tv_dict_add_str(dict, S_LEN("mode"), mapmode); - -  xfree(lhs); -  xfree(mapmode); +  tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode);  }  /* diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 4521085519..c339a5cdd2 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1387,11 +1387,32 @@ int tv_dict_add_str(dict_T *const d,                      const char *const val)    FUNC_ATTR_NONNULL_ALL  { +  return tv_dict_add_allocated_str(d, key, key_len, xstrdup(val)); +} + +/// Add a string entry to dictionary +/// +/// Unlike tv_dict_add_str() saves val to the new dictionary item in place of +/// creating a new copy. +/// +/// @warning String will be freed even in case addition fails. +/// +/// @param[out]  d  Dictionary to add entry to. +/// @param[in]  key  Key to add. +/// @param[in]  key_len  Key length. +/// @param[in]  val  String to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_allocated_str(dict_T *const d, +                              const char *const key, const size_t key_len, +                              char *const val) +  FUNC_ATTR_NONNULL_ALL +{    dictitem_T *const item = tv_dict_item_alloc_len(key, key_len);    item->di_tv.v_lock = VAR_UNLOCKED;    item->di_tv.v_type = VAR_STRING; -  item->di_tv.vval.v_string = (char_u *)xstrdup(val); +  item->di_tv.vval.v_string = (char_u *)val;    if (tv_dict_add(d, item) == FAIL) {      tv_dict_item_free(item);      return FAIL; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 4e42042959..fc1b8ccfcb 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1806,7 +1806,7 @@ static int vgetorpeek(int advance)                   * <M-a> and then changing 'encoding'. Beware                   * that 0x80 is escaped. */                  char_u *p1 = mp->m_keys; -                char_u *p2 = mb_unescape(&p1); +                char_u *p2 = (char_u *)mb_unescape((const char **)&p1);                  if (has_mbyte && p2 != NULL && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2))                    mlen = 0; @@ -3999,12 +3999,10 @@ int put_escstr(FILE *fd, char_u *strstart, int what)      return OK;    } -  for (; *str != NUL; ++str) { -    char_u  *p; - -    /* Check for a multi-byte character, which may contain escaped -     * K_SPECIAL and CSI bytes */ -    p = mb_unescape(&str); +  for (; *str != NUL; str++) { +    // Check for a multi-byte character, which may contain escaped +    // K_SPECIAL and CSI bytes. +    const char *p = mb_unescape((const char **)&str);      if (p != NULL) {        while (*p != NUL)          if (fputc(*p++, fd) < 0) diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index d5907da2ed..5b00a4b9a8 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1739,52 +1739,55 @@ int mb_charlen_len(char_u *str, int len)    return count;  } -/* - * Try to un-escape a multi-byte character. - * Used for the "to" and "from" part of a mapping. - * Return the un-escaped string if it is a multi-byte character, and advance - * "pp" to just after the bytes that formed it. - * Return NULL if no multi-byte char was found. - */ -char_u * mb_unescape(char_u **pp) -{ -  static char_u buf[6]; -  int n; -  int m = 0; -  char_u              *str = *pp; - -  /* Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI -   * KS_EXTRA KE_CSI to CSI. -   * Maximum length of a utf-8 character is 4 bytes. */ -  for (n = 0; str[n] != NUL && m < 4; ++n) { -    if (str[n] == K_SPECIAL -        && str[n + 1] == KS_SPECIAL -        && str[n + 2] == KE_FILLER) { -      buf[m++] = K_SPECIAL; -      n += 2; -    } else if ((str[n] == K_SPECIAL -          ) -        && str[n + 1] == KS_EXTRA -        && str[n + 2] == (int)KE_CSI) { -      buf[m++] = CSI; -      n += 2; -    } else if (str[n] == K_SPECIAL -        ) -      break;                    /* a special key can't be a multibyte char */ -    else -      buf[m++] = str[n]; -    buf[m] = NUL; +/// Try to unescape a multibyte character +/// +/// Used for the rhs and lhs of the mappings. +/// +/// @param[in,out]  pp  String to unescape. Is advanced to just after the bytes +///                     that form a multibyte character. +/// +/// @return Unescaped string if it is a multibyte character, NULL if no +///         multibyte character was found. Returns a static buffer, always one +///         and the same. +const char *mb_unescape(const char **const pp) +  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ +  static char buf[6]; +  size_t buf_idx = 0; +  uint8_t *str = (uint8_t *)(*pp); + +  // Must translate K_SPECIAL KS_SPECIAL KE_FILLER to K_SPECIAL and CSI +  // KS_EXTRA KE_CSI to CSI. +  // Maximum length of a utf-8 character is 4 bytes. +  for (size_t str_idx = 0; str[str_idx] != NUL && buf_idx < 4; str_idx++) { +    if (str[str_idx] == K_SPECIAL +        && str[str_idx + 1] == KS_SPECIAL +        && str[str_idx + 2] == KE_FILLER) { +      buf[buf_idx++] = (char)K_SPECIAL; +      str_idx += 2; +    } else if ((str[str_idx] == K_SPECIAL) +               && str[str_idx + 1] == KS_EXTRA +               && str[str_idx + 2] == KE_CSI) { +      buf[buf_idx++] = (char)CSI; +      str_idx += 2; +    } else if (str[str_idx] == K_SPECIAL) { +      break;  // A special key can't be a multibyte char. +    } else { +      buf[buf_idx++] = (char)str[str_idx]; +    } +    buf[buf_idx] = NUL; -    /* Return a multi-byte character if it's found.  An illegal sequence -     * will result in a 1 here. */ -    if ((*mb_ptr2len)(buf) > 1) { -      *pp = str + n + 1; +    // Return a multi-byte character if it's found.  An illegal sequence +    // will result in a 1 here. +    if (utf_ptr2len((const char_u *)buf) > 1) { +      *pp = (const char *)str + buf_idx + 1;        return buf;      } -    /* Bail out quickly for ASCII. */ -    if (buf[0] < 128) +    // Bail out quickly for ASCII. +    if ((uint8_t)buf[0] < 128) {        break; +    }    }    return NULL;  } diff --git a/src/nvim/message.c b/src/nvim/message.c index 057ce75f79..8a9d8e1bc6 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1269,7 +1269,7 @@ msg_outtrans_special (        string = "<Space>";        str++;      } else { -      string = (const char *)str2special((char_u **)&str, from); +      string = str2special((const char **)&str, from, false);      }      const int len = vim_strsize((char_u *)string);      // Highlight special keys @@ -1281,108 +1281,125 @@ msg_outtrans_special (    return retval;  } -/* - * Return the lhs or rhs of a mapping, with the key codes turned into printable - * strings, in an allocated string. - */ -char_u * -str2special_save ( -    char_u *str, -    int is_lhs          /* TRUE for lhs, FALSE for rhs */ -) +/// Convert string, replacing key codes with printables +/// +/// Used for lhs or rhs of mappings. +/// +/// @param[in]  str  String to convert. +/// @param[in]  replace_spaces  Convert spaces into `<Space>`, normally used fo +///                             lhs, but not rhs. +/// @param[in]  replace_lt  Convert `<` into `<lt>`. +/// +/// @return [allocated] Converted string. +char *str2special_save(const char *const str, const bool replace_spaces, +                       const bool replace_lt) +  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC +  FUNC_ATTR_NONNULL_RET  {    garray_T ga; -  char_u      *p = str; -    ga_init(&ga, 1, 40); -  while (*p != NUL) -    ga_concat(&ga, str2special(&p, is_lhs)); + +  const char *p = str; +  while (*p != NUL) { +    ga_concat(&ga, (const char_u *)str2special(&p, replace_spaces, replace_lt)); +  }    ga_append(&ga, NUL); -  return (char_u *)ga.ga_data; +  return (char *)ga.ga_data;  } -/* - * Return the printable string for the key codes at "*sp". - * Used for translating the lhs or rhs of a mapping to printable chars. - * Advances "sp" to the next code. - */ -char_u * -str2special ( -    char_u **sp, -    int from               /* TRUE for lhs of mapping */ -) -{ -  int c; -  static char_u buf[7]; -  char_u              *str = *sp; -  int modifiers = 0; -  int special = FALSE; - -  if (has_mbyte) { -    char_u  *p; - -    /* Try to un-escape a multi-byte character.  Return the un-escaped -     * string if it is a multi-byte character. */ -    p = mb_unescape(sp); -    if (p != NULL) -      return p; +/// Convert character, replacing key one key code with printable representation +/// +/// @param[in,out]  sp  String to convert. Is advanced to the next key code. +/// @param[in]  replace_spaces  Convert spaces into <Space>, normally used for +///                             lhs, but not rhs. +/// @param[in]  replace_lt  Convert `<` into `<lt>`. +/// +/// @return Converted key code, in a static buffer. Buffer is always one and the +///         same, so save converted string somewhere before running str2special +///         for the second time. +const char *str2special(const char **const sp, const bool replace_spaces, +                        const bool replace_lt) +  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET +{ +  static char buf[7]; + +  // Try to un-escape a multi-byte character.  Return the un-escaped +  // string if it is a multi-byte character. +  const char *const p = mb_unescape(sp); +  if (p != NULL) { +    return p;    } -  c = *str; +  const char *str = *sp; +  int c = (uint8_t)(*str); +  int modifiers = 0; +  bool special = false;    if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { -    if (str[1] == KS_MODIFIER) { -      modifiers = str[2]; +    if ((uint8_t)str[1] == KS_MODIFIER) { +      modifiers = (uint8_t)str[2];        str += 3; -      c = *str; +      c = (uint8_t)(*str);      }      if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { -      c = TO_SPECIAL(str[1], str[2]); +      c = TO_SPECIAL((uint8_t)str[1], (uint8_t)str[2]);        str += 2; -      if (c == KS_ZERO)         /* display <Nul> as ^@ or <Nul> */ +      if (c == KS_ZERO) {  // display <Nul> as ^@ or <Nul>          c = NUL; +      } +    } +    if (IS_SPECIAL(c) || modifiers) {  // Special key. +      special = true;      } -    if (IS_SPECIAL(c) || modifiers)     /* special key */ -      special = TRUE;    } -  if (has_mbyte && !IS_SPECIAL(c)) { -    int len = (*mb_ptr2len)(str); +  if (!IS_SPECIAL(c)) { +    const int len = utf_ptr2len((const char_u *)str); -    /* For multi-byte characters check for an illegal byte. */ -    if (has_mbyte && MB_BYTE2LEN(*str) > len) { -      transchar_nonprint(buf, c); +    // Check for an illegal byte. +    if (MB_BYTE2LEN((uint8_t)(*str)) > len) { +      transchar_nonprint((char_u *)buf, c);        *sp = str + 1;        return buf;      } -    /* Since 'special' is TRUE the multi-byte character 'c' will be -     * processed by get_special_key_name() */ -    c = (*mb_ptr2char)(str); +    // Since 'special' is TRUE the multi-byte character 'c' will be +    // processed by get_special_key_name(). +    c = utf_ptr2char((const char_u *)str);      *sp = str + len; -  } else +  } else {      *sp = str + 1; +  } -  /* Make unprintable characters in <> form, also <M-Space> and <Tab>. -   * Use <Space> only for lhs of a mapping. */ -  if (special || char2cells(c) > 1 || (from && c == ' ')) -    return get_special_key_name(c, modifiers); +  // Make unprintable characters in <> form, also <M-Space> and <Tab>. +  if (special +      || char2cells(c) > 1 +      || (replace_spaces && c == ' ') +      || (replace_lt && c == '<')) { +    return (const char *)get_special_key_name(c, modifiers); +  }    buf[0] = c;    buf[1] = NUL;    return buf;  } -/* - * Translate a key sequence into special key names. - */ -void str2specialbuf(char_u *sp, char_u *buf, int len) +/// Convert string, replacing key codes with printables +/// +/// @param[in]  str  String to convert. +/// @param[out]  buf  Buffer to save results to. +/// @param[in]  len  Buffer length. +void str2specialbuf(const char *sp, char *buf, size_t len) +  FUNC_ATTR_NONNULL_ALL  { -  char_u      *s; - -  *buf = NUL;    while (*sp) { -    s = str2special(&sp, FALSE); -    if ((int)(STRLEN(s) + STRLEN(buf)) < len) -      STRCAT(buf, s); +    const char *s = str2special(&sp, false, false); +    const size_t s_len = strlen(s); +    if (s_len <= len) { +      break; +    } +    memcpy(buf, s, s_len); +    buf += s_len; +    len -= s_len;    } +  *buf = NUL;  }  /* diff --git a/src/nvim/option.c b/src/nvim/option.c index b48ffae85b..7287db6eb8 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5175,9 +5175,13 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int e       * CTRL-V or backslash */      if (valuep == &p_pt) {        s = *valuep; -      while (*s != NUL) -        if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL) +      while (*s != NUL) { +        if (put_escstr(fd, (char_u *)str2special((const char **)&s, false, +                                                 false), 2) +            == FAIL) {            return FAIL; +        } +      }      } else if (expand) {        buf = xmalloc(MAXPATHL);        home_replace(NULL, *valuep, buf, MAXPATHL, FALSE); @@ -6173,15 +6177,16 @@ option_value2string (      }    } else {  // P_STRING      varp = *(char_u **)(varp); -    if (varp == NULL)                       /* just in case */ +    if (varp == NULL) {  // Just in case.        NameBuff[0] = NUL; -    else if (opp->flags & P_EXPAND) -      home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE); -    /* Translate 'pastetoggle' into special key names */ -    else if ((char_u **)opp->var == &p_pt) -      str2specialbuf(p_pt, NameBuff, MAXPATHL); -    else +    } else if (opp->flags & P_EXPAND) { +      home_replace(NULL, varp, NameBuff, MAXPATHL, false); +    // Translate 'pastetoggle' into special key names. +    } else if ((char_u **)opp->var == &p_pt) { +      str2specialbuf((const char *)p_pt, (char *)NameBuff, MAXPATHL); +    } else {        STRLCPY(NameBuff, varp, MAXPATHL); +    }    }  } | 
