mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	fix(grid): handle clearing half a double-width char (#27023)
This commit is contained in:
		@@ -655,6 +655,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
 | 
			
		||||
  // two-cell character in the same grid, truncate that into a '>'.
 | 
			
		||||
  if (col > 0 && grid->chars[off_to + (size_t)col] == 0) {
 | 
			
		||||
    linebuf_char[col - 1] = schar_from_ascii('>');
 | 
			
		||||
    linebuf_attr[col - 1] = grid->attrs[off_to + (size_t)col - 1];
 | 
			
		||||
    col--;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -676,7 +677,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  redraw_next = grid_char_needs_redraw(grid, col, (size_t)col + off_to, endcol - col);
 | 
			
		||||
  redraw_next = grid_char_needs_redraw(grid, col, off_to + (size_t)col, endcol - col);
 | 
			
		||||
 | 
			
		||||
  int start_dirty = -1;
 | 
			
		||||
  int end_dirty = 0;
 | 
			
		||||
@@ -688,7 +689,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
 | 
			
		||||
      char_cells = 2;
 | 
			
		||||
    }
 | 
			
		||||
    bool redraw_this = redraw_next;  // Does character need redraw?
 | 
			
		||||
    size_t off = (size_t)col + off_to;
 | 
			
		||||
    size_t off = off_to + (size_t)col;
 | 
			
		||||
    redraw_next = grid_char_needs_redraw(grid, col + char_cells,
 | 
			
		||||
                                         off + (size_t)char_cells,
 | 
			
		||||
                                         endcol - col - char_cells);
 | 
			
		||||
@@ -732,16 +733,22 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
 | 
			
		||||
  if (clear_next) {
 | 
			
		||||
    // Clear the second half of a double-wide character of which the left
 | 
			
		||||
    // half was overwritten with a single-wide character.
 | 
			
		||||
    grid->chars[(size_t)col + off_to] = schar_from_ascii(' ');
 | 
			
		||||
    grid->chars[off_to + (size_t)col] = schar_from_ascii(' ');
 | 
			
		||||
    end_dirty++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // When clearing the left half of a double-wide char also clear the right half.
 | 
			
		||||
  if (off_to + (size_t)clear_width < max_off_to
 | 
			
		||||
      && grid->chars[off_to + (size_t)clear_width] == 0) {
 | 
			
		||||
    clear_width++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int clear_dirty_start = -1, clear_end = -1;
 | 
			
		||||
  // blank out the rest of the line
 | 
			
		||||
  // TODO(bfredl): we could cache winline widths
 | 
			
		||||
  col = clear_start;
 | 
			
		||||
  while (col < clear_width) {
 | 
			
		||||
    size_t off = (size_t)col + off_to;
 | 
			
		||||
    size_t off = off_to + (size_t)col;
 | 
			
		||||
    if (grid->chars[off] != schar_from_ascii(' ')
 | 
			
		||||
        || grid->attrs[off] != bg_attr
 | 
			
		||||
        || rdb_flags & RDB_NODELTA) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@ describe('multibyte rendering', function()
 | 
			
		||||
      [3] = { background = Screen.colors.LightMagenta },
 | 
			
		||||
      [4] = { bold = true },
 | 
			
		||||
      [5] = { foreground = Screen.colors.Blue },
 | 
			
		||||
      [6] = { reverse = true, bold = true },
 | 
			
		||||
      [7] = { reverse = true },
 | 
			
		||||
    })
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
@@ -84,7 +86,7 @@ describe('multibyte rendering', function()
 | 
			
		||||
      {4:-- INSERT --}                                                |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    -- check double-with char is temporarily hidden when overlapped
 | 
			
		||||
    -- check double-width char is temporarily hidden when overlapped
 | 
			
		||||
    fn.complete(4, { 'xx', 'yy' })
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ab xx^                                                       |
 | 
			
		||||
@@ -104,6 +106,34 @@ describe('multibyte rendering', function()
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('no stray chars when splitting left of window with double-width chars', function()
 | 
			
		||||
    api.nvim_buf_set_lines(0, 0, -1, true, {
 | 
			
		||||
      ('口'):rep(16),
 | 
			
		||||
      'a' .. ('口'):rep(16),
 | 
			
		||||
      'aa' .. ('口'):rep(16),
 | 
			
		||||
      'aaa' .. ('口'):rep(16),
 | 
			
		||||
      'aaaa' .. ('口'):rep(16),
 | 
			
		||||
    })
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ^口口口口口口口口口口口口口口口口                            |
 | 
			
		||||
      a口口口口口口口口口口口口口口口口                           |
 | 
			
		||||
      aa口口口口口口口口口口口口口口口口                          |
 | 
			
		||||
      aaa口口口口口口口口口口口口口口口口                         |
 | 
			
		||||
      aaaa口口口口口口口口口口口口口口口口                        |
 | 
			
		||||
                                                                  |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    command('20vnew')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      ^                    │口口口口口口口口口口口口口口口口       |
 | 
			
		||||
      {1:~                   }│a口口口口口口口口口口口口口口口口      |
 | 
			
		||||
      {1:~                   }│aa口口口口口口口口口口口口口口口口     |
 | 
			
		||||
      {1:~                   }│aaa口口口口口口口口口口口口口口口口    |
 | 
			
		||||
      {6:[No Name]            }{7:[No Name] [+]                          }|
 | 
			
		||||
                                                                  |
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('0xffff is shown as 4 hex digits', function()
 | 
			
		||||
    command([[call setline(1, "\uFFFF!!!")]])
 | 
			
		||||
    feed('$')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user