Repository: neovim/neovim
File: src/nvim/grid.c (C)

Code before:
  for (int col = first; col < last; col++) {
    linebuf_vcol[mirror - col] = scratch_vcol[col];
  }

  *firstp = width - *clearp;
  *clearp = width - first;
  *lastp = width - last;
}

/// End a group of grid_line_puts calls and send the screen buffer to the UI layer.
void grid_line_flush(void)
{
  ScreenGrid *grid = grid_line_grid;
  grid_line_grid = NULL;
  grid_line_clear_to = MAX(grid_line_last, grid_line_clear_to);

  // In extreme layouts we may end up with grid_line_clear_to slightly past grid_line_maxcol,
  // clamp it so we never try to clear beyond the available segment.
  if (grid_line_clear_to > grid_line_maxcol) {
    if (grid_line_maxcol < 0) {
      grid_line_maxcol = 0;
    }
    grid_line_clear_to = grid_line_maxcol;
  }

  assert(grid_line_clear_to <= grid_line_maxcol);
  if (grid_line_first >= grid_line_clear_to) {
    return;
  }

  grid_put_linebuf(grid, grid_line_row, grid_line_coloff, grid_line_first, grid_line_last,
                   grid_line_clear_to, grid_line_bg_attr, grid_line_clear_attr, -1,
                   grid_line_flags);
}

/// flush grid line but only if on a valid row
///
/// This is a stopgap until message.c has been refactored to behave
void grid_line_flush_if_valid_row(void)
{
  if (grid_line_row < 0 || grid_line_row >= grid_line_grid->rows) {
    if (rdb_flags & kOptRdbFlagInvalid) {
      abort();
    } else {
      grid_line_grid = NULL;
      return;
    }
  }
  grid_line_flush();
}


Review comment (bug):
This `assert` is here because the situation your code works-around, presumably indicates a bug somewhere else. So adding this workaround (1) doesn't fix the actual problem, and (2) makes this assert redundant (except the `=` case, which strangely the new code does not workaround...)



Code after:

/// End a group of grid_line_puts calls and send the screen buffer to the UI layer.
void grid_line_flush(void)
{
  ScreenGrid *grid = grid_line_grid;
  grid_line_grid = NULL;
  grid_line_clear_to = MAX(grid_line_last, grid_line_clear_to);
  assert(grid_line_clear_to <= grid_line_maxcol);
  if (grid_line_first >= grid_line_clear_to) {
    return;
  }

  grid_put_linebuf(grid, grid_line_row, grid_line_coloff, grid_line_first, grid_line_last,
                   grid_line_clear_to, grid_line_bg_attr, grid_line_clear_attr, -1,
                   grid_line_flags);
}

/// flush grid line but only if on a valid row
///
/// This is a stopgap until message.c has been refactored to behave
void grid_line_flush_if_valid_row(void)
{
  if (grid_line_row < 0 || grid_line_row >= grid_line_grid->rows) {
    if (rdb_flags & kOptRdbFlagInvalid) {
      abort();
    } else {
      grid_line_grid = NULL;
      return;
    }
  }
  grid_line_flush();
}

void grid_clear(GridView *grid, int start_row, int end_row, int start_col, int end_col, int attr)
{
  for (int row = start_row; row < end_row; row++) {
    grid_line_start(grid, row);
    end_col = MIN(end_col, grid_line_maxcol);
    if (grid_line_row >= grid_line_grid->rows || start_col >= end_col) {
      grid_line_grid = NULL;  // TODO(bfredl): make callers behave instead
      return;
    }
    grid_line_clear_end(start_col, end_col, attr, 0);
    grid_line_flush();
  }
}

/// Check whether the given character needs redrawing:
/// - the (first byte of the) character is different
/// - the attributes are different
/// - the character is multi-byte and the next byte is different