aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/memline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/memline.c')
-rw-r--r--src/nvim/memline.c114
1 files changed, 69 insertions, 45 deletions
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index d5788d96b3..57ed0d6588 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -257,11 +257,12 @@ int ml_open(buf_T *buf)
/*
* init fields in memline struct
*/
- buf->b_ml.ml_stack_size = 0; /* no stack yet */
- buf->b_ml.ml_stack = NULL; /* no stack yet */
- buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
- buf->b_ml.ml_locked = NULL; /* no cached block */
- buf->b_ml.ml_line_lnum = 0; /* no cached line */
+ buf->b_ml.ml_stack_size = 0; // no stack yet
+ buf->b_ml.ml_stack = NULL; // no stack yet
+ buf->b_ml.ml_stack_top = 0; // nothing in the stack
+ buf->b_ml.ml_locked = NULL; // no cached block
+ buf->b_ml.ml_line_lnum = 0; // no cached line
+ buf->b_ml.ml_line_offset = 0;
buf->b_ml.ml_chunksize = NULL;
if (cmdmod.noswapfile) {
@@ -831,11 +832,12 @@ void ml_recover(bool checkext)
/*
* init fields in memline struct
*/
- buf->b_ml.ml_stack_size = 0; /* no stack yet */
- buf->b_ml.ml_stack = NULL; /* no stack yet */
- buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
- buf->b_ml.ml_line_lnum = 0; /* no cached line */
- buf->b_ml.ml_locked = NULL; /* no locked block */
+ buf->b_ml.ml_stack_size = 0; // no stack yet
+ buf->b_ml.ml_stack = NULL; // no stack yet
+ buf->b_ml.ml_stack_top = 0; // nothing in the stack
+ buf->b_ml.ml_line_lnum = 0; // no cached line
+ buf->b_ml.ml_line_offset = 0;
+ buf->b_ml.ml_locked = NULL; // no locked block
buf->b_ml.ml_flags = 0;
/*
@@ -1358,7 +1360,7 @@ recover_names (
* Try finding a swap file by simply adding ".swp" to the file name.
*/
if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) {
- char_u *swapname = (char_u *)modname((char *)fname_res, ".swp", TRUE);
+ char_u *swapname = (char_u *)modname((char *)fname_res, ".swp", true);
if (swapname != NULL) {
if (os_path_exists(swapname)) {
files = xmalloc(sizeof(char_u *));
@@ -1636,10 +1638,11 @@ static int recov_file_names(char_u **names, char_u *path, int prepend_dot)
// May also add the file name with a dot prepended, for swap file in same
// dir as original file.
if (prepend_dot) {
- names[num_names] = (char_u *)modname((char *)path, ".sw?", TRUE);
- if (names[num_names] == NULL)
+ names[num_names] = (char_u *)modname((char *)path, ".sw?", true);
+ if (names[num_names] == NULL) {
return num_names;
- ++num_names;
+ }
+ num_names++;
}
// Form the normal swap file name pattern by appending ".sw?".
@@ -1816,6 +1819,7 @@ ml_get_buf (
linenr_T lnum,
bool will_change // line will be changed
)
+ FUNC_ATTR_NONNULL_ALL
{
bhdr_T *hp;
DATA_BL *dp;
@@ -2403,12 +2407,13 @@ void ml_add_deleted_len_buf(buf_T *buf, char_u *ptr, ssize_t len)
if (len == -1) {
len = STRLEN(ptr);
}
- buf->deleted_bytes += len+1;
- if (buf->update_need_codepoints) {
- mb_utflen(ptr, len, &buf->deleted_codepoints,
- &buf->deleted_codeunits);
- buf->deleted_codepoints++; // NL char
- buf->deleted_codeunits++;
+ curbuf->deleted_bytes += len+1;
+ curbuf->deleted_bytes2 += len+1;
+ if (curbuf->update_need_codepoints) {
+ mb_utflen(ptr, len, &curbuf->deleted_codepoints,
+ &curbuf->deleted_codeunits);
+ curbuf->deleted_codepoints++; // NL char
+ curbuf->deleted_codeunits++;
}
}
@@ -2418,17 +2423,17 @@ int ml_replace(linenr_T lnum, char_u *line, bool copy)
return ml_replace_buf(curbuf, lnum, line, copy);
}
-/*
- * Replace line lnum, with buffering, in current buffer.
- *
- * If "copy" is TRUE, make a copy of the line, otherwise the line has been
- * copied to allocated memory already.
- *
- * Check: The caller of this function should probably also call
- * changed_lines(), unless update_screen(NOT_VALID) is used.
- *
- * return FAIL for failure, OK otherwise
- */
+// Replace line "lnum", with buffering, in current buffer.
+//
+// If "copy" is true, make a copy of the line, otherwise the line has been
+// copied to allocated memory already.
+// If "copy" is false the "line" may be freed to add text properties!
+// Do not use it after calling ml_replace().
+//
+// Check: The caller of this function should probably also call
+// changed_lines(), unless update_screen(NOT_VALID) is used.
+//
+// return FAIL for failure, OK otherwise
int ml_replace_buf(buf_T *buf, linenr_T lnum, char_u *line, bool copy)
{
if (line == NULL) /* just checking... */
@@ -2831,6 +2836,7 @@ static void ml_flush_line(buf_T *buf)
}
buf->b_ml.ml_line_lnum = 0;
+ buf->b_ml.ml_line_offset = 0;
}
/*
@@ -3188,6 +3194,12 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name
char_u *fname_res = fname;
#ifdef HAVE_READLINK
char_u fname_buf[MAXPATHL];
+
+ // Expand symlink in the file name, so that we put the swap file with the
+ // actual file instead of with the symlink.
+ if (resolve_symlink(fname, fname_buf) == OK) {
+ fname_res = fname_buf;
+ }
#endif
int len = (int)STRLEN(dir_name);
@@ -3196,20 +3208,14 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name
&& len > 1
&& s[-1] == s[-2]) { // Ends with '//', Use Full path
r = NULL;
- if ((s = (char_u *)make_percent_swname((char *)dir_name, (char *)fname)) != NULL) {
- r = (char_u *)modname((char *)s, ".swp", FALSE);
+ s = (char_u *)make_percent_swname((char *)dir_name, (char *)fname_res);
+ if (s != NULL) {
+ r = (char_u *)modname((char *)s, ".swp", false);
xfree(s);
}
return r;
}
-#ifdef HAVE_READLINK
- /* Expand symlink in the file name, so that we put the swap file with the
- * actual file instead of with the symlink. */
- if (resolve_symlink(fname, fname_buf) == OK)
- fname_res = fname_buf;
-#endif
-
// Prepend a '.' to the swap file name for the current directory.
r = (char_u *)modname((char *)fname_res, ".swp",
dir_name[0] == '.' && dir_name[1] == NUL);
@@ -3980,10 +3986,10 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype)
/// Find offset for line or line with offset.
///
/// @param buf buffer to use
-/// @param lnum if > 0, find offset of lnum, store offset in offp
+/// @param lnum if > 0, find offset of lnum, return offset
/// if == 0, return line with offset *offp
-/// @param offp Location where offset of line is stored, or to read offset to
-/// use to find line. In the later case, store remaining offset.
+/// @param offp offset to use to find line, store remaining column offset
+/// Should be NULL when getting offset of line
/// @param no_ff ignore 'fileformat' option, always use one byte for NL.
///
/// @return -1 if information is not available
@@ -4003,8 +4009,22 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff)
int ffdos = !no_ff && (get_fileformat(buf) == EOL_DOS);
int extra = 0;
- // take care of cached line first
- ml_flush_line(buf);
+ // take care of cached line first. Only needed if the cached line is before
+ // the requested line. Additionally cache the value for the cached line.
+ // This is used by the extmark code which needs the byte offset of the edited
+ // line. So when doing multiple small edits on the same line the value is
+ // only calculated once.
+ //
+ // NB: caching doesn't work with 'fileformat'. This is not a problem for
+ // bytetracking, as bytetracking ignores 'fileformat' option. But calling
+ // line2byte() will invalidate the cache for the time being (this function
+ // was never cached to start with anyway).
+ bool can_cache = (lnum != 0 && !ffdos && buf->b_ml.ml_line_lnum == lnum);
+ if (lnum == 0 || buf->b_ml.ml_line_lnum < lnum || !no_ff) {
+ ml_flush_line(curbuf);
+ } else if (can_cache && buf->b_ml.ml_line_offset > 0) {
+ return buf->b_ml.ml_line_offset;
+ }
if (buf->b_ml.ml_usedchunks == -1
|| buf->b_ml.ml_chunksize == NULL
@@ -4100,6 +4120,10 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff)
}
}
+ if (can_cache && size > 0) {
+ buf->b_ml.ml_line_offset = size;
+ }
+
return size;
}