Hi list.

I have implemented wcwidth() function.
Based commit was 7.2.444.

It is useful to get width of character,
for e.g., when creating plugin which needs to
align text not to exceed &columns,
or which needs to concern character width like tetris game :)

I'm new to hack Vim source.
So please tell me if I did it wrongly.

-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 1e7d6f3..98407f1 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1932,6 +1932,8 @@ type( {name})			Number	type of variable {name}
 values( {dict})			List	values in {dict}
 virtcol( {expr})		Number	screen column of cursor or mark
 visualmode( [expr])		String	last visual mode used
+wcwidth( {expr})
+				Number	the number of display cells String {expr} occupies
 winbufnr( {nr})			Number	buffer number of window {nr}
 wincol()			Number	window column of the cursor
 winheight( {nr})		Number	height of window {nr}
@@ -5669,6 +5671,14 @@ visualmode([expr])						*visualmode()*
 		Dictionary or Float is not a Number or String, thus does not
 		cause the mode to be cleared.
 
+							*wcwidth()*
+wcwidth( {expr})	The result is a Number, which is
+		the number of display cells String {expr} occupies.
+		When {expr} contains characters with East Asian Width Class
+		Ambiguous, this function's return value depends on 'ambiwidth'.
+		If 'ambiwidth' is "single", wcwidth() counts that character as 1.
+		If 'ambiwidth' is "double", wcwidth() counts that character as 2.
+
 							*winbufnr()*
 winbufnr({nr})	The result is a Number, which is the number of the buffer
 		associated with window {nr}.  When {nr} is zero, the number of
diff --git a/src/eval.c b/src/eval.c
index 32e3d20..7ed5403 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -717,6 +717,7 @@ static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_wcwidth __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
@@ -7795,6 +7796,7 @@ static struct fst
     {"values",		1, 1, f_values},
     {"virtcol",		1, 1, f_virtcol},
     {"visualmode",	0, 1, f_visualmode},
+    {"wcwidth",		1, 1, f_wcwidth},
     {"winbufnr",	1, 1, f_winbufnr},
     {"wincol",		0, 0, f_wincol},
     {"winheight",	1, 1, f_winheight},
@@ -17360,6 +17362,18 @@ f_visualmode(argvars, rettv)
 }
 
 /*
+ * "wcwidth()" function
+ */
+    static void
+f_wcwidth(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    char_u	*str = get_tv_string(&argvars[0]);
+    rettv->vval.v_number = (varnumber_T)MB_CHARWIDTH(str);
+}
+
+/*
  * "winbufnr(nr)" function
  */
     static void
diff --git a/src/macros.h b/src/macros.h
index 51e4dd4..d974d86 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -285,6 +285,7 @@
 
 # define MB_COPY_CHAR(f, t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++
 # define MB_CHARLEN(p)	    (has_mbyte ? mb_charlen(p) : (int)STRLEN(p))
+# define MB_CHARWIDTH(p)    (has_mbyte ? mb_charwidth(p) : (int)STRLEN(p))
 # define PTR2CHAR(p)	    (has_mbyte ? mb_ptr2char(p) : (int)*(p))
 #else
 # define mb_ptr_adv(p)		++p
@@ -292,6 +293,7 @@
 # define mb_ptr_back(s, p)	--p
 # define MB_COPY_CHAR(f, t)	*t++ = *f++
 # define MB_CHARLEN(p)		STRLEN(p)
+# define MB_CHARWIDTH(p)	STRLEN(p)
 # define PTR2CHAR(p)		((int)*(p))
 #endif
 
diff --git a/src/mbyte.c b/src/mbyte.c
index 7a3a27e..5985a6b 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -3607,6 +3607,36 @@ mb_charlen(str)
     return count;
 }
 
+/*
+ * Return the number of display cells "str" occupies.
+ */
+    int
+mb_charwidth(str)
+    char_u	*str;
+{
+    int		len;
+    int		clen;
+    char_u	*im_str, *p;
+
+    len = (int)STRLEN(str);
+
+    if (input_conv.vc_type != CONV_NONE)
+    {
+	im_str = string_convert(&input_conv, (char_u *)str, &len);
+	if (im_str == NULL)
+	    return;
+    }
+    else
+	im_str = (char_u *)str;
+    clen = 0;
+    for (p = im_str; p < im_str + len; p += (*mb_ptr2len)(p))
+	clen += (*mb_ptr2cells)(p);
+    if (input_conv.vc_type != CONV_NONE)
+	vim_free(im_str);
+
+    return clen;
+}
+
 #if defined(FEAT_SPELL) || defined(PROTO)
 /*
  * Like mb_charlen() but for a string with specified length.
@@ -4367,10 +4397,7 @@ im_commit_cb(GtkIMContext *context 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;
 
 #ifdef XIM_DEBUG
     xim_log("im_commit_cb(): %s\n", str);
@@ -4396,19 +4423,7 @@ im_commit_cb(GtkIMContext *context UNUSED,
      * flushed to screen, then it can't get correct "preedit_start_col".
      * Thus, it should calculate the cells by adding cells of the committed
      * string. */
-    if (input_conv.vc_type != CONV_NONE)
-    {
-	im_str = string_convert(&input_conv, (char_u *)str, &len);
-	g_return_if_fail(im_str != NULL);
-    }
-    else
-	im_str = (char_u *)str;
-    clen = 0;
-    for (p = im_str; p < im_str + len; p += (*mb_ptr2len)(p))
-	clen += (*mb_ptr2cells)(p);
-    if (input_conv.vc_type != CONV_NONE)
-	vim_free(im_str);
-    preedit_start_col += clen;
+    preedit_start_col += MB_CHARWIDTH(str);
 
     /* Is this a single character that matches a keypad key that's just
      * been pressed?  If so, we don't want it to be entered as such - let

Raspunde prin e-mail lui