diff options
Diffstat (limited to 'src/nvim/api/buffer.c')
-rw-r--r-- | src/nvim/api/buffer.c | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 4e3468f8d1..775b6e8ea7 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -386,27 +386,29 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ } try_start(); - aco_save_T aco; - aucmd_prepbuf(&aco, buf); if (!MODIFIABLE(buf)) { api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'"); goto end; } - if (u_save((linenr_T)(start - 1), (linenr_T)end) == FAIL) { + if (!buf_ensure_loaded(buf)) { + goto end; + } + + if (u_save_buf(buf, (linenr_T)(start - 1), (linenr_T)end) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to save undo information"); goto end; } - bcount_t deleted_bytes = get_region_bytecount(curbuf, (linenr_T)start, (linenr_T)end, 0, 0); + bcount_t deleted_bytes = get_region_bytecount(buf, (linenr_T)start, (linenr_T)end, 0, 0); // If the size of the range is reducing (ie, new_len < old_len) we // need to delete some old_len. We do this at the start, by // repeatedly deleting line "start". size_t to_delete = (new_len < old_len) ? old_len - new_len : 0; for (size_t i = 0; i < to_delete; i++) { - if (ml_delete((linenr_T)start, false) == FAIL) { + if (ml_delete_buf(buf, (linenr_T)start, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to delete line"); goto end; } @@ -428,7 +430,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ goto end; }); - if (ml_replace((linenr_T)lnum, lines[i], false) == FAIL) { + if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to replace line"); goto end; } @@ -447,7 +449,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ goto end; }); - if (ml_append((linenr_T)lnum, lines[i], 0, false) == FAIL) { + if (ml_append_buf(buf, (linenr_T)lnum, lines[i], 0, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to insert line"); goto end; } @@ -462,20 +464,18 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ // Adjust marks. Invalidate any which lie in the // changed range, and move any in the remainder of the buffer. - // Only adjust marks if we managed to switch to a window that holds - // the buffer, otherwise line numbers will be invalid. - mark_adjust((linenr_T)start, - (linenr_T)(end - 1), - MAXLNUM, - (linenr_T)extra, - kExtmarkNOOP); - - extmark_splice(curbuf, (int)start - 1, 0, (int)(end - start), 0, + mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), MAXLNUM, (linenr_T)extra, + true, true, kExtmarkNOOP); + + extmark_splice(buf, (int)start - 1, 0, (int)(end - start), 0, deleted_bytes, (int)new_len, 0, inserted_bytes, kExtmarkUndo); - changed_lines((linenr_T)start, 0, (linenr_T)end, (linenr_T)extra, true); - fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra); + changed_lines(buf, (linenr_T)start, 0, (linenr_T)end, (linenr_T)extra, true); + if (curwin->w_buffer == buf) { + // mark_adjust_buf handles non-current windows + fix_cursor(curwin, (linenr_T)start, (linenr_T)end, (linenr_T)extra); + } end: for (size_t i = 0; i < new_len; i++) { @@ -483,7 +483,6 @@ end: } xfree(lines); - aucmd_restbuf(&aco); try_end(err); } @@ -630,17 +629,19 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In } try_start(); - aco_save_T aco; - aucmd_prepbuf(&aco, buf); if (!MODIFIABLE(buf)) { api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'"); goto end; } + if (!buf_ensure_loaded(buf)) { + goto end; + } + // Small note about undo states: unlike set_lines, we want to save the // undo state of one past the end_row, since end_row is inclusive. - if (u_save((linenr_T)start_row - 1, (linenr_T)end_row + 1) == FAIL) { + if (u_save_buf(buf, (linenr_T)start_row - 1, (linenr_T)end_row + 1) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to save undo information"); goto end; } @@ -653,7 +654,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In // repeatedly deleting line "start". size_t to_delete = (new_len < old_len) ? old_len - new_len : 0; for (size_t i = 0; i < to_delete; i++) { - if (ml_delete((linenr_T)start_row, false) == FAIL) { + if (ml_delete_buf(buf, (linenr_T)start_row, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to delete line"); goto end; } @@ -674,7 +675,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In goto end; }); - if (ml_replace((linenr_T)lnum, lines[i], false) == FAIL) { + if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to replace line"); goto end; } @@ -691,7 +692,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In goto end; }); - if (ml_append((linenr_T)lnum, lines[i], 0, false) == FAIL) { + if (ml_append_buf(buf, (linenr_T)lnum, lines[i], 0, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to insert line"); goto end; } @@ -702,35 +703,37 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In extra++; } + colnr_T col_extent = (colnr_T)(end_col + - ((end_row == start_row) ? start_col : 0)); + // Adjust marks. Invalidate any which lie in the // changed range, and move any in the remainder of the buffer. - mark_adjust((linenr_T)start_row, - (linenr_T)end_row, - MAXLNUM, - (linenr_T)extra, - kExtmarkNOOP); + // Do not adjust any cursors. need to use column-aware logic (below) + mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row, MAXLNUM, (linenr_T)extra, + true, false, kExtmarkNOOP); - colnr_T col_extent = (colnr_T)(end_col - - ((end_row == start_row) ? start_col : 0)); extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col, (int)(end_row - start_row), col_extent, old_byte, (int)new_len - 1, (colnr_T)last_item.size, new_byte, kExtmarkUndo); - changed_lines((linenr_T)start_row, 0, (linenr_T)end_row + 1, (linenr_T)extra, true); + changed_lines(buf, (linenr_T)start_row, 0, (linenr_T)end_row + 1, (linenr_T)extra, true); - // adjust cursor like an extmark ( i e it was inside last_part_len) - if (curwin->w_cursor.lnum == end_row && curwin->w_cursor.col > end_col) { - curwin->w_cursor.col -= col_extent - (colnr_T)last_item.size; + FOR_ALL_TAB_WINDOWS(tp, win) { + if (win->w_buffer == buf) { + // adjust cursor like an extmark ( i e it was inside last_part_len) + if (win->w_cursor.lnum == end_row && win->w_cursor.col > end_col) { + win->w_cursor.col -= col_extent - (colnr_T)last_item.size; + } + fix_cursor(win, (linenr_T)start_row, (linenr_T)end_row, (linenr_T)extra); + } } - fix_cursor((linenr_T)start_row, (linenr_T)end_row, (linenr_T)extra); end: for (size_t i = 0; i < new_len; i++) { xfree(lines[i]); } xfree(lines); - aucmd_restbuf(&aco); try_end(err); early_end: @@ -1317,21 +1320,19 @@ Dictionary nvim__buf_stats(Buffer buffer, Error *err) // Check if deleting lines made the cursor position invalid. // Changed lines from `lo` to `hi`; added `extra` lines (negative if deleted). -static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra) +static void fix_cursor(win_T *win, linenr_T lo, linenr_T hi, linenr_T extra) { - if (curwin->w_cursor.lnum >= lo) { + if (win->w_cursor.lnum >= lo) { // Adjust cursor position if it's in/after the changed lines. - if (curwin->w_cursor.lnum >= hi) { - curwin->w_cursor.lnum += extra; - check_cursor_col(); + if (win->w_cursor.lnum >= hi) { + win->w_cursor.lnum += extra; } else if (extra < 0) { - check_cursor(); - } else { - check_cursor_col(); + check_cursor_lnum(win); } - changed_cline_bef_curs(); + check_cursor_col_win(win); + changed_cline_bef_curs(win); } - invalidate_botline(); + invalidate_botline(win); } /// Initialise a string array either: |