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.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 6b2f26b2d8..5acf4f0c37 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -30,6 +30,10 @@
// changed (lines appended/deleted/changed) or when it is flushed it gets a
// positive number. Use mf_trans_del() to get the new number, before calling
// mf_get().
+//
+// "Mom, can we get ropes?"
+// "We have ropes at home."
+// Ropes at home:
#include <assert.h>
#include <errno.h>
@@ -1174,7 +1178,7 @@ void ml_recover(bool checkext)
} else {
for (idx = 1; idx <= lnum; idx++) {
// Need to copy one line, fetching the other one may flush it.
- p = xstrdup(ml_get(idx));
+ p = xstrnsave(ml_get(idx), (size_t)ml_get_len(idx));
int i = strcmp(p, ml_get(idx + lnum));
xfree(p);
if (i != 0) {
@@ -1192,7 +1196,7 @@ void ml_recover(bool checkext)
ml_delete(curbuf->b_ml.ml_line_count, false);
}
curbuf->b_flags |= BF_RECOVERED;
- check_cursor();
+ check_cursor(curwin);
recoverymode = false;
if (got_int) {
@@ -1834,6 +1838,28 @@ char *ml_get_pos(const pos_T *pos)
return ml_get_buf(curbuf, pos->lnum) + pos->col;
}
+/// @return length (excluding the NUL) of the given line.
+colnr_T ml_get_len(linenr_T lnum)
+{
+ return ml_get_buf_len(curbuf, lnum);
+}
+
+/// @return length (excluding the NUL) of the text after position "pos".
+colnr_T ml_get_pos_len(pos_T *pos)
+{
+ return ml_get_buf_len(curbuf, pos->lnum) - pos->col;
+}
+
+/// @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) {
+ return 0;
+ }
+
+ return buf->b_ml.ml_line_len - 1;
+}
+
/// @return codepoint at pos. pos must be either valid or have col set to MAXCOL!
int gchar_pos(pos_T *pos)
FUNC_ATTR_NONNULL_ARG(1)
@@ -1865,6 +1891,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_lnum = lnum;
return questions;
}
@@ -1873,6 +1900,7 @@ errorret:
}
if (buf->b_ml.ml_mfp == NULL) { // there are no lines
+ buf->b_ml.ml_line_len = 1;
return "";
}
@@ -1903,8 +1931,14 @@ errorret:
DataBlock *dp = hp->bh_data;
- char *ptr = (char *)dp + (dp->db_index[lnum - buf->b_ml.ml_locked_low] & DB_INDEX_MASK);
- buf->b_ml.ml_line_ptr = ptr;
+ int idx = lnum - buf->b_ml.ml_locked_low;
+ unsigned start = (dp->db_index[idx] & DB_INDEX_MASK);
+ // The text ends where the previous line starts. The first line ends
+ // at the end of the block.
+ 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_lnum = lnum;
buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED);
}
@@ -1922,7 +1956,8 @@ errorret:
#ifdef ML_GET_ALLOC_LINES
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 = xstrdup(buf->b_ml.ml_line_ptr);
+ buf->b_ml.ml_line_ptr = xmemdup(buf->b_ml.ml_line_ptr,
+ (size_t)buf->b_ml.ml_line_len);
buf->b_ml.ml_flags |= ML_ALLOCATED;
if (will_change) {
// can't make the change in the data block
@@ -2468,6 +2503,7 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy, bool noallo
}
buf->b_ml.ml_line_ptr = line;
+ buf->b_ml.ml_line_len = (colnr_T)strlen(line) + 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) {
@@ -2765,7 +2801,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 = (colnr_T)strlen(new_line) + 1;
+ colnr_T new_len = buf->b_ml.ml_line_len;
int extra = new_len - old_len; // negative if lines gets smaller
// if new line fits in data block, replace directly
@@ -3456,7 +3492,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
char *const name = xmalloc(name_len);
memcpy(name, sw_msg_1, sw_msg_1_len + 1);
- home_replace(NULL, fname, &name[sw_msg_1_len], fname_len, true);
+ home_replace(NULL, fname, name + sw_msg_1_len, fname_len, true);
xstrlcat(name, sw_msg_2, name_len);
int dialog_result
= do_dialog(VIM_WARNING,
@@ -3734,7 +3770,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 = (int)strlen(buf->b_ml.ml_line_ptr) + 1;
+ buf->b_ml.ml_chunksize[0].mlcs_totalsize = buf->b_ml.ml_line_len;
return;
}
@@ -4050,14 +4086,14 @@ void goto_byte(int cnt)
if (lnum < 1) { // past the end
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
curwin->w_curswant = MAXCOL;
- coladvance(MAXCOL);
+ coladvance(curwin, MAXCOL);
} else {
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = (colnr_T)boff;
curwin->w_cursor.coladd = 0;
curwin->w_set_curswant = true;
}
- check_cursor();
+ check_cursor(curwin);
// Make sure the cursor is on the first byte of a multi-byte char.
mb_adjust_cursor();
@@ -4107,7 +4143,7 @@ int dec(pos_T *lp)
if (lp->col == MAXCOL) {
// past end of line
char *p = ml_get(lp->lnum);
- lp->col = (colnr_T)strlen(p);
+ lp->col = ml_get_len(lp->lnum);
lp->col -= utf_head_off(p, p + lp->col);
return 0;
}
@@ -4123,7 +4159,7 @@ int dec(pos_T *lp)
// there is a prior line
lp->lnum--;
char *p = ml_get(lp->lnum);
- lp->col = (colnr_T)strlen(p);
+ lp->col = ml_get_len(lp->lnum);
lp->col -= utf_head_off(p, p + lp->col);
return 1;
}