diff options
Diffstat (limited to 'src/nvim/memline.c')
-rw-r--r-- | src/nvim/memline.c | 114 |
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; } |