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.c166
1 files changed, 125 insertions, 41 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 81bbc56eb9..cd77f48320 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -45,6 +45,7 @@
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/hashtab.h"
+#include "nvim/highlight.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/main.h"
@@ -251,7 +252,7 @@ open_buffer (
msg_silent = old_msg_silent;
// Help buffer is filtered.
- if (curbuf->b_help) {
+ if (bt_help(curbuf)) {
fix_help_buffer();
}
} else if (read_stdin) {
@@ -295,6 +296,11 @@ open_buffer (
}
save_file_ff(curbuf); // keep this fileformat
+ // Set last_changedtick to avoid triggering a TextChanged autocommand right
+ // after it was added.
+ curbuf->b_last_changedtick = buf_get_changedtick(curbuf);
+ curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf);
+
/* require "!" to overwrite the file, because it wasn't read completely */
if (aborting())
curbuf->b_flags |= BF_READERR;
@@ -504,14 +510,20 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)
int nwindows = buf->b_nwindows;
- /* decrease the link count from windows (unless not in any window) */
- if (buf->b_nwindows > 0)
- --buf->b_nwindows;
+ // decrease the link count from windows (unless not in any window)
+ if (buf->b_nwindows > 0) {
+ buf->b_nwindows--;
+ }
+
+ if (diffopt_hiddenoff() && !unload_buf && buf->b_nwindows == 0) {
+ diff_buf_delete(buf); // Clear 'diff' for hidden buffer.
+ }
/* Return when a window is displaying the buffer or when it's not
* unloaded. */
- if (buf->b_nwindows > 0 || !unload_buf)
+ if (buf->b_nwindows > 0 || !unload_buf) {
return;
+ }
if (buf->terminal) {
terminal_close(buf->terminal, NULL);
@@ -829,8 +841,8 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
* aborting() returns FALSE when closing a window. */
enter_cleanup(&cs);
- /* Quitting means closing the split window, nothing else. */
- win_close(curwin, TRUE);
+ // Quitting means closing the split window, nothing else.
+ win_close(curwin, true);
swap_exists_action = SEA_NONE;
swap_exists_did_quit = TRUE;
@@ -872,7 +884,15 @@ void handle_swap_exists(bufref_T *old_curbuf)
buf = old_curbuf->br_buf;
}
if (buf != NULL) {
+ int old_msg_silent = msg_silent;
+
+ if (shortmess(SHM_FILEINFO)) {
+ msg_silent = 1; // prevent fileinfo message
+ }
enter_buffer(buf);
+ // restore msg_silent, so that the command line will be shown
+ msg_silent = old_msg_silent;
+
if (old_tw != curbuf->b_p_tw) {
check_colorcolumn(curwin);
}
@@ -2647,9 +2667,8 @@ buf_T *setaltfname(char_u *ffname, char_u *sfname, linenr_T lnum)
* Get alternate file name for current window.
* Return NULL if there isn't any, and give error message if requested.
*/
-char_u *
-getaltfname (
- int errmsg /* give error message */
+char_u * getaltfname(
+ bool errmsg // give error message
)
{
char_u *fname;
@@ -3219,10 +3238,11 @@ int build_stl_str_hl(
// Get the byte value now, in case we need it below. This is more
// efficient than making a copy of the line.
int byteval;
- if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr))
+ if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr)) {
byteval = 0;
- else
- byteval = (*mb_ptr2char)(line_ptr + wp->w_cursor.col);
+ } else {
+ byteval = utf_ptr2char(line_ptr + wp->w_cursor.col);
+ }
int groupdepth = 0;
@@ -3602,7 +3622,7 @@ int build_stl_str_hl(
// Store the current buffer number as a string variable
vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum);
- set_internal_string_var((char_u *)"actual_curbuf", tmp);
+ set_internal_string_var((char_u *)"g:actual_curbuf", tmp);
buf_T *o_curbuf = curbuf;
win_T *o_curwin = curwin;
@@ -3711,10 +3731,11 @@ int build_stl_str_hl(
case STL_OFFSET_X:
base = kNumBaseHexadecimal;
- // fallthrough
+ FALLTHROUGH;
case STL_OFFSET:
{
- long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL);
+ long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL,
+ false);
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) || l < 0 ?
0L : l + 1 + (!(State & INSERT) && empty_line ?
0 : (int)wp->w_cursor.col);
@@ -3722,7 +3743,7 @@ int build_stl_str_hl(
}
case STL_BYTEVAL_X:
base = kNumBaseHexadecimal;
- // fallthrough
+ FALLTHROUGH;
case STL_BYTEVAL:
num = byteval;
if (num == NL)
@@ -4419,7 +4440,7 @@ do_arg_all (
if (i < alist->al_ga.ga_len
&& (AARGLIST(alist)[i].ae_fnum == buf->b_fnum
|| path_full_compare(alist_name(&AARGLIST(alist)[i]),
- buf->b_ffname, TRUE) & kEqualFiles)) {
+ buf->b_ffname, true) & kEqualFiles)) {
int weight = 1;
if (old_curtab == curtab) {
@@ -4513,9 +4534,10 @@ do_arg_all (
use_firstwin = true;
}
- for (i = 0; i < count && i < opened_len && !got_int; ++i) {
- if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
- arg_had_last = TRUE;
+ for (i = 0; i < count && i < opened_len && !got_int; i++) {
+ if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) {
+ arg_had_last = true;
+ }
if (opened[i] > 0) {
/* Move the already present window to below the current window */
if (curwin->w_arg_idx != i) {
@@ -4639,10 +4661,10 @@ void ex_buffer_all(exarg_T *eap)
&& !ONE_WINDOW
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
) {
- win_close(wp, FALSE);
- wpnext = firstwin; /* just in case an autocommand does
- something strange with windows */
- tpnext = first_tabpage; /* start all over...*/
+ win_close(wp, false);
+ wpnext = firstwin; // just in case an autocommand does
+ // something strange with windows
+ tpnext = first_tabpage; // start all over...
open_wins = 0;
} else
++open_wins;
@@ -4711,9 +4733,9 @@ void ex_buffer_all(exarg_T *eap)
* aborting() returns FALSE when closing a window. */
enter_cleanup(&cs);
- /* User selected Quit at ATTENTION prompt; close this window. */
- win_close(curwin, TRUE);
- --open_wins;
+ // User selected Quit at ATTENTION prompt; close this window.
+ win_close(curwin, true);
+ open_wins--;
swap_exists_action = SEA_NONE;
swap_exists_did_quit = TRUE;
@@ -4918,6 +4940,12 @@ chk_modeline (
return retval;
}
+// Return true if "buf" is a help buffer.
+bool bt_help(const buf_T *const buf)
+{
+ return buf != NULL && buf->b_help;
+}
+
/*
* Return special buffer name.
* Returns NULL when the buffer has a normal file name.
@@ -5057,13 +5085,16 @@ linenr_T buf_change_sign_type(
return (linenr_T)0;
}
-int buf_getsigntype(
- buf_T *buf,
- linenr_T lnum,
- int type /* SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL */
- )
+/// Gets a sign from a given line.
+/// In case of multiple signs, returns the most recently placed one.
+///
+/// @param buf Buffer in which to search
+/// @param lnum Line in which to search
+/// @param type Type of sign to look for
+/// @return Identifier of the first matching sign, or 0
+int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type)
{
- signlist_T *sign; /* a sign in a b_signlist */
+ signlist_T *sign; // a sign in a b_signlist
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
if (sign->lnum == lnum
@@ -5071,7 +5102,9 @@ int buf_getsigntype(
|| (type == SIGN_TEXT
&& sign_get_text(sign->typenr) != NULL)
|| (type == SIGN_LINEHL
- && sign_get_attr(sign->typenr, TRUE) != 0))) {
+ && sign_get_attr(sign->typenr, SIGN_LINEHL) != 0)
+ || (type == SIGN_NUMHL
+ && sign_get_attr(sign->typenr, SIGN_NUMHL) != 0))) {
return sign->typenr;
}
}
@@ -5357,6 +5390,45 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
}
}
+int bufhl_add_virt_text(buf_T *buf,
+ int src_id,
+ linenr_T lnum,
+ VirtText virt_text)
+{
+ static int next_src_id = 1;
+ if (src_id == 0) {
+ src_id = next_src_id++;
+ }
+
+ BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, true);
+
+ bufhl_clear_virttext(&lineinfo->virt_text);
+ if (kv_size(virt_text) > 0) {
+ lineinfo->virt_text_src = src_id;
+ lineinfo->virt_text = virt_text;
+ } else {
+ lineinfo->virt_text_src = 0;
+ // currently not needed, but allow a future caller with
+ // 0 size and non-zero capacity
+ kv_destroy(virt_text);
+ }
+
+ if (0 < lnum && lnum <= buf->b_ml.ml_line_count) {
+ changed_lines_buf(buf, lnum, lnum+1, 0);
+ redraw_buf_later(buf, VALID);
+ }
+ return src_id;
+}
+
+static void bufhl_clear_virttext(VirtText *text)
+{
+ for (size_t i = 0; i < kv_size(*text); i++) {
+ xfree(kv_A(*text, i).text);
+ }
+ kv_destroy(*text);
+ *text = (VirtText)KV_INITIAL_VALUE;
+}
+
/// Clear bufhl highlights from a given source group and range of lines.
///
/// @param buf The buffer to remove highlights from
@@ -5412,6 +5484,7 @@ void bufhl_clear_line_range(buf_T *buf,
static BufhlLineStatus bufhl_clear_line(BufhlLine *lineinfo, int src_id,
linenr_T lnum)
{
+ BufhlLineStatus changed = kBLSUnchanged;
size_t oldsize = kv_size(lineinfo->items);
if (src_id < 0) {
kv_size(lineinfo->items) = 0;
@@ -5427,14 +5500,25 @@ static BufhlLineStatus bufhl_clear_line(BufhlLine *lineinfo, int src_id,
}
kv_size(lineinfo->items) = newidx;
}
+ if (kv_size(lineinfo->items) != oldsize) {
+ changed = kBLSChanged;
+ }
+
+ if (kv_size(lineinfo->virt_text) != 0
+ && (src_id < 0 || src_id == lineinfo->virt_text_src)) {
+ bufhl_clear_virttext(&lineinfo->virt_text);
+ lineinfo->virt_text_src = 0;
+ changed = kBLSChanged;
+ }
- if (kv_size(lineinfo->items) == 0) {
+ if (kv_size(lineinfo->items) == 0 && kv_size(lineinfo->virt_text) == 0) {
kv_destroy(lineinfo->items);
return kBLSDeleted;
}
- return kv_size(lineinfo->items) != oldsize ? kBLSChanged : kBLSUnchanged;
+ return changed;
}
+
/// Remove all highlights and free the highlight data
void bufhl_clear_all(buf_T *buf)
{
@@ -5509,8 +5593,8 @@ bool bufhl_start_line(buf_T *buf, linenr_T lnum, BufhlLineInfo *info)
return false;
}
info->valid_to = -1;
- info->entries = lineinfo->items;
- return kv_size(info->entries) > 0;
+ info->line = lineinfo;
+ return true;
}
/// get highlighting at column col
@@ -5530,8 +5614,8 @@ int bufhl_get_attr(BufhlLineInfo *info, colnr_T col)
}
int attr = 0;
info->valid_to = MAXCOL;
- for (size_t i = 0; i < kv_size(info->entries); i++) {
- BufhlItem entry = kv_A(info->entries, i);
+ for (size_t i = 0; i < kv_size(info->line->items); i++) {
+ BufhlItem entry = kv_A(info->line->items, i);
if (entry.start <= col && col <= entry.stop) {
int entry_attr = syn_id2attr(entry.hl_id);
attr = hl_combine_attr(attr, entry_attr);