mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:9.0.1602: stray character visible if marker on top of double-wide char (#23897)
Problem:    Stray character is visible if 'smoothscroll' marker is displayed
            on top of a double-wide character.
Solution:   When overwriting a double-width character with the 'smoothscroll'
            marker clear the second half. (closes vim/vim#12469)
ecb87dd7d3
			
			
This commit is contained in:
		| @@ -500,8 +500,6 @@ static int grid_char_needs_redraw(ScreenGrid *grid, size_t off_from, size_t off_ | ||||
| void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int clear_width, | ||||
|                       int rlflag, win_T *wp, int bg_attr, bool wrap) | ||||
| { | ||||
|   size_t max_off_from; | ||||
|   size_t max_off_to; | ||||
|   int col = 0; | ||||
|   bool redraw_next;                         // redraw_this for next character | ||||
|   bool clear_next = false; | ||||
| @@ -519,6 +517,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle | ||||
|     endcol = grid->cols; | ||||
|   } | ||||
|  | ||||
|   const size_t max_off_from = (size_t)grid->cols; | ||||
|   grid_adjust(&grid, &row, &coloff); | ||||
|  | ||||
|   // Safety check. Avoids clang warnings down the call stack. | ||||
| @@ -529,8 +528,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle | ||||
|  | ||||
|   size_t off_from = 0; | ||||
|   size_t off_to = grid->line_offset[row] + (size_t)coloff; | ||||
|   max_off_from = linebuf_size; | ||||
|   max_off_to = grid->line_offset[row] + (size_t)grid->cols; | ||||
|   const size_t max_off_to = grid->line_offset[row] + (size_t)grid->cols; | ||||
|  | ||||
|   // Take care of putting "<<<" on the first line for 'smoothscroll'. | ||||
|   if (topline && wp->w_skipcol > 0 | ||||
| @@ -538,18 +536,23 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle | ||||
|       && *get_showbreak_value(wp) == NUL | ||||
|       // do not overwrite the 'listchars' "precedes" text with "<<<" | ||||
|       && !(wp->w_p_list && wp->w_p_lcs_chars.prec != 0)) { | ||||
|     int off = 0; | ||||
|     int skip = 0; | ||||
|     size_t off = 0; | ||||
|     size_t skip = 0; | ||||
|     if (wp->w_p_nu && wp->w_p_rnu) { | ||||
|       // do not overwrite the line number, change "123 text" to | ||||
|       // "123>>>xt". | ||||
|       while (skip < wp->w_width_inner && ascii_isdigit(*linebuf_char[off])) { | ||||
|       while (skip < max_off_from && ascii_isdigit(*linebuf_char[off])) { | ||||
|         off++; | ||||
|         skip++; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < 3 && i + skip < wp->w_width_inner; i++) { | ||||
|     for (size_t i = 0; i < 3 && i + skip < max_off_from; i++) { | ||||
|       if (line_off2cells(linebuf_char, off, max_off_from) > 1) { | ||||
|         // When the first half of a double-width character is | ||||
|         // overwritten, change the second half to a space. | ||||
|         schar_from_ascii(linebuf_char[off + 1], ' '); | ||||
|       } | ||||
|       schar_from_ascii(linebuf_char[off], '<'); | ||||
|       linebuf_attr[off] = HL_ATTR(HLF_AT); | ||||
|       off++; | ||||
|   | ||||
| @@ -667,6 +667,32 @@ describe('smoothscroll', function() | ||||
|     screen:expect(s1) | ||||
|   end) | ||||
|  | ||||
|   -- oldtest: Test_smoothscroll_marker_over_double_width_dump() | ||||
|   it('marker is drawn over double-width char correctly', function() | ||||
|     screen:try_resize(40, 6) | ||||
|     exec([[ | ||||
|       call setline(1, 'a'->repeat(&columns) .. '口'->repeat(10)) | ||||
|       setlocal smoothscroll | ||||
|     ]]) | ||||
|     screen:expect([[ | ||||
|       ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| | ||||
|       口口口口口口口口口口                    | | ||||
|       ~                                       | | ||||
|       ~                                       | | ||||
|       ~                                       | | ||||
|                                               | | ||||
|     ]]) | ||||
|     feed('<C-E>') | ||||
|     screen:expect([[ | ||||
|       <<< 口口口口口口口^口                    | | ||||
|       ~                                       | | ||||
|       ~                                       | | ||||
|       ~                                       | | ||||
|       ~                                       | | ||||
|                                               | | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   -- oldtest: Test_smoothscroll_zero_width() | ||||
|   it("does not divide by zero with a narrow window", function() | ||||
|     screen:try_resize(12, 2) | ||||
|   | ||||
| @@ -399,6 +399,67 @@ func Test_smoothscroll_long_line_showbreak() | ||||
|   call StopVimInTerminal(buf) | ||||
| endfunc | ||||
|  | ||||
| " Check that 'smoothscroll' marker is drawn over double-width char correctly. | ||||
| " Run with multiple encodings. | ||||
| func Test_smoothscroll_marker_over_double_width() | ||||
|   " Run this in a separate Vim instance to avoid messing up. | ||||
|   let after =<< trim [CODE] | ||||
|     scriptencoding utf-8 | ||||
|     call setline(1, 'a'->repeat(&columns) .. '口'->repeat(10)) | ||||
|     setlocal smoothscroll | ||||
|     redraw | ||||
|     exe "norm \<C-E>" | ||||
|     redraw | ||||
|     " Check the chars one by one. Don't check the whole line concatenated. | ||||
|     call assert_equal('<', screenstring(1, 1)) | ||||
|     call assert_equal('<', screenstring(1, 2)) | ||||
|     call assert_equal('<', screenstring(1, 3)) | ||||
|     call assert_equal(' ', screenstring(1, 4)) | ||||
|     call assert_equal('口', screenstring(1, 5)) | ||||
|     call assert_equal('口', screenstring(1, 7)) | ||||
|     call assert_equal('口', screenstring(1, 9)) | ||||
|     call assert_equal('口', screenstring(1, 11)) | ||||
|     call assert_equal('口', screenstring(1, 13)) | ||||
|     call assert_equal('口', screenstring(1, 15)) | ||||
|     call writefile(v:errors, 'Xresult') | ||||
|     qall! | ||||
|   [CODE] | ||||
|  | ||||
|   let encodings = ['utf-8', 'cp932', 'cp936', 'cp949', 'cp950'] | ||||
|   if !has('win32') | ||||
|     let encodings += ['euc-jp'] | ||||
|   endif | ||||
|   if has('nvim') | ||||
|     let encodings = ['utf-8'] | ||||
|   endif | ||||
|   for enc in encodings | ||||
|     let msg = 'enc=' .. enc | ||||
|     if RunVim([], after, $'--clean --cmd "set encoding={enc}"') | ||||
|       call assert_equal([], readfile('Xresult'), msg) | ||||
|     endif | ||||
|     call delete('Xresult') | ||||
|   endfor | ||||
| endfunc | ||||
|  | ||||
| " Same as the test above, but check the text actually shown on screen. | ||||
| " Only run with UTF-8 encoding. | ||||
| func Test_smoothscroll_marker_over_double_width_dump() | ||||
|   CheckScreendump | ||||
|  | ||||
|   let lines =<< trim END | ||||
|     call setline(1, 'a'->repeat(&columns) .. '口'->repeat(10)) | ||||
|     setlocal smoothscroll | ||||
|   END | ||||
|   call writefile(lines, 'XSmoothMarkerOverDoubleWidth', 'D') | ||||
|   let buf = RunVimInTerminal('-S XSmoothMarkerOverDoubleWidth', #{rows: 6, cols: 40}) | ||||
|   call VerifyScreenDump(buf, 'Test_smooth_marker_over_double_width_1', {}) | ||||
|  | ||||
|   call term_sendkeys(buf, "\<C-E>") | ||||
|   call VerifyScreenDump(buf, 'Test_smooth_marker_over_double_width_2', {}) | ||||
|  | ||||
|   call StopVimInTerminal(buf) | ||||
| endfunc | ||||
|  | ||||
| func s:check_col_calc(win_col, win_line, buf_col) | ||||
|   call assert_equal(a:win_col, wincol()) | ||||
|   call assert_equal(a:win_line, winline()) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq