# HG changeset patch # User Bram Moolenaar # Date 1546261206 -3600 # Node ID c4d62945d96fe87beb398b3b9c4ca8f7f2a53b28 # Parent cecacba2a0d8687d5e107209fb98b1670005b935 patch 8.1.0665: text property display wrong when 'spell' is set commit https://github.com/vim/vim/commit/c6d86dccc4edff8627e309fb23dc8f810ef36b28 Author: Bram Moolenaar Date: Mon Dec 31 13:57:36 2018 +0100 patch 8.1.0665: text property display wrong when 'spell' is set Problem: Text property display wrong when 'spell' is set. (Dominique Pelle) Solution: Remove unnecessary assignment to char_attr. Combine attributes if needed. Add a screenshot test. diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -3051,6 +3051,38 @@ fill_foldcolumn( } #endif /* FEAT_FOLDING */ +#ifdef FEAT_TEXT_PROP +static textprop_T *current_text_props = NULL; +static buf_T *current_buf = NULL; + + static int +#ifdef __BORLANDC__ +_RTLENTRYF +#endif +text_prop_compare(const void *s1, const void *s2) +{ + int idx1, idx2; + proptype_T *pt1, *pt2; + colnr_T col1, col2; + + idx1 = *(int *)s1; + idx2 = *(int *)s2; + pt1 = text_prop_type_by_id(current_buf, current_text_props[idx1].tp_type); + pt2 = text_prop_type_by_id(current_buf, current_text_props[idx2].tp_type); + if (pt1 == pt2) + return 0; + if (pt1 == NULL) + return -1; + if (pt2 == NULL) + return 1; + if (pt1->pt_priority != pt2->pt_priority) + return pt1->pt_priority > pt2->pt_priority ? 1 : -1; + col1 = current_text_props[idx1].tp_col; + col2 = current_text_props[idx2].tp_col; + return col1 == col2 ? 0 : col1 > col2 ? 1 : -1; +} +#endif + /* * Display line "lnum" of window 'wp' on the screen. * Start at row "startrow", stop when "endrow" is reached. @@ -4322,34 +4354,32 @@ win_line( && vcol >= text_props[text_prop_next].tp_col - 1) text_prop_idxs[text_props_active++] = text_prop_next++; - text_prop_type = NULL; + text_prop_attr = 0; if (text_props_active > 0) { - int max_priority = INT_MIN; - int max_col = 0; - - // Get the property type with the highest priority - // and/or starting last. + // Sort the properties on priority and/or starting last. + // Then combine the attributes, highest priority last. + current_text_props = text_props; + current_buf = wp->w_buffer; + qsort((void *)text_prop_idxs, (size_t)text_props_active, + sizeof(int), text_prop_compare); + for (pi = 0; pi < text_props_active; ++pi) { - int tpi = text_prop_idxs[pi]; - proptype_T *pt; - - pt = text_prop_type_by_id( - curwin->w_buffer, text_props[tpi].tp_type); - if (pt != NULL - && (pt->pt_priority > max_priority - || (pt->pt_priority == max_priority - && text_props[tpi].tp_col >= max_col))) + int tpi = text_prop_idxs[pi]; + proptype_T *pt = text_prop_type_by_id(wp->w_buffer, text_props[tpi].tp_type); + + if (pt != NULL) { + int pt_attr = syn_id2attr(pt->pt_hl_id); + text_prop_type = pt; - max_priority = pt->pt_priority; - max_col = text_props[tpi].tp_col; + if (text_prop_attr == 0) + text_prop_attr = pt_attr; + else + text_prop_attr = hl_combine_attr(text_prop_attr, pt_attr); } } - if (text_prop_type != NULL) - text_prop_attr = - syn_id2attr(text_prop_type->pt_hl_id); } } #endif @@ -4775,10 +4805,6 @@ win_line( if (has_spell && v >= word_end && v > cur_checked_col) { spell_attr = 0; -# ifdef FEAT_SYN_HL - if (!attr_pri) - char_attr = syntax_attr; -# endif if (c != 0 && ( # ifdef FEAT_SYN_HL !has_syntax || diff --git a/src/testdir/dumps/Test_textprop_01.dump b/src/testdir/dumps/Test_textprop_01.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_textprop_01.dump @@ -0,0 +1,20 @@ +| +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|e|r| |1+0#4040ff13#ffffff0|2|3| +0#0000000#ffff4012|a|n|d| |t|h|e|n| |4+0#4040ff13#ffffff0|5|6|7|.+0#0000000#ffff4012| +0&#ffffff0@45 +| +0#af5f00255&@1|3| |T+0#0000000#ffff4012|h|r|e+0&#ffffff0@1| @65 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|1|,|1| @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 @@ -5,6 +5,8 @@ if !has('textprop') finish endif +source screendump.vim + func Test_proptype_global() call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) let proptypes = prop_type_list() @@ -283,5 +285,27 @@ func Test_prop_byteoff() call prop_type_delete('comment') endfunc +" screenshot test with textprop highlighting +funct Test_textprop_screenshots() + if !CanRunVimInTerminal() + return + endif + call writefile([ + \ "call setline(1, ['One two', 'Number 123 and then 4567.', 'Three'])", + \ "hi NumberProp ctermfg=blue", + \ "hi LongProp ctermbg=yellow", + \ "call prop_type_add('number', {'highlight': 'NumberProp'})", + \ "call prop_type_add('long', {'highlight': 'LongProp'})", + \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})", + \ "call prop_add(2, 8, {'length': 3, 'type': 'number'})", + \ "call prop_add(2, 21, {'length': 4, 'type': 'number'})", + \ "set number", + \ "set spell", + \], 'XtestProp') + let buf = RunVimInTerminal('-S XtestProp', {}) + call VerifyScreenDump(buf, 'Test_textprop_01', {}) -" TODO: screenshot test with highlighting + " clean up + call StopVimInTerminal(buf) + call delete('Xtest_folds_with_rnu') +endfunc 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 */ /**/ + 665, +/**/ 664, /**/ 663,