]> granicus.if.org Git - vim/commitdiff
Added strwidth() and strchars() functions.
authorBram Moolenaar <Bram@vim.org>
Sun, 18 Jul 2010 13:31:08 +0000 (15:31 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 18 Jul 2010 13:31:08 +0000 (15:31 +0200)
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

index 707412c3c9ae522049c9ea778f8c6e1b6f8571f5..f1eeb73032679346fd3065b0909942ef36245bb6 100644 (file)
@@ -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, which is the length of the String
 <
                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
index fc3f2b49293fb994d22aa58676c21a2f55a10aee..098a431f66de0411a55ea8b70beb28972e17e03d 100644 (file)
@@ -1193,8 +1193,8 @@ Awaiting updated patches:
                        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
index 295512e34a624f697ba5898438f937c4b0657210..a344cd2a52110d2429f5245d984635d2680f20aa 100644 (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));
 #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 *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_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},
@@ -16777,6 +16781,48 @@ f_strlen(argvars, rettv)
                                              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
  */
index 4075997f0101cbea44cb82e1b0b31c9ca2d7e993..68999926f6d382f859c28f5310c0f0f7539eb0db 100644 (file)
--- a/src/gui.c
+++ b/src/gui.c
@@ -2329,14 +2329,9 @@ gui_outstr_nowrap(s, len, flags, fg, bg, back)
 # 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
     }
index f6aa22b57467a250ebc34650fc1bffb5f9a35e63..2f0f7f865713e1192f0b337ed3e364f36920407b 100644 (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 */
        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_u *s, int len, int flags)
        /* 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);
index f7e6d597f845403cb0e94724d536c026a466b15e..68667846b9d9bc813818652ebe447b68a222fd7e 100644 (file)
@@ -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
index cfd4b785716646fd9e47ef2ffcd1494e059716da..1fdc99396e9b92660f0fbeaf8953a542087b142f 100644 (file)
@@ -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
index 3a83eb482097fe5b98974627544b3685d5cf5adb..3719b85b673d53bcebfa40117337e215638c2556 100644 (file)
@@ -1578,6 +1578,23 @@ dbcs_char2cells(c)
     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.
  * Return number of display cells for char at ScreenLines[off].
@@ -4364,12 +4381,12 @@ im_commit_cb(GtkIMContext *context UNUSED,
             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 UNUSED,
     }
     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;
index e805cb442e2344eb3a3386313963e193fa5a8b40..9519a19371f2c0771f10020a1cf121f3cfe4f809 100644 (file)
@@ -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));
index 5b9a0737f847e2072bd4551ae48da155d6572555..74898f82dd278156259cb516c9007668a70d539b 100644 (file)
@@ -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;