diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/change.c | 18 | ||||
-rw-r--r-- | src/nvim/diff.c | 6 | ||||
-rw-r--r-- | src/nvim/edit.c | 2 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 7 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 6 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 12 | ||||
-rw-r--r-- | src/nvim/fileio.c | 10 | ||||
-rw-r--r-- | src/nvim/globals.h | 3 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 4 | ||||
-rw-r--r-- | src/nvim/undo.c | 333 |
11 files changed, 216 insertions, 186 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 17bd81b230..a4d9229b51 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -525,6 +525,7 @@ struct file_buffer { int b_flags; // various BF_ flags int b_locked; // Buffer is being closed or referenced, don't // let autocommands wipe it out. + int b_ro_locked; // Replacement for curbuf_lock // // b_ffname has the full path of the file (NULL for no name). diff --git a/src/nvim/change.c b/src/nvim/change.c index c0183d4317..ca98d8f40b 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -40,18 +40,18 @@ /// "col" is the column for the message; non-zero when in insert mode and /// 'showmode' is on. /// Careful: may trigger autocommands that reload the buffer. -void change_warning(int col) +void change_warning(buf_T *buf, int col) { static char *w_readonly = N_("W10: Warning: Changing a readonly file"); - if (curbuf->b_did_warn == false + if (buf->b_did_warn == false && curbufIsChanged() == 0 && !autocmd_busy - && curbuf->b_p_ro) { - curbuf_lock++; - apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, false, curbuf); - curbuf_lock--; - if (!curbuf->b_p_ro) { + && buf->b_p_ro) { + buf->b_ro_locked++; + apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, false, buf); + buf->b_ro_locked--; + if (!buf->b_p_ro) { return; } // Do what msg() does, but with a column offset if the warning should @@ -70,7 +70,7 @@ void change_warning(int col) ui_flush(); os_delay(1002L, true); // give the user time to think about it } - curbuf->b_did_warn = true; + buf->b_did_warn = true; redraw_cmdline = false; // don't redraw and erase the message if (msg_row < Rows - 1) { showmode(); @@ -91,7 +91,7 @@ void changed(void) // Give a warning about changing a read-only file. This may also // check-out the file, thus change "curbuf"! - change_warning(0); + change_warning(curbuf, 0); // Create a swap file if that is wanted. // Don't do this for "nofile" and "nowrite" buffer types. diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 53cb14bcc7..d462cea9dd 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1334,9 +1334,9 @@ static void set_diff_option(win_T *wp, int value) curwin = wp; curbuf = curwin->w_buffer; - curbuf_lock++; + curbuf->b_ro_locked++; set_option_value("diff", (long)value, NULL, OPT_LOCAL); - curbuf_lock--; + curbuf->b_ro_locked--; curwin = old_curwin; curbuf = curwin->w_buffer; } @@ -2603,7 +2603,7 @@ void ex_diffgetput(exarg_T *eap) // FileChangedRO autocommand, which may do nasty things and mess // everything up. if (!curbuf->b_changed) { - change_warning(0); + change_warning(curbuf, 0); if (diff_buf_idx(curbuf) != idx_to) { EMSG(_("E787: Buffer changed unexpectedly")); goto theend; diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 5887817ec3..1fe8c0e8e9 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -467,7 +467,7 @@ static void insert_enter(InsertState *s) } if (!p_im && did_restart_edit == 0) { - change_warning(s->i == 0 ? 0 : s->i + 1); + change_warning(curbuf, s->i == 0 ? 0 : s->i + 1); } ui_cursor_shape(); // may show different cursor shape diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1ba31bfe68..3cda7ec5d4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1078,10 +1078,11 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - /* Check for undo allowed here, because if something was already inserted - * the line was already saved for undo and this check isn't done. */ - if (!undo_allowed()) + // Check for undo allowed here, because if something was already inserted + // the line was already saved for undo and this check isn't done. + if (!undo_allowed(curbuf)) { return; + } if (argvars[1].v_type != VAR_LIST) { EMSG(_(e_invarg)); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 4af7794317..c5400f8781 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2607,7 +2607,7 @@ int do_ecmd( && (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)) { // Sync first so that this is a separate undo-able action. u_sync(false); - if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, true) + if (u_savecommon(curbuf, 0, curbuf->b_ml.ml_line_count + 1, 0, true) == FAIL) { xfree(new_name); goto theend; @@ -5159,9 +5159,9 @@ void fix_help_buffer(void) // Set filetype to "help". if (STRCMP(curbuf->b_p_ft, "help") != 0) { - curbuf_lock++; + curbuf->b_ro_locked++; set_option_value("ft", 0L, "help", OPT_LOCAL); - curbuf_lock--; + curbuf->b_ro_locked--; } if (!syntax_present(curwin)) { diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index f63987136f..2dfe2950fc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2412,13 +2412,11 @@ char_u * get_text_locked_msg(void) { } } -/* - * Check if "curbuf_lock" or "allbuf_lock" is set and return TRUE when it is - * and give an error message. - */ +/// Check if "curbuf_lock" or "allbuf_lock" is set and return TRUE when it is +/// and give an error message. int curbuf_locked(void) { - if (curbuf_lock > 0) { + if (curbuf->b_ro_locked > 0) { EMSG(_("E788: Not allowed to edit another buffer now")); return TRUE; } @@ -6513,7 +6511,7 @@ static int open_cmdwin(void) curwin->w_p_fen = false; // Don't allow switching to another buffer. - curbuf_lock++; + curbuf->b_ro_locked++; // Showing the prompt may have set need_wait_return, reset it. need_wait_return = false; @@ -6526,7 +6524,7 @@ static int open_cmdwin(void) } set_option_value("ft", 0L, "vim", OPT_LOCAL); } - curbuf_lock--; + curbuf->b_ro_locked--; // Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin // sets 'textwidth' to 78). diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 645423eafe..5d44a70a05 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -4687,7 +4687,7 @@ check_timestamps( } if (!stuff_empty() || global_busy || !typebuf_typed() - || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0 + || autocmd_busy || curbuf->b_ro_locked > 0 || allbuf_lock > 0 ) { need_check_timestamps = true; // check later } else { @@ -5015,10 +5015,10 @@ void buf_reload(buf_T *buf, int orig_mode) old_topline = curwin->w_topline; if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { - /* Save all the text, so that the reload can be undone. - * Sync first so that this is a separate undo-able action. */ - u_sync(FALSE); - saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE); + // Save all the text, so that the reload can be undone. + // Sync first so that this is a separate undo-able action. + u_sync(false); + saved = u_savecommon(curbuf, 0, curbuf->b_ml.ml_line_count + 1, 0, true); flags |= READ_KEEP_UNDO; } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 7c7ce5e65f..a7959bcfe3 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -508,9 +508,6 @@ EXTERN int secure INIT(= false); /// allowed. EXTERN int textlock INIT(= 0); -/// Non-zero when the current buffer can't be changed. Used for FileChangedRO. -EXTERN int curbuf_lock INIT(= 0); - /// Non-zero when no buffer name can be changed, no buffer can be deleted and /// current directory can't be changed. Used for SwapExists et al. EXTERN int allbuf_lock INIT(= 0); diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 71624baaf4..77f86e75cc 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4180,7 +4180,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, // Set the 'filetype' to "qf" each time after filling the buffer. This // resembles reading a file into a buffer, it's more logical when using // autocommands. - curbuf_lock++; + curbuf->b_locked++; set_option_value("ft", 0L, "qf", OPT_LOCAL); curbuf->b_p_ma = false; @@ -4190,7 +4190,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, false, curbuf); keep_filetype = false; - curbuf_lock--; + curbuf->b_locked--; // make sure it will be redrawn redraw_curbuf_later(NOT_VALID); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 2010aa42d8..ea254033f1 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -234,7 +234,7 @@ int u_save(linenr_T top, linenr_T bot) if (top + 2 == bot) u_saveline((linenr_T)(top + 1)); - return u_savecommon(top, bot, (linenr_T)0, FALSE); + return u_savecommon(curbuf, top, bot, (linenr_T)0, false); } /* @@ -245,7 +245,7 @@ int u_save(linenr_T top, linenr_T bot) */ int u_savesub(linenr_T lnum) { - return u_savecommon(lnum - 1, lnum + 1, lnum + 1, false); + return u_savecommon(curbuf, lnum - 1, lnum + 1, lnum + 1, false); } /* @@ -256,7 +256,7 @@ int u_savesub(linenr_T lnum) */ int u_inssub(linenr_T lnum) { - return u_savecommon(lnum - 1, lnum, lnum + 1, false); + return u_savecommon(curbuf, lnum - 1, lnum, lnum + 1, false); } /* @@ -268,18 +268,19 @@ int u_inssub(linenr_T lnum) */ int u_savedel(linenr_T lnum, long nlines) { - return u_savecommon(lnum - 1, lnum + nlines, - nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE); + return u_savecommon( + curbuf, lnum - 1, lnum + nlines, + nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, false); } /// Return true when undo is allowed. Otherwise print an error message and /// return false. /// /// @return true if undo is allowed. -bool undo_allowed(void) +bool undo_allowed(buf_T *buf) { - /* Don't allow changes when 'modifiable' is off. */ - if (!MODIFIABLE(curbuf)) { + // Don't allow changes when 'modifiable' is off. + if (!MODIFIABLE(buf)) { EMSG(_(e_modifiable)); return false; } @@ -301,12 +302,12 @@ bool undo_allowed(void) } /// Get the 'undolevels' value for the current buffer. -static long get_undolevel(void) +static long get_undolevel(buf_T *buf) { - if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) { + if (buf->b_p_ul == NO_LOCAL_UNDOLEVEL) { return p_ul; } - return curbuf->b_p_ul; + return buf->b_p_ul; } static inline void zero_fmark_additional_data(fmark_T *fmarks) @@ -326,7 +327,9 @@ static inline void zero_fmark_additional_data(fmark_T *fmarks) * Careful: may trigger autocommands that reload the buffer. * Returns FAIL when lines could not be saved, OK otherwise. */ -int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) +int u_savecommon(buf_T *buf, + linenr_T top, linenr_T bot, + linenr_T newbot, int reload) { linenr_T lnum; long i; @@ -337,22 +340,24 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) long size; if (!reload) { - /* When making changes is not allowed return FAIL. It's a crude way - * to make all change commands fail. */ - if (!undo_allowed()) + // When making changes is not allowed return FAIL. It's a crude way + // to make all change commands fail. + if (!undo_allowed(buf)) { return FAIL; + } + // Saving text for undo means we are going to make a change. Give a + // warning for a read-only file before making the change, so that the + // FileChangedRO event can replace the buffer with a read-write version + // (e.g., obtained from a source control system). + // TODO(vigoux): change_warning is tricky because of curbuf_lock... + if (buf == curbuf) { + change_warning(buf, 0); + } - /* - * Saving text for undo means we are going to make a change. Give a - * warning for a read-only file before making the change, so that the - * FileChangedRO event can replace the buffer with a read-write version - * (e.g., obtained from a source control system). - */ - change_warning(0); - if (bot > curbuf->b_ml.ml_line_count + 1) { - /* This happens when the FileChangedRO autocommand changes the - * file in a way it becomes shorter. */ + if (bot > buf->b_ml.ml_line_count + 1) { + // This happens when the FileChangedRO autocommand changes the + // file in a way it becomes shorter. EMSG(_("E881: Line count changed unexpectedly")); return FAIL; } @@ -364,18 +369,14 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) size = bot - top - 1; - /* - * If curbuf->b_u_synced == true make a new header. - */ - if (curbuf->b_u_synced) { - /* Need to create new entry in b_changelist. */ - curbuf->b_new_change = true; - - if (get_undolevel() >= 0) { - /* - * Make a new header entry. Do this first so that we don't mess - * up the undo info when out of memory. - */ + // If curbuf->b_u_synced == true make a new header. + if (buf->b_u_synced) { + // Need to create new entry in b_changelist. + buf->b_new_change = true; + + if (get_undolevel(buf) >= 0) { + // Make a new header entry. Do this first so that we don't mess + // up the undo info when out of memory. uhp = xmalloc(sizeof(u_header_T)); kv_init(uhp->uh_extmark); #ifdef U_DEBUG @@ -388,63 +389,73 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) * If we undid more than we redid, move the entry lists before and * including curbuf->b_u_curhead to an alternate branch. */ - old_curhead = curbuf->b_u_curhead; + old_curhead = buf->b_u_curhead; if (old_curhead != NULL) { - curbuf->b_u_newhead = old_curhead->uh_next.ptr; - curbuf->b_u_curhead = NULL; + buf->b_u_newhead = old_curhead->uh_next.ptr; + buf->b_u_curhead = NULL; } /* * free headers to keep the size right */ - while (curbuf->b_u_numhead > get_undolevel() - && curbuf->b_u_oldhead != NULL) { - u_header_T *uhfree = curbuf->b_u_oldhead; - - if (uhfree == old_curhead) - /* Can't reconnect the branch, delete all of it. */ - u_freebranch(curbuf, uhfree, &old_curhead); - else if (uhfree->uh_alt_next.ptr == NULL) - /* There is no branch, only free one header. */ - u_freeheader(curbuf, uhfree, &old_curhead); - else { - /* Free the oldest alternate branch as a whole. */ - while (uhfree->uh_alt_next.ptr != NULL) + while (buf->b_u_numhead > get_undolevel(buf) + && buf->b_u_oldhead != NULL) { + u_header_T *uhfree = buf->b_u_oldhead; + + if (uhfree == old_curhead) { + // Can't reconnect the branch, delete all of it. + u_freebranch(buf, uhfree, &old_curhead); + } else if (uhfree->uh_alt_next.ptr == NULL) { + // There is no branch, only free one header. + u_freeheader(buf, uhfree, &old_curhead); + } else { + // Free the oldest alternate branch as a whole. + while (uhfree->uh_alt_next.ptr != NULL) { uhfree = uhfree->uh_alt_next.ptr; - u_freebranch(curbuf, uhfree, &old_curhead); + } + u_freebranch(buf, uhfree, &old_curhead); } #ifdef U_DEBUG u_check(TRUE); #endif } - if (uhp == NULL) { /* no undo at all */ - if (old_curhead != NULL) - u_freebranch(curbuf, old_curhead, NULL); - curbuf->b_u_synced = false; + if (uhp == NULL) { // no undo at all + if (old_curhead != NULL) { + u_freebranch(buf, old_curhead, NULL); + } + buf->b_u_synced = false; return OK; } uhp->uh_prev.ptr = NULL; - uhp->uh_next.ptr = curbuf->b_u_newhead; + uhp->uh_next.ptr = buf->b_u_newhead; uhp->uh_alt_next.ptr = old_curhead; if (old_curhead != NULL) { uhp->uh_alt_prev.ptr = old_curhead->uh_alt_prev.ptr; - if (uhp->uh_alt_prev.ptr != NULL) + + if (uhp->uh_alt_prev.ptr != NULL) { uhp->uh_alt_prev.ptr->uh_alt_next.ptr = uhp; + } + old_curhead->uh_alt_prev.ptr = uhp; - if (curbuf->b_u_oldhead == old_curhead) - curbuf->b_u_oldhead = uhp; - } else + + if (buf->b_u_oldhead == old_curhead) { + buf->b_u_oldhead = uhp; + } + } else { uhp->uh_alt_prev.ptr = NULL; - if (curbuf->b_u_newhead != NULL) - curbuf->b_u_newhead->uh_prev.ptr = uhp; + } - uhp->uh_seq = ++curbuf->b_u_seq_last; - curbuf->b_u_seq_cur = uhp->uh_seq; + if (buf->b_u_newhead != NULL) { + buf->b_u_newhead->uh_prev.ptr = uhp; + } + + uhp->uh_seq = ++buf->b_u_seq_last; + buf->b_u_seq_cur = uhp->uh_seq; uhp->uh_time = time(NULL); uhp->uh_save_nr = 0; - curbuf->b_u_time_cur = uhp->uh_time + 1; + buf->b_u_time_cur = uhp->uh_time + 1; uhp->uh_walk = 0; uhp->uh_entry = NULL; @@ -455,23 +466,26 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) else uhp->uh_cursor_vcol = -1; - /* save changed and buffer empty flag for undo */ - uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) + - ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); + // save changed and buffer empty flag for undo + uhp->uh_flags = (buf->b_changed ? UH_CHANGED : 0) + + ((buf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); + + // save named marks and Visual marks for undo + zero_fmark_additional_data(buf->b_namedm); + memmove(uhp->uh_namedm, buf->b_namedm, + sizeof(buf->b_namedm[0]) * NMARKS); + uhp->uh_visual = buf->b_visual; - /* save named marks and Visual marks for undo */ - zero_fmark_additional_data(curbuf->b_namedm); - memmove(uhp->uh_namedm, curbuf->b_namedm, - sizeof(curbuf->b_namedm[0]) * NMARKS); - uhp->uh_visual = curbuf->b_visual; + buf->b_u_newhead = uhp; - curbuf->b_u_newhead = uhp; - if (curbuf->b_u_oldhead == NULL) - curbuf->b_u_oldhead = uhp; - ++curbuf->b_u_numhead; + if (buf->b_u_oldhead == NULL) { + buf->b_u_oldhead = uhp; + } + buf->b_u_numhead++; } else { - if (get_undolevel() < 0) /* no undo at all */ + if (get_undolevel(buf) < 0) { // no undo at all return OK; + } /* * When saving a single line, and it has been saved just before, it @@ -483,7 +497,7 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) * long. */ if (size == 1) { - uep = u_get_headentry(); + uep = u_get_headentry(buf); prev_uep = NULL; for (i = 0; i < 10; ++i) { if (uep == NULL) @@ -491,16 +505,17 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) /* If lines have been inserted/deleted we give up. * Also when the line was included in a multi-line save. */ - if ((curbuf->b_u_newhead->uh_getbot_entry != uep + if ((buf->b_u_newhead->uh_getbot_entry != uep ? (uep->ue_top + uep->ue_size + 1 != (uep->ue_bot == 0 - ? curbuf->b_ml.ml_line_count + 1 + ? buf->b_ml.ml_line_count + 1 : uep->ue_bot)) - : uep->ue_lcount != curbuf->b_ml.ml_line_count) + : uep->ue_lcount != buf->b_ml.ml_line_count) || (uep->ue_size > 1 && top >= uep->ue_top - && top + 2 <= uep->ue_top + uep->ue_size + 1)) + && top + 2 <= uep->ue_top + uep->ue_size + 1)) { break; + } /* If it's the same line we can skip saving it again. */ if (uep->ue_size == 1 && uep->ue_top == top) { @@ -508,8 +523,8 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) /* It's not the last entry: get ue_bot for the last * entry now. Following deleted/inserted lines go to * the re-used entry. */ - u_getbot(); - curbuf->b_u_synced = false; + u_getbot(buf); + buf->b_u_synced = false; /* Move the found entry to become the last entry. The * order of undo/redo doesn't matter for the entries @@ -518,18 +533,18 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) * for the found entry if the line count is changed by * the executed command. */ prev_uep->ue_next = uep->ue_next; - uep->ue_next = curbuf->b_u_newhead->uh_entry; - curbuf->b_u_newhead->uh_entry = uep; + uep->ue_next = buf->b_u_newhead->uh_entry; + buf->b_u_newhead->uh_entry = uep; } - /* The executed command may change the line count. */ - if (newbot != 0) + // The executed command may change the line count. + if (newbot != 0) { uep->ue_bot = newbot; - else if (bot > curbuf->b_ml.ml_line_count) + } else if (bot > buf->b_ml.ml_line_count) { uep->ue_bot = 0; - else { - uep->ue_lcount = curbuf->b_ml.ml_line_count; - curbuf->b_u_newhead->uh_getbot_entry = uep; + } else { + uep->ue_lcount = buf->b_ml.ml_line_count; + buf->b_u_newhead->uh_getbot_entry = uep; } return OK; } @@ -538,8 +553,8 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) } } - /* find line number for ue_bot for previous u_save() */ - u_getbot(); + // find line number for ue_bot for previous u_save() + u_getbot(buf); } /* @@ -553,17 +568,15 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) uep->ue_size = size; uep->ue_top = top; - if (newbot != 0) + if (newbot != 0) { uep->ue_bot = newbot; - /* - * Use 0 for ue_bot if bot is below last line. - * Otherwise we have to compute ue_bot later. - */ - else if (bot > curbuf->b_ml.ml_line_count) + // Use 0 for ue_bot if bot is below last line. + // Otherwise we have to compute ue_bot later. + } else if (bot > buf->b_ml.ml_line_count) { uep->ue_bot = 0; - else { - uep->ue_lcount = curbuf->b_ml.ml_line_count; - curbuf->b_u_newhead->uh_getbot_entry = uep; + } else { + uep->ue_lcount = buf->b_ml.ml_line_count; + buf->b_u_newhead->uh_getbot_entry = uep; } if (size > 0) { @@ -574,17 +587,19 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload) u_freeentry(uep, i); return FAIL; } - uep->ue_array[i] = u_save_line(lnum++); + uep->ue_array[i] = u_save_line_buf(buf, lnum++); } - } else + } else { uep->ue_array = NULL; - uep->ue_next = curbuf->b_u_newhead->uh_entry; - curbuf->b_u_newhead->uh_entry = uep; + } + + uep->ue_next = buf->b_u_newhead->uh_entry; + buf->b_u_newhead->uh_entry = uep; if (reload) { // buffer was reloaded, notify text change subscribers curbuf->b_u_newhead->uh_flags |= UH_RELOAD; } - curbuf->b_u_synced = false; + buf->b_u_synced = false; undo_undoes = false; #ifdef U_DEBUG @@ -1846,8 +1861,9 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) { int count = startcount; - if (!undo_allowed()) + if (!undo_allowed(curbuf)) { return; + } u_newcount = 0; u_oldcount = 0; @@ -1858,15 +1874,16 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) * needed. This may cause the file to be reloaded, that must happen * before we do anything, because it may change curbuf->b_u_curhead * and more. */ - change_warning(0); + change_warning(curbuf, 0); if (undo_undoes) { - if (curbuf->b_u_curhead == NULL) /* first undo */ + if (curbuf->b_u_curhead == NULL) { // first undo curbuf->b_u_curhead = curbuf->b_u_newhead; - else if (get_undolevel() > 0) /* multi level undo */ - /* get next undo */ + } else if (get_undolevel(curbuf) > 0) { // multi level undo + // get next undo curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr; - /* nothing to undo */ + } + // nothing to undo if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) { /* stick curbuf->b_u_curhead at end */ curbuf->b_u_curhead = curbuf->b_u_oldhead; @@ -1880,8 +1897,8 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event) u_undoredo(true, do_buf_event); } else { - if (curbuf->b_u_curhead == NULL || get_undolevel() <= 0) { - beep_flush(); /* nothing to redo */ + if (curbuf->b_u_curhead == NULL || get_undolevel(curbuf) <= 0) { + beep_flush(); // nothing to redo if (count == startcount - 1) { MSG(_("Already at newest change")); return; @@ -2122,8 +2139,8 @@ target_zero: if (uhp != NULL || target == 0) { // First go up the tree as much as needed. while (!got_int) { - /* Do the change warning now, for the same reason as above. */ - change_warning(0); + // Do the change warning now, for the same reason as above. + change_warning(curbuf, 0); uhp = curbuf->b_u_curhead; if (uhp == NULL) @@ -2147,7 +2164,7 @@ target_zero: // And now go down the tree (redo), branching off where needed. while (!got_int) { // Do the change warning now, for the same reason as above. - change_warning(0); + change_warning(curbuf, 0); uhp = curbuf->b_u_curhead; if (uhp == NULL) { @@ -2591,13 +2608,15 @@ u_sync( int force // Also sync when no_u_sync is set. ) { - /* Skip it when already synced or syncing is disabled. */ - if (curbuf->b_u_synced || (!force && no_u_sync > 0)) + // Skip it when already synced or syncing is disabled. + if (curbuf->b_u_synced || (!force && no_u_sync > 0)) { return; - if (get_undolevel() < 0) - curbuf->b_u_synced = true; /* no entries, nothing to do */ - else { - u_getbot(); /* compute ue_bot of previous u_save */ + } + + if (get_undolevel(curbuf) < 0) { + curbuf->b_u_synced = true; // no entries, nothing to do + } else { + u_getbot(curbuf); // compute ue_bot of previous u_save curbuf->b_u_curhead = NULL; } } @@ -2708,7 +2727,7 @@ void ex_undojoin(exarg_T *eap) if (!curbuf->b_u_synced) { return; // already unsynced } - if (get_undolevel() < 0) { + if (get_undolevel(curbuf) < 0) { return; // no entries, nothing to do } else { curbuf->b_u_synced = false; // Append next change to last entry @@ -2792,38 +2811,39 @@ static void u_unch_branch(u_header_T *uhp) * Get pointer to last added entry. * If it's not valid, give an error message and return NULL. */ -static u_entry_T *u_get_headentry(void) +static u_entry_T *u_get_headentry(buf_T *buf) { - if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL) { + if (buf->b_u_newhead == NULL || buf->b_u_newhead->uh_entry == NULL) { IEMSG(_("E439: undo list corrupt")); return NULL; } - return curbuf->b_u_newhead->uh_entry; + return buf->b_u_newhead->uh_entry; } /* * u_getbot(): compute the line number of the previous u_save * It is called only when b_u_synced is false. */ -static void u_getbot(void) +static void u_getbot(buf_T *buf) { u_entry_T *uep; linenr_T extra; - uep = u_get_headentry(); /* check for corrupt undo list */ - if (uep == NULL) + uep = u_get_headentry(buf); // check for corrupt undo list + if (uep == NULL) { return; + } - uep = curbuf->b_u_newhead->uh_getbot_entry; + uep = buf->b_u_newhead->uh_getbot_entry; if (uep != NULL) { /* * the new ue_bot is computed from the number of lines that has been * inserted (0 - deleted) since calling u_save. This is equal to the * old line count subtracted from the current line count. */ - extra = curbuf->b_ml.ml_line_count - uep->ue_lcount; + extra = buf->b_ml.ml_line_count - uep->ue_lcount; uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra; - if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count) { + if (uep->ue_bot < 1 || uep->ue_bot > buf->b_ml.ml_line_count) { IEMSG(_("E440: undo line missing")); uep->ue_bot = uep->ue_top + 1; // assume all lines deleted, will // get all the old lines back @@ -2831,10 +2851,10 @@ static void u_getbot(void) // ones } - curbuf->b_u_newhead->uh_getbot_entry = NULL; + buf->b_u_newhead->uh_getbot_entry = NULL; } - curbuf->b_u_synced = true; + buf->b_u_synced = true; } /* @@ -3014,10 +3034,12 @@ void u_undoline(void) return; } - /* first save the line for the 'u' command */ - if (u_savecommon(curbuf->b_u_line_lnum - 1, - curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) + // first save the line for the 'u' command + if (u_savecommon(curbuf, curbuf->b_u_line_lnum - 1, + curbuf->b_u_line_lnum + 1, (linenr_T)0, false) == FAIL) { return; + } + oldp = u_save_line(curbuf->b_u_line_lnum); ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true); changed_bytes(curbuf->b_u_line_lnum, 0); @@ -3048,12 +3070,21 @@ void u_blockfree(buf_T *buf) xfree(buf->b_u_line_ptr); } -/* - * u_save_line(): allocate memory and copy line 'lnum' into it. - */ +/// Allocate memory and copy curbuf line into it. +/// +/// @param lnum the line to copy static char_u *u_save_line(linenr_T lnum) { - return vim_strsave(ml_get(lnum)); + return u_save_line_buf(curbuf, lnum); +} + +/// Allocate memory and copy line into it +/// +/// @param lnum line to copy +/// @param buf buffer to copy from +static char_u *u_save_line_buf(buf_T *buf, linenr_T lnum) +{ + return vim_strsave(ml_get_buf(buf, lnum, false)); } /// Check if the 'modified' flag is set, or 'ff' has changed (only need to @@ -3146,11 +3177,13 @@ u_header_T *u_force_get_undo_header(buf_T *buf) buf_T *save_curbuf = curbuf; curbuf = buf; // Args are tricky: this means replace empty range by empty range.. - u_savecommon(0, 1, 1, true); + u_savecommon(curbuf, 0, 1, 1, true); + curbuf = save_curbuf; + uhp = buf->b_u_curhead; if (!uhp) { uhp = buf->b_u_newhead; - if (get_undolevel() > 0 && !uhp) { + if (get_undolevel(curbuf) > 0 && !uhp) { abort(); } } |