aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r--src/nvim/buffer.c90
1 files changed, 61 insertions, 29 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 839d61cd2e..a8cb90ff0e 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -602,8 +602,12 @@ void close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
* Remove the buffer from the list.
*/
if (wipe_buf) {
- xfree(buf->b_ffname);
- xfree(buf->b_sfname);
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ } else {
+ buf->b_sfname = NULL;
+ }
+ XFREE_CLEAR(buf->b_ffname);
if (buf->b_prev == NULL) {
firstbuf = buf->b_next;
} else {
@@ -1693,15 +1697,18 @@ static inline void buf_init_changedtick(buf_T *const buf)
/// if the buffer already exists.
/// This is the ONLY way to create a new buffer.
///
-/// @param ffname full path of fname or relative
-/// @param sfname short fname or NULL
+/// @param ffname_arg full path of fname or relative
+/// @param sfname_arg short fname or NULL
/// @param lnum preferred cursor line
/// @param flags BLN_ defines
/// @param bufnr
///
/// @return pointer to the buffer
-buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
+buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum,
+ int flags)
{
+ char_u *ffname = ffname_arg;
+ char_u *sfname = sfname_arg;
buf_T *buf;
fname_expand(curbuf, &ffname, &sfname); // will allocate ffname
@@ -1787,8 +1794,12 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
buf->b_wininfo = xcalloc(1, sizeof(wininfo_T));
if (ffname != NULL && (buf->b_ffname == NULL || buf->b_sfname == NULL)) {
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ } else {
+ buf->b_sfname = NULL;
+ }
XFREE_CLEAR(buf->b_ffname);
- XFREE_CLEAR(buf->b_sfname);
if (buf != curbuf) {
free_buffer(buf);
}
@@ -2778,28 +2789,32 @@ int buflist_name_nr(int fnum, char_u **fname, linenr_T *lnum)
return OK;
}
-/*
- * Set the file name for "buf"' to 'ffname', short file name to 'sfname'.
- * The file name with the full path is also remembered, for when :cd is used.
- * Returns FAIL for failure (file name already in use by other buffer)
- * OK otherwise.
- */
-int
-setfname(
+// Set the file name for "buf" to "ffname_arg", short file name to
+// "sfname_arg".
+// The file name with the full path is also remembered, for when :cd is used.
+// Returns FAIL for failure (file name already in use by other buffer)
+// OK otherwise.
+int setfname(
buf_T *buf,
- char_u *ffname,
- char_u *sfname,
+ char_u *ffname_arg,
+ char_u *sfname_arg,
bool message // give message when buffer already exists
)
{
+ char_u *ffname = ffname_arg;
+ char_u *sfname = sfname_arg;
buf_T *obuf = NULL;
FileID file_id;
bool file_id_valid = false;
if (ffname == NULL || *ffname == NUL) {
// Removing the name.
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ } else {
+ buf->b_sfname = NULL;
+ }
XFREE_CLEAR(buf->b_ffname);
- XFREE_CLEAR(buf->b_sfname);
} else {
fname_expand(buf, &ffname, &sfname); // will allocate ffname
if (ffname == NULL) { // out of memory
@@ -2830,8 +2845,10 @@ setfname(
#ifdef USE_FNAME_CASE
path_fix_case(sfname); // set correct case for short file name
#endif
+ if (buf->b_sfname != buf->b_ffname) {
+ xfree(buf->b_sfname);
+ }
xfree(buf->b_ffname);
- xfree(buf->b_sfname);
buf->b_ffname = ffname;
buf->b_sfname = sfname;
}
@@ -2857,7 +2874,9 @@ void buf_set_name(int fnum, char_u *name)
buf = buflist_findnr(fnum);
if (buf != NULL) {
- xfree(buf->b_sfname);
+ if (buf->b_sfname != buf->b_ffname) {
+ xfree(buf->b_sfname);
+ }
xfree(buf->b_ffname);
buf->b_ffname = vim_strsave(name);
buf->b_sfname = NULL;
@@ -4633,16 +4652,18 @@ static bool append_arg_number(win_T *wp, char_u *buf, int buflen, bool add_file)
return true;
}
-/*
- * Make "ffname" a full file name, set "sfname" to "ffname" if not NULL.
- * "ffname" becomes a pointer to allocated memory (or NULL).
- */
+// Make "*ffname" a full file name, set "*sfname" to "*ffname" if not NULL.
+// "*ffname" becomes a pointer to allocated memory (or NULL).
+// When resolving a link both "*sfname" and "*ffname" will point to the same
+// allocated memory.
+// The "*ffname" and "*sfname" pointer values on call will not be freed.
+// Note that the resulting "*ffname" pointer should be considered not allocaed.
void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname)
{
- if (*ffname == NULL) { // if no file name given, nothing to do
+ if (*ffname == NULL) { // no file name given, nothing to do
return;
}
- if (*sfname == NULL) { // if no short file name given, use ffname
+ if (*sfname == NULL) { // no short file name given, use ffname
*sfname = *ffname;
}
*ffname = (char_u *)fix_fname((char *)(*ffname)); // expand to full path
@@ -4685,7 +4706,6 @@ do_arg_all(
int keep_tabs // keep current tabs, for ":tab drop file"
)
{
- int i;
char_u *opened; // Array of weight for which args are open:
// 0: not opened
// 1: opened in other tab
@@ -4694,6 +4714,7 @@ do_arg_all(
int opened_len; // length of opened[]
int use_firstwin = false; // use first window for arglist
+ bool tab_drop_empty_window = false;
int split_ret = OK;
bool p_ea_save;
alist_T *alist; // argument list to be used
@@ -4741,6 +4762,7 @@ do_arg_all(
win_T *wpnext = NULL;
tpnext = curtab->tp_next;
for (win_T *wp = firstwin; wp != NULL; wp = wpnext) {
+ int i;
wpnext = wp->w_next;
buf = wp->w_buffer;
if (buf->b_ffname == NULL
@@ -4846,14 +4868,15 @@ do_arg_all(
last_curwin = curwin;
last_curtab = curtab;
win_enter(lastwin, false);
- // ":drop all" 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.
if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
&& curbuf->b_ffname == NULL && !curbuf->b_changed) {
use_firstwin = true;
+ tab_drop_empty_window = true;
}
- for (i = 0; i < count && i < opened_len && !got_int; i++) {
+ for (int i = 0; i < count && !got_int; i++) {
if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) {
arg_had_last = true;
}
@@ -4873,6 +4896,10 @@ do_arg_all(
}
}
} else if (split_ret == OK) {
+ // trigger events for tab drop
+ if (tab_drop_empty_window && i == count - 1) {
+ autocmd_no_enter--;
+ }
if (!use_firstwin) { // split current window
p_ea_save = p_ea;
p_ea = true; // use space from all windows
@@ -4898,6 +4925,9 @@ do_arg_all(
|| bufIsChanged(curwin->w_buffer))
? ECMD_HIDE : 0) + ECMD_OLDBUF,
curwin);
+ if (tab_drop_empty_window && i == count - 1) {
+ autocmd_no_enter++;
+ }
if (use_firstwin) {
autocmd_no_leave++;
}
@@ -5449,7 +5479,9 @@ int buf_signcols(buf_T *buf)
curline = sign->lnum;
linesum = 0;
}
- linesum++;
+ if (sign->has_text_or_icon) {
+ linesum++;
+ }
}
if (linesum > buf->b_signcols_max) {
buf->b_signcols_max = linesum;