From 2c7dc648ca796786b4847771c1df71dea20a1774 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 8 Apr 2022 10:45:42 +0800 Subject: [PATCH] vim-patch:8.2.3925: diff mode confused by NUL bytes (#18033) Problem: Diff mode confused by NUL bytes. Solution: Handle NUL bytes differently. (Christian Brabandt, closes vim/vim#9421, closes vim/vim#9418) https://github.com/vim/vim/commit/06f6095623cfcc72da08748c058d13b465652fd4 --- src/nvim/diff.c | 14 +++- src/nvim/testdir/test_diffmode.vim | 37 +++++++++ test/functional/ui/diff_spec.lua | 127 +++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 4 deletions(-) diff --git a/src/nvim/diff.c b/src/nvim/diff.c index a6bbe40999..0b55fb877c 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -743,11 +743,16 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { for (char_u *s = ml_get_buf(buf, lnum, false); *s != NUL;) { if (diff_flags & DIFF_ICASE) { + int c; char_u cbuf[MB_MAXBYTES + 1]; - // xdiff doesn't support ignoring case, fold-case the text. - int c = utf_ptr2char(s); - c = utf_fold(c); + if (*s == NL) { + c = NUL; + } else { + // xdiff doesn't support ignoring case, fold-case the text. + c = utf_ptr2char(s); + c = utf_fold(c); + } const int orig_len = utfc_ptr2len(s); if (utf_char2bytes(c, cbuf) != orig_len) { // TODO(Bram): handle byte length difference @@ -759,7 +764,8 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) s += orig_len; len += orig_len; } else { - ptr[len++] = *s++; + ptr[len++] = *s == NL ? NUL : *s; + s++; } } ptr[len++] = NL; diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index 10eb979b45..be9a77ee75 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -1295,4 +1295,41 @@ func Test_diff_filler_cursorcolumn() endfunc +func Test_diff_binary() + CheckScreendump + + let content =<< trim END + call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g']) + vnew + call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g']) + windo diffthis + wincmd p + norm! gg0 + redraw! + END + call writefile(content, 'Xtest_diff_bin') + let buf = RunVimInTerminal('-S Xtest_diff_bin', {}) + + " Test using internal diff + call VerifyScreenDump(buf, 'Test_diff_bin_01', {}) + + " Test using internal diff and case folding + call term_sendkeys(buf, ":set diffopt+=icase\") + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_diff_bin_02', {}) + " Test using external diff + call term_sendkeys(buf, ":set diffopt=filler\") + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_diff_bin_03', {}) + " Test using external diff and case folding + call term_sendkeys(buf, ":set diffopt=filler,icase\") + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_diff_bin_04', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('Xtest_diff_bin') + set diffopt&vim +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index 3a25d7e813..6f67dea2be 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -1226,3 +1226,130 @@ it('Align the filler lines when changing text in diff mode', function() | ]]} end) + +it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', function() + clear() + local screen = Screen.new(40, 20) + screen:set_default_attr_ids({ + [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray}; + [2] = {reverse = true}; + [3] = {background = Screen.colors.LightBlue}; + [4] = {background = Screen.colors.LightMagenta}; + [5] = {background = Screen.colors.Red, bold = true}; + [6] = {foreground = Screen.colors.Blue, bold = true}; + [7] = {background = Screen.colors.Red, foreground = Screen.colors.Blue, bold = true}; + [8] = {reverse = true, bold = true}; + }) + screen:attach() + exec([[ + call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g']) + vnew + call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g']) + windo diffthis + wincmd p + norm! gg0 + redraw! + ]]) + + -- Test using internal diff + screen:expect([[ + {1: }{5:^A}{4: }{2:│}{1: }{5:a}{4: }| + {1: }b {2:│}{1: }b | + {1: }{4:c }{2:│}{1: }{4:c}{7:^@}{4: }| + {1: }d {2:│}{1: }d | + {1: }{5:E}{4: }{2:│}{1: }{5:e}{4: }| + {1: }f {2:│}{1: }f | + {1: }g {2:│}{1: }g | + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + + -- Test using internal diff and case folding + command('set diffopt+=icase') + feed('') + screen:expect([[ + {1: }^A {2:│}{1: }a | + {1: }b {2:│}{1: }b | + {1: }{4:c }{2:│}{1: }{4:c}{7:^@}{4: }| + {1: }d {2:│}{1: }d | + {1: }E {2:│}{1: }e | + {1: }f {2:│}{1: }f | + {1: }g {2:│}{1: }g | + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + + -- Test using external diff + command('set diffopt=filler') + feed('') + screen:expect([[ + {1: }{5:^A}{4: }{2:│}{1: }{5:a}{4: }| + {1: }b {2:│}{1: }b | + {1: }{4:c }{2:│}{1: }{4:c}{7:^@}{4: }| + {1: }d {2:│}{1: }d | + {1: }{5:E}{4: }{2:│}{1: }{5:e}{4: }| + {1: }f {2:│}{1: }f | + {1: }g {2:│}{1: }g | + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + + -- Test using external diff and case folding + command('set diffopt+=filler,icase') + feed('') + screen:expect([[ + {1: }^A {2:│}{1: }a | + {1: }b {2:│}{1: }b | + {1: }{4:c }{2:│}{1: }{4:c}{7:^@}{4: }| + {1: }d {2:│}{1: }d | + {1: }E {2:│}{1: }e | + {1: }f {2:│}{1: }f | + {1: }g {2:│}{1: }g | + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {6:~ }{2:│}{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) +end)