mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #12971 from vigoux/decurbuf
Decrease reliance on curbuf in BUFEMPTY and `undo.c`
This commit is contained in:
commit
1c41689287
@ -55,7 +55,6 @@
|
|||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
#include "nvim/extmark.h"
|
#include "nvim/extmark.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memline.h"
|
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
@ -139,7 +138,7 @@ read_buffer(
|
|||||||
if (read_stdin) {
|
if (read_stdin) {
|
||||||
// Set or reset 'modified' before executing autocommands, so that
|
// Set or reset 'modified' before executing autocommands, so that
|
||||||
// it can be changed there.
|
// it can be changed there.
|
||||||
if (!readonlymode && !BUFEMPTY()) {
|
if (!readonlymode && !buf_is_empty(curbuf)) {
|
||||||
changed();
|
changed();
|
||||||
} else if (retval != FAIL) {
|
} else if (retval != FAIL) {
|
||||||
unchanged(curbuf, false, true);
|
unchanged(curbuf, false, true);
|
||||||
@ -1921,7 +1920,7 @@ bool curbuf_reusable(void)
|
|||||||
return (curbuf != NULL
|
return (curbuf != NULL
|
||||||
&& curbuf->b_ffname == NULL
|
&& curbuf->b_ffname == NULL
|
||||||
&& curbuf->b_nwindows <= 1
|
&& curbuf->b_nwindows <= 1
|
||||||
&& (curbuf->b_ml.ml_mfp == NULL || BUFEMPTY())
|
&& (curbuf->b_ml.ml_mfp == NULL || buf_is_empty(curbuf))
|
||||||
&& !bt_quickfix(curbuf)
|
&& !bt_quickfix(curbuf)
|
||||||
&& !curbufIsChanged());
|
&& !curbufIsChanged());
|
||||||
}
|
}
|
||||||
@ -2061,7 +2060,7 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit)
|
|||||||
// If 'switchbuf' contains "split", "vsplit" or "newtab" and the
|
// If 'switchbuf' contains "split", "vsplit" or "newtab" and the
|
||||||
// current buffer isn't empty: open new tab or window
|
// current buffer isn't empty: open new tab or window
|
||||||
if (wp == NULL && (swb_flags & (SWB_VSPLIT | SWB_SPLIT | SWB_NEWTAB))
|
if (wp == NULL && (swb_flags & (SWB_VSPLIT | SWB_SPLIT | SWB_NEWTAB))
|
||||||
&& !BUFEMPTY()) {
|
&& !buf_is_empty(curbuf)) {
|
||||||
if (swb_flags & SWB_NEWTAB) {
|
if (swb_flags & SWB_NEWTAB) {
|
||||||
tabpage_new();
|
tabpage_new();
|
||||||
} else if (win_split(0, (swb_flags & SWB_VSPLIT) ? WSP_VERT : 0)
|
} else if (win_split(0, (swb_flags & SWB_VSPLIT) ? WSP_VERT : 0)
|
||||||
@ -4951,7 +4950,7 @@ do_arg_all(
|
|||||||
win_enter(lastwin, false);
|
win_enter(lastwin, false);
|
||||||
// ":tab drop file" should re-use an empty window to avoid "--remote-tab"
|
// ":tab drop file" should re-use an empty window to avoid "--remote-tab"
|
||||||
// leaving an empty tab page when executed locally.
|
// leaving an empty tab page when executed locally.
|
||||||
if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
|
if (keep_tabs && buf_is_empty(curbuf) && curbuf->b_nwindows == 1
|
||||||
&& curbuf->b_ffname == NULL && !curbuf->b_changed) {
|
&& curbuf->b_ffname == NULL && !curbuf->b_changed) {
|
||||||
use_firstwin = true;
|
use_firstwin = true;
|
||||||
tab_drop_empty_window = true;
|
tab_drop_empty_window = true;
|
||||||
@ -5696,3 +5695,4 @@ void buf_open_scratch(handle_T bufnr, char *bufname)
|
|||||||
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
||||||
RESET_BINDING(curwin);
|
RESET_BINDING(curwin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "nvim/func_attr.h"
|
#include "nvim/func_attr.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/macros.h"
|
#include "nvim/macros.h"
|
||||||
|
#include "nvim/memline.h"
|
||||||
|
|
||||||
// Values for buflist_getfile()
|
// Values for buflist_getfile()
|
||||||
enum getf_values {
|
enum getf_values {
|
||||||
@ -128,4 +129,10 @@ static inline void buf_inc_changedtick(buf_T *const buf)
|
|||||||
buf_set_changedtick(buf, buf_get_changedtick(buf) + 1);
|
buf_set_changedtick(buf, buf_get_changedtick(buf) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool buf_is_empty(buf_T *buf)
|
||||||
|
{
|
||||||
|
return buf->b_ml.ml_line_count == 1
|
||||||
|
&& *ml_get_buf(buf, (linenr_T)1, false) == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NVIM_BUFFER_H
|
#endif // NVIM_BUFFER_H
|
||||||
|
@ -525,6 +525,8 @@ struct file_buffer {
|
|||||||
int b_flags; // various BF_ flags
|
int b_flags; // various BF_ flags
|
||||||
int b_locked; // Buffer is being closed or referenced, don't
|
int b_locked; // Buffer is being closed or referenced, don't
|
||||||
// let autocommands wipe it out.
|
// let autocommands wipe it out.
|
||||||
|
int b_ro_locked; // Non-zero when the buffer can't be changed.
|
||||||
|
// Used for FileChangedRO
|
||||||
|
|
||||||
//
|
//
|
||||||
// b_ffname has the full path of the file (NULL for no name).
|
// b_ffname has the full path of the file (NULL for no name).
|
||||||
|
@ -40,18 +40,18 @@
|
|||||||
/// "col" is the column for the message; non-zero when in insert mode and
|
/// "col" is the column for the message; non-zero when in insert mode and
|
||||||
/// 'showmode' is on.
|
/// 'showmode' is on.
|
||||||
/// Careful: may trigger autocommands that reload the buffer.
|
/// 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");
|
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
|
&& curbufIsChanged() == 0
|
||||||
&& !autocmd_busy
|
&& !autocmd_busy
|
||||||
&& curbuf->b_p_ro) {
|
&& buf->b_p_ro) {
|
||||||
curbuf_lock++;
|
buf->b_ro_locked++;
|
||||||
apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, false, curbuf);
|
apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, false, buf);
|
||||||
curbuf_lock--;
|
buf->b_ro_locked--;
|
||||||
if (!curbuf->b_p_ro) {
|
if (!buf->b_p_ro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Do what msg() does, but with a column offset if the warning should
|
// Do what msg() does, but with a column offset if the warning should
|
||||||
@ -70,7 +70,7 @@ void change_warning(int col)
|
|||||||
ui_flush();
|
ui_flush();
|
||||||
os_delay(1002L, true); // give the user time to think about it
|
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
|
redraw_cmdline = false; // don't redraw and erase the message
|
||||||
if (msg_row < Rows - 1) {
|
if (msg_row < Rows - 1) {
|
||||||
showmode();
|
showmode();
|
||||||
@ -91,7 +91,7 @@ void changed(void)
|
|||||||
|
|
||||||
// Give a warning about changing a read-only file. This may also
|
// Give a warning about changing a read-only file. This may also
|
||||||
// check-out the file, thus change "curbuf"!
|
// check-out the file, thus change "curbuf"!
|
||||||
change_warning(0);
|
change_warning(curbuf, 0);
|
||||||
|
|
||||||
// Create a swap file if that is wanted.
|
// Create a swap file if that is wanted.
|
||||||
// Don't do this for "nofile" and "nowrite" buffer types.
|
// Don't do this for "nofile" and "nowrite" buffer types.
|
||||||
|
@ -1334,9 +1334,9 @@ static void set_diff_option(win_T *wp, int value)
|
|||||||
|
|
||||||
curwin = wp;
|
curwin = wp;
|
||||||
curbuf = curwin->w_buffer;
|
curbuf = curwin->w_buffer;
|
||||||
curbuf_lock++;
|
curbuf->b_ro_locked++;
|
||||||
set_option_value("diff", (long)value, NULL, OPT_LOCAL);
|
set_option_value("diff", (long)value, NULL, OPT_LOCAL);
|
||||||
curbuf_lock--;
|
curbuf->b_ro_locked--;
|
||||||
curwin = old_curwin;
|
curwin = old_curwin;
|
||||||
curbuf = curwin->w_buffer;
|
curbuf = curwin->w_buffer;
|
||||||
}
|
}
|
||||||
@ -2603,7 +2603,7 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
// FileChangedRO autocommand, which may do nasty things and mess
|
// FileChangedRO autocommand, which may do nasty things and mess
|
||||||
// everything up.
|
// everything up.
|
||||||
if (!curbuf->b_changed) {
|
if (!curbuf->b_changed) {
|
||||||
change_warning(0);
|
change_warning(curbuf, 0);
|
||||||
if (diff_buf_idx(curbuf) != idx_to) {
|
if (diff_buf_idx(curbuf) != idx_to) {
|
||||||
EMSG(_("E787: Buffer changed unexpectedly"));
|
EMSG(_("E787: Buffer changed unexpectedly"));
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -2669,7 +2669,7 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_empty = BUFEMPTY();
|
buf_empty = buf_is_empty(curbuf);
|
||||||
added = 0;
|
added = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; ++i) {
|
for (i = 0; i < count; ++i) {
|
||||||
|
@ -467,7 +467,7 @@ static void insert_enter(InsertState *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!p_im && did_restart_edit == 0) {
|
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
|
ui_cursor_shape(); // may show different cursor shape
|
||||||
@ -8047,7 +8047,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
|
|||||||
// can't backup past first character in buffer
|
// can't backup past first character in buffer
|
||||||
// can't backup past starting point unless 'backspace' > 1
|
// can't backup past starting point unless 'backspace' > 1
|
||||||
// can backup to a previous line if 'backspace' == 0
|
// can backup to a previous line if 'backspace' == 0
|
||||||
if (BUFEMPTY()
|
if (buf_is_empty(curbuf)
|
||||||
|| (!revins_on
|
|| (!revins_on
|
||||||
&& ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
|
&& ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
|
||||||
|| (!can_bs(BS_START)
|
|| (!can_bs(BS_START)
|
||||||
|
@ -1078,10 +1078,11 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for undo allowed here, because if something was already inserted
|
// Check for undo allowed here, because if something was already inserted
|
||||||
* the line was already saved for undo and this check isn't done. */
|
// the line was already saved for undo and this check isn't done.
|
||||||
if (!undo_allowed())
|
if (!undo_allowed(curbuf)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (argvars[1].v_type != VAR_LIST) {
|
if (argvars[1].v_type != VAR_LIST) {
|
||||||
EMSG(_(e_invarg));
|
EMSG(_(e_invarg));
|
||||||
|
@ -2607,7 +2607,7 @@ int do_ecmd(
|
|||||||
&& (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)) {
|
&& (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)) {
|
||||||
// Sync first so that this is a separate undo-able action.
|
// Sync first so that this is a separate undo-able action.
|
||||||
u_sync(false);
|
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) {
|
== FAIL) {
|
||||||
xfree(new_name);
|
xfree(new_name);
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -5159,9 +5159,9 @@ void fix_help_buffer(void)
|
|||||||
|
|
||||||
// Set filetype to "help".
|
// Set filetype to "help".
|
||||||
if (STRCMP(curbuf->b_p_ft, "help") != 0) {
|
if (STRCMP(curbuf->b_p_ft, "help") != 0) {
|
||||||
curbuf_lock++;
|
curbuf->b_ro_locked++;
|
||||||
set_option_value("ft", 0L, "help", OPT_LOCAL);
|
set_option_value("ft", 0L, "help", OPT_LOCAL);
|
||||||
curbuf_lock--;
|
curbuf->b_ro_locked--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!syntax_present(curwin)) {
|
if (!syntax_present(curwin)) {
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
#define EX_SBOXOK 0x40000 // allowed in the sandbox
|
#define EX_SBOXOK 0x40000 // allowed in the sandbox
|
||||||
#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing
|
#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing
|
||||||
// disallows editing another buffer when
|
// disallows editing another buffer when
|
||||||
// curbuf_lock is set
|
// current buffer is locked
|
||||||
#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
|
#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
|
||||||
#define EX_FLAGS 0x200000 // allow flags after count in argument
|
#define EX_FLAGS 0x200000 // allow flags after count in argument
|
||||||
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
|
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
|
||||||
|
@ -1518,7 +1518,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
goto doend;
|
goto doend;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow editing another buffer when "curbuf_lock" is set.
|
// Disallow editing another buffer when "curbuf->b_ro_locked" is set.
|
||||||
// Do allow ":checktime" (it is postponed).
|
// Do allow ":checktime" (it is postponed).
|
||||||
// Do allow ":edit" (check for an argument later).
|
// Do allow ":edit" (check for an argument later).
|
||||||
// Do allow ":file" with no arguments (check for an argument later).
|
// Do allow ":file" with no arguments (check for an argument later).
|
||||||
@ -1601,7 +1601,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
else
|
else
|
||||||
ea.arg = skipwhite(p);
|
ea.arg = skipwhite(p);
|
||||||
|
|
||||||
// ":file" cannot be run with an argument when "curbuf_lock" is set
|
// ":file" cannot be run with an argument when "curbuf->b_ro_locked" is set
|
||||||
if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked()) {
|
if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked()) {
|
||||||
goto doend;
|
goto doend;
|
||||||
}
|
}
|
||||||
@ -7345,16 +7345,18 @@ do_exedit(
|
|||||||
old_curwin == NULL ? curwin : NULL);
|
old_curwin == NULL ? curwin : NULL);
|
||||||
} else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
|
} else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
|
||||||
|| *eap->arg != NUL) {
|
|| *eap->arg != NUL) {
|
||||||
/* Can't edit another file when "curbuf_lock" is set. Only ":edit"
|
// Can't edit another file when "curbuf->b_ro_lockec" is set. Only ":edit"
|
||||||
* can bring us here, others are stopped earlier. */
|
// can bring us here, others are stopped earlier.
|
||||||
if (*eap->arg != NUL && curbuf_locked())
|
if (*eap->arg != NUL && curbuf_locked()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
n = readonlymode;
|
n = readonlymode;
|
||||||
if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
|
if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview) {
|
||||||
readonlymode = TRUE;
|
readonlymode = true;
|
||||||
else if (eap->cmdidx == CMD_enew)
|
} else if (eap->cmdidx == CMD_enew) {
|
||||||
readonlymode = FALSE; /* 'readonly' doesn't make sense in an
|
readonlymode = false; // 'readonly' doesn't make sense
|
||||||
empty buffer */
|
// in an empty buffer
|
||||||
|
}
|
||||||
if (eap->cmdidx != CMD_balt && eap->cmdidx != CMD_badd) {
|
if (eap->cmdidx != CMD_balt && eap->cmdidx != CMD_badd) {
|
||||||
setpcmark();
|
setpcmark();
|
||||||
}
|
}
|
||||||
|
@ -2412,13 +2412,11 @@ char_u * get_text_locked_msg(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Check if "curbuf->b_ro_locked" or "allbuf_lock" is set and
|
||||||
* Check if "curbuf_lock" or "allbuf_lock" is set and return TRUE when it is
|
/// return TRUE when it is and give an error message.
|
||||||
* and give an error message.
|
|
||||||
*/
|
|
||||||
int curbuf_locked(void)
|
int curbuf_locked(void)
|
||||||
{
|
{
|
||||||
if (curbuf_lock > 0) {
|
if (curbuf->b_ro_locked > 0) {
|
||||||
EMSG(_("E788: Not allowed to edit another buffer now"));
|
EMSG(_("E788: Not allowed to edit another buffer now"));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -6513,7 +6511,7 @@ static int open_cmdwin(void)
|
|||||||
curwin->w_p_fen = false;
|
curwin->w_p_fen = false;
|
||||||
|
|
||||||
// Don't allow switching to another buffer.
|
// Don't allow switching to another buffer.
|
||||||
curbuf_lock++;
|
curbuf->b_ro_locked++;
|
||||||
|
|
||||||
// Showing the prompt may have set need_wait_return, reset it.
|
// Showing the prompt may have set need_wait_return, reset it.
|
||||||
need_wait_return = false;
|
need_wait_return = false;
|
||||||
@ -6526,7 +6524,7 @@ static int open_cmdwin(void)
|
|||||||
}
|
}
|
||||||
set_option_value("ft", 0L, "vim", OPT_LOCAL);
|
set_option_value("ft", 0L, "vim", OPT_LOCAL);
|
||||||
}
|
}
|
||||||
curbuf_lock--;
|
curbuf->b_ro_locked--;
|
||||||
|
|
||||||
// Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
|
// Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
|
||||||
// sets 'textwidth' to 78).
|
// sets 'textwidth' to 78).
|
||||||
|
@ -4687,7 +4687,7 @@ check_timestamps(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!stuff_empty() || global_busy || !typebuf_typed()
|
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
|
need_check_timestamps = true; // check later
|
||||||
} else {
|
} else {
|
||||||
@ -5015,10 +5015,10 @@ void buf_reload(buf_T *buf, int orig_mode)
|
|||||||
old_topline = curwin->w_topline;
|
old_topline = curwin->w_topline;
|
||||||
|
|
||||||
if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) {
|
if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) {
|
||||||
/* Save all the text, so that the reload can be undone.
|
// Save all the text, so that the reload can be undone.
|
||||||
* Sync first so that this is a separate undo-able action. */
|
// Sync first so that this is a separate undo-able action.
|
||||||
u_sync(FALSE);
|
u_sync(false);
|
||||||
saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
|
saved = u_savecommon(curbuf, 0, curbuf->b_ml.ml_line_count + 1, 0, true);
|
||||||
flags |= READ_KEEP_UNDO;
|
flags |= READ_KEEP_UNDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5027,7 +5027,7 @@ void buf_reload(buf_T *buf, int orig_mode)
|
|||||||
// buffer contents. But if reading the file fails we should keep
|
// buffer contents. But if reading the file fails we should keep
|
||||||
// the old contents. Can't use memory only, the file might be
|
// the old contents. Can't use memory only, the file might be
|
||||||
// too big. Use a hidden buffer to move the buffer contents to.
|
// too big. Use a hidden buffer to move the buffer contents to.
|
||||||
if (BUFEMPTY() || saved == FAIL) {
|
if (buf_is_empty(curbuf) || saved == FAIL) {
|
||||||
savebuf = NULL;
|
savebuf = NULL;
|
||||||
} else {
|
} else {
|
||||||
// Allocate a buffer without putting it in the buffer list.
|
// Allocate a buffer without putting it in the buffer list.
|
||||||
@ -5060,7 +5060,7 @@ void buf_reload(buf_T *buf, int orig_mode)
|
|||||||
if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) {
|
if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) {
|
||||||
// Put the text back from the save buffer. First
|
// Put the text back from the save buffer. First
|
||||||
// delete any lines that readfile() added.
|
// delete any lines that readfile() added.
|
||||||
while (!BUFEMPTY()) {
|
while (!buf_is_empty(curbuf)) {
|
||||||
if (ml_delete(buf->b_ml.ml_line_count, false) == FAIL) {
|
if (ml_delete(buf->b_ml.ml_line_count, false) == FAIL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -508,9 +508,6 @@ EXTERN int secure INIT(= false);
|
|||||||
/// allowed.
|
/// allowed.
|
||||||
EXTERN int textlock INIT(= 0);
|
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
|
/// 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.
|
/// current directory can't be changed. Used for SwapExists et al.
|
||||||
EXTERN int allbuf_lock INIT(= 0);
|
EXTERN int allbuf_lock INIT(= 0);
|
||||||
|
@ -34,10 +34,6 @@
|
|||||||
/// LINEEMPTY() - return TRUE if the line is empty
|
/// LINEEMPTY() - return TRUE if the line is empty
|
||||||
#define LINEEMPTY(p) (*ml_get(p) == NUL)
|
#define LINEEMPTY(p) (*ml_get(p) == NUL)
|
||||||
|
|
||||||
/// BUFEMPTY() - return TRUE if the current buffer is empty
|
|
||||||
#define BUFEMPTY() (curbuf->b_ml.ml_line_count == 1 && *ml_get((linenr_T)1) == \
|
|
||||||
NUL)
|
|
||||||
|
|
||||||
// toupper() and tolower() that use the current locale.
|
// toupper() and tolower() that use the current locale.
|
||||||
// Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
|
// Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
|
||||||
// range 0 - 255. toupper()/tolower() on some systems can't handle others.
|
// range 0 - 255. toupper()/tolower() on some systems can't handle others.
|
||||||
|
@ -1444,11 +1444,9 @@ static void read_stdin(void)
|
|||||||
no_wait_return = true;
|
no_wait_return = true;
|
||||||
int save_msg_didany = msg_didany;
|
int save_msg_didany = msg_didany;
|
||||||
set_buflisted(true);
|
set_buflisted(true);
|
||||||
|
|
||||||
// Create memfile and read from stdin.
|
// Create memfile and read from stdin.
|
||||||
(void)open_buffer(true, NULL, 0);
|
(void)open_buffer(true, NULL, 0);
|
||||||
|
if (buf_is_empty(curbuf) && curbuf->b_next != NULL) {
|
||||||
if (BUFEMPTY() && curbuf->b_next != NULL) {
|
|
||||||
// stdin was empty, go to buffer 2 (e.g. "echo file1 | xargs nvim"). #8561
|
// stdin was empty, go to buffer 2 (e.g. "echo file1 | xargs nvim"). #8561
|
||||||
do_cmdline_cmd("silent! bnext");
|
do_cmdline_cmd("silent! bnext");
|
||||||
// Delete the empty stdin buffer.
|
// Delete the empty stdin buffer.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
#include "nvim/cursor.h"
|
#include "nvim/cursor.h"
|
||||||
@ -172,7 +173,7 @@ void update_topline(win_T *wp)
|
|||||||
old_topfill = wp->w_topfill;
|
old_topfill = wp->w_topfill;
|
||||||
|
|
||||||
// If the buffer is empty, always set topline to 1.
|
// If the buffer is empty, always set topline to 1.
|
||||||
if (BUFEMPTY()) { // special case - file is empty
|
if (buf_is_empty(curbuf)) { // special case - file is empty
|
||||||
if (wp->w_topline != 1) {
|
if (wp->w_topline != 1) {
|
||||||
redraw_later(wp, NOT_VALID);
|
redraw_later(wp, NOT_VALID);
|
||||||
}
|
}
|
||||||
|
@ -3069,7 +3069,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
|||||||
}
|
}
|
||||||
// In an empty buffer the empty line is going to be replaced, include
|
// In an empty buffer the empty line is going to be replaced, include
|
||||||
// it in the saved lines.
|
// it in the saved lines.
|
||||||
if ((BUFEMPTY() ? u_save(0, 2) : u_save(lnum - 1, lnum)) == FAIL) {
|
if ((buf_is_empty(curbuf) ?
|
||||||
|
u_save(0, 2) : u_save(lnum - 1, lnum)) == FAIL) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (dir == FORWARD) {
|
if (dir == FORWARD) {
|
||||||
|
@ -880,7 +880,7 @@ void set_init_3(void)
|
|||||||
xfree(p);
|
xfree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BUFEMPTY()) {
|
if (buf_is_empty(curbuf)) {
|
||||||
int idx_ffs = findoption_len(S_LEN("ffs"));
|
int idx_ffs = findoption_len(S_LEN("ffs"));
|
||||||
|
|
||||||
// Apply the first entry of 'fileformats' to the initial buffer.
|
// Apply the first entry of 'fileformats' to the initial buffer.
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
@ -735,7 +736,7 @@ static int pum_set_selected(int n, int repeat)
|
|||||||
&& (curbuf->b_p_bt[2] == 'f')
|
&& (curbuf->b_p_bt[2] == 'f')
|
||||||
&& (curbuf->b_p_bh[0] == 'w')) {
|
&& (curbuf->b_p_bh[0] == 'w')) {
|
||||||
// Already a "wipeout" buffer, make it empty.
|
// Already a "wipeout" buffer, make it empty.
|
||||||
while (!BUFEMPTY()) {
|
while (!buf_is_empty(curbuf)) {
|
||||||
ml_delete((linenr_T)1, false);
|
ml_delete((linenr_T)1, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -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
|
// 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
|
// resembles reading a file into a buffer, it's more logical when using
|
||||||
// autocommands.
|
// autocommands.
|
||||||
curbuf_lock++;
|
curbuf->b_ro_locked++;
|
||||||
set_option_value("ft", 0L, "qf", OPT_LOCAL);
|
set_option_value("ft", 0L, "qf", OPT_LOCAL);
|
||||||
curbuf->b_p_ma = false;
|
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,
|
apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL,
|
||||||
false, curbuf);
|
false, curbuf);
|
||||||
keep_filetype = false;
|
keep_filetype = false;
|
||||||
curbuf_lock--;
|
curbuf->b_ro_locked--;
|
||||||
|
|
||||||
// make sure it will be redrawn
|
// make sure it will be redrawn
|
||||||
redraw_curbuf_later(NOT_VALID);
|
redraw_curbuf_later(NOT_VALID);
|
||||||
|
@ -6672,7 +6672,7 @@ void ex_spelldump(exarg_T *eap)
|
|||||||
set_option_value("spl", dummy, (char *)spl, OPT_LOCAL);
|
set_option_value("spl", dummy, (char *)spl, OPT_LOCAL);
|
||||||
xfree(spl);
|
xfree(spl);
|
||||||
|
|
||||||
if (!BUFEMPTY()) {
|
if (!buf_is_empty(curbuf)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2965,7 +2965,7 @@ func Test_cclose_in_autocmd()
|
|||||||
" call test_override('starting', 0)
|
" call test_override('starting', 0)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Check that ":file" without an argument is possible even when "curbuf_lock"
|
" Check that ":file" without an argument is possible even when curbuf is locked
|
||||||
" is set.
|
" is set.
|
||||||
func Test_file_from_copen()
|
func Test_file_from_copen()
|
||||||
" Works without argument.
|
" Works without argument.
|
||||||
|
338
src/nvim/undo.c
338
src/nvim/undo.c
@ -234,7 +234,7 @@ int u_save(linenr_T top, linenr_T bot)
|
|||||||
if (top + 2 == bot)
|
if (top + 2 == bot)
|
||||||
u_saveline((linenr_T)(top + 1));
|
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)
|
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)
|
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)
|
int u_savedel(linenr_T lnum, long nlines)
|
||||||
{
|
{
|
||||||
return u_savecommon(lnum - 1, lnum + nlines,
|
return u_savecommon(
|
||||||
nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE);
|
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 true when undo is allowed. Otherwise print an error message and
|
||||||
/// return false.
|
/// return false.
|
||||||
///
|
///
|
||||||
/// @return true if undo is allowed.
|
/// @return true if undo is allowed.
|
||||||
bool undo_allowed(void)
|
bool undo_allowed(buf_T *buf)
|
||||||
{
|
{
|
||||||
/* Don't allow changes when 'modifiable' is off. */
|
// Don't allow changes when 'modifiable' is off.
|
||||||
if (!MODIFIABLE(curbuf)) {
|
if (!MODIFIABLE(buf)) {
|
||||||
EMSG(_(e_modifiable));
|
EMSG(_(e_modifiable));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -301,12 +302,12 @@ bool undo_allowed(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the 'undolevels' value for the current buffer.
|
/// 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 p_ul;
|
||||||
}
|
}
|
||||||
return curbuf->b_p_ul;
|
return buf->b_p_ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void zero_fmark_additional_data(fmark_T *fmarks)
|
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.
|
* Careful: may trigger autocommands that reload the buffer.
|
||||||
* Returns FAIL when lines could not be saved, OK otherwise.
|
* 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;
|
linenr_T lnum;
|
||||||
long i;
|
long i;
|
||||||
@ -337,22 +340,23 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
long size;
|
long size;
|
||||||
|
|
||||||
if (!reload) {
|
if (!reload) {
|
||||||
/* When making changes is not allowed return FAIL. It's a crude way
|
// When making changes is not allowed return FAIL. It's a crude way
|
||||||
* to make all change commands fail. */
|
// to make all change commands fail.
|
||||||
if (!undo_allowed())
|
if (!undo_allowed(buf)) {
|
||||||
return FAIL;
|
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).
|
||||||
|
if (buf == curbuf) {
|
||||||
|
change_warning(buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if (bot > buf->b_ml.ml_line_count + 1) {
|
||||||
* Saving text for undo means we are going to make a change. Give a
|
// This happens when the FileChangedRO autocommand changes the
|
||||||
* warning for a read-only file before making the change, so that the
|
// file in a way it becomes shorter.
|
||||||
* 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. */
|
|
||||||
EMSG(_("E881: Line count changed unexpectedly"));
|
EMSG(_("E881: Line count changed unexpectedly"));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@ -364,18 +368,14 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
|
|
||||||
size = bot - top - 1;
|
size = bot - top - 1;
|
||||||
|
|
||||||
/*
|
// If curbuf->b_u_synced == true make a new header.
|
||||||
* If curbuf->b_u_synced == true make a new header.
|
if (buf->b_u_synced) {
|
||||||
*/
|
// Need to create new entry in b_changelist.
|
||||||
if (curbuf->b_u_synced) {
|
buf->b_new_change = true;
|
||||||
/* Need to create new entry in b_changelist. */
|
|
||||||
curbuf->b_new_change = true;
|
|
||||||
|
|
||||||
if (get_undolevel() >= 0) {
|
if (get_undolevel(buf) >= 0) {
|
||||||
/*
|
// Make a new header entry. Do this first so that we don't mess
|
||||||
* Make a new header entry. Do this first so that we don't mess
|
// up the undo info when out of memory.
|
||||||
* up the undo info when out of memory.
|
|
||||||
*/
|
|
||||||
uhp = xmalloc(sizeof(u_header_T));
|
uhp = xmalloc(sizeof(u_header_T));
|
||||||
kv_init(uhp->uh_extmark);
|
kv_init(uhp->uh_extmark);
|
||||||
#ifdef U_DEBUG
|
#ifdef U_DEBUG
|
||||||
@ -388,63 +388,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
|
* If we undid more than we redid, move the entry lists before and
|
||||||
* including curbuf->b_u_curhead to an alternate branch.
|
* 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) {
|
if (old_curhead != NULL) {
|
||||||
curbuf->b_u_newhead = old_curhead->uh_next.ptr;
|
buf->b_u_newhead = old_curhead->uh_next.ptr;
|
||||||
curbuf->b_u_curhead = NULL;
|
buf->b_u_curhead = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* free headers to keep the size right
|
* free headers to keep the size right
|
||||||
*/
|
*/
|
||||||
while (curbuf->b_u_numhead > get_undolevel()
|
while (buf->b_u_numhead > get_undolevel(buf)
|
||||||
&& curbuf->b_u_oldhead != NULL) {
|
&& buf->b_u_oldhead != NULL) {
|
||||||
u_header_T *uhfree = curbuf->b_u_oldhead;
|
u_header_T *uhfree = buf->b_u_oldhead;
|
||||||
|
|
||||||
if (uhfree == old_curhead)
|
if (uhfree == old_curhead) {
|
||||||
/* Can't reconnect the branch, delete all of it. */
|
// Can't reconnect the branch, delete all of it.
|
||||||
u_freebranch(curbuf, uhfree, &old_curhead);
|
u_freebranch(buf, uhfree, &old_curhead);
|
||||||
else if (uhfree->uh_alt_next.ptr == NULL)
|
} else if (uhfree->uh_alt_next.ptr == NULL) {
|
||||||
/* There is no branch, only free one header. */
|
// There is no branch, only free one header.
|
||||||
u_freeheader(curbuf, uhfree, &old_curhead);
|
u_freeheader(buf, uhfree, &old_curhead);
|
||||||
else {
|
} else {
|
||||||
/* Free the oldest alternate branch as a whole. */
|
// Free the oldest alternate branch as a whole.
|
||||||
while (uhfree->uh_alt_next.ptr != NULL)
|
while (uhfree->uh_alt_next.ptr != NULL) {
|
||||||
uhfree = uhfree->uh_alt_next.ptr;
|
uhfree = uhfree->uh_alt_next.ptr;
|
||||||
u_freebranch(curbuf, uhfree, &old_curhead);
|
}
|
||||||
|
u_freebranch(buf, uhfree, &old_curhead);
|
||||||
}
|
}
|
||||||
#ifdef U_DEBUG
|
#ifdef U_DEBUG
|
||||||
u_check(TRUE);
|
u_check(TRUE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uhp == NULL) { /* no undo at all */
|
if (uhp == NULL) { // no undo at all
|
||||||
if (old_curhead != NULL)
|
if (old_curhead != NULL) {
|
||||||
u_freebranch(curbuf, old_curhead, NULL);
|
u_freebranch(buf, old_curhead, NULL);
|
||||||
curbuf->b_u_synced = false;
|
}
|
||||||
|
buf->b_u_synced = false;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uhp->uh_prev.ptr = NULL;
|
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;
|
uhp->uh_alt_next.ptr = old_curhead;
|
||||||
if (old_curhead != NULL) {
|
if (old_curhead != NULL) {
|
||||||
uhp->uh_alt_prev.ptr = old_curhead->uh_alt_prev.ptr;
|
uhp->uh_alt_prev.ptr = old_curhead->uh_alt_prev.ptr;
|
||||||
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
|
|
||||||
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;
|
if (uhp->uh_alt_prev.ptr != NULL) {
|
||||||
curbuf->b_u_seq_cur = uhp->uh_seq;
|
uhp->uh_alt_prev.ptr->uh_alt_next.ptr = uhp;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_curhead->uh_alt_prev.ptr = uhp;
|
||||||
|
|
||||||
|
if (buf->b_u_oldhead == old_curhead) {
|
||||||
|
buf->b_u_oldhead = uhp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uhp->uh_alt_prev.ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_time = time(NULL);
|
||||||
uhp->uh_save_nr = 0;
|
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_walk = 0;
|
||||||
uhp->uh_entry = NULL;
|
uhp->uh_entry = NULL;
|
||||||
@ -455,23 +465,26 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
else
|
else
|
||||||
uhp->uh_cursor_vcol = -1;
|
uhp->uh_cursor_vcol = -1;
|
||||||
|
|
||||||
/* save changed and buffer empty flag for undo */
|
// save changed and buffer empty flag for undo
|
||||||
uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
|
uhp->uh_flags = (buf->b_changed ? UH_CHANGED : 0) +
|
||||||
((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
|
((buf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
|
||||||
|
|
||||||
/* save named marks and Visual marks for undo */
|
// save named marks and Visual marks for undo
|
||||||
zero_fmark_additional_data(curbuf->b_namedm);
|
zero_fmark_additional_data(buf->b_namedm);
|
||||||
memmove(uhp->uh_namedm, curbuf->b_namedm,
|
memmove(uhp->uh_namedm, buf->b_namedm,
|
||||||
sizeof(curbuf->b_namedm[0]) * NMARKS);
|
sizeof(buf->b_namedm[0]) * NMARKS);
|
||||||
uhp->uh_visual = curbuf->b_visual;
|
uhp->uh_visual = buf->b_visual;
|
||||||
|
|
||||||
curbuf->b_u_newhead = uhp;
|
buf->b_u_newhead = uhp;
|
||||||
if (curbuf->b_u_oldhead == NULL)
|
|
||||||
curbuf->b_u_oldhead = uhp;
|
if (buf->b_u_oldhead == NULL) {
|
||||||
++curbuf->b_u_numhead;
|
buf->b_u_oldhead = uhp;
|
||||||
|
}
|
||||||
|
buf->b_u_numhead++;
|
||||||
} else {
|
} else {
|
||||||
if (get_undolevel() < 0) /* no undo at all */
|
if (get_undolevel(buf) < 0) { // no undo at all
|
||||||
return OK;
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When saving a single line, and it has been saved just before, it
|
* When saving a single line, and it has been saved just before, it
|
||||||
@ -483,7 +496,7 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
* long.
|
* long.
|
||||||
*/
|
*/
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
uep = u_get_headentry();
|
uep = u_get_headentry(buf);
|
||||||
prev_uep = NULL;
|
prev_uep = NULL;
|
||||||
for (i = 0; i < 10; ++i) {
|
for (i = 0; i < 10; ++i) {
|
||||||
if (uep == NULL)
|
if (uep == NULL)
|
||||||
@ -491,16 +504,17 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
|
|
||||||
/* If lines have been inserted/deleted we give up.
|
/* If lines have been inserted/deleted we give up.
|
||||||
* Also when the line was included in a multi-line save. */
|
* 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_top + uep->ue_size + 1
|
||||||
!= (uep->ue_bot == 0
|
!= (uep->ue_bot == 0
|
||||||
? curbuf->b_ml.ml_line_count + 1
|
? buf->b_ml.ml_line_count + 1
|
||||||
: uep->ue_bot))
|
: 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
|
|| (uep->ue_size > 1
|
||||||
&& top >= uep->ue_top
|
&& top >= uep->ue_top
|
||||||
&& top + 2 <= uep->ue_top + uep->ue_size + 1))
|
&& top + 2 <= uep->ue_top + uep->ue_size + 1)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* If it's the same line we can skip saving it again. */
|
/* If it's the same line we can skip saving it again. */
|
||||||
if (uep->ue_size == 1 && uep->ue_top == top) {
|
if (uep->ue_size == 1 && uep->ue_top == top) {
|
||||||
@ -508,8 +522,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
|
/* It's not the last entry: get ue_bot for the last
|
||||||
* entry now. Following deleted/inserted lines go to
|
* entry now. Following deleted/inserted lines go to
|
||||||
* the re-used entry. */
|
* the re-used entry. */
|
||||||
u_getbot();
|
u_getbot(buf);
|
||||||
curbuf->b_u_synced = false;
|
buf->b_u_synced = false;
|
||||||
|
|
||||||
/* Move the found entry to become the last entry. The
|
/* Move the found entry to become the last entry. The
|
||||||
* order of undo/redo doesn't matter for the entries
|
* order of undo/redo doesn't matter for the entries
|
||||||
@ -518,18 +532,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
|
* for the found entry if the line count is changed by
|
||||||
* the executed command. */
|
* the executed command. */
|
||||||
prev_uep->ue_next = uep->ue_next;
|
prev_uep->ue_next = uep->ue_next;
|
||||||
uep->ue_next = curbuf->b_u_newhead->uh_entry;
|
uep->ue_next = buf->b_u_newhead->uh_entry;
|
||||||
curbuf->b_u_newhead->uh_entry = uep;
|
buf->b_u_newhead->uh_entry = uep;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The executed command may change the line count. */
|
// The executed command may change the line count.
|
||||||
if (newbot != 0)
|
if (newbot != 0) {
|
||||||
uep->ue_bot = newbot;
|
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;
|
uep->ue_bot = 0;
|
||||||
else {
|
} else {
|
||||||
uep->ue_lcount = curbuf->b_ml.ml_line_count;
|
uep->ue_lcount = buf->b_ml.ml_line_count;
|
||||||
curbuf->b_u_newhead->uh_getbot_entry = uep;
|
buf->b_u_newhead->uh_getbot_entry = uep;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -538,8 +552,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() */
|
// find line number for ue_bot for previous u_save()
|
||||||
u_getbot();
|
u_getbot(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -553,17 +567,15 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
|
|
||||||
uep->ue_size = size;
|
uep->ue_size = size;
|
||||||
uep->ue_top = top;
|
uep->ue_top = top;
|
||||||
if (newbot != 0)
|
if (newbot != 0) {
|
||||||
uep->ue_bot = newbot;
|
uep->ue_bot = newbot;
|
||||||
/*
|
// Use 0 for ue_bot if bot is below last line.
|
||||||
* Use 0 for ue_bot if bot is below last line.
|
// Otherwise we have to compute ue_bot later.
|
||||||
* Otherwise we have to compute ue_bot later.
|
} else if (bot > buf->b_ml.ml_line_count) {
|
||||||
*/
|
|
||||||
else if (bot > curbuf->b_ml.ml_line_count)
|
|
||||||
uep->ue_bot = 0;
|
uep->ue_bot = 0;
|
||||||
else {
|
} else {
|
||||||
uep->ue_lcount = curbuf->b_ml.ml_line_count;
|
uep->ue_lcount = buf->b_ml.ml_line_count;
|
||||||
curbuf->b_u_newhead->uh_getbot_entry = uep;
|
buf->b_u_newhead->uh_getbot_entry = uep;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
@ -574,17 +586,19 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
|
|||||||
u_freeentry(uep, i);
|
u_freeentry(uep, i);
|
||||||
return FAIL;
|
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_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) {
|
if (reload) {
|
||||||
// buffer was reloaded, notify text change subscribers
|
// buffer was reloaded, notify text change subscribers
|
||||||
curbuf->b_u_newhead->uh_flags |= UH_RELOAD;
|
curbuf->b_u_newhead->uh_flags |= UH_RELOAD;
|
||||||
}
|
}
|
||||||
curbuf->b_u_synced = false;
|
buf->b_u_synced = false;
|
||||||
undo_undoes = false;
|
undo_undoes = false;
|
||||||
|
|
||||||
#ifdef U_DEBUG
|
#ifdef U_DEBUG
|
||||||
@ -1846,8 +1860,9 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event)
|
|||||||
{
|
{
|
||||||
int count = startcount;
|
int count = startcount;
|
||||||
|
|
||||||
if (!undo_allowed())
|
if (!undo_allowed(curbuf)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
u_newcount = 0;
|
u_newcount = 0;
|
||||||
u_oldcount = 0;
|
u_oldcount = 0;
|
||||||
@ -1858,15 +1873,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
|
* needed. This may cause the file to be reloaded, that must happen
|
||||||
* before we do anything, because it may change curbuf->b_u_curhead
|
* before we do anything, because it may change curbuf->b_u_curhead
|
||||||
* and more. */
|
* and more. */
|
||||||
change_warning(0);
|
change_warning(curbuf, 0);
|
||||||
|
|
||||||
if (undo_undoes) {
|
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;
|
curbuf->b_u_curhead = curbuf->b_u_newhead;
|
||||||
else if (get_undolevel() > 0) /* multi level undo */
|
} else if (get_undolevel(curbuf) > 0) { // multi level undo
|
||||||
/* get next undo */
|
// get next undo
|
||||||
curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr;
|
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) {
|
if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) {
|
||||||
/* stick curbuf->b_u_curhead at end */
|
/* stick curbuf->b_u_curhead at end */
|
||||||
curbuf->b_u_curhead = curbuf->b_u_oldhead;
|
curbuf->b_u_curhead = curbuf->b_u_oldhead;
|
||||||
@ -1880,8 +1896,8 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event)
|
|||||||
|
|
||||||
u_undoredo(true, do_buf_event);
|
u_undoredo(true, do_buf_event);
|
||||||
} else {
|
} else {
|
||||||
if (curbuf->b_u_curhead == NULL || get_undolevel() <= 0) {
|
if (curbuf->b_u_curhead == NULL || get_undolevel(curbuf) <= 0) {
|
||||||
beep_flush(); /* nothing to redo */
|
beep_flush(); // nothing to redo
|
||||||
if (count == startcount - 1) {
|
if (count == startcount - 1) {
|
||||||
MSG(_("Already at newest change"));
|
MSG(_("Already at newest change"));
|
||||||
return;
|
return;
|
||||||
@ -2122,8 +2138,8 @@ target_zero:
|
|||||||
if (uhp != NULL || target == 0) {
|
if (uhp != NULL || target == 0) {
|
||||||
// First go up the tree as much as needed.
|
// First go up the tree as much as needed.
|
||||||
while (!got_int) {
|
while (!got_int) {
|
||||||
/* Do the change warning now, for the same reason as above. */
|
// Do the change warning now, for the same reason as above.
|
||||||
change_warning(0);
|
change_warning(curbuf, 0);
|
||||||
|
|
||||||
uhp = curbuf->b_u_curhead;
|
uhp = curbuf->b_u_curhead;
|
||||||
if (uhp == NULL)
|
if (uhp == NULL)
|
||||||
@ -2147,7 +2163,7 @@ target_zero:
|
|||||||
// And now go down the tree (redo), branching off where needed.
|
// And now go down the tree (redo), branching off where needed.
|
||||||
while (!got_int) {
|
while (!got_int) {
|
||||||
// Do the change warning now, for the same reason as above.
|
// Do the change warning now, for the same reason as above.
|
||||||
change_warning(0);
|
change_warning(curbuf, 0);
|
||||||
|
|
||||||
uhp = curbuf->b_u_curhead;
|
uhp = curbuf->b_u_curhead;
|
||||||
if (uhp == NULL) {
|
if (uhp == NULL) {
|
||||||
@ -2414,7 +2430,7 @@ static void u_undoredo(int undo, bool do_buf_event)
|
|||||||
|
|
||||||
curhead->uh_entry = newlist;
|
curhead->uh_entry = newlist;
|
||||||
curhead->uh_flags = new_flags;
|
curhead->uh_flags = new_flags;
|
||||||
if ((old_flags & UH_EMPTYBUF) && BUFEMPTY()) {
|
if ((old_flags & UH_EMPTYBUF) && buf_is_empty(curbuf)) {
|
||||||
curbuf->b_ml.ml_flags |= ML_EMPTY;
|
curbuf->b_ml.ml_flags |= ML_EMPTY;
|
||||||
}
|
}
|
||||||
if (old_flags & UH_CHANGED) {
|
if (old_flags & UH_CHANGED) {
|
||||||
@ -2591,13 +2607,15 @@ u_sync(
|
|||||||
int force // Also sync when no_u_sync is set.
|
int force // Also sync when no_u_sync is set.
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Skip it when already synced or syncing is disabled. */
|
// Skip it when already synced or syncing is disabled.
|
||||||
if (curbuf->b_u_synced || (!force && no_u_sync > 0))
|
if (curbuf->b_u_synced || (!force && no_u_sync > 0)) {
|
||||||
return;
|
return;
|
||||||
if (get_undolevel() < 0)
|
}
|
||||||
curbuf->b_u_synced = true; /* no entries, nothing to do */
|
|
||||||
else {
|
if (get_undolevel(curbuf) < 0) {
|
||||||
u_getbot(); /* compute ue_bot of previous u_save */
|
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;
|
curbuf->b_u_curhead = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2708,7 +2726,7 @@ void ex_undojoin(exarg_T *eap)
|
|||||||
if (!curbuf->b_u_synced) {
|
if (!curbuf->b_u_synced) {
|
||||||
return; // already unsynced
|
return; // already unsynced
|
||||||
}
|
}
|
||||||
if (get_undolevel() < 0) {
|
if (get_undolevel(curbuf) < 0) {
|
||||||
return; // no entries, nothing to do
|
return; // no entries, nothing to do
|
||||||
} else {
|
} else {
|
||||||
curbuf->b_u_synced = false; // Append next change to last entry
|
curbuf->b_u_synced = false; // Append next change to last entry
|
||||||
@ -2792,38 +2810,39 @@ static void u_unch_branch(u_header_T *uhp)
|
|||||||
* Get pointer to last added entry.
|
* Get pointer to last added entry.
|
||||||
* If it's not valid, give an error message and return NULL.
|
* 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"));
|
IEMSG(_("E439: undo list corrupt"));
|
||||||
return NULL;
|
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
|
* u_getbot(): compute the line number of the previous u_save
|
||||||
* It is called only when b_u_synced is false.
|
* 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;
|
u_entry_T *uep;
|
||||||
linenr_T extra;
|
linenr_T extra;
|
||||||
|
|
||||||
uep = u_get_headentry(); /* check for corrupt undo list */
|
uep = u_get_headentry(buf); // check for corrupt undo list
|
||||||
if (uep == NULL)
|
if (uep == NULL) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uep = curbuf->b_u_newhead->uh_getbot_entry;
|
uep = buf->b_u_newhead->uh_getbot_entry;
|
||||||
if (uep != NULL) {
|
if (uep != NULL) {
|
||||||
/*
|
/*
|
||||||
* the new ue_bot is computed from the number of lines that has been
|
* 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
|
* inserted (0 - deleted) since calling u_save. This is equal to the
|
||||||
* old line count subtracted from the current line count.
|
* 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;
|
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"));
|
IEMSG(_("E440: undo line missing"));
|
||||||
uep->ue_bot = uep->ue_top + 1; // assume all lines deleted, will
|
uep->ue_bot = uep->ue_top + 1; // assume all lines deleted, will
|
||||||
// get all the old lines back
|
// get all the old lines back
|
||||||
@ -2831,10 +2850,10 @@ static void u_getbot(void)
|
|||||||
// ones
|
// 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 +3033,12 @@ void u_undoline(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first save the line for the 'u' command */
|
// first save the line for the 'u' command
|
||||||
if (u_savecommon(curbuf->b_u_line_lnum - 1,
|
if (u_savecommon(curbuf, curbuf->b_u_line_lnum - 1,
|
||||||
curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
|
curbuf->b_u_line_lnum + 1, (linenr_T)0, false) == FAIL) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
oldp = u_save_line(curbuf->b_u_line_lnum);
|
oldp = u_save_line(curbuf->b_u_line_lnum);
|
||||||
ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
|
ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
|
||||||
changed_bytes(curbuf->b_u_line_lnum, 0);
|
changed_bytes(curbuf->b_u_line_lnum, 0);
|
||||||
@ -3048,12 +3069,21 @@ void u_blockfree(buf_T *buf)
|
|||||||
xfree(buf->b_u_line_ptr);
|
xfree(buf->b_u_line_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Allocate memory and copy curbuf line into it.
|
||||||
* u_save_line(): allocate memory and copy line 'lnum' into it.
|
///
|
||||||
*/
|
/// @param lnum the line to copy
|
||||||
static char_u *u_save_line(linenr_T lnum)
|
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
|
/// Check if the 'modified' flag is set, or 'ff' has changed (only need to
|
||||||
@ -3143,18 +3173,16 @@ u_header_T *u_force_get_undo_header(buf_T *buf)
|
|||||||
if (!uhp) {
|
if (!uhp) {
|
||||||
// Undo is normally invoked in change code, which already has swapped
|
// Undo is normally invoked in change code, which already has swapped
|
||||||
// curbuf.
|
// curbuf.
|
||||||
buf_T *save_curbuf = curbuf;
|
|
||||||
curbuf = buf;
|
|
||||||
// Args are tricky: this means replace empty range by empty range..
|
// Args are tricky: this means replace empty range by empty range..
|
||||||
u_savecommon(0, 1, 1, true);
|
u_savecommon(curbuf, 0, 1, 1, true);
|
||||||
|
|
||||||
uhp = buf->b_u_curhead;
|
uhp = buf->b_u_curhead;
|
||||||
if (!uhp) {
|
if (!uhp) {
|
||||||
uhp = buf->b_u_newhead;
|
uhp = buf->b_u_newhead;
|
||||||
if (get_undolevel() > 0 && !uhp) {
|
if (get_undolevel(curbuf) > 0 && !uhp) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
curbuf = save_curbuf;
|
|
||||||
}
|
}
|
||||||
return uhp;
|
return uhp;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/iconv.h"
|
#include "nvim/iconv.h"
|
||||||
#include "nvim/version.h"
|
#include "nvim/version.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
@ -2190,7 +2191,7 @@ void list_version(void)
|
|||||||
/// Show the intro message when not editing a file.
|
/// Show the intro message when not editing a file.
|
||||||
void maybe_intro_message(void)
|
void maybe_intro_message(void)
|
||||||
{
|
{
|
||||||
if (BUFEMPTY()
|
if (buf_is_empty(curbuf)
|
||||||
&& (curbuf->b_fname == NULL)
|
&& (curbuf->b_fname == NULL)
|
||||||
&& (firstwin->w_next == NULL)
|
&& (firstwin->w_next == NULL)
|
||||||
&& (vim_strchr(p_shm, SHM_INTRO) == NULL)) {
|
&& (vim_strchr(p_shm, SHM_INTRO) == NULL)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user