# HG changeset patch # User Bram Moolenaar # Date 1659802503 -7200 # Node ID dd96f3d8ed85913b8759c46fda3e89b52c741fe7 # Parent e64d1aee6bfe7baca72770882caaad65a965deef patch 9.0.0154: text properties wrong after splitting a line Commit: https://github.com/vim/vim/commit/7d0f7e9524975ebcc3c7d98b5507de1b7df74370 Author: Bram Moolenaar Date: Sat Aug 6 17:10:57 2022 +0100 patch 9.0.0154: text properties wrong after splitting a line Problem: Text properties wrong after splitting a line. Solution: Check for text properties after the line. (closes https://github.com/vim/vim/issues/10857) diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -1944,7 +1944,7 @@ skip_comment( } /* - * Join 'count' lines (minimal 2) at cursor position. + * Join 'count' lines (minimal 2) at the cursor position. * When "save_undo" is TRUE save lines for undo first. * Set "use_formatoptions" to FALSE when e.g. processing backspace and comment * leaders should not be removed. diff --git a/src/testdir/dumps/Test_prop_with_text_after_join_split_1.dump b/src/testdir/dumps/Test_prop_with_text_after_join_split_1.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_with_text_after_join_split_1.dump @@ -0,0 +1,8 @@ +|1+0&#ffffff0@1| @57 +>2@1| @57 +| +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | +0#0000000#ffffff0@43 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_after_join_split_2.dump b/src/testdir/dumps/Test_prop_with_text_after_join_split_2.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_with_text_after_join_split_2.dump @@ -0,0 +1,8 @@ +|1+0&#ffffff0@1> |2@1| @54 +| +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | +0#0000000#ffffff0@43 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|1|,|3| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_after_join_split_3.dump b/src/testdir/dumps/Test_prop_with_text_after_join_split_3.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_with_text_after_join_split_3.dump @@ -0,0 +1,8 @@ +|1+0&#ffffff0@1> |2@1| +0&#ffff4012|a|f|t|e|r| |t|h|e| |t|e|x|t| | +0&#ffffff0@27| +0&#ffff4012|r|i|g|h|t| |h|e|r|e +| +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | +0#0000000#ffffff0@43 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +|:+0#0000000&|c|a|l@1| |A|d@1|M|o|r|e|(|)| @26|1|,|3| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_after_join_split_4.dump b/src/testdir/dumps/Test_prop_with_text_after_join_split_4.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_with_text_after_join_split_4.dump @@ -0,0 +1,8 @@ +|1+0&#ffffff0@1| @57 +>2@1| +0&#ffff4012|a|f|t|e|r| |t|h|e| |t|e|x|t| | +0&#ffffff0@30| +0&#ffff4012|r|i|g|h|t| |h|e|r|e +| +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | +0#0000000#ffffff0@43 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_after_join_split_5.dump b/src/testdir/dumps/Test_prop_with_text_after_join_split_5.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_prop_with_text_after_join_split_5.dump @@ -0,0 +1,8 @@ +|1+0&#ffffff0@1> |2@1| +0&#ffff4012|a|f|t|e|r| |t|h|e| |t|e|x|t| | +0&#ffffff0@27| +0&#ffff4012|r|i|g|h|t| |h|e|r|e +| +0#ffffff16#e000002|B|e|l|o|w| |t|h|e| |l|i|n|e| | +0#0000000#ffffff0@43 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|~| @58 +|~| @58 +| +0#0000000&@41|1|,|3| @10|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 @@ -2450,6 +2450,41 @@ func Test_props_with_text_after_nowrap() call delete('XscriptPropsAfterNowrap') endfunc +func Test_props_with_text_after_split_join() + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, ['1122']) + call prop_type_add('belowprop', #{highlight: 'ErrorMsg'}) + call prop_add(1, 0, #{type: 'belowprop', text: ' Below the line ', text_align: 'below'}) + exe "normal f2i\\" + + func AddMore() + call prop_type_add('another', #{highlight: 'Search'}) + call prop_add(1, 0, #{type: 'another', text: ' after the text ', text_align: 'after'}) + call prop_add(1, 0, #{type: 'another', text: ' right here', text_align: 'right'}) + endfunc + END + call writefile(lines, 'XscriptPropsAfterSplitJoin') + let buf = RunVimInTerminal('-S XscriptPropsAfterSplitJoin', #{rows: 8, cols: 60}) + call VerifyScreenDump(buf, 'Test_prop_with_text_after_join_split_1', {}) + + call term_sendkeys(buf, "ggJ") + call VerifyScreenDump(buf, 'Test_prop_with_text_after_join_split_2', {}) + + call term_sendkeys(buf, ":call AddMore()\") + call VerifyScreenDump(buf, 'Test_prop_with_text_after_join_split_3', {}) + + call term_sendkeys(buf, "ggf s\\") + call VerifyScreenDump(buf, 'Test_prop_with_text_after_join_split_4', {}) + + call term_sendkeys(buf, "ggJ") + call VerifyScreenDump(buf, 'Test_prop_with_text_after_join_split_5', {}) + + call StopVimInTerminal(buf) + call delete('XscriptPropsAfterSplitJoin') +endfunc + func Test_removed_prop_with_text_cleans_up_array() new call setline(1, 'some text here') diff --git a/src/textprop.c b/src/textprop.c --- a/src/textprop.c +++ b/src/textprop.c @@ -621,6 +621,8 @@ prop_count_below(buf_T *buf, linenr_T ln * Return the number of text properties on line "lnum" in the current buffer. * When "only_starting" is true only text properties starting in this line will * be considered. + * When "last_line" is FALSE then text properties after the line are not + * counted. */ int count_props(linenr_T lnum, int only_starting, int last_line) @@ -634,7 +636,7 @@ count_props(linenr_T lnum, int only_star for (i = 0; i < proplen; ++i) { mch_memmove(&prop, props + i * sizeof(prop), sizeof(prop)); - // A prop is droppend when in the first line and it continues from the + // A prop is dropped when in the first line and it continues from the // previous line, or when not in the last line and it is virtual text // after the line. if ((only_starting && (prop.tp_flags & TP_FLAG_CONT_PREV)) @@ -706,7 +708,7 @@ set_text_props(linenr_T lnum, char_u *pr } /* - * Add "text_props" with "text_prop_count" text propertis to line "lnum". + * Add "text_props" with "text_prop_count" text properties to line "lnum". */ void add_text_props(linenr_T lnum, textprop_T *text_props, int text_prop_count) @@ -2031,8 +2033,9 @@ adjust_props_for_split( pt = text_prop_type_by_id(curbuf, prop.tp_type); start_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL)); end_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL)); - cont_prev = prop.tp_col + !start_incl <= kept; - cont_next = skipped <= prop.tp_col + prop.tp_len - !end_incl; + cont_prev = prop.tp_col != MAXCOL && prop.tp_col + !start_incl <= kept; + cont_next = prop.tp_col != MAXCOL + && skipped <= prop.tp_col + prop.tp_len - !end_incl; if (cont_prev && ga_grow(&prevprop, 1) == OK) { @@ -2048,17 +2051,22 @@ adjust_props_for_split( // Only add the property to the next line if the length is bigger than // zero. - if (cont_next && ga_grow(&nextprop, 1) == OK) + if ((cont_next || prop.tp_col == MAXCOL) + && ga_grow(&nextprop, 1) == OK) { textprop_T *p = ((textprop_T *)nextprop.ga_data) + nextprop.ga_len; + *p = prop; ++nextprop.ga_len; - if (p->tp_col > skipped) - p->tp_col -= skipped - 1; - else + if (p->tp_col != MAXCOL) { - p->tp_len -= skipped - p->tp_col; - p->tp_col = 1; + if (p->tp_col > skipped) + p->tp_col -= skipped - 1; + else + { + p->tp_len -= skipped - p->tp_col; + p->tp_col = 1; + } } if (cont_prev) p->tp_flags |= TP_FLAG_CONT_PREV; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -736,6 +736,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 154, +/**/ 153, /**/ 152,