changeset 4029:d179a8eff9d7 v7.3.769

updated for version 7.3.769 Problem: 'matchpairs' does not work with multi-byte characters. Solution: Make it work. (Christian Brabandt)
author Bram Moolenaar <bram@vim.org>
date Thu, 17 Jan 2013 17:02:05 +0100
parents 639564cb15a1
children e27a6d286f3e
files src/misc1.c src/option.c src/proto/option.pro src/search.c src/testdir/test69.in src/testdir/test69.ok src/version.c
diffstat 7 files changed, 179 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -2288,14 +2288,18 @@ ins_char_bytes(buf, charlen)
      */
     if (p_sm && (State & INSERT)
 	    && msg_silent == 0
-#ifdef FEAT_MBYTE
-	    && charlen == 1
-#endif
 #ifdef FEAT_INS_EXPAND
 	    && !ins_compl_active()
 #endif
        )
-	showmatch(c);
+    {
+#ifdef FEAT_MBYTE
+	if (has_mbyte)
+	    showmatch(mb_ptr2char(buf));
+	else
+#endif
+	    showmatch(c);
+    }
 
 #ifdef FEAT_RIGHTLEFT
     if (!p_ri || (State & REPLACE_FLAG))
--- a/src/option.c
+++ b/src/option.c
@@ -6149,16 +6149,46 @@ did_set_string_option(opt_idx, varp, new
     /* 'matchpairs' */
     else if (gvarp == &p_mps)
     {
-	/* Check for "x:y,x:y" */
-	for (p = *varp; *p != NUL; p += 4)
-	{
-	    if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
-	    {
-		errmsg = e_invarg;
-		break;
-	    }
-	    if (p[3] == NUL)
-		break;
+#ifdef FEAT_MBYTE
+	if (has_mbyte)
+	{
+	    for (p = *varp; *p != NUL; ++p)
+	    {
+		int x2,x3 = -1;
+
+		if (*p != NUL)
+		    p += mb_ptr2len(p);
+		if (*p != NUL)
+		    x2 = *p++;
+		if (*p != NUL)
+		{
+		    x3 = mb_ptr2char(p);
+		    p += mb_ptr2len(p);
+		}
+		if (x2 != ':' || x2 == -1 || x3 == -1
+						  || (*p != NUL && *p != ','))
+		{
+		    errmsg = e_invarg;
+		    break;
+		}
+		if (*p == NUL)
+		    break;
+	    }
+	}
+	else
+#endif
+	{
+	    /* Check for "x:y,x:y" */
+	    for (p = *varp; *p != NUL; p += 4)
+	    {
+		if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
+		{
+		    errmsg = e_invarg;
+		    break;
+		}
+		if (p[3] == NUL)
+		    break;
+	    }
 	}
     }
 
@@ -11453,3 +11483,101 @@ get_sts_value()
 {
     return curbuf->b_p_sts < 0 ? get_sw_value() : curbuf->b_p_sts;
 }
+
+/*
+ * Check matchpairs option for "*initc".
+ * If there is a match set "*initc" to the matching character and "*findc" to
+ * the opposite character.  Set "*backwards" to the direction.
+ * When "switchit" is TRUE swap the direction.
+ */
+    void
+find_mps_values(initc, findc, backwards, switchit)
+    int	    *initc;
+    int	    *findc;
+    int	    *backwards;
+    int	    switchit;
+{
+    char_u	*ptr;
+
+    ptr = curbuf->b_p_mps;
+    while (*ptr != NUL)
+    {
+#ifdef FEAT_MBYTE
+	if (has_mbyte)
+	{
+	    char_u *prev;
+
+	    if (mb_ptr2char(ptr) == *initc)
+	    {
+		if (switchit)
+		{
+		    *findc = *initc;
+		    *initc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
+		    *backwards = TRUE;
+		}
+		else
+		{
+		    *findc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
+		    *backwards = FALSE;
+		}
+		return;
+	    }
+	    prev = ptr;
+	    ptr += mb_ptr2len(ptr) + 1;
+	    if (mb_ptr2char(ptr) == *initc)
+	    {
+		if (switchit)
+		{
+		    *findc = *initc;
+		    *initc = mb_ptr2char(prev);
+		    *backwards = FALSE;
+		}
+		else
+		{
+		    *findc = mb_ptr2char(prev);
+		    *backwards = TRUE;
+		}
+		return;
+	    }
+	    ptr += mb_ptr2len(ptr);
+	}
+	else
+#endif
+	{
+	    if (*ptr == *initc)
+	    {
+		if (switchit)
+		{
+		    *backwards = TRUE;
+		    *findc = *initc;
+		    *initc = ptr[2];
+		}
+		else
+		{
+		    *backwards = FALSE;
+		    *findc = ptr[2];
+		}
+		return;
+	    }
+	    ptr += 2;
+	    if (*ptr == *initc)
+	    {
+		if (switchit)
+		{
+		    *backwards = FALSE;
+		    *findc = *initc;
+		    *initc = ptr[-2];
+		}
+		else
+		{
+		    *backwards = TRUE;
+		    *findc =  ptr[-2];
+		}
+		return;
+	    }
+	    ++ptr;
+	}
+	if (*ptr == ',')
+	    ++ptr;
+    }
+}
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -59,4 +59,5 @@ int file_ff_differs __ARGS((buf_T *buf, 
 int check_ff_value __ARGS((char_u *p));
 long get_sw_value __ARGS((void));
 long get_sts_value __ARGS((void));
+void find_mps_values __ARGS((int *initc, int *findc, int *backwards, int switchit));
 /* vim: set ft=c : */
--- a/src/search.c
+++ b/src/search.c
@@ -1786,28 +1786,8 @@ findmatchlimit(oap, initc, flags, maxtra
     }
     else if (initc != '#' && initc != NUL)
     {
-	/* 'matchpairs' is "x:y,x:y" */
-	for (ptr = curbuf->b_p_mps; *ptr; ptr += 2)
-	{
-	    if (*ptr == initc)
-	    {
-		findc = initc;
-		initc = ptr[2];
-		backwards = TRUE;
-		break;
-	    }
-	    ptr += 2;
-	    if (*ptr == initc)
-	    {
-		findc = initc;
-		initc = ptr[-2];
-		backwards = FALSE;
-		break;
-	    }
-	    if (ptr[1] != ',')
-		break;
-	}
-	if (!findc)		/* invalid initc! */
+	find_mps_values(&initc, &findc, &backwards, TRUE);
+	if (findc == NUL)
 	    return NULL;
     }
     /*
@@ -1886,36 +1866,14 @@ findmatchlimit(oap, initc, flags, maxtra
 		    --pos.col;
 		for (;;)
 		{
-		    initc = linep[pos.col];
+		    initc = PTR2CHAR(linep + pos.col);
 		    if (initc == NUL)
 			break;
 
-		    for (ptr = curbuf->b_p_mps; *ptr; ++ptr)
-		    {
-			if (*ptr == initc)
-			{
-			    findc = ptr[2];
-			    backwards = FALSE;
-			    break;
-			}
-			ptr += 2;
-			if (*ptr == initc)
-			{
-			    findc = ptr[-2];
-			    backwards = TRUE;
-			    break;
-			}
-			if (!*++ptr)
-			    break;
-		    }
+		    find_mps_values(&initc, &findc, &backwards, FALSE);
 		    if (findc)
 			break;
-#ifdef FEAT_MBYTE
-		    if (has_mbyte)
-			pos.col += (*mb_ptr2len)(linep + pos.col);
-		    else
-#endif
-			++pos.col;
+		    pos.col += MB_PTR2LEN(linep + pos.col);
 		}
 		if (!findc)
 		{
@@ -2260,7 +2218,8 @@ findmatchlimit(oap, initc, flags, maxtra
 	 *   inquote if the number of quotes in a line is even, unless this
 	 *   line or the previous one ends in a '\'.  Complicated, isn't it?
 	 */
-	switch (c = linep[pos.col])
+	c = PTR2CHAR(linep + pos.col);
+	switch (c)
 	{
 	case NUL:
 	    /* at end of line without trailing backslash, reset inquote */
@@ -2469,20 +2428,23 @@ showmatch(c)
      * Only show match for chars in the 'matchpairs' option.
      */
     /* 'matchpairs' is "x:y,x:y" */
-    for (p = curbuf->b_p_mps; *p != NUL; p += 2)
+    for (p = curbuf->b_p_mps; *p != NUL; ++p)
     {
+	if (PTR2CHAR(p) == c
 #ifdef FEAT_RIGHTLEFT
-	if (*p == c && (curwin->w_p_rl ^ p_ri))
-	    break;
+		    && (curwin->w_p_rl ^ p_ri)
 #endif
-	p += 2;
-	if (*p == c
+	   )
+	    break;
+	p += MB_PTR2LEN(p) + 1;
+	if (PTR2CHAR(p) == c
 #ifdef FEAT_RIGHTLEFT
 		&& !(curwin->w_p_rl ^ p_ri)
 #endif
 	   )
 	    break;
-	if (p[1] != ',')
+	p += MB_PTR2LEN(p);
+	if (*p == NUL)
 	    return;
     }
 
--- a/src/testdir/test69.in
+++ b/src/testdir/test69.in
@@ -1,4 +1,5 @@
 Test for multi-byte text formatting.
+Also test, that 'mps' with multibyte chars works.
 
 STARTTEST
 :so mbyte.vim
@@ -134,6 +135,15 @@ ENDTEST
 }
 
 STARTTEST
+/^{/+1
+:set mps+=u2018:u2019
+d%
+ENDTEST
+
+{
+‘ two three ’ four
+}
+STARTTEST
 :g/^STARTTEST/.,/^ENDTEST/d
 :1;/^Results/,$wq! test.out
 ENDTEST
--- a/src/testdir/test69.ok
+++ b/src/testdir/test69.ok
@@ -140,3 +140,7 @@ a
 a
 }
 
+
+{
+ four
+}
--- a/src/version.c
+++ b/src/version.c
@@ -726,6 +726,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    769,
+/**/
     768,
 /**/
     767,