changeset 16211:5fb0f15fafea v8.1.1110

patch 8.1.1110: composing chars on space wrong when 'listchars' is set commit https://github.com/vim/vim/commit/e5e4e22c1c15c8c22b14935affe969569acc8df9 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Apr 4 13:28:45 2019 +0200 patch 8.1.1110: composing chars on space wrong when 'listchars' is set Problem: Composing chars on space wrong when 'listchars' is set. Solution: Do not use "space" and "nbsp" entries of 'listchars' when there is a composing character. (Yee Cheng Chin, closes #4197)
author Bram Moolenaar <Bram@vim.org>
date Thu, 04 Apr 2019 13:30:05 +0200
parents 4ef3771aa5e2
children 862f5ea5dcb0
files src/screen.c src/testdir/test_listchars.vim src/version.c
diffstat 3 files changed, 63 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/screen.c
+++ b/src/screen.c
@@ -4808,34 +4808,36 @@ win_line(
 		}
 #endif
 
-		// 'list': change char 160 to lcs_nbsp and space to lcs_space.
-		if (wp->w_p_list)
-		{
-		    if ((c == 160
-			      || (mb_utf8 && (mb_c == 160 || mb_c == 0x202f)))
-			    && lcs_nbsp)
+		// 'list': Change char 160 to lcs_nbsp and space to lcs_space.
+		// But not when the character is followed by a composing
+		// character (use mb_l to check that).
+		if (wp->w_p_list
+			&& ((((c == 160 && mb_l == 1)
+			      || (mb_utf8
+				  && ((mb_c == 160 && mb_l == 2)
+				      || (mb_c == 0x202f && mb_l == 3))))
+			     && lcs_nbsp)
+			    || (c == ' '
+				&& mb_l == 1
+				&& lcs_space
+				&& ptr - line <= trailcol)))
+		{
+		    c = (c == ' ') ? lcs_space : lcs_nbsp;
+		    if (area_attr == 0 && search_attr == 0)
 		    {
-			c = lcs_nbsp;
-			mb_c = c;
-			if (enc_utf8 && utf_char2len(c) > 1)
-			{
-			    mb_utf8 = TRUE;
-			    u8cc[0] = 0;
-			    c = 0xc0;
-			}
-			else
-			    mb_utf8 = FALSE;
+			n_attr = 1;
+			extra_attr = HL_ATTR(HLF_8);
+			saved_attr2 = char_attr; /* save current attr */
 		    }
-		    else if (c == ' ' && lcs_space && ptr - line <= trailcol)
+		    mb_c = c;
+		    if (enc_utf8 && utf_char2len(c) > 1)
 		    {
-			c = lcs_space;
-			if (mb_utf8 == FALSE && area_attr == 0 && search_attr == 0)
-			{
-			    n_attr = 1;
-			    extra_attr = HL_ATTR(HLF_8);
-			    saved_attr2 = char_attr; // save current attr
-			}
+			mb_utf8 = TRUE;
+			u8cc[0] = 0;
+			c = 0xc0;
 		    }
+		    else
+			mb_utf8 = FALSE;
 		}
 
 		if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ')
--- a/src/testdir/test_listchars.vim
+++ b/src/testdir/test_listchars.vim
@@ -114,6 +114,33 @@ func Test_listchars()
   set listchars& ff&
 endfunc
 
+" Test that unicode listchars characters get properly inserted
+func Test_listchars_unicode()
+  enew!
+  let oldencoding=&encoding
+  set encoding=utf-8
+  set ff=unix
+
+  set listchars=eol:⇔,space:␣,nbsp:≠,tab:←↔→
+  set list
+
+  let nbsp = nr2char(0xa0)
+  call append(0, [
+        \ "a\tb c".nbsp."d"
+        \ ])
+  let expected = [
+        \ 'a←↔↔↔↔↔→b␣c≠d⇔'
+        \ ]
+  redraw!
+  call cursor(1, 1)
+  call assert_equal(expected, ScreenLines(1, virtcol('$')))
+  let &encoding=oldencoding
+  enew!
+  set listchars& ff&
+endfunction
+
+" Tests that space characters following composing character won't get replaced
+" by listchars.
 func Test_listchars_composing()
   enew!
   let oldencoding=&encoding
@@ -121,18 +148,20 @@ func Test_listchars_composing()
   set ff=unix
   set list
 
-  set listchars=eol:$,space:_
+  set listchars=eol:$,space:_,nbsp:=
+  
+  let nbsp1 = nr2char(0xa0)
+  let nbsp2 = nr2char(0x202f)
   call append(0, [
-        \ "  \u3099	 \u309A"
+        \ "  \u3099\t \u309A".nbsp1.nbsp1."\u0302".nbsp2.nbsp2."\u0302",
         \ ])
   let expected = [
-        \ "_ \u3099^I \u309A$"
+        \ "_ \u3099^I \u309A=".nbsp1."\u0302=".nbsp2."\u0302$"
         \ ]
   redraw!
   call cursor(1, 1)
-  let got = ScreenLines(1, virtcol('$'))
-  bw!
-  call assert_equal(expected, got)
+  call assert_equal(expected, ScreenLines(1, virtcol('$')))
   let &encoding=oldencoding
+  enew!
   set listchars& ff&
 endfunction
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1110,
+/**/
     1109,
 /**/
     1108,