0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 9.0.0438: cannot put virtual text above a line

Problem:    Cannot put virtual text above a line.
Solution:   Add the "above" value for "text_align".
This commit is contained in:
Bram Moolenaar 2022-09-10 20:00:56 +01:00
parent 55e9366e32
commit 04e0ed1ddf
11 changed files with 198 additions and 103 deletions

View File

@ -153,6 +153,7 @@ prop_add({lnum}, {col}, {props})
the text wraps to the next screen the text wraps to the next screen
line) line)
below in the next screen line below in the next screen line
above just above the line
When omitted "after" is used. Only one When omitted "after" is used. Only one
"right" property can fit in each line, if "right" property can fit in each line, if
there are two ore more these will go in a there are two ore more these will go in a

View File

@ -1069,40 +1069,6 @@ lbr_chartabsize_adv(chartabsize_T *cts)
return retval; return retval;
} }
#if defined(FEAT_PROP_POPUP) || defined(PROTO)
/*
* Return the cell size of virtual text after truncation.
*/
int
textprop_size_after_trunc(
win_T *wp,
int below,
int added,
char_u *text,
int *n_used_ptr)
{
int space = below ? wp->w_width : added;
int len = (int)STRLEN(text);
int strsize = 0;
int n_used;
// if the remaining size is to small wrap
// anyway and use the next line
if (space < PROP_TEXT_MIN_CELLS)
space += wp->w_width;
for (n_used = 0; n_used < len; n_used += (*mb_ptr2len)(text + n_used))
{
int clen = ptr2cells(text + n_used);
if (strsize + clen > space)
break;
strsize += clen;
}
*n_used_ptr = n_used;
return strsize;
}
#endif
/* /*
* Return the screen size of the character indicated by "cts". * Return the screen size of the character indicated by "cts".
* "cts->cts_cur_text_width" is set to the extra size for a text property that * "cts->cts_cur_text_width" is set to the extra size for a text property that
@ -1142,6 +1108,7 @@ win_lbr_chartabsize(
#if defined(FEAT_PROP_POPUP) #if defined(FEAT_PROP_POPUP)
cts->cts_cur_text_width = 0; cts->cts_cur_text_width = 0;
cts->cts_first_char = 0;
#endif #endif
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP) #if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
@ -1194,9 +1161,12 @@ win_lbr_chartabsize(
if (tp->tp_id < 0 if (tp->tp_id < 0
&& ((tp->tp_col - 1 >= col && ((tp->tp_col - 1 >= col
&& tp->tp_col - 1 < col + charlen) && tp->tp_col - 1 < col + charlen)
|| (tp->tp_col == MAXCOL && (s[0] == NUL || s[1] == NUL) || (tp->tp_col == MAXCOL
&& cts->cts_with_trailing)) && ((tp->tp_flags & TP_FLAG_ALIGN_ABOVE)
&& -tp->tp_id - 1 < gap->ga_len) ? col == 0
: (s[0] == NUL || s[1] == NUL)
&& cts->cts_with_trailing)))
&& tp->tp_id - 1 < gap->ga_len)
{ {
char_u *p = ((char_u **)gap->ga_data)[-tp->tp_id - 1]; char_u *p = ((char_u **)gap->ga_data)[-tp->tp_id - 1];
@ -1218,6 +1188,8 @@ win_lbr_chartabsize(
else else
cells = vim_strsize(p); cells = vim_strsize(p);
cts->cts_cur_text_width += cells; cts->cts_cur_text_width += cells;
if (tp->tp_flags & TP_FLAG_ALIGN_ABOVE)
cts->cts_first_char += cells;
cts->cts_start_incl = tp->tp_flags & TP_FLAG_START_INCL; cts->cts_start_incl = tp->tp_flags & TP_FLAG_START_INCL;
size += cells; size += cells;
if (*s == TAB) if (*s == TAB)
@ -1564,6 +1536,11 @@ getvcol(
#endif #endif
break; break;
} }
#ifdef FEAT_PROP_POPUP
if (cursor == &wp->w_virtcol && cts.cts_ptr == cts.cts_line)
// do not count the virtual text above for w_curswant
wp->w_virtcol_first_char = cts.cts_first_char;
#endif
if (posptr != NULL && cts.cts_ptr >= posptr) if (posptr != NULL && cts.cts_ptr >= posptr)
// character at pos->col // character at pos->col

View File

@ -278,6 +278,38 @@ get_sign_display_info(
#endif #endif
#if defined(FEAT_PROP_POPUP) || defined(PROTO) #if defined(FEAT_PROP_POPUP) || defined(PROTO)
/*
* Return the cell size of virtual text after truncation.
*/
static int
textprop_size_after_trunc(
win_T *wp,
int flags, // TP_FLAG_ALIGN_*
int added,
char_u *text,
int *n_used_ptr)
{
int space = (flags & (TP_FLAG_ALIGN_BELOW | TP_FLAG_ALIGN_ABOVE))
? wp->w_width : added;
int len = (int)STRLEN(text);
int strsize = 0;
int n_used;
// if the remaining size is to small wrap anyway and use the next line
if (space < PROP_TEXT_MIN_CELLS)
space += wp->w_width;
for (n_used = 0; n_used < len; n_used += (*mb_ptr2len)(text + n_used))
{
int clen = ptr2cells(text + n_used);
if (strsize + clen > space)
break;
strsize += clen;
}
*n_used_ptr = n_used;
return strsize;
}
/* /*
* Take care of padding, right-align and truncation of virtual text after a * Take care of padding, right-align and truncation of virtual text after a
* line. * line.
@ -297,6 +329,7 @@ text_prop_position(
int *n_attr_skip) // cells to skip attr, NULL if not used int *n_attr_skip) // cells to skip attr, NULL if not used
{ {
int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT); int right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT);
int above = (tp->tp_flags & TP_FLAG_ALIGN_ABOVE);
int below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW); int below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW);
int wrap = (tp->tp_flags & TP_FLAG_WRAP); int wrap = (tp->tp_flags & TP_FLAG_WRAP);
int padding = tp->tp_col == MAXCOL && tp->tp_len > 1 int padding = tp->tp_col == MAXCOL && tp->tp_len > 1
@ -304,36 +337,45 @@ text_prop_position(
int col_with_padding = vcol + (below ? 0 : padding); int col_with_padding = vcol + (below ? 0 : padding);
int col_off = 0; int col_off = 0;
int room = wp->w_width - col_with_padding; int room = wp->w_width - col_with_padding;
int added = room; int before = room; // spaces before the text
int after = 0; // spaces after the text
int n_used = *n_extra; int n_used = *n_extra;
char_u *l = NULL; char_u *l = NULL;
int strsize = vim_strsize(*p_extra); int strsize = vim_strsize(*p_extra);
int cells = wrap ? strsize int cells = wrap ? strsize : textprop_size_after_trunc(wp,
: textprop_size_after_trunc(wp, below, added, *p_extra, &n_used); tp->tp_flags, before, *p_extra, &n_used);
if (wrap || right || below || padding > 0 || n_used < *n_extra) if (wrap || right || above || below || padding > 0 || n_used < *n_extra)
{ {
// Right-align: fill with spaces if (above)
if (right)
added -= cells;
if (added < 0
|| !(right || below)
|| (below
? (col_with_padding == 0 || !wp->w_p_wrap)
: (n_used < *n_extra)))
{ {
if (right && (wrap || room < PROP_TEXT_MIN_CELLS)) before = 0;
after = wp->w_width - cells;
}
else
{
// Right-align: fill with before
if (right)
before -= cells;
if (before < 0
|| !(right || below)
|| (below
? (col_with_padding == 0 || !wp->w_p_wrap)
: (n_used < *n_extra)))
{ {
// right-align on next line instead of wrapping if possible if (right && (wrap || room < PROP_TEXT_MIN_CELLS))
col_off = win_col_off(wp) + win_col_off2(wp); {
added = wp->w_width - col_off - strsize + room; // right-align on next line instead of wrapping if possible
if (added < 0) col_off = win_col_off(wp) + win_col_off2(wp);
added = 0; before = wp->w_width - col_off - strsize + room;
if (before < 0)
before = 0;
else
n_used = *n_extra;
}
else else
n_used = *n_extra; before = 0;
} }
else
added = 0;
} }
// With 'nowrap' add one to show the "extends" character if needed (it // With 'nowrap' add one to show the "extends" character if needed (it
@ -346,15 +388,15 @@ text_prop_position(
// add 1 for NUL, 2 for when '…' is used // add 1 for NUL, 2 for when '…' is used
if (n_attr != NULL) if (n_attr != NULL)
l = alloc(n_used + added + padding + 3); l = alloc(n_used + before + after + padding + 3);
if (n_attr == NULL || l != NULL) if (n_attr == NULL || l != NULL)
{ {
int off = 0; int off = 0;
if (n_attr != NULL) if (n_attr != NULL)
{ {
vim_memset(l, ' ', added); vim_memset(l, ' ', before);
off += added; off += before;
if (padding > 0) if (padding > 0)
{ {
vim_memset(l + off, ' ', padding); vim_memset(l + off, ' ', padding);
@ -365,8 +407,8 @@ text_prop_position(
} }
else else
{ {
off = added + padding + n_used; off = before + after + padding + n_used;
cells += added + padding; cells += before + after + padding;
} }
if (n_attr != NULL) if (n_attr != NULL)
{ {
@ -385,10 +427,16 @@ text_prop_position(
// change last character to '>' // change last character to '>'
*lp = '>'; *lp = '>';
} }
else if (after > 0)
{
vim_memset(l + off, ' ', after);
l[off + after] = NUL;
}
*p_extra = l; *p_extra = l;
*n_extra = n_used + added + padding; *n_extra = n_used + before + after + padding;
*n_attr = mb_charlen(*p_extra); *n_attr = mb_charlen(*p_extra);
*n_attr_skip = added + padding + col_off; *n_attr_skip = before + padding + col_off;
} }
} }
} }
@ -1694,11 +1742,14 @@ win_line(
// text prop can show. // text prop can show.
while (text_prop_next < text_prop_count while (text_prop_next < text_prop_count
&& (text_props[text_prop_next].tp_col == MAXCOL && (text_props[text_prop_next].tp_col == MAXCOL
? (*ptr == NUL ? ((*ptr == NUL
&& (wp->w_p_wrap && (wp->w_p_wrap
|| wlv.row == startrow || wlv.row == startrow
|| (text_props[text_prop_next].tp_flags || (text_props[text_prop_next].tp_flags
& TP_FLAG_ALIGN_BELOW))) & TP_FLAG_ALIGN_BELOW)))
|| (bcol == 0 &&
(text_props[text_prop_next].tp_flags
& TP_FLAG_ALIGN_ABOVE)))
: bcol >= text_props[text_prop_next].tp_col - 1)) : bcol >= text_props[text_prop_next].tp_col - 1))
{ {
if (text_props[text_prop_next].tp_col == MAXCOL if (text_props[text_prop_next].tp_col == MAXCOL
@ -1773,6 +1824,8 @@ win_line(
{ {
int right = (tp->tp_flags int right = (tp->tp_flags
& TP_FLAG_ALIGN_RIGHT); & TP_FLAG_ALIGN_RIGHT);
int above = (tp->tp_flags
& TP_FLAG_ALIGN_ABOVE);
int below = (tp->tp_flags int below = (tp->tp_flags
& TP_FLAG_ALIGN_BELOW); & TP_FLAG_ALIGN_BELOW);
int wrap = (tp->tp_flags & TP_FLAG_WRAP); int wrap = (tp->tp_flags & TP_FLAG_WRAP);
@ -1797,18 +1850,15 @@ win_line(
// don't combine char attr after EOL // don't combine char attr after EOL
text_prop_flags &= ~PT_FLAG_COMBINE; text_prop_flags &= ~PT_FLAG_COMBINE;
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
if (below || right || !wrap) if (above || below || right || !wrap)
{ {
// no 'showbreak' before "below" text property // no 'showbreak' before "below" text property
// or after "right" text property // or after "above" or "right" text property
need_showbreak = FALSE; need_showbreak = FALSE;
dont_use_showbreak = TRUE; dont_use_showbreak = TRUE;
} }
#endif #endif
// Keep in sync with where if ((right || above || below || !wrap || padding > 0)
// textprop_size_after_trunc() is called in
// win_lbr_chartabsize().
if ((right || below || !wrap || padding > 0)
&& wp->w_width > 2) && wp->w_width > 2)
{ {
char_u *prev_p_extra = wlv.p_extra; char_u *prev_p_extra = wlv.p_extra;

View File

@ -85,7 +85,7 @@ getviscol2(colnr_T col, colnr_T coladd UNUSED)
} }
/* /*
* Try to advance the Cursor to the specified screen column. * Try to advance the Cursor to the specified screen column "wantcol".
* If virtual editing: fine tune the cursor position. * If virtual editing: fine tune the cursor position.
* Note that all virtual positions off the end of a line should share * Note that all virtual positions off the end of a line should share
* a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)), * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
@ -94,29 +94,30 @@ getviscol2(colnr_T col, colnr_T coladd UNUSED)
* return OK if desired column is reached, FAIL if not * return OK if desired column is reached, FAIL if not
*/ */
int int
coladvance(colnr_T wcol) coladvance(colnr_T wantcol)
{ {
int rc = getvpos(&curwin->w_cursor, wcol); int rc = getvpos(&curwin->w_cursor, wantcol);
if (wcol == MAXCOL || rc == FAIL) if (wantcol == MAXCOL || rc == FAIL)
curwin->w_valid &= ~VALID_VIRTCOL; curwin->w_valid &= ~VALID_VIRTCOL;
else if (*ml_get_cursor() != TAB) else if (*ml_get_cursor() != TAB)
{ {
// Virtcol is valid when not on a TAB // Virtcol is valid when not on a TAB
curwin->w_valid |= VALID_VIRTCOL; curwin->w_valid |= VALID_VIRTCOL;
curwin->w_virtcol = wcol; curwin->w_virtcol = wantcol;
} }
return rc; return rc;
} }
/* /*
* Return in "pos" the position of the cursor advanced to screen column "wcol". * Return in "pos" the position of the cursor advanced to screen column
* "wantcol".
* return OK if desired column is reached, FAIL if not * return OK if desired column is reached, FAIL if not
*/ */
int int
getvpos(pos_T *pos, colnr_T wcol) getvpos(pos_T *pos, colnr_T wantcol)
{ {
return coladvance2(pos, FALSE, virtual_active(), wcol); return coladvance2(pos, FALSE, virtual_active(), wantcol);
} }
static int static int
@ -156,8 +157,8 @@ coladvance2(
} }
else else
{ {
int width = curwin->w_width - win_col_off(curwin); int width = curwin->w_width - win_col_off(curwin);
chartabsize_T cts; chartabsize_T cts;
if (finetune if (finetune
&& curwin->w_p_wrap && curwin->w_p_wrap
@ -183,6 +184,9 @@ coladvance2(
init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line); init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL) while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL)
{ {
#ifdef FEAT_PROP_POPUP
int at_start = cts.cts_ptr == cts.cts_line;
#endif
// Count a tab for what it's worth (if list mode not on) // Count a tab for what it's worth (if list mode not on)
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
csize = win_lbr_chartabsize(&cts, &head); csize = win_lbr_chartabsize(&cts, &head);
@ -191,6 +195,11 @@ coladvance2(
csize = lbr_chartabsize_adv(&cts); csize = lbr_chartabsize_adv(&cts);
#endif #endif
cts.cts_vcol += csize; cts.cts_vcol += csize;
#ifdef FEAT_PROP_POPUP
if (at_start)
// do not count the columns for virtual text above
cts.cts_vcol -= cts.cts_first_char;
#endif
} }
col = cts.cts_vcol; col = cts.cts_vcol;
idx = (int)(cts.cts_ptr - line); idx = (int)(cts.cts_ptr - line);
@ -2400,7 +2409,7 @@ update_mouseshape(int shape_idx)
/* /*
* Change directory to "new_dir". Search 'cdpath' for relative directory * Change directory to "new_dir". Search 'cdpath' for relative directory
* names, otherwise just mch_chdir(). * names.
*/ */
int int
vim_chdir(char_u *new_dir) vim_chdir(char_u *new_dir)

View File

@ -476,7 +476,11 @@ update_curswant(void)
if (curwin->w_set_curswant) if (curwin->w_set_curswant)
{ {
validate_virtcol(); validate_virtcol();
curwin->w_curswant = curwin->w_virtcol; curwin->w_curswant = curwin->w_virtcol
#ifdef FEAT_PROP_POPUP
- curwin->w_virtcol_first_char
#endif
;
curwin->w_set_curswant = FALSE; curwin->w_set_curswant = FALSE;
} }
} }
@ -835,6 +839,9 @@ validate_virtcol_win(win_T *wp)
check_cursor_moved(wp); check_cursor_moved(wp);
if (!(wp->w_valid & VALID_VIRTCOL)) if (!(wp->w_valid & VALID_VIRTCOL))
{ {
#ifdef FEAT_PROP_POPUP
wp->w_virtcol_first_char = 0;
#endif
getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL); getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
#ifdef FEAT_SYN_HL #ifdef FEAT_SYN_HL
redraw_for_cursorcolumn(wp); redraw_for_cursorcolumn(wp);
@ -982,6 +989,11 @@ curs_columns(
if (!(curwin->w_valid & VALID_CROW)) if (!(curwin->w_valid & VALID_CROW))
curs_rows(curwin); curs_rows(curwin);
#ifdef FEAT_PROP_POPUP
// will be set by getvvcol() but not reset
curwin->w_virtcol_first_char = 0;
#endif
/* /*
* Compute the number of virtual columns. * Compute the number of virtual columns.
*/ */

View File

@ -34,7 +34,6 @@ void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T
void clear_chartabsize_arg(chartabsize_T *cts); void clear_chartabsize_arg(chartabsize_T *cts);
int lbr_chartabsize(chartabsize_T *cts); int lbr_chartabsize(chartabsize_T *cts);
int lbr_chartabsize_adv(chartabsize_T *cts); int lbr_chartabsize_adv(chartabsize_T *cts);
int textprop_size_after_trunc(win_T *wp, int below, int added, char_u *text, int *n_used_ptr);
int win_lbr_chartabsize(chartabsize_T *cts, int *headp); int win_lbr_chartabsize(chartabsize_T *cts, int *headp);
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end); void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
colnr_T getvcol_nolist(pos_T *posp); colnr_T getvcol_nolist(pos_T *posp);

View File

@ -813,12 +813,13 @@ typedef struct textprop_S
#define TP_FLAG_CONT_PREV 0x2 // property was continued from prev line #define TP_FLAG_CONT_PREV 0x2 // property was continued from prev line
// without these text is placed after the end of the line // without these text is placed after the end of the line
#define TP_FLAG_ALIGN_RIGHT 0x10 // virtual text is right-aligned #define TP_FLAG_ALIGN_RIGHT 0x010 // virtual text is right-aligned
#define TP_FLAG_ALIGN_BELOW 0x20 // virtual text on next screen line #define TP_FLAG_ALIGN_ABOVE 0x020 // virtual text above the line
#define TP_FLAG_ALIGN_BELOW 0x040 // virtual text on next screen line
#define TP_FLAG_WRAP 0x40 // virtual text wraps - when missing #define TP_FLAG_WRAP 0x080 // virtual text wraps - when missing
// text is truncated // text is truncated
#define TP_FLAG_START_INCL 0x80 // "start_incl" copied from proptype #define TP_FLAG_START_INCL 0x100 // "start_incl" copied from proptype
#define PROP_TEXT_MIN_CELLS 4 // minimun number of cells to use for #define PROP_TEXT_MIN_CELLS 4 // minimun number of cells to use for
// the text, even when truncating // the text, even when truncating
@ -3678,6 +3679,11 @@ struct window_S
// more than one screen line or when // more than one screen line or when
// w_leftcol is non-zero // w_leftcol is non-zero
#ifdef FEAT_PROP_POPUP
colnr_T w_virtcol_first_char; // offset for w_virtcol when there are
// virtual text properties above the
// line
#endif
/* /*
* w_wrow and w_wcol specify the cursor position in the window. * w_wrow and w_wcol specify the cursor position in the window.
* This is related to positions in the window, not in the display or * This is related to positions in the window, not in the display or
@ -4607,6 +4613,7 @@ typedef struct {
textprop_T *cts_text_props; // text props (allocated) textprop_T *cts_text_props; // text props (allocated)
char cts_has_prop_with_text; // TRUE if if a property inserts text char cts_has_prop_with_text; // TRUE if if a property inserts text
int cts_cur_text_width; // width of current inserted text int cts_cur_text_width; // width of current inserted text
int cts_first_char; // width text props above the line
int cts_with_trailing; // include size of trailing props with int cts_with_trailing; // include size of trailing props with
// last character // last character
int cts_start_incl; // prop has true "start_incl" arg int cts_start_incl; // prop has true "start_incl" arg

View File

@ -0,0 +1,9 @@
|f+0&#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| @42
|s+0&#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| @41
|o+0&#ffffff0|n|e| |t|w|o| @52
|t|h|r>e@1| |f|o|u|r| @49
|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| @46
|f+0&#ffffff0|i|v|e| |s|i|x| @51
|~+0#4040ff13&| @58
|~| @58
| +0#0000000&@41|2|,|4| @10|A|l@1|

View File

@ -2848,6 +2848,26 @@ func Test_props_with_text_below_nowrap()
call delete('XscriptPropsBelowNowrap') call delete('XscriptPropsBelowNowrap')
endfunc endfunc
func Test_props_with_text_above()
CheckRunVimInTerminal
let lines =<< trim END
call setline(1, ['one two', 'three four', 'five six'])
call prop_type_add('above1', #{highlight: 'Search'})
call prop_type_add('above2', #{highlight: 'DiffChange'})
call prop_add(1, 0, #{type: 'above1', text: 'first thing above', text_align: 'above'})
call prop_add(1, 0, #{type: 'above2', text: 'second thing above', text_align: 'above'})
call prop_add(3, 0, #{type: 'above1', text: 'another thing', text_align: 'above'})
normal gglllj
END
call writefile(lines, 'XscriptPropsWithTextAbove', 'D')
let buf = RunVimInTerminal('-S XscriptPropsWithTextAbove', #{rows: 9, cols: 60})
call VerifyScreenDump(buf, 'Test_prop_with_text_above_1', {})
call StopVimInTerminal(buf)
endfunc
func Test_props_with_text_override() func Test_props_with_text_override()
CheckRunVimInTerminal CheckRunVimInTerminal

View File

@ -497,6 +497,8 @@ prop_add_common(
} }
if (STRCMP(p, "right") == 0) if (STRCMP(p, "right") == 0)
flags |= TP_FLAG_ALIGN_RIGHT; flags |= TP_FLAG_ALIGN_RIGHT;
else if (STRCMP(p, "above") == 0)
flags |= TP_FLAG_ALIGN_ABOVE;
else if (STRCMP(p, "below") == 0) else if (STRCMP(p, "below") == 0)
flags |= TP_FLAG_ALIGN_BELOW; flags |= TP_FLAG_ALIGN_BELOW;
else if (STRCMP(p, "after") != 0) else if (STRCMP(p, "after") != 0)
@ -673,6 +675,21 @@ count_props(linenr_T lnum, int only_starting, int last_line)
static textprop_T *text_prop_compare_props; static textprop_T *text_prop_compare_props;
static buf_T *text_prop_compare_buf; static buf_T *text_prop_compare_buf;
/* Score for sorting on position of the text property: 0: above,
* 1: after (default), 2: right, 3: below (comes last)
*/
static int
text_prop_order(int flags)
{
if (flags & TP_FLAG_ALIGN_ABOVE)
return 0;
if (flags & TP_FLAG_ALIGN_RIGHT)
return 2;
if (flags & TP_FLAG_ALIGN_BELOW)
return 3;
return 1;
}
/* /*
* Function passed to qsort() to sort text properties. * Function passed to qsort() to sort text properties.
* Return 1 if "s1" has priority over "s2", -1 if the other way around, zero if * Return 1 if "s1" has priority over "s2", -1 if the other way around, zero if
@ -694,21 +711,13 @@ text_prop_compare(const void *s1, const void *s2)
col2 = tp2->tp_col; col2 = tp2->tp_col;
if (col1 == MAXCOL && col2 == MAXCOL) if (col1 == MAXCOL && col2 == MAXCOL)
{ {
int flags1 = 0; int order1 = text_prop_order(tp1->tp_flags);
int flags2 = 0; int order2 = text_prop_order(tp2->tp_flags);
// both props add text are after the line, order on 0: after (default), // both props add text before or after the line, sort on order where it
// 1: right, 2: below (comes last) // is added
if (tp1->tp_flags & TP_FLAG_ALIGN_RIGHT) if (order1 != order2)
flags1 = 1; return order1 < order2 ? 1 : -1;
if (tp1->tp_flags & TP_FLAG_ALIGN_BELOW)
flags1 = 2;
if (tp2->tp_flags & TP_FLAG_ALIGN_RIGHT)
flags2 = 1;
if (tp2->tp_flags & TP_FLAG_ALIGN_BELOW)
flags2 = 2;
if (flags1 != flags2)
return flags1 < flags2 ? 1 : -1;
} }
// property that inserts text has priority over one that doesn't // property that inserts text has priority over one that doesn't

View File

@ -703,6 +703,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
438,
/**/ /**/
437, 437,
/**/ /**/