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".
diff --git a/src/drawline.c b/src/drawline.c
index 6c298b6..56d42e2 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -279,6 +279,38 @@
 
 #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
  * line.
  * if "n_attr" is not NULL then "n_extra" and "p_extra" are adjusted for any
@@ -297,6 +329,7 @@
 	int	    *n_attr_skip)   // cells to skip attr, NULL if not used
 {
     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	    wrap = (tp->tp_flags & TP_FLAG_WRAP);
     int	    padding = tp->tp_col == MAXCOL && tp->tp_len > 1
@@ -304,36 +337,45 @@
     int	    col_with_padding = vcol + (below ? 0 : padding);
     int	    col_off = 0;
     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;
     char_u  *l = NULL;
     int	    strsize = vim_strsize(*p_extra);
-    int	    cells = wrap ? strsize
-	      : textprop_size_after_trunc(wp, below, added, *p_extra, &n_used);
+    int	    cells = wrap ? strsize : textprop_size_after_trunc(wp,
+				      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 (right)
-	    added -= cells;
-	if (added < 0
-		|| !(right || below)
-		|| (below
-		    ? (col_with_padding == 0 || !wp->w_p_wrap)
-		    : (n_used < *n_extra)))
+	if (above)
 	{
-	    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
-		col_off = win_col_off(wp) + win_col_off2(wp);
-		added = wp->w_width - col_off - strsize + room;
-		if (added < 0)
-		    added = 0;
+		if (right && (wrap || room < PROP_TEXT_MIN_CELLS))
+		{
+		    // right-align on next line instead of wrapping if possible
+		    col_off = win_col_off(wp) + win_col_off2(wp);
+		    before = wp->w_width - col_off - strsize + room;
+		    if (before < 0)
+			before = 0;
+		    else
+			n_used = *n_extra;
+		}
 		else
-		    n_used = *n_extra;
+		    before = 0;
 	    }
-	    else
-		added = 0;
 	}
 
 	// With 'nowrap' add one to show the "extends" character if needed (it
@@ -346,15 +388,15 @@
 
 	// add 1 for NUL, 2 for when '…' is used
 	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)
 	{
 	    int off = 0;
 
 	    if (n_attr != NULL)
 	    {
-		vim_memset(l, ' ', added);
-		off += added;
+		vim_memset(l, ' ', before);
+		off += before;
 		if (padding > 0)
 		{
 		    vim_memset(l + off, ' ', padding);
@@ -365,8 +407,8 @@
 	    }
 	    else
 	    {
-		off = added + padding + n_used;
-		cells += added + padding;
+		off = before + after + padding + n_used;
+		cells += before + after + padding;
 	    }
 	    if (n_attr != NULL)
 	    {
@@ -385,10 +427,16 @@
 			// change last character to '>'
 			*lp = '>';
 		}
+		else if (after > 0)
+		{
+		    vim_memset(l + off, ' ', after);
+		    l[off + after] = NUL;
+		}
+
 		*p_extra = l;
-		*n_extra = n_used + added + padding;
+		*n_extra = n_used + before + after + padding;
 		*n_attr = mb_charlen(*p_extra);
-		*n_attr_skip = added + padding + col_off;
+		*n_attr_skip = before + padding + col_off;
 	    }
 	}
     }
@@ -1694,11 +1742,14 @@
 		// text prop can show.
 		while (text_prop_next < text_prop_count
 			   && (text_props[text_prop_next].tp_col == MAXCOL
-			      ? (*ptr == NUL
+			      ? ((*ptr == NUL
 				  && (wp->w_p_wrap
 				      || wlv.row == startrow
 				      || (text_props[text_prop_next].tp_flags
 						       & 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))
 		{
 		    if (text_props[text_prop_next].tp_col == MAXCOL
@@ -1773,6 +1824,8 @@
 			{
 			    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	    wrap = (tp->tp_flags & TP_FLAG_WRAP);
@@ -1797,18 +1850,15 @@
 				// don't combine char attr after EOL
 				text_prop_flags &= ~PT_FLAG_COMBINE;
 #ifdef FEAT_LINEBREAK
-			    if (below || right || !wrap)
+			    if (above || below || right || !wrap)
 			    {
 				// no 'showbreak' before "below" text property
-				// or after "right" text property
+				// or after "above" or "right" text property
 				need_showbreak = FALSE;
 				dont_use_showbreak = TRUE;
 			    }
 #endif
-			    // Keep in sync with where
-			    // textprop_size_after_trunc() is called in
-			    // win_lbr_chartabsize().
-			    if ((right || below || !wrap || padding > 0)
+			    if ((right || above || below || !wrap || padding > 0)
 							    && wp->w_width > 2)
 			    {
 				char_u	*prev_p_extra = wlv.p_extra;