Mercurial > vim
diff src/evalfunc.c @ 23380:2351b40af967 v8.2.2233
patch 8.2.2233: cannot convert a byte index into a character index
Commit: https://github.com/vim/vim/commit/17793ef23aae0bc94539390ccfe5e63b0ad39ff2
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Dec 28 12:56:58 2020 +0100
patch 8.2.2233: cannot convert a byte index into a character index
Problem: Cannot convert a byte index into a character index.
Solution: Add charidx(). (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/7561)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 28 Dec 2020 13:00:07 +0100 |
parents | b79cdad3ea2e |
children | f8382c4e6551 |
line wrap: on
line diff
--- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -47,6 +47,7 @@ static void f_ceil(typval_T *argvars, ty #endif static void f_changenr(typval_T *argvars, typval_T *rettv); static void f_char2nr(typval_T *argvars, typval_T *rettv); +static void f_charidx(typval_T *argvars, typval_T *rettv); static void f_col(typval_T *argvars, typval_T *rettv); static void f_confirm(typval_T *argvars, typval_T *rettv); static void f_copy(typval_T *argvars, typval_T *rettv); @@ -789,6 +790,8 @@ static funcentry_T global_functions[] = ret_number, f_char2nr}, {"charclass", 1, 1, FEARG_1, NULL, ret_number, f_charclass}, + {"charidx", 2, 3, FEARG_1, NULL, + ret_number, f_charidx}, {"chdir", 1, 1, FEARG_1, NULL, ret_string, f_chdir}, {"cindent", 1, 1, FEARG_1, NULL, @@ -2420,6 +2423,57 @@ f_char2nr(typval_T *argvars, typval_T *r rettv->vval.v_number = tv_get_string(&argvars[0])[0]; } +/* + * "charidx()" function + */ + static void +f_charidx(typval_T *argvars, typval_T *rettv) +{ + char_u *str; + varnumber_T idx; + int countcc = FALSE; + char_u *p; + int len; + int (*ptr2len)(char_u *); + + rettv->vval.v_number = -1; + + if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER + || (argvars[2].v_type != VAR_UNKNOWN + && argvars[2].v_type != VAR_NUMBER)) + { + emsg(_(e_invarg)); + return; + } + + str = tv_get_string_chk(&argvars[0]); + idx = tv_get_number_chk(&argvars[1], NULL); + if (str == NULL || idx < 0) + return; + + if (argvars[2].v_type != VAR_UNKNOWN) + countcc = (int)tv_get_bool(&argvars[2]); + if (countcc < 0 || countcc > 1) + { + semsg(_(e_using_number_as_bool_nr), countcc); + return; + } + + if (enc_utf8 && countcc) + ptr2len = utf_ptr2len; + else + ptr2len = mb_ptr2len; + + for (p = str, len = 0; p <= str + idx; len++) + { + if (*p == NUL) + return; + p += ptr2len(p); + } + + rettv->vval.v_number = len > 0 ? len - 1 : 0; +} + win_T * get_optional_window(typval_T *argvars, int idx) {