diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-08-21 14:52:17 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-08-26 12:02:05 +0200 |
commit | 008154954791001efcc46c28146e21403f3a698b (patch) | |
tree | 306721ca60456ba9562c16b9d41cf5ec8d5a360c /src/nvim/change.c | |
parent | 1635c9e75e21e07c4331cf983e14a11c7e09b119 (diff) | |
download | rneovim-008154954791001efcc46c28146e21403f3a698b.tar.gz rneovim-008154954791001efcc46c28146e21403f3a698b.tar.bz2 rneovim-008154954791001efcc46c28146e21403f3a698b.zip |
refactor(change): do API changes to buffer without curbuf switch
Most of the messy things when changing a non-current buffer is
not about the buffer, it is about windows. In particular, it is about
`curwin`.
When editing a non-current buffer which is displayed in some other
window in the current tabpage, one such window will be "borrowed" as the
curwin. But this means if two or more non-current windows displayed the buffers,
one of them will be treated differenty. this is not desirable.
In particular, with nvim_buf_set_text, cursor _column_ position was only
corrected for one single window. Two new tests are added: the test
with just one non-current window passes, but the one with two didn't.
Two corresponding such tests were also added for nvim_buf_set_lines.
This already worked correctly on master, but make sure this is
well-tested for future refactors.
Also, nvim_create_buf no longer invokes autocmds just because you happened
to use `scratch=true`. No option value was changed, therefore OptionSet
must not be fired.
Diffstat (limited to 'src/nvim/change.c')
-rw-r--r-- | src/nvim/change.c | 122 |
1 files changed, 65 insertions, 57 deletions
diff --git a/src/nvim/change.c b/src/nvim/change.c index 36f0fc70a1..067b48faee 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -101,28 +101,28 @@ void change_warning(buf_T *buf, int col) } } -/// Call this function when something in the current buffer is changed. +/// Call this function when something in a buffer is changed. /// /// Most often called through changed_bytes() and changed_lines(), which also /// mark the area of the display to be redrawn. /// /// Careful: may trigger autocommands that reload the buffer. -void changed(void) +void changed(buf_T *buf) { - if (!curbuf->b_changed) { + if (!buf->b_changed) { int save_msg_scroll = msg_scroll; // Give a warning about changing a read-only file. This may also // check-out the file, thus change "curbuf"! - change_warning(curbuf, 0); + change_warning(buf, 0); // Create a swap file if that is wanted. // Don't do this for "nofile" and "nowrite" buffer types. - if (curbuf->b_may_swap && !bt_dontwrite(curbuf)) { + if (buf->b_may_swap && !bt_dontwrite(buf)) { bool save_need_wait_return = need_wait_return; need_wait_return = false; - ml_open_file(curbuf); + ml_open_file(buf); // The ml_open_file() can cause an ATTENTION message. // Wait two seconds, to make sure the user reads this unexpected @@ -137,9 +137,9 @@ void changed(void) need_wait_return = save_need_wait_return; } } - changed_internal(); + changed_internal(buf); } - buf_inc_changedtick(curbuf); + buf_inc_changedtick(buf); // If a pattern is highlighted, the position may now be invalid. highlight_match = false; @@ -147,12 +147,12 @@ void changed(void) /// Internal part of changed(), no user interaction. /// Also used for recovery. -void changed_internal(void) +void changed_internal(buf_T *buf) { - curbuf->b_changed = true; - curbuf->b_changed_invalid = true; - ml_setflags(curbuf); - redraw_buf_status_later(curbuf); + buf->b_changed = true; + buf->b_changed_invalid = true; + ml_setflags(buf); + redraw_buf_status_later(buf); redraw_tabline = true; need_maketitle = true; // set window title later } @@ -160,13 +160,15 @@ void changed_internal(void) /// Common code for when a change was made. /// See changed_lines() for the arguments. /// Careful: may trigger autocommands that reload the buffer. -static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra) +static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra) { // mark the buffer as modified - changed(); + changed(buf); - if (curwin->w_p_diff && diff_internal()) { - curtab->tp_diff_update = true; + FOR_ALL_WINDOWS_IN_TAB(win, curtab) { + if (win->w_buffer == buf && win->w_p_diff && diff_internal()) { + curtab->tp_diff_update = true; + } } // set the '. mark @@ -174,22 +176,25 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T fmarkv_T view = INIT_FMARKV; // Set the markview only if lnum is visible, as changes might be done // outside of the current window view. - if (lnum >= curwin->w_topline && lnum <= curwin->w_botline) { - view = mark_view_make(curwin->w_topline, curwin->w_cursor); + + if (curwin->w_buffer == buf) { + if (lnum >= curwin->w_topline && lnum <= curwin->w_botline) { + view = mark_view_make(curwin->w_topline, curwin->w_cursor); + } } - RESET_FMARK(&curbuf->b_last_change, ((pos_T) { lnum, col, 0 }), curbuf->handle, view); + RESET_FMARK(&buf->b_last_change, ((pos_T) { lnum, col, 0 }), buf->handle, view); // Create a new entry if a new undo-able change was started or we // don't have an entry yet. - if (curbuf->b_new_change || curbuf->b_changelistlen == 0) { + if (buf->b_new_change || buf->b_changelistlen == 0) { int add; - if (curbuf->b_changelistlen == 0) { + if (buf->b_changelistlen == 0) { add = true; } else { // Don't create a new entry when the line number is the same // as the last one and the column is not too far away. Avoids // creating many entries for typing "xxxxx". - pos_T *p = &curbuf->b_changelist[curbuf->b_changelistlen - 1].mark; + pos_T *p = &buf->b_changelist[buf->b_changelistlen - 1].mark; if (p->lnum != lnum) { add = true; } else { @@ -204,17 +209,17 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T // This is the first of a new sequence of undo-able changes // and it's at some distance of the last change. Use a new // position in the changelist. - curbuf->b_new_change = false; + buf->b_new_change = false; - if (curbuf->b_changelistlen == JUMPLISTSIZE) { + if (buf->b_changelistlen == JUMPLISTSIZE) { // changelist is full: remove oldest entry - curbuf->b_changelistlen = JUMPLISTSIZE - 1; - memmove(curbuf->b_changelist, curbuf->b_changelist + 1, - sizeof(curbuf->b_changelist[0]) * (JUMPLISTSIZE - 1)); + buf->b_changelistlen = JUMPLISTSIZE - 1; + memmove(buf->b_changelist, buf->b_changelist + 1, + sizeof(buf->b_changelist[0]) * (JUMPLISTSIZE - 1)); FOR_ALL_TAB_WINDOWS(tp, wp) { // Correct position in changelist for other windows on // this buffer. - if (wp->w_buffer == curbuf && wp->w_changelistidx > 0) { + if (wp->w_buffer == buf && wp->w_changelistidx > 0) { wp->w_changelistidx--; } } @@ -222,27 +227,29 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T FOR_ALL_TAB_WINDOWS(tp, wp) { // For other windows, if the position in the changelist is // at the end it stays at the end. - if (wp->w_buffer == curbuf - && wp->w_changelistidx == curbuf->b_changelistlen) { + if (wp->w_buffer == buf + && wp->w_changelistidx == buf->b_changelistlen) { wp->w_changelistidx++; } } - curbuf->b_changelistlen++; + buf->b_changelistlen++; } } - curbuf->b_changelist[curbuf->b_changelistlen - 1] = - curbuf->b_last_change; + buf->b_changelist[buf->b_changelistlen - 1] = + buf->b_last_change; // The current window is always after the last change, so that "g," // takes you back to it. - curwin->w_changelistidx = curbuf->b_changelistlen; + if (curwin->w_buffer == buf) { + curwin->w_changelistidx = buf->b_changelistlen; + } } - if (VIsual_active) { + if (curwin->w_buffer == buf && VIsual_active) { check_visual_pos(); } FOR_ALL_TAB_WINDOWS(tp, wp) { - if (wp->w_buffer == curbuf) { + if (wp->w_buffer == buf) { // Mark this window to be redrawn later. if (wp->w_redr_type < UPD_VALID) { wp->w_redr_type = UPD_VALID; @@ -295,7 +302,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T if (wp->w_cursor.lnum > lnum) { changed_line_abv_curs_win(wp); } else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) { - changed_cline_bef_curs_win(wp); + changed_cline_bef_curs(wp); } if (wp->w_botline >= lnum) { // Assume that botline doesn't change (inserted lines make @@ -361,7 +368,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T } // when the cursor line is changed always trigger CursorMoved - if (last_cursormoved_win == curwin + if (last_cursormoved_win == curwin && curwin->w_buffer == buf && lnum <= curwin->w_cursor.lnum && lnume + (xtra < 0 ? -xtra : xtra) > curwin->w_cursor.lnum) { last_cursormoved.lnum = 0; @@ -394,7 +401,7 @@ static void changedOneline(buf_T *buf, linenr_T lnum) void changed_bytes(linenr_T lnum, colnr_T col) { changedOneline(curbuf, lnum); - changed_common(lnum, col, lnum + 1, 0); + changed_common(curbuf, lnum, col, lnum + 1, 0); // When text has been changed at the end of the line, possibly the start of // the next line may have SpellCap that should be removed or it needs to be // displayed. Schedule the next line for redrawing just in case. @@ -438,14 +445,14 @@ void inserted_bytes(linenr_T lnum, colnr_T start_col, int old_col, int new_col) /// Takes care of marking the buffer to be redrawn and sets the changed flag. void appended_lines(linenr_T lnum, linenr_T count) { - changed_lines(lnum + 1, 0, lnum + 1, count, true); + changed_lines(curbuf, lnum + 1, 0, lnum + 1, count, true); } /// Like appended_lines(), but adjust marks first. void appended_lines_mark(linenr_T lnum, int count) { mark_adjust(lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L, kExtmarkUndo); - changed_lines(lnum + 1, 0, lnum + 1, (linenr_T)count, true); + changed_lines(curbuf, lnum + 1, 0, lnum + 1, (linenr_T)count, true); } /// Deleted "count" lines at line "lnum" in the current buffer. @@ -453,7 +460,7 @@ void appended_lines_mark(linenr_T lnum, int count) /// Takes care of marking the buffer to be redrawn and sets the changed flag. void deleted_lines(linenr_T lnum, linenr_T count) { - changed_lines(lnum, 0, lnum + count, -count, true); + changed_lines(curbuf, lnum, 0, lnum + count, -count, true); } /// Like deleted_lines(), but adjust marks first. @@ -467,7 +474,7 @@ void deleted_lines_mark(linenr_T lnum, int count) // if we deleted the entire buffer, we need to implicitly add a new empty line extmark_adjust(curbuf, lnum, (linenr_T)(lnum + count - 1), MAXLNUM, -(linenr_T)count + (made_empty ? 1 : 0), kExtmarkUndo); - changed_lines(lnum, 0, lnum + (linenr_T)count, (linenr_T)(-count), true); + changed_lines(curbuf, lnum, 0, lnum + (linenr_T)count, (linenr_T)(-count), true); } /// Marks the area to be redrawn after a change. @@ -477,7 +484,7 @@ void deleted_lines_mark(linenr_T lnum, int count) /// @param lnum first line with change /// @param lnume line below last changed line /// @param xtra number of extra lines (negative when deleting) -void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra) +void buf_redraw_changed_lines_later(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra) { if (buf->b_mod_set) { // find the maximum area that must be redisplayed @@ -504,7 +511,7 @@ void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra) } } -/// Changed lines for the current buffer. +/// Changed lines for a buffer. /// Must be called AFTER the change and after mark_adjust(). /// - mark the buffer changed by calling changed() /// - mark the windows on this buffer to be redisplayed @@ -522,11 +529,12 @@ void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra) /// @param do_buf_event some callers like undo/redo call changed_lines() and /// then increment changedtick *again*. This flag allows these callers to send /// the nvim_buf_lines_event events after they're done modifying changedtick. -void changed_lines(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra, bool do_buf_event) +void changed_lines(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra, + bool do_buf_event) { - changed_lines_buf(curbuf, lnum, lnume, xtra); + buf_redraw_changed_lines_later(buf, lnum, lnume, xtra); - if (xtra == 0 && curwin->w_p_diff && !diff_internal()) { + if (xtra == 0 && curwin->w_p_diff && curwin->w_buffer == buf && !diff_internal()) { // When the number of lines doesn't change then mark_adjust() isn't // called and other diff buffers still need to be marked for // displaying. @@ -537,19 +545,19 @@ void changed_lines(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra, bo redraw_later(wp, UPD_VALID); wlnum = diff_lnum_win(lnum, wp); if (wlnum > 0) { - changed_lines_buf(wp->w_buffer, wlnum, - lnume - lnum + wlnum, 0L); + buf_redraw_changed_lines_later(wp->w_buffer, wlnum, + lnume - lnum + wlnum, 0L); } } } } - changed_common(lnum, col, lnume, xtra); + changed_common(buf, lnum, col, lnume, xtra); if (do_buf_event) { int64_t num_added = (int64_t)(lnume + xtra - lnum); int64_t num_removed = lnume - lnum; - buf_updates_send_changes(curbuf, lnum, num_added, num_removed); + buf_updates_send_changes(buf, lnum, num_added, num_removed); } } @@ -1119,7 +1127,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) *p_extra = NUL; } - u_clearline(); // cannot do "U" command when adding lines + u_clearline(curbuf); // cannot do "U" command when adding lines did_si = false; ai_col = 0; @@ -1807,7 +1815,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) saved_line = NULL; if (did_append) { - changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, + changed_lines(curbuf, curwin->w_cursor.lnum, curwin->w_cursor.col, curwin->w_cursor.lnum + 1, 1L, true); did_append = false; @@ -1833,7 +1841,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) curwin->w_cursor.lnum = old_cursor.lnum + 1; } if (did_append) { - changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L, true); + changed_lines(curbuf, curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L, true); // bail out and just get the final length of the line we just manipulated bcount_t extra = (bcount_t)strlen(ml_get(curwin->w_cursor.lnum)); extmark_splice(curbuf, (int)curwin->w_cursor.lnum - 1, 0, @@ -1958,7 +1966,7 @@ void del_lines(long nlines, bool undo) // Correct the cursor position before calling deleted_lines_mark(), it may // trigger a callback to display the cursor. curwin->w_cursor.col = 0; - check_cursor_lnum(); + check_cursor_lnum(curwin); // adjust marks, mark the buffer as changed and prepare for displaying deleted_lines_mark(first, n); |