From 14c7530c4fca786d3594508e28943f10125827c3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar <Bram@vim.org> Date: Sun, 15 Aug 2021 14:28:40 +0200 Subject: [PATCH] patch 8.2.3348: line2byte() returns wrong value after adding textprop Problem: line2byte() returns wrong value after adding textprop. (Yuto Kimura) Solution: Reduce the length by the size of the text property. (closes #8759) --- src/memline.c | 20 +++++++++++++++++--- src/testdir/test_textprop.vim | 10 ++++++++++ src/version.c | 2 ++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/memline.c b/src/memline.c index 75c17d2ed7..40eecea6ce 100644 --- a/src/memline.c +++ b/src/memline.c @@ -3977,6 +3977,9 @@ ml_flush_line(buf_T *buf) */ if ((int)dp->db_free >= extra) { +#ifdef FEAT_BYTEOFF + int old_prop_len = 0; +#endif // if the length changes and there are following lines count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; if (extra != 0 && idx < count - 1) @@ -3995,13 +3998,24 @@ ml_flush_line(buf_T *buf) // adjust free space dp->db_free -= extra; dp->db_txt_start -= extra; +#ifdef FEAT_BYTEOFF + if (buf->b_has_textprop) + old_prop_len = old_len - STRLEN(new_line) - 1; +#endif // copy new line into the data block mch_memmove(old_line - extra, new_line, (size_t)new_len); buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); #ifdef FEAT_BYTEOFF // The else case is already covered by the insert and delete - ml_updatechunk(buf, lnum, (long)extra, ML_CHNK_UPDLINE); + if (buf->b_has_textprop) + { + // Do not count the size of any text properties. + extra += old_prop_len; + extra -= new_len - STRLEN(new_line) - 1; + } + if (extra != 0) + ml_updatechunk(buf, lnum, (long)extra, ML_CHNK_UPDLINE); #endif } else @@ -5595,7 +5609,7 @@ ml_updatechunk( else #endif { - if (idx == 0)// first line in block, text at the end + if (idx == 0) // first line in block, text at the end text_end = dp->db_txt_end; else text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); @@ -5734,7 +5748,7 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp) return 1; // Not a "find offset" and offset 0 _must_ be in line 1 /* * Find the last chunk before the one containing our line. Last chunk is - * special because it will never qualify + * special because it will never qualify. */ curline = 1; curix = size = 0; diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index acdbf48493..847968c075 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -809,8 +809,18 @@ func Test_prop_line2byte() call assert_equal(19, line2byte(3)) call prop_add(1, 1, {'end_col': 3, 'type': 'comment'}) call assert_equal(19, line2byte(3)) + bwipe! + new + call setline(1, range(500)) + call assert_equal(1491, line2byte(401)) + call prop_add(2, 1, {'type': 'comment'}) + call prop_add(222, 1, {'type': 'comment'}) + call assert_equal(1491, line2byte(401)) + call prop_remove({'type': 'comment'}) + call assert_equal(1491, line2byte(401)) bwipe! + call prop_type_delete('comment') endfunc diff --git a/src/version.c b/src/version.c index 34793f11ef..21efafcef4 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 3348, /**/ 3347, /**/ -- GitLab