diff src/drawline.c @ 31938:96d6d31dd66b v9.0.1301

patch 9.0.1301: virtual text below empty line not displayed Commit: https://github.com/vim/vim/commit/9d9a20ee8799bafe9caac616fef11b7a26db6a8d Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 11 13:49:01 2023 +0000 patch 9.0.1301: virtual text below empty line not displayed Problem: Virtual text below empty line not displayed. Solution: Adjust flags and computations. (closes https://github.com/vim/vim/issues/11959)
author Bram Moolenaar <Bram@vim.org>
date Sat, 11 Feb 2023 15:00:04 +0100
parents 7d0025a2940a
children 87ed5e064db2
line wrap: on
line diff
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -1085,6 +1085,7 @@ win_line(
     int		save_did_emsg;
 #endif
 #ifdef FEAT_PROP_POPUP
+    int		did_line = FALSE;	// set to TRUE when line text done
     int		text_prop_count;
     int		text_prop_next = 0;	// next text property to use
     textprop_T	*text_props = NULL;
@@ -1914,17 +1915,20 @@ win_line(
 		// Check if any active property ends.
 		for (pi = 0; pi < text_props_active; ++pi)
 		{
-		    int tpi = text_prop_idxs[pi];
-
-		    if (text_props[tpi].tp_col != MAXCOL
-			    && bcol >= text_props[tpi].tp_col - 1
-						      + text_props[tpi].tp_len)
+		    int		tpi = text_prop_idxs[pi];
+		    textprop_T  *tp = &text_props[tpi];
+
+		    // An inline property ends when after the start column plus
+		    // length. An "above" property ends when used and n_extra
+		    // is zero.
+		    if ((tp->tp_col != MAXCOL
+				       && bcol >= tp->tp_col - 1 + tp->tp_len))
 		    {
 			if (pi + 1 < text_props_active)
 			    mch_memmove(text_prop_idxs + pi,
 					text_prop_idxs + pi + 1,
 					sizeof(int)
-					 * (text_props_active - (pi + 1)));
+					     * (text_props_active - (pi + 1)));
 			--text_props_active;
 			--pi;
 # ifdef FEAT_LINEBREAK
@@ -1940,6 +1944,9 @@ win_line(
 		    // not on the next char yet, don't start another prop
 		    --bcol;
 # endif
+		int display_text_first = FALSE;
+		int active_before = text_props_active;
+
 		// Add any text property that starts in this column.
 		// With 'nowrap' and not in the first screen line only "below"
 		// text prop can show.
@@ -1950,16 +1957,24 @@ win_line(
 				      || wlv.row == startrow
 				      || (text_props[text_prop_next].tp_flags
 						       & TP_FLAG_ALIGN_BELOW)))
-			       || (bcol == 0 &&
-				      (text_props[text_prop_next].tp_flags
+			       || (bcol == 0
+					&& (text_props[text_prop_next].tp_flags
 						       & TP_FLAG_ALIGN_ABOVE)))
 			      : bcol >= text_props[text_prop_next].tp_col - 1))
 		{
 		    if (text_props[text_prop_next].tp_col == MAXCOL
-			     && *ptr == NUL && wp->w_p_list && lcs_eol_one > 0)
+			     && *ptr == NUL
+			     && ((wp->w_p_list && lcs_eol_one > 0)
+				 || (ptr == line
+					&& !did_line
+					&& (text_props[text_prop_next].tp_flags
+						       & TP_FLAG_ALIGN_BELOW))))
 		    {
-			// first display the '$' after the line
+			// first display the '$' after the line or display an
+			// empty line
 			text_prop_follows = TRUE;
+			if (text_props_active == active_before)
+			    display_text_first = TRUE;
 			break;
 		    }
 		    if (text_props[text_prop_next].tp_col == MAXCOL
@@ -1978,16 +1993,18 @@ win_line(
 		    text_prop_id = 0;
 		    reset_extra_attr = FALSE;
 		}
-		if (text_props_active > 0 && wlv.n_extra == 0)
+		if (text_props_active > 0 && wlv.n_extra == 0
+							&& !display_text_first)
 		{
 		    int used_tpi = -1;
 		    int used_attr = 0;
 		    int other_tpi = -1;
 
+		    text_prop_above = FALSE;
+		    text_prop_follows = FALSE;
+
 		    // Sort the properties on priority and/or starting last.
 		    // Then combine the attributes, highest priority last.
-		    text_prop_above = FALSE;
-		    text_prop_follows = FALSE;
 		    sort_text_props(wp->w_buffer, text_props,
 					    text_prop_idxs, text_props_active);
 
@@ -2159,8 +2176,8 @@ win_line(
 			// must wrap anyway.
 			text_prop_above = above;
 			text_prop_follows |= other_tpi != -1
-			    && (wp->w_p_wrap
-				   || (text_props[other_tpi].tp_flags
+					&& (wp->w_p_wrap
+					     || (text_props[other_tpi].tp_flags
 			       & (TP_FLAG_ALIGN_BELOW | TP_FLAG_ALIGN_RIGHT)));
 
 			if (bail_out)
@@ -2495,6 +2512,12 @@ win_line(
 #ifdef FEAT_LINEBREAK
 	    c0 = *ptr;
 #endif
+#ifdef FEAT_PROP_POPUP
+	    if (c == NUL)
+		// text is finished, may display a "below" virtual text
+		did_line = TRUE;
+#endif
+
 	    if (has_mbyte)
 	    {
 		mb_c = c;
@@ -3576,20 +3599,31 @@ win_line(
 	// At end of the text line.
 	if (c == NUL)
 	{
-	    draw_screen_line(wp, &wlv);
-
-	    // Update w_cline_height and w_cline_folded if the cursor line was
-	    // updated (saves a call to plines() later).
-	    if (wp == curwin && lnum == curwin->w_cursor.lnum)
+#ifdef FEAT_PROP_POPUP
+	    if (text_prop_follows)
+	    {
+		// Put the pointer back to the NUL.
+		--ptr;
+		c = ' ';
+	    }
+	    else
+#endif
 	    {
-		curwin->w_cline_row = startrow;
-		curwin->w_cline_height = wlv.row - startrow;
+		draw_screen_line(wp, &wlv);
+
+		// Update w_cline_height and w_cline_folded if the cursor line
+		// was updated (saves a call to plines() later).
+		if (wp == curwin && lnum == curwin->w_cursor.lnum)
+		{
+		    curwin->w_cline_row = startrow;
+		    curwin->w_cline_height = wlv.row - startrow;
 #ifdef FEAT_FOLDING
-		curwin->w_cline_folded = FALSE;
+		    curwin->w_cline_folded = FALSE;
 #endif
-		curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
+		    curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
+		}
+		break;
 	    }
-	    break;
 	}
 
 	// Show "extends" character from 'listchars' if beyond the line end and