# HG changeset patch # User Bram Moolenaar # Date 1546384505 -3600 # Node ID 03a7a9fdb7926536b2cd6e32c9763f3f2b06eca9 # Parent 90d037c7fa06a2c2e6ab2763ff4dff559d800064 patch 8.1.0678: text properties as not adjusted for inserted text commit https://github.com/vim/vim/commit/44746aa1eb506ebe6e8fc71f6e549a0dcb754526 Author: Bram Moolenaar Date: Wed Jan 2 00:02:11 2019 +0100 patch 8.1.0678: text properties as not adjusted for inserted text Problem: Text properties as not adjusted for inserted text. Solution: Adjust text properties when inserting text. diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -2322,7 +2322,7 @@ ins_bytes_len(char_u *p, int len) for (i = 0; i < len; i += n) { if (enc_utf8) - /* avoid reading past p[len] */ + // avoid reading past p[len] n = utfc_ptr2len_len(p + i, len - i); else n = (*mb_ptr2len)(p + i); @@ -2365,12 +2365,12 @@ ins_char(int c) ins_char_bytes(char_u *buf, int charlen) { int c = buf[0]; - int newlen; /* nr of bytes inserted */ - int oldlen; /* nr of bytes deleted (0 when not replacing) */ + int newlen; // nr of bytes inserted + int oldlen; // nr of bytes deleted (0 when not replacing) char_u *p; char_u *newp; char_u *oldp; - int linelen; /* length of old line including NUL */ + int linelen; // length of old line including NUL colnr_T col; linenr_T lnum = curwin->w_cursor.lnum; int i; @@ -2439,8 +2439,7 @@ ins_char_bytes(char_u *buf, int charlen) } curwin->w_p_list = old_list; } - else - if (oldp[col] != NUL) + else if (oldp[col] != NUL) { /* normal replace */ #ifdef FEAT_MBYTE @@ -2494,11 +2493,11 @@ ins_char_bytes(char_u *buf, int charlen) while (i < newlen) p[i++] = ' '; - /* Replace the line in the buffer. */ + // Replace the line in the buffer. ml_replace(lnum, newp, FALSE); - /* mark the buffer as changed and prepare for displaying */ - changed_bytes(lnum, col); + // mark the buffer as changed and prepare for displaying + inserted_bytes(lnum, col, newlen - oldlen); /* * If we're in Insert or Replace mode and 'showmatch' is set, then briefly @@ -2566,7 +2565,7 @@ ins_str(char_u *s) mch_memmove(newp + col, s, (size_t)newlen); mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1)); ml_replace(lnum, newp, FALSE); - changed_bytes(lnum, col); + inserted_bytes(lnum, col, newlen); curwin->w_cursor.col += newlen; } @@ -3016,6 +3015,21 @@ changed_bytes(linenr_T lnum, colnr_T col #endif } +/* + * Like changed_bytes() but also adjust text properties for "added" bytes. + * When "added" is negative text was deleted. + */ + void +inserted_bytes(linenr_T lnum, colnr_T col, int added) +{ + changed_bytes(lnum, col); + +#ifdef FEAT_TEXT_PROP + if (curbuf->b_has_textprop && added != 0) + adjust_prop_columns(lnum, col, added); +#endif +} + static void changedOneline(buf_T *buf, linenr_T lnum) { diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -35,6 +35,7 @@ char_u *skip_to_option_part(char_u *p); void changed(void); void changed_int(void); void changed_bytes(linenr_T lnum, colnr_T col); +void inserted_bytes(linenr_T lnum, colnr_T col, int added); void appended_lines(linenr_T lnum, long count); void appended_lines_mark(linenr_T lnum, long count); void deleted_lines(linenr_T lnum, long count); diff --git a/src/testdir/dumps/Test_textprop_01.dump b/src/testdir/dumps/Test_textprop_01.dump --- a/src/testdir/dumps/Test_textprop_01.dump +++ b/src/testdir/dumps/Test_textprop_01.dump @@ -1,6 +1,6 @@ -| +0#af5f00255#ffffff0@1|1| >O+0#0000000&|n|e| +0&#ffff4012|t|w|o| +0&#ffffff0@63 +| +0#af5f00255#ffffff0@1|1| |O+0#0000000&|n|e| +0&#ffff4012|t|w|o| +0&#ffffff0@63 | +0#af5f00255&@1|2| |N+0#0000000#ffff4012|u|m|b|é|r| |1+0#4040ff13&|2|3| +0#0000000&|ä|n|d| |t|h|œ|n| |4+0#4040ff13&|¾|7|.+0#0000000&| +0&#ffffff0@46 -| +0#af5f00255&@1|3| |T+0#0000000#ffff4012|h|r+0&#ffffff0|e@1| @65 +| +0#af5f00255&@1|3| |-+0#0000000#ffff4012@1|x+0&#ffffff0|a+0#4040ff13&@1|x+0#0000000&|-@1|x+0#4040ff13&|b@1|x+0#0000000&|-@1|x|c+0#4040ff13&@1|x|-+0#0000000&@1|x+0#4040ff13&|d@1>x|-+0#0000000&@1| @44 |~+0#4040ff13&| @73 |~| @73 -| +0#0000000&@56|1|,|1| @10|A|l@1| +| +0#0000000&@56|3|,|2|4| @9|A|l@1| diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -300,17 +300,25 @@ funct Test_textprop_screenshots() return endif call writefile([ - \ "call setline(1, ['One two', 'Numbér 123 änd thœn 4¾7.', 'Three'])", + \ "call setline(1, ['One two', 'Numbér 123 änd thœn 4¾7.', '--aa--bb--cc--dd--'])", \ "hi NumberProp ctermfg=blue", \ "hi LongProp ctermbg=yellow", \ "call prop_type_add('number', {'highlight': 'NumberProp'})", \ "call prop_type_add('long', {'highlight': 'LongProp'})", + \ "call prop_type_add('start', {'highlight': 'NumberProp', 'start_incl': 1})", + \ "call prop_type_add('end', {'highlight': 'NumberProp', 'end_incl': 1})", + \ "call prop_type_add('both', {'highlight': 'NumberProp', 'start_incl': 1, 'end_incl': 1})", \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})", \ "call prop_add(2, 9, {'length': 3, 'type': 'number'})", \ "call prop_add(2, 24, {'length': 4, 'type': 'number'})", + \ "call prop_add(3, 3, {'length': 2, 'type': 'number'})", + \ "call prop_add(3, 7, {'length': 2, 'type': 'start'})", + \ "call prop_add(3, 11, {'length': 2, 'type': 'end'})", + \ "call prop_add(3, 15, {'length': 2, 'type': 'both'})", \ "set number", \ "hi clear SpellBad", \ "set spell", + \ "normal 3G0llix\lllix\lllix\lllix\lllix\lllix\lllix\lllix\", \], 'XtestProp') let buf = RunVimInTerminal('-S XtestProp', {'rows': 6}) call VerifyScreenDump(buf, 'Test_textprop_01', {}) diff --git a/src/textprop.c b/src/textprop.c --- a/src/textprop.c +++ b/src/textprop.c @@ -915,11 +915,47 @@ clear_buf_prop_types(buf_T *buf) /* * Adjust the columns of text properties in line "lnum" after position "col" to * shift by "bytes_added" (can be negative). + * Note that "col" is zero-based, while tp_col is one-based. + * Only for the current buffer. + * Called is expected to check b_has_textprop and "bytes_added" being non-zero. */ void -adjust_prop_columns(linenr_T lnum UNUSED, colnr_T col UNUSED, int bytes_added UNUSED) +adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added) { - // TODO + int proplen; + char_u *props; + textprop_T tmp_prop; + proptype_T *pt; + int dirty = FALSE; + int i; + + proplen = get_text_props(curbuf, lnum, &props, TRUE); + if (proplen == 0) + return; + + for (i = 0; i < proplen; ++i) + { + mch_memmove(&tmp_prop, props + i * sizeof(textprop_T), + sizeof(textprop_T)); + pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type); + + if (tmp_prop.tp_col >= col + (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL) ? 2 : 1)) + { + tmp_prop.tp_col += bytes_added; + dirty = TRUE; + } + else if (tmp_prop.tp_col + tmp_prop.tp_len > col + (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL) ? 0 : 1)) + { + tmp_prop.tp_len += bytes_added; + dirty = TRUE; + } + if (dirty) + { + curbuf->b_ml.ml_flags |= ML_LINE_DIRTY; + mch_memmove(props + i * sizeof(textprop_T), &tmp_prop, + sizeof(textprop_T)); + } + } } #endif // FEAT_TEXT_PROP diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -800,6 +800,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 678, +/**/ 677, /**/ 676,