0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

Added strwidth() and strchars() functions.

This commit is contained in:
Bram Moolenaar 2010-07-18 15:31:08 +02:00
parent 9855d6b361
commit 72597a57b5
10 changed files with 99 additions and 42 deletions

View File

@ -1909,6 +1909,7 @@ split( {expr} [, {pat} [, {keepempty}]])
sqrt( {expr} Float squar root of {expr} sqrt( {expr} Float squar root of {expr}
str2float( {expr}) Float convert String to Float str2float( {expr}) Float convert String to Float
str2nr( {expr} [, {base}]) Number convert String to Number 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 strftime( {format}[, {time}]) String time in specified format
stridx( {haystack}, {needle}[, {start}]) stridx( {haystack}, {needle}[, {start}])
Number index of {needle} in {haystack} Number index of {needle} in {haystack}
@ -1919,6 +1920,7 @@ strpart( {src}, {start}[, {len}])
strridx( {haystack}, {needle} [, {start}]) strridx( {haystack}, {needle} [, {start}])
Number last index of {needle} in {haystack} Number last index of {needle} in {haystack}
strtrans( {expr}) String translate string to make it printable 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" submatch( {nr}) String specific match in ":substitute"
substitute( {expr}, {pat}, {sub}, {flags}) substitute( {expr}, {pat}, {sub}, {flags})
String all {pat} in {expr} replaced with {sub} String all {pat} in {expr} replaced with {sub}
@ -5362,6 +5364,12 @@ str2nr( {expr} [, {base}]) *str2nr()*
Text after the number is silently ignored. 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()* strftime({format} [, {time}]) *strftime()*
The result is a String, which is a formatted date and time, as The result is a String, which is a formatted date and time, as
specified by the {format} string. The given {time} is used, specified by the {format} string. The given {time} is used,
@ -5424,7 +5432,7 @@ strlen({expr}) The result is a Number, which is the length of the String
< <
If the argument is a Number it is first converted to a String. If the argument is a Number it is first converted to a String.
For other types an error is given. For other types an error is given.
Also see |len()|. Also see |len()|, |strchars()| and |strwidth()|.
strpart({src}, {start}[, {len}]) *strpart()* strpart({src}, {start}[, {len}]) *strpart()*
The result is a String, which is part of {src}, starting from 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 < This displays a newline in register a as "^@" instead of
starting a new line. 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()* submatch({nr}) *submatch()*
Only for an expression in a |:substitute| command. Returns Only for an expression in a |:substitute| command. Returns
the {nr}'th submatch of the matched text. When {nr} is 0 the {nr}'th submatch of the matched text. When {nr} is 0

View File

@ -1193,8 +1193,8 @@ Awaiting updated patches:
Search in 'runtimepath'? Search in 'runtimepath'?
More docs needed about how to use this. More docs needed about how to use this.
How to get the messages into the .po files? How to get the messages into the .po files?
charlen() Like strlen() but counting characters instead of strchars() Like strlen() and strwidth() but counting characters
bytes. instead of bytes.
confirm() add "flags" argument, with 'v' for vertical confirm() add "flags" argument, with 'v' for vertical
layout and 'c' for console dialog. (Haegg) layout and 'c' for console dialog. (Haegg)
Flemming Madsen has a patch for the 'c' flag Flemming Madsen has a patch for the 'c' flag

View File

@ -700,6 +700,7 @@ static void f_sqrt __ARGS((typval_T *argvars, typval_T *rettv));
static void f_str2float __ARGS((typval_T *argvars, typval_T *rettv)); static void f_str2float __ARGS((typval_T *argvars, typval_T *rettv));
#endif #endif
static void f_str2nr __ARGS((typval_T *argvars, typval_T *rettv)); 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 #ifdef HAVE_STRFTIME
static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv)); static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
#endif #endif
@ -709,6 +710,7 @@ static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv)); 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_strridx __ARGS((typval_T *argvars, typval_T *rettv));
static void f_strtrans __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_submatch __ARGS((typval_T *argvars, typval_T *rettv));
static void f_substitute __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)); static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
@ -7856,6 +7858,7 @@ static struct fst
{"str2float", 1, 1, f_str2float}, {"str2float", 1, 1, f_str2float},
#endif #endif
{"str2nr", 1, 2, f_str2nr}, {"str2nr", 1, 2, f_str2nr},
{"strchars", 1, 1, f_strchars},
#ifdef HAVE_STRFTIME #ifdef HAVE_STRFTIME
{"strftime", 1, 2, f_strftime}, {"strftime", 1, 2, f_strftime},
#endif #endif
@ -7865,6 +7868,7 @@ static struct fst
{"strpart", 2, 3, f_strpart}, {"strpart", 2, 3, f_strpart},
{"strridx", 2, 3, f_strridx}, {"strridx", 2, 3, f_strridx},
{"strtrans", 1, 1, f_strtrans}, {"strtrans", 1, 1, f_strtrans},
{"strwidth", 1, 1, f_strwidth},
{"submatch", 1, 1, f_submatch}, {"submatch", 1, 1, f_submatch},
{"substitute", 4, 4, f_substitute}, {"substitute", 4, 4, f_substitute},
{"synID", 3, 3, f_synID}, {"synID", 3, 3, f_synID},
@ -16777,6 +16781,48 @@ f_strlen(argvars, rettv)
get_tv_string(&argvars[0]))); get_tv_string(&argvars[0])));
} }
/*
* "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 * "strpart()" function
*/ */

View File

@ -2329,14 +2329,9 @@ gui_outstr_nowrap(s, len, flags, fg, bg, back)
# ifdef FEAT_MBYTE # ifdef FEAT_MBYTE
if (enc_dbcs == DBCS_JPNU) if (enc_dbcs == DBCS_JPNU)
{ {
int clen = 0;
int i;
/* Get the length in display cells, this can be different from the /* Get the length in display cells, this can be different from the
* number of bytes for "euc-jp". */ * number of bytes for "euc-jp". */
for (i = 0; i < len; i += (*mb_ptr2len)(s + i)) len = mb_string2cells(s, len);
clen += (*mb_ptr2cells)(s + i);
len = clen;
} }
# endif # endif
} }

View File

@ -3983,13 +3983,8 @@ draw_string_QD(int row, int col, char_u *s, int len, int flags)
/* Multibyte computation taken from gui_w32.c */ /* Multibyte computation taken from gui_w32.c */
if (has_mbyte) if (has_mbyte)
{ {
int cell_len = 0;
int n;
/* Compute the length in display cells. */ /* Compute the length in display cells. */
for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) rc.right = FILL_X(col + mb_string2cells(s, len));
cell_len += (*mb_ptr2cells)(s + n);
rc.right = FILL_X(col + cell_len);
} }
else else
#endif #endif
@ -4087,13 +4082,8 @@ draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
/* Multibyte computation taken from gui_w32.c */ /* Multibyte computation taken from gui_w32.c */
if (has_mbyte) if (has_mbyte)
{ {
int cell_len = 0;
int n;
/* Compute the length in display cells. */ /* Compute the length in display cells. */
for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) rc.right = FILL_X(col + mb_string2cells(s, len));
cell_len += (*mb_ptr2cells)(s + n);
rc.right = FILL_X(col + cell_len);
} }
else else
rc.right = FILL_X(col + len) + (col + len == Columns); rc.right = FILL_X(col + len) + (col + len == Columns);

View File

@ -664,12 +664,8 @@ gui_mch_draw_string(
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
int cell_len = 0;
/* Compute the length in display cells. */ /* Compute the length in display cells. */
for (n = 0; n < len; n += MB_BYTE2LEN(text[n])) rc.right = FILL_X(col + mb_string2cells(text, len));
cell_len += (*mb_ptr2cells)(text + n);
rc.right = FILL_X(col + cell_len);
} }
else else
#endif #endif

View File

@ -2261,12 +2261,8 @@ gui_mch_draw_string(
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
int cell_len = 0;
/* Compute the length in display cells. */ /* Compute the length in display cells. */
for (n = 0; n < len; n += MB_BYTE2LEN(text[n])) rc.right = FILL_X(col + mb_string2cells(text, len));
cell_len += (*mb_ptr2cells)(text + n);
rc.right = FILL_X(col + cell_len);
} }
else else
#endif #endif

View File

@ -1578,6 +1578,23 @@ dbcs_char2cells(c)
return MB_BYTE2LEN((unsigned)c >> 8); return MB_BYTE2LEN((unsigned)c >> 8);
} }
/*
* 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. * mb_off2cells() function pointer.
* Return number of display cells for char at ScreenLines[off]. * Return number of display cells for char at ScreenLines[off].
@ -4364,12 +4381,12 @@ im_commit_cb(GtkIMContext *context UNUSED,
const gchar *str, const gchar *str,
gpointer data UNUSED) gpointer data UNUSED)
{ {
int slen = (int)STRLEN(str); int slen = (int)STRLEN(str);
int add_to_input = TRUE; int add_to_input = TRUE;
int clen; int clen;
int len = slen; int len = slen;
int commit_with_preedit = TRUE; int commit_with_preedit = TRUE;
char_u *im_str, *p; char_u *im_str;
#ifdef XIM_DEBUG #ifdef XIM_DEBUG
xim_log("im_commit_cb(): %s\n", str); xim_log("im_commit_cb(): %s\n", str);
@ -4402,9 +4419,9 @@ im_commit_cb(GtkIMContext *context UNUSED,
} }
else else
im_str = (char_u *)str; im_str = (char_u *)str;
clen = 0;
for (p = im_str; p < im_str + len; p += (*mb_ptr2len)(p)) clen = mb_string2cells(im_str, len);
clen += (*mb_ptr2cells)(p);
if (input_conv.vc_type != CONV_NONE) if (input_conv.vc_type != CONV_NONE)
vim_free(im_str); vim_free(im_str);
preedit_start_col += clen; preedit_start_col += clen;

View File

@ -14,6 +14,7 @@ int utf_ptr2cells __ARGS((char_u *p));
int dbcs_ptr2cells __ARGS((char_u *p)); int dbcs_ptr2cells __ARGS((char_u *p));
int latin_ptr2cells_len __ARGS((char_u *p, int size)); int latin_ptr2cells_len __ARGS((char_u *p, int size));
int latin_char2cells __ARGS((int c)); 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 latin_off2cells __ARGS((unsigned off, unsigned max_off));
int dbcs_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)); int utf_off2cells __ARGS((unsigned off, unsigned max_off));

View File

@ -6168,8 +6168,8 @@ win_redr_status(wp)
int clen = 0, i; int clen = 0, i;
/* Count total number of display cells. */ /* Count total number of display cells. */
for (i = 0; p[i] != NUL; i += (*mb_ptr2len)(p + i)) clen = mb_string2cells(p, -1);
clen += (*mb_ptr2cells)(p + i);
/* Find first character that will fit. /* Find first character that will fit.
* Going from start to end is much faster for DBCS. */ * Going from start to end is much faster for DBCS. */
for (i = 0; p[i] != NUL && clen >= this_ru_col - 1; for (i = 0; p[i] != NUL && clen >= this_ru_col - 1;