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

Code before:
    qf_winid = (int)win->handle;
  }

  // autocommands may cause trouble
  incr_quickfix_busy();

  aco_save_T aco;

  if (old_last == NULL) {
    // set curwin/curbuf to buf and save a few things
    aucmd_prepbuf(&aco, buf);
  }

  qf_update_win_titlevar(qi);

  qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
  buf_inc_changedtick(buf);

  if (buf_updates_active(buf)) {
    linenr_T new_line_count = buf->b_ml.ml_line_count;
    colnr_T new_endcol = ml_get_buf_len(buf, new_line_count);
    bcount_t new_byte_count;

    if (old_last == NULL) {
      new_byte_count = get_region_bytecount(buf, 1, new_line_count, 0, new_endcol);
      extmark_splice(buf, 0, 0, new_line_count, 0, old_byte_count, new_line_count - 1,
                     new_endcol, new_byte_count, kExtmarkNoUndo);

      changed_lines(buf, 1, 0, old_line_count > 0 ? old_line_count + 1 : 1,
                    new_line_count - old_line_count, true);
    } else {
      linenr_T start_lnum = old_line_count + 1;
      new_byte_count = get_region_bytecount(buf, start_lnum, new_line_count, 0, new_endcol);
      extmark_splice(buf, old_line_count - 1, old_endcol,
                     0, 0, 0,
                     new_line_count - old_line_count, new_endcol,
                     new_byte_count, kExtmarkNoUndo);

      changed_lines(buf, start_lnum, 0, new_line_count + 1, new_line_count - old_line_count + 1,
                    true);
    }
  }

  if (old_last == NULL) {
    qf_win_pos_update(qi, 0);

    // restore curwin/curbuf and a few other things
    aucmd_restbuf(&aco);
  }

  // Only redraw when added lines are visible.  This avoids flickering when

Review comment (suggestion):
Looking at `qf_fill_buffer()`, it seems multiple lines can be replaced when `old_last == NULL`, so this should be reflected in `old_row` here. Probably:
```suggestion
      extmark_splice(buf, 0, 0, old_line_count - 1, 0, old_byte_count, new_line_count - 1,
```
? Would be good to add a test that replaces multiple lines.

Code after:

  // autocommands may cause trouble
  incr_quickfix_busy();

  aco_save_T aco;

  if (old_last == NULL) {
    // set curwin/curbuf to buf and save a few things
    aucmd_prepbuf(&aco, buf);
  }

  qf_update_win_titlevar(qi);

  qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);

  linenr_T new_line_count = buf->b_ml.ml_line_count;
  colnr_T new_endcol = ml_get_buf_len(buf, new_line_count);
  bcount_t new_byte_count;

  linenr_T delta = new_line_count - old_line_count;
  if (old_last == NULL) {
    new_byte_count = get_region_bytecount(buf, 1, new_line_count, 0, new_endcol);
    extmark_splice(buf, 0, 0, old_line_count - 1, 0, old_bytecount, new_line_count - 1, new_endcol,
                   new_byte_count, kExtmarkNoUndo);
    changed_lines(buf, 1, 0, old_line_count > 0 ? old_line_count + 1 : 1, delta, true);
  } else {
    linenr_T start_lnum = old_line_count + 1;
    new_byte_count = get_region_bytecount(buf, start_lnum, new_line_count, 0, new_endcol);
    extmark_splice(buf, old_line_count - 1, old_endcol, 0, 0, 0, delta, new_endcol, new_byte_count,
                   kExtmarkNoUndo);
    changed_lines(buf, start_lnum, 0, new_line_count + 1, delta + 1, true);
  }
  buf->b_changed = false;

  if (old_last == NULL) {
    qf_win_pos_update(qi, 0);

    // restore curwin/curbuf and a few other things
    aucmd_restbuf(&aco);
  }

  // Only redraw when added lines are visible.  This avoids flickering when
  // the added lines are not visible.
  if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
    redraw_buf_later(buf, UPD_NOT_VALID);
  }

  // always called after incr_quickfix_busy()
  decr_quickfix_busy();
}