mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
vim-patch:9.1.0151: ml_get_buf_len() does not consider text properties (#37094)
Problem: ml_get_buf_len() does not consider text properties
(zeertzj)
Solution: Store text length excluding text properties length
in addition in the memline
related vim/vim#14123
closes: vim/vim#14133
a72d1be5a9
--------
Replace ml_line_len with ml_line_textlen to be explicit
that Nvim doesn't currently support Vim's text properties
and Nvim doesn't support lines with "ambiguous" length.
--------
vim-patch:9.1.0153: Text properties corrupted with fo+=aw and backspace
Problem: Text properties corrupted with fo+=aw and backspace
Solution: Allocate line and move text properties
(zeertzjq)
closes: vim/vim#14147
7ac1145fbe
vim-patch:9.1.0163: Calling STRLEN() to compute ml_line_textlen when not needed
Problem: Calling STRLEN() to compute ml_line_textlen when not needed.
Solution: Use 0 when STRLEN() will be required and call STRLEN() later.
(zeertzjq)
closes: vim/vim#14155
82e079df81
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
This commit is contained in:
@@ -937,14 +937,14 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
|
||||
ml_add_deleted_len(curbuf->b_ml.ml_line_ptr, oldlen);
|
||||
newp = oldp; // use same allocated memory
|
||||
} else { // need to allocate a new line
|
||||
newp = xmalloc((size_t)newlen + 1);
|
||||
newp = xmallocz((size_t)newlen);
|
||||
memmove(newp, oldp, (size_t)col);
|
||||
}
|
||||
memmove(newp + col, oldp + col + count, (size_t)movelen);
|
||||
if (alloc_newp) {
|
||||
ml_replace(lnum, newp, false);
|
||||
} else {
|
||||
curbuf->b_ml.ml_line_len -= count;
|
||||
curbuf->b_ml.ml_line_textlen = newlen + 1;
|
||||
}
|
||||
|
||||
// mark the buffer as changed and prepare for displaying
|
||||
|
||||
@@ -3386,11 +3386,17 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
|
||||
// again when auto-formatting.
|
||||
if (has_format_option(FO_AUTO)
|
||||
&& has_format_option(FO_WHITE_PAR)) {
|
||||
char *ptr = ml_get_buf_mut(curbuf, curwin->w_cursor.lnum);
|
||||
const char *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum);
|
||||
int len = get_cursor_line_len();
|
||||
if (len > 0 && ptr[len - 1] == ' ') {
|
||||
ptr[len - 1] = NUL;
|
||||
curbuf->b_ml.ml_line_len--;
|
||||
char *newp = xmemdupz(ptr, (size_t)(len - 1));
|
||||
|
||||
if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) {
|
||||
xfree(curbuf->b_ml.ml_line_ptr);
|
||||
}
|
||||
curbuf->b_ml.ml_line_ptr = newp;
|
||||
curbuf->b_ml.ml_line_textlen--;
|
||||
curbuf->b_ml.ml_flags |= ML_LINE_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4038,17 +4044,18 @@ static bool ins_tab(void)
|
||||
int i = cursor->col - fpos.col;
|
||||
if (i > 0) {
|
||||
if (!(State & VREPLACE_FLAG)) {
|
||||
char *newp = xmalloc((size_t)(curbuf->b_ml.ml_line_len - i));
|
||||
const colnr_T newp_len = curbuf->b_ml.ml_line_textlen - i;
|
||||
char *newp = xmalloc((size_t)newp_len);
|
||||
ptrdiff_t col = ptr - curbuf->b_ml.ml_line_ptr;
|
||||
if (col > 0) {
|
||||
memmove(newp, ptr - col, (size_t)col);
|
||||
}
|
||||
memmove(newp + col, ptr + i, (size_t)(curbuf->b_ml.ml_line_len - col - i));
|
||||
memmove(newp + col, ptr + i, (size_t)(newp_len - col));
|
||||
if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) {
|
||||
xfree(curbuf->b_ml.ml_line_ptr);
|
||||
}
|
||||
curbuf->b_ml.ml_line_ptr = newp;
|
||||
curbuf->b_ml.ml_line_len -= i;
|
||||
curbuf->b_ml.ml_line_textlen = newp_len;
|
||||
curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
|
||||
inserted_bytes(fpos.lnum, change_col,
|
||||
cursor->col - change_col, fpos.col - change_col);
|
||||
|
||||
@@ -1804,6 +1804,7 @@ theend:
|
||||
/// On failure an error message is given and IObuff is returned (to avoid
|
||||
/// having to check for error everywhere).
|
||||
char *ml_get(linenr_T lnum)
|
||||
FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
return ml_get_buf_impl(curbuf, lnum, false);
|
||||
}
|
||||
@@ -1813,6 +1814,7 @@ char *ml_get(linenr_T lnum)
|
||||
/// This is the same as ml_get(), but taking in the buffer
|
||||
/// as an argument.
|
||||
char *ml_get_buf(buf_T *buf, linenr_T lnum)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
return ml_get_buf_impl(buf, lnum, false);
|
||||
}
|
||||
@@ -1824,6 +1826,7 @@ char *ml_get_buf(buf_T *buf, linenr_T lnum)
|
||||
///
|
||||
/// @return a pointer to a line in the buffer
|
||||
char *ml_get_buf_mut(buf_T *buf, linenr_T lnum)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
return ml_get_buf_impl(buf, lnum, true);
|
||||
}
|
||||
@@ -1850,11 +1853,14 @@ colnr_T ml_get_pos_len(pos_T *pos)
|
||||
/// @return length (excluding the NUL) of the given line in the given buffer.
|
||||
colnr_T ml_get_buf_len(buf_T *buf, linenr_T lnum)
|
||||
{
|
||||
if (*ml_get_buf(buf, lnum) == NUL) {
|
||||
const char *line = ml_get_buf(buf, lnum);
|
||||
|
||||
if (*line == NUL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return buf->b_ml.ml_line_len - 1;
|
||||
assert(buf->b_ml.ml_line_textlen > 0);
|
||||
return buf->b_ml.ml_line_textlen - 1;
|
||||
}
|
||||
|
||||
/// @return codepoint at pos. pos must be either valid or have col set to MAXCOL!
|
||||
@@ -1872,13 +1878,13 @@ int gchar_pos(pos_T *pos)
|
||||
///
|
||||
/// @return a pointer to a line in a specific buffer
|
||||
static char *ml_get_buf_impl(buf_T *buf, linenr_T lnum, bool will_change)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
static int recursive = 0;
|
||||
static char questions[4];
|
||||
|
||||
if (buf->b_ml.ml_mfp == NULL) { // there are no lines
|
||||
buf->b_ml.ml_line_len = 1;
|
||||
buf->b_ml.ml_line_textlen = 1;
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -1893,7 +1899,7 @@ static char *ml_get_buf_impl(buf_T *buf, linenr_T lnum, bool will_change)
|
||||
ml_flush_line(buf, false);
|
||||
errorret:
|
||||
STRCPY(questions, "???");
|
||||
buf->b_ml.ml_line_len = 4;
|
||||
buf->b_ml.ml_line_textlen = 4;
|
||||
buf->b_ml.ml_line_lnum = lnum;
|
||||
return questions;
|
||||
}
|
||||
@@ -1933,7 +1939,7 @@ errorret:
|
||||
unsigned end = idx == 0 ? dp->db_txt_end : (dp->db_index[idx - 1] & DB_INDEX_MASK);
|
||||
|
||||
buf->b_ml.ml_line_ptr = (char *)dp + start;
|
||||
buf->b_ml.ml_line_len = (colnr_T)(end - start);
|
||||
buf->b_ml.ml_line_textlen = (colnr_T)(end - start);
|
||||
buf->b_ml.ml_line_lnum = lnum;
|
||||
buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED);
|
||||
}
|
||||
@@ -1952,7 +1958,7 @@ errorret:
|
||||
if ((buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) == 0) {
|
||||
// make sure the text is in allocated memory
|
||||
buf->b_ml.ml_line_ptr = xmemdup(buf->b_ml.ml_line_ptr,
|
||||
(size_t)buf->b_ml.ml_line_len);
|
||||
(size_t)buf->b_ml.ml_line_textlen);
|
||||
buf->b_ml.ml_flags |= ML_ALLOCATED;
|
||||
if (will_change) {
|
||||
// can't make the change in the data block
|
||||
@@ -2526,7 +2532,6 @@ int ml_replace_buf_len(buf_T *buf, linenr_T lnum, char *line_arg, size_t len_arg
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
char *line = line_arg;
|
||||
colnr_T len = (colnr_T)len_arg;
|
||||
|
||||
if (line == NULL) { // just checking...
|
||||
return FAIL;
|
||||
@@ -2556,7 +2561,7 @@ int ml_replace_buf_len(buf_T *buf, linenr_T lnum, char *line_arg, size_t len_arg
|
||||
}
|
||||
|
||||
buf->b_ml.ml_line_ptr = line;
|
||||
buf->b_ml.ml_line_len = len + 1;
|
||||
buf->b_ml.ml_line_textlen = (colnr_T)len_arg + 1;
|
||||
buf->b_ml.ml_line_lnum = lnum;
|
||||
buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
|
||||
if (noalloc) {
|
||||
@@ -2875,7 +2880,7 @@ static void ml_flush_line(buf_T *buf, bool noalloc)
|
||||
} else { // text of previous line follows
|
||||
old_len = (int)(dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
|
||||
}
|
||||
colnr_T new_len = buf->b_ml.ml_line_len;
|
||||
colnr_T new_len = buf->b_ml.ml_line_textlen;
|
||||
int extra = new_len - old_len; // negative if lines gets smaller
|
||||
|
||||
// if new line fits in data block, replace directly
|
||||
@@ -3833,7 +3838,7 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, int len, int updtype)
|
||||
// First line in empty buffer from ml_flush_line() -- reset
|
||||
buf->b_ml.ml_usedchunks = 1;
|
||||
buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
|
||||
buf->b_ml.ml_chunksize[0].mlcs_totalsize = buf->b_ml.ml_line_len;
|
||||
buf->b_ml.ml_chunksize[0].mlcs_totalsize = buf->b_ml.ml_line_textlen;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ typedef struct {
|
||||
#define ML_ALLOCATED 0x10 // ml_line_ptr is an allocated copy
|
||||
int ml_flags;
|
||||
|
||||
colnr_T ml_line_len; // length of the cached line + NUL
|
||||
// colnr_T ml_line_len;
|
||||
colnr_T ml_line_textlen; // length of the cached line + NUL
|
||||
linenr_T ml_line_lnum; // line number of cached line, 0 if not valid
|
||||
char *ml_line_ptr; // pointer to cached line
|
||||
size_t ml_line_offset; // cached byte offset of ml_line_lnum
|
||||
|
||||
@@ -1053,7 +1053,7 @@ static void pbyte(pos_T lp, int c)
|
||||
{
|
||||
assert(c <= UCHAR_MAX);
|
||||
char *p = ml_get_buf_mut(curbuf, lp.lnum);
|
||||
colnr_T len = curbuf->b_ml.ml_line_len;
|
||||
colnr_T len = curbuf->b_ml.ml_line_textlen;
|
||||
|
||||
// safety check
|
||||
if (lp.col >= len) {
|
||||
|
||||
Reference in New Issue
Block a user