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