To: vim_dev@googlegroups.com Subject: Patch 8.2.5014 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.5014 Problem: Byte offsets are wrong when using text properties. Solution: Make sure text properties do not affect the byte counts. (Paul Ollis, closes #10474) Files: src/memline.c, src/textprop.c, src/testdir/test_textprop.vim *** ../vim-8.2.5013/src/memline.c 2022-05-16 10:04:46.674376854 +0100 --- src/memline.c 2022-05-24 21:22:09.836491617 +0100 *************** *** 4004,4009 **** --- 4004,4011 ---- { #if defined(FEAT_BYTEOFF) && defined(FEAT_PROP_POPUP) int old_prop_len = 0; + if (buf->b_has_textprop) + old_prop_len = old_len - (int)STRLEN(old_line) - 1; #endif // if the length changes and there are following lines count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; *************** *** 4023,4032 **** // adjust free space dp->db_free -= extra; dp->db_txt_start -= extra; - #if defined(FEAT_BYTEOFF) && defined(FEAT_PROP_POPUP) - if (buf->b_has_textprop) - old_prop_len = old_len - (int)STRLEN(new_line) - 1; - #endif // copy new line into the data block mch_memmove(old_line - extra, new_line, (size_t)new_len); --- 4025,4030 ---- *** ../vim-8.2.5013/src/textprop.c 2022-05-14 18:10:12.166454734 +0100 --- src/textprop.c 2022-05-24 21:22:09.840491616 +0100 *************** *** 344,349 **** --- 344,353 ---- if (get_bufnr_from_arg(&argvars[0], &buf) == FAIL) return; + // This must be done _before_ we start adding properties because property + // changes trigger buffer (memline) reorganisation, which needs this flag + // to be correctly set. + buf->b_has_textprop = TRUE; // this is never reset FOR_ALL_LIST_ITEMS(argvars[1].vval.v_list, li) { if (li->li_tv.v_type != VAR_LIST || li->li_tv.vval.v_list == NULL) *************** *** 368,374 **** return; } - buf->b_has_textprop = TRUE; // this is never reset redraw_buf_later(buf, VALID); } --- 372,377 ---- *************** *** 441,449 **** if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL) return; prop_add_one(buf, type_name, id, start_lnum, end_lnum, start_col, end_col); - buf->b_has_textprop = TRUE; // this is never reset redraw_buf_later(buf, VALID); } --- 444,456 ---- if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL) return; + // This must be done _before_ we add the property because property changes + // trigger buffer (memline) reorganisation, which needs this flag to be + // correctly set. + buf->b_has_textprop = TRUE; // this is never reset + prop_add_one(buf, type_name, id, start_lnum, end_lnum, start_col, end_col); redraw_buf_later(buf, VALID); } *** ../vim-8.2.5013/src/testdir/test_textprop.vim 2022-05-21 11:20:38.102070988 +0100 --- src/testdir/test_textprop.vim 2022-05-24 21:22:09.836491617 +0100 *************** *** 2094,2097 **** --- 2094,2190 ---- bwipe! endfunc + func Do_test_props_do_not_affect_byte_offsets(ff, increment) + new + let lcount = 410 + + " File format affects byte-offset calculations, so make sure it is known. + exec 'setlocal fileformat=' . a:ff + + " Fill the buffer with varying length lines. We need a suitably large number + " to force Vim code through paths wehere previous error have occurred. This + " is more 'art' than 'science'. + let text = 'a' + call setline(1, text) + let offsets = [1] + for idx in range(lcount) + call add(offsets, offsets[idx] + len(text) + a:increment) + if (idx % 6) == 0 + let text = text . 'a' + endif + call append(line('$'), text) + endfor + + " Set a property that spans a few lines to cause Vim's internal buffer code + " to perform a reasonable amount of rearrangement. + call prop_type_add('one', {'highlight': 'ErrorMsg'}) + call prop_add(1, 1, {'type': 'one', 'end_lnum': 6, 'end_col': 2}) + + for idx in range(lcount) + let boff = line2byte(idx + 1) + call assert_equal(offsets[idx], boff, 'Bad byte offset at line ' . (idx + 1)) + endfor + + call prop_type_delete('one') + bwipe! + endfunc + + func Test_props_do_not_affect_byte_offsets() + call Do_test_props_do_not_affect_byte_offsets('unix', 1) + endfunc + + func Test_props_do_not_affect_byte_offsets_dos() + call Do_test_props_do_not_affect_byte_offsets('dos', 2) + endfunc + + func Test_props_do_not_affect_byte_offsets_editline() + new + let lcount = 410 + + " File format affects byte-offset calculations, so make sure it is known. + setlocal fileformat=unix + + " Fill the buffer with varying length lines. We need a suitably large number + " to force Vim code through paths wehere previous error have occurred. This + " is more 'art' than 'science'. + let text = 'aa' + call setline(1, text) + let offsets = [1] + for idx in range(lcount) + call add(offsets, offsets[idx] + len(text) + 1) + if (idx % 6) == 0 + let text = text . 'a' + endif + call append(line('$'), text) + endfor + + " Set a property that just covers the first line. When this test was + " developed, this did not trigger a byte-offset error. + call prop_type_add('one', {'highlight': 'ErrorMsg'}) + call prop_add(1, 1, {'type': 'one', 'end_lnum': 1, 'end_col': 3}) + + for idx in range(lcount) + let boff = line2byte(idx + 1) + call assert_equal(offsets[idx], boff, + \ 'Confounding bad byte offset at line ' . (idx + 1)) + endfor + + " Insert text in the middle of the first line, keeping the property + " unchanged. + :1 + normal aHello + for idx in range(1, lcount) + let offsets[idx] = offsets[idx] + 5 + endfor + + for idx in range(lcount) + let boff = line2byte(idx + 1) + call assert_equal(offsets[idx], boff, + \ 'Bad byte offset at line ' . (idx + 1)) + endfor + + call prop_type_delete('one') + bwipe! + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.5013/src/version.c 2022-05-24 13:57:50.434117756 +0100 --- src/version.c 2022-05-24 21:24:19.784415036 +0100 *************** *** 736,737 **** --- 736,739 ---- { /* Add new patch number below this line */ + /**/ + 5014, /**/ -- GALAHAD: No. Look, I can tackle this lot single-handed! GIRLS: Yes, yes, let him Tackle us single-handed! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///