Mercurial > vim
changeset 2338:da6ec32d8d8f vim73
Added strwidth() and strchars() functions.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Sun, 18 Jul 2010 15:31:08 +0200 |
parents | a0f87fc19d1d |
children | 01e4b4d37842 |
files | runtime/doc/eval.txt runtime/doc/todo.txt src/eval.c src/gui.c src/gui_mac.c src/gui_w16.c src/gui_w32.c src/mbyte.c src/proto/mbyte.pro src/screen.c |
diffstat | 10 files changed, 99 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1909,6 +1909,7 @@ split( {expr} [, {pat} [, {keepempty}]]) sqrt( {expr} Float squar root of {expr} str2float( {expr}) Float convert String to Float str2nr( {expr} [, {base}]) Number convert String to Number +strchars( {expr}) Number character length of the String {expr} strftime( {format}[, {time}]) String time in specified format stridx( {haystack}, {needle}[, {start}]) Number index of {needle} in {haystack} @@ -1919,6 +1920,7 @@ strpart( {src}, {start}[, {len}]) strridx( {haystack}, {needle} [, {start}]) Number last index of {needle} in {haystack} strtrans( {expr}) String translate string to make it printable +strwidth( {expr}) Number display cell length of the String {expr} submatch( {nr}) String specific match in ":substitute" substitute( {expr}, {pat}, {sub}, {flags}) String all {pat} in {expr} replaced with {sub} @@ -5362,6 +5364,12 @@ str2nr( {expr} [, {base}]) *str2nr()* Text after the number is silently ignored. +strchars({expr}) *strchars()* + The result is a Number, which is the number of characters + String {expr} occupies. Composing characters are counted + separately. + Also see |strlen()| and |strwidth()|. + strftime({format} [, {time}]) *strftime()* The result is a String, which is a formatted date and time, as specified by the {format} string. The given {time} is used, @@ -5424,7 +5432,7 @@ strlen({expr}) The result is a Number, w < If the argument is a Number it is first converted to a String. For other types an error is given. - Also see |len()|. + Also see |len()|, |strchars()| and |strwidth()|. strpart({src}, {start}[, {len}]) *strpart()* The result is a String, which is part of {src}, starting from @@ -5467,6 +5475,14 @@ strtrans({expr}) *strtrans()* < This displays a newline in register a as "^@" instead of starting a new line. +strwidth({expr}) *strwidth()* + The result is a Number, which is the number of display cells + String {expr} occupies. A Tab character is counted as one + cell (on the screen it depends on the position). + When {expr} contains characters with East Asian Width Class + Ambiguous, this function's return value depends on 'ambiwidth'. + Also see |strlen()| and |strchars()|. + submatch({nr}) *submatch()* Only for an expression in a |:substitute| command. Returns the {nr}'th submatch of the matched text. When {nr} is 0
--- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1193,8 +1193,8 @@ 8 Add functions: Search in 'runtimepath'? More docs needed about how to use this. How to get the messages into the .po files? - charlen() Like strlen() but counting characters instead of - bytes. + strchars() Like strlen() and strwidth() but counting characters + instead of bytes. confirm() add "flags" argument, with 'v' for vertical layout and 'c' for console dialog. (Haegg) Flemming Madsen has a patch for the 'c' flag
--- a/src/eval.c +++ b/src/eval.c @@ -700,6 +700,7 @@ static void f_sqrt __ARGS((typval_T *arg static void f_str2float __ARGS((typval_T *argvars, typval_T *rettv)); #endif static void f_str2nr __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_strchars __ARGS((typval_T *argvars, typval_T *rettv)); #ifdef HAVE_STRFTIME static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv)); #endif @@ -709,6 +710,7 @@ static void f_strlen __ARGS((typval_T *a static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv)); static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv)); static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_strwidth __ARGS((typval_T *argvars, typval_T *rettv)); static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv)); static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv)); static void f_synID __ARGS((typval_T *argvars, typval_T *rettv)); @@ -7856,6 +7858,7 @@ static struct fst {"str2float", 1, 1, f_str2float}, #endif {"str2nr", 1, 2, f_str2nr}, + {"strchars", 1, 1, f_strchars}, #ifdef HAVE_STRFTIME {"strftime", 1, 2, f_strftime}, #endif @@ -7865,6 +7868,7 @@ static struct fst {"strpart", 2, 3, f_strpart}, {"strridx", 2, 3, f_strridx}, {"strtrans", 1, 1, f_strtrans}, + {"strwidth", 1, 1, f_strwidth}, {"submatch", 1, 1, f_submatch}, {"substitute", 4, 4, f_substitute}, {"synID", 3, 3, f_synID}, @@ -16778,6 +16782,48 @@ f_strlen(argvars, rettv) } /* + * "strchars()" function + */ + static void +f_strchars(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u *s = get_tv_string(&argvars[0]); +#ifdef FEAT_MBYTE + varnumber_T len = 0; + + while (*s != NUL) + { + mb_cptr2char_adv(&s); + ++len; + } + rettv->vval.v_number = len; +#else + rettv->vval.v_number = (varnumber_T)(STRLEN(s)); +#endif +} + +/* + * "strwidth()" function + */ + static void +f_strwidth(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u *s = get_tv_string(&argvars[0]); + + rettv->vval.v_number = (varnumber_T)( +#ifdef FEAT_MBYTE + mb_string2cells(s, -1) +#else + STRLEN(s) +#endif + ); +} + +/* * "strpart()" function */ static void
--- a/src/gui.c +++ b/src/gui.c @@ -2329,14 +2329,9 @@ gui_outstr_nowrap(s, len, flags, fg, bg, # ifdef FEAT_MBYTE if (enc_dbcs == DBCS_JPNU) { - int clen = 0; - int i; - /* Get the length in display cells, this can be different from the * number of bytes for "euc-jp". */ - for (i = 0; i < len; i += (*mb_ptr2len)(s + i)) - clen += (*mb_ptr2cells)(s + i); - len = clen; + len = mb_string2cells(s, len); } # endif }
--- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -3983,13 +3983,8 @@ draw_string_QD(int row, int col, char_u /* Multibyte computation taken from gui_w32.c */ if (has_mbyte) { - int cell_len = 0; - int n; - /* Compute the length in display cells. */ - for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) - cell_len += (*mb_ptr2cells)(s + n); - rc.right = FILL_X(col + cell_len); + rc.right = FILL_X(col + mb_string2cells(s, len)); } else #endif @@ -4087,13 +4082,8 @@ draw_string_ATSUI(int row, int col, char /* Multibyte computation taken from gui_w32.c */ if (has_mbyte) { - int cell_len = 0; - int n; - /* Compute the length in display cells. */ - for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) - cell_len += (*mb_ptr2cells)(s + n); - rc.right = FILL_X(col + cell_len); + rc.right = FILL_X(col + mb_string2cells(s, len)); } else rc.right = FILL_X(col + len) + (col + len == Columns);
--- a/src/gui_w16.c +++ b/src/gui_w16.c @@ -664,12 +664,8 @@ gui_mch_draw_string( #ifdef FEAT_MBYTE if (has_mbyte) { - int cell_len = 0; - /* Compute the length in display cells. */ - for (n = 0; n < len; n += MB_BYTE2LEN(text[n])) - cell_len += (*mb_ptr2cells)(text + n); - rc.right = FILL_X(col + cell_len); + rc.right = FILL_X(col + mb_string2cells(text, len)); } else #endif
--- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -2261,12 +2261,8 @@ gui_mch_draw_string( #ifdef FEAT_MBYTE if (has_mbyte) { - int cell_len = 0; - /* Compute the length in display cells. */ - for (n = 0; n < len; n += MB_BYTE2LEN(text[n])) - cell_len += (*mb_ptr2cells)(text + n); - rc.right = FILL_X(col + cell_len); + rc.right = FILL_X(col + mb_string2cells(text, len)); } else #endif
--- a/src/mbyte.c +++ b/src/mbyte.c @@ -1579,6 +1579,23 @@ dbcs_char2cells(c) } /* + * Return the number of cells occupied by string "p". + * Stop at a NUL character. When "len" >= 0 stop at character "p[len]". + */ + int +mb_string2cells(p, len) + char_u *p; + int len; +{ + int i; + int clen = 0; + + for (i = 0; (len < 0 || i < len) && p[i] != NUL; i += (*mb_ptr2len)(p + i)) + clen += (*mb_ptr2cells)(p + i); + return clen; +} + +/* * mb_off2cells() function pointer. * Return number of display cells for char at ScreenLines[off]. * We make sure that the offset used is less than "max_off". @@ -4364,12 +4381,12 @@ im_commit_cb(GtkIMContext *context UNUSE const gchar *str, gpointer data UNUSED) { - int slen = (int)STRLEN(str); - int add_to_input = TRUE; - int clen; - int len = slen; - int commit_with_preedit = TRUE; - char_u *im_str, *p; + int slen = (int)STRLEN(str); + int add_to_input = TRUE; + int clen; + int len = slen; + int commit_with_preedit = TRUE; + char_u *im_str; #ifdef XIM_DEBUG xim_log("im_commit_cb(): %s\n", str); @@ -4402,9 +4419,9 @@ im_commit_cb(GtkIMContext *context UNUSE } else im_str = (char_u *)str; - clen = 0; - for (p = im_str; p < im_str + len; p += (*mb_ptr2len)(p)) - clen += (*mb_ptr2cells)(p); + + clen = mb_string2cells(im_str, len); + if (input_conv.vc_type != CONV_NONE) vim_free(im_str); preedit_start_col += clen;
--- a/src/proto/mbyte.pro +++ b/src/proto/mbyte.pro @@ -14,6 +14,7 @@ int utf_ptr2cells __ARGS((char_u *p)); int dbcs_ptr2cells __ARGS((char_u *p)); int latin_ptr2cells_len __ARGS((char_u *p, int size)); int latin_char2cells __ARGS((int c)); +int mb_string2cells __ARGS((char_u *p, int len)); int latin_off2cells __ARGS((unsigned off, unsigned max_off)); int dbcs_off2cells __ARGS((unsigned off, unsigned max_off)); int utf_off2cells __ARGS((unsigned off, unsigned max_off));
--- a/src/screen.c +++ b/src/screen.c @@ -6168,8 +6168,8 @@ win_redr_status(wp) int clen = 0, i; /* Count total number of display cells. */ - for (i = 0; p[i] != NUL; i += (*mb_ptr2len)(p + i)) - clen += (*mb_ptr2cells)(p + i); + clen = mb_string2cells(p, -1); + /* Find first character that will fit. * Going from start to end is much faster for DBCS. */ for (i = 0; p[i] != NUL && clen >= this_ru_col - 1;