src/nvim/screen.c
/// Move one buffered line to the window grid, but only the characters that
/// have actually changed.  Handle insert/delete character.
/// "coloff" gives the first column on the grid for this line.
/// "endcol" gives the columns where valid characters are.
/// "clear_width" is the width of the window.  It's > 0 if the rest of the line
/// needs to be cleared, negative otherwise.
/// "rlflag" is TRUE in a rightleft window:
///    When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
///    When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
/// If "wrap" is true, then hint to the UI that "row" contains a line
/// which has wrapped into the next row.
Move one buffered line to the window grid, but only the characters that
have actually changed.  Handle insert/delete character.
"coloff" gives the first column on the grid for this line.
"endcol" gives the columns where valid characters are.
"clear_width" is the width of the window.  It's > 0 if the rest of the line
needs to be cleared, negative otherwise.
Move one buffered line to the window grid but only the characters that have actually changed . Handle insert / delete character . " coloff " gives the first column on the grid for this line . " endcol " gives the columns where valid characters are . " clear_width " is the width of the window . It ' s > 0 if the rest of the line needs to be cleared negative otherwise .
static 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)
{
  unsigned off_from;
  unsigned off_to;
  unsigned max_off_from;
  unsigned max_off_to;
  int col = 0;
  bool redraw_this;                         
  bool redraw_next;                         
  bool clear_next = false;
  int char_cells;                           
  int start_dirty = -1, end_dirty = 0;
  if (row >= grid->Rows) {
    row = grid->Rows - 1;
  }
  if (endcol > grid->Columns) {
    endcol = grid->Columns;
  }
  screen_adjust_grid(&grid, &row, &coloff);
  if (grid->chars == NULL || row >= grid->Rows || coloff >= grid->Columns) {
    DLOG("invalid state, skipped");
    return;
  }
  off_from = 0;
  off_to = grid->line_offset[row] + coloff;
  max_off_from = linebuf_size;
  max_off_to = grid->line_offset[row] + grid->Columns;
  if (rlflag) {
    if (clear_width > 0) {
      while (col <= endcol && grid->chars[off_to][0] == ' '
             && grid->chars[off_to][1] == NUL
             && grid->attrs[off_to] == bg_attr
             ) {
        ++off_to;
        ++col;
      }
      if (col <= endcol) {
        grid_fill(grid, row, row + 1, col + coloff, endcol + coloff + 1,
                  ' ', ' ', bg_attr);
      }
    }
    col = endcol + 1;
    off_to = grid->line_offset[row] + col + coloff;
    off_from += col;
    endcol = (clear_width > 0 ? clear_width : -clear_width);
  }
  if (bg_attr) {
    for (int c = col; c < endcol; c++) {
      linebuf_attr[off_from+c] =
        hl_combine_attr(bg_attr, linebuf_attr[off_from+c]);
    }
  }
  redraw_next = grid_char_needs_redraw(grid, off_from, off_to, endcol - col);
  while (col < endcol) {
    char_cells = 1;
    if (col + 1 < endcol) {
      char_cells = line_off2cells(linebuf_char, off_from, max_off_from);
    }
    redraw_this = redraw_next;
    redraw_next = grid_char_needs_redraw(grid, off_from + char_cells,
                                         off_to + char_cells,
                                         endcol - col - char_cells);
    if (redraw_this) {
      if (start_dirty == -1) {
        start_dirty = col;
      }
      end_dirty = col + char_cells;
      if (col + char_cells == endcol
          && ((char_cells == 1
               && grid_off2cells(grid, off_to, max_off_to) > 1)
              || (char_cells == 2
                  && grid_off2cells(grid, off_to, max_off_to) == 1
                  && grid_off2cells(grid, off_to + 1, max_off_to) > 1))) {
        clear_next = true;
      }
      schar_copy(grid->chars[off_to], linebuf_char[off_from]);
      if (char_cells == 2) {
        schar_copy(grid->chars[off_to+1], linebuf_char[off_from+1]);
      }
      grid->attrs[off_to] = linebuf_attr[off_from];
      if (char_cells == 2) {
        grid->attrs[off_to + 1] = linebuf_attr[off_from];
      }
    }
    off_to += char_cells;
    off_from += char_cells;
    col += char_cells;
  }
  if (clear_next) {
    schar_from_ascii(grid->chars[off_to], ' ');
    end_dirty++;
  }
  int clear_end = -1;
  if (clear_width > 0 && !rlflag) {
    while (col < clear_width) {
      if (grid->chars[off_to][0] != ' '
          || grid->chars[off_to][1] != NUL
          || grid->attrs[off_to] != bg_attr) {
        grid->chars[off_to][0] = ' ';
        grid->chars[off_to][1] = NUL;
        grid->attrs[off_to] = bg_attr;
        if (start_dirty == -1) {
          start_dirty = col;
          end_dirty = col;
        } else if (clear_end == -1) {
          end_dirty = endcol;
        }
        clear_end = col+1;
      }
      col++;
      off_to++;
    }
  }
  if (clear_width > 0 || wp->w_width != grid->Columns) {
    grid->line_wraps[row] = false;
  }
  if (clear_end < end_dirty) {
    clear_end = end_dirty;
  }
  if (start_dirty == -1) {
    start_dirty = end_dirty;
  }
  if (clear_end > start_dirty) {
    ui_line(grid, row, coloff+start_dirty, coloff+end_dirty, coloff+clear_end,
            bg_attr, wrap);
  }
}
static 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 ) { unsigned off_from ; unsigned off_to ; unsigned max_off_from ; unsigned max_off_to ; int col = 0 ; bool redraw_this ; bool redraw_next ; bool clear_next = false ; int char_cells ; int start_dirty = -1 , end_dirty = 0 ; if ( row >= grid -> Rows ) { row = grid -> Rows - 1 ; } if ( endcol > grid -> Columns ) { endcol = grid -> Columns ; } screen_adjust_grid ( & grid , & row , & coloff ) ; if ( grid -> chars == NULL || row >= grid -> Rows || coloff >= grid -> Columns ) { DLOG ( " " ) ; return ; } off_from = 0 ; off_to = grid -> line_offset [ row ] + coloff ; max_off_from = linebuf_size ; max_off_to = grid -> line_offset [ row ] + grid -> Columns ; if ( rlflag ) { if ( clear_width > 0 ) { while ( col <= endcol && grid -> chars [ off_to ] [ 0 ] == ' ' && grid -> chars [ off_to ] [ 1 ] == NUL && grid -> attrs [ off_to ] == bg_attr ) { ++ off_to ; ++ col ; } if ( col <= endcol ) { grid_fill ( grid , row , row + 1 , col + coloff , endcol + coloff + 1 , ' ' , ' ' , bg_attr ) ; } } col = endcol + 1 ; off_to = grid -> line_offset [ row ] + col + coloff ; off_from += col ; endcol = ( clear_width > 0 ? clear_width : - clear_width ) ; } if ( bg_attr ) { for ( int c = col ; c < endcol ; c ++ ) { linebuf_attr [ off_from + c ] = hl_combine_attr ( bg_attr , linebuf_attr [ off_from + c ] ) ; } } redraw_next = grid_char_needs_redraw ( grid , off_from , off_to , endcol - col ) ; while ( col < endcol ) { char_cells = 1 ; if ( col + 1 < endcol ) { char_cells = line_off2cells ( linebuf_char , off_from , max_off_from ) ; } redraw_this = redraw_next ; redraw_next = grid_char_needs_redraw ( grid , off_from + char_cells , off_to + char_cells , endcol - col - char_cells ) ; if ( redraw_this ) { if ( start_dirty == -1 ) { start_dirty = col ; } end_dirty = col + char_cells ; if ( col + char_cells == endcol && ( ( char_cells == 1 && grid_off2cells ( grid , off_to , max_off_to ) > 1 ) || ( char_cells == 2 && grid_off2cells ( grid , off_to , max_off_to ) == 1 && grid_off2cells ( grid , off_to + 1 , max_off_to ) > 1 ) ) ) { clear_next = true ; } schar_copy ( grid -> chars [ off_to ] , linebuf_char [ off_from ] ) ; if ( char_cells == 2 ) { schar_copy ( grid -> chars [ off_to + 1 ] , linebuf_char [ off_from + 1 ] ) ; } grid -> attrs [ off_to ] = linebuf_attr [ off_from ] ; if ( char_cells == 2 ) { grid -> attrs [ off_to + 1 ] = linebuf_attr [ off_from ] ; } } off_to += char_cells ; off_from += char_cells ; col += char_cells ; } if ( clear_next ) { schar_from_ascii ( grid -> chars [ off_to ] , ' ' ) ; end_dirty ++ ; } int clear_end = -1 ; if ( clear_width > 0 && ! rlflag ) { while ( col < clear_width ) { if ( grid -> chars [ off_to ] [ 0 ] != ' ' || grid -> chars [ off_to ] [ 1 ] != NUL || grid -> attrs [ off_to ] != bg_attr ) { grid -> chars [ off_to ] [ 0 ] = ' ' ; grid -> chars [ off_to ] [ 1 ] = NUL ; grid -> attrs [ off_to ] = bg_attr ; if ( start_dirty == -1 ) { start_dirty = col ; end_dirty = col ; } else if ( clear_end == -1 ) { end_dirty = endcol ; } clear_end = col + 1 ; } col ++ ; off_to ++ ; } } if ( clear_width > 0 || wp -> w_width != grid -> Columns ) { grid -> line_wraps [ row ] = false ; } if ( clear_end < end_dirty ) { clear_end = end_dirty ; } if ( start_dirty == -1 ) { start_dirty = end_dirty ; } if ( clear_end > start_dirty ) { ui_line ( grid , row , coloff + start_dirty , coloff + end_dirty , coloff + clear_end , bg_attr , wrap ) ; } }
Move one buffered line to the window grid, but only the characters that
have actually changed.
Move one buffered line to the window grid but only the characters that have actually changed .
// Does character need redraw? // redraw_this for next character // 1: normal char // 2: occupies two display cells // TODO(bfredl): check all callsites and eliminate // Check for illegal row and col, just in case // Safety check. Avoids clang warnings down the call stack. /* Clear rest first, because it's left of the text. */ // When writing a single-width character over a double-width // character and at the end of the redrawn text, need to clear out // the right halve of the old character. // Also required when writing the right halve of a double-width // char over the left halve of an existing one // For simplicity set the attributes of second half of a // double-wide character equal to the first half. /* Clear the second half of a double-wide character of which the left
     * half was overwritten with a single-wide character. */ // blank out the rest of the line // TODO(bfredl): we could cache winline widths // If we cleared after the end of the line, it did not wrap. // For vsplit, line wrapping is not possible.