From b7963df98f9dbbb824713acad2f47c9989fcf8f3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 31 Jul 2022 17:12:43 +0100 Subject: patch 9.0.0121: cannot put virtual text after or below a line Problem: Cannot put virtual text after or below a line. Solution: Add "text_align" and "text_wrap" arguments. --- src/textprop.c | 98 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 22 deletions(-) (limited to 'src/textprop.c') diff --git a/src/textprop.c b/src/textprop.c index 939b164074..f544a3ce5a 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -163,11 +163,6 @@ f_prop_add(typval_T *argvars, typval_T *rettv) start_lnum = tv_get_number(&argvars[0]); start_col = tv_get_number(&argvars[1]); - if (start_col < 1) - { - semsg(_(e_invalid_column_number_nr), (long)start_col); - return; - } if (argvars[2].v_type != VAR_DICT) { emsg(_(e_dictionary_required)); @@ -190,6 +185,7 @@ prop_add_one( char_u *type_name, int id, char_u *text_arg, + int text_flags, linenr_T start_lnum, linenr_T end_lnum, colnr_T start_col, @@ -256,7 +252,7 @@ prop_add_one( col = start_col; else col = 1; - if (col - 1 > (colnr_T)textlen) + if (col - 1 > (colnr_T)textlen && !(col == 0 && text_arg != NULL)) { semsg(_(e_invalid_column_number_nr), (long)start_col); goto theend; @@ -271,6 +267,13 @@ prop_add_one( if (length < 0) length = 0; // zero-width property + if (text_arg != NULL) + { + length = 1; // text is placed on one character + if (col == 0) + col = MAXCOL; // after the line + } + // Allocate the new line with space for the new property. newtext = alloc(buf->b_ml.ml_line_len + sizeof(textprop_T)); if (newtext == NULL) @@ -296,8 +299,9 @@ prop_add_one( tmp_prop.tp_len = length; tmp_prop.tp_id = id; tmp_prop.tp_type = type->pt_id; - tmp_prop.tp_flags = (lnum > start_lnum ? TP_FLAG_CONT_PREV : 0) - | (lnum < end_lnum ? TP_FLAG_CONT_NEXT : 0); + tmp_prop.tp_flags = text_flags + | (lnum > start_lnum ? TP_FLAG_CONT_PREV : 0) + | (lnum < end_lnum ? TP_FLAG_CONT_NEXT : 0); mch_memmove(newprops + i * sizeof(textprop_T), &tmp_prop, sizeof(textprop_T)); @@ -390,7 +394,7 @@ f_prop_add_list(typval_T *argvars, typval_T *rettv UNUSED) emsg(_(e_invalid_argument)); return; } - if (prop_add_one(buf, type_name, id, NULL, start_lnum, end_lnum, + if (prop_add_one(buf, type_name, id, NULL, 0, start_lnum, end_lnum, start_col, end_col) == FAIL) return; } @@ -428,6 +432,7 @@ prop_add_common( buf_T *buf = default_buf; int id = 0; char_u *text = NULL; + int flags = 0; if (dict == NULL || !dict_has_key(dict, "type")) { @@ -483,6 +488,45 @@ prop_add_common( goto theend; // use a default length of 1 to make multiple props show up end_col = start_col + 1; + + if (dict_has_key(dict, "text_align")) + { + char_u *p = dict_get_string(dict, "text_align", FALSE); + + if (p == NULL) + goto theend; + if (STRCMP(p, "right") == 0) + flags |= TP_FLAG_ALIGN_RIGHT; + else if (STRCMP(p, "below") == 0) + flags |= TP_FLAG_ALIGN_BELOW; + else if (STRCMP(p, "after") != 0) + { + semsg(_(e_invalid_value_for_argument_str_str), "text_align", p); + goto theend; + } + } + + if (dict_has_key(dict, "text_wrap")) + { + char_u *p = dict_get_string(dict, "text_wrap", FALSE); + if (p == NULL) + goto theend; + if (STRCMP(p, "wrap") == 0) + flags |= TP_FLAG_WRAP; + else if (STRCMP(p, "truncate") != 0) + { + semsg(_(e_invalid_value_for_argument_str_str), "text_wrap", p); + goto theend; + } + } + } + + // Column must be 1 or more for a normal text property; when "text" is + // present zero means it goes after the line. + if (start_col < (text == NULL ? 1 : 0)) + { + semsg(_(e_invalid_column_number_nr), (long)start_col); + goto theend; } if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL) @@ -501,7 +545,7 @@ prop_add_common( // correctly set. buf->b_has_textprop = TRUE; // this is never reset - prop_add_one(buf, type_name, id, text, + prop_add_one(buf, type_name, id, text, flags, start_lnum, end_lnum, start_col, end_col); text = NULL; @@ -1738,22 +1782,32 @@ typedef struct */ static adjustres_T adjust_prop( - textprop_T *prop, - colnr_T col, - int added, - int flags) + textprop_T *prop, + colnr_T col, + int added, + int flags) { - proptype_T *pt = text_prop_type_by_id(curbuf, prop->tp_type); - int start_incl = (pt != NULL - && (pt->pt_flags & PT_FLAG_INS_START_INCL)) + proptype_T *pt; + int start_incl; + int end_incl; + int droppable; + adjustres_T res = {TRUE, FALSE}; + + // prop after end of the line doesn't move + if (prop->tp_col == MAXCOL) + { + res.dirty = FALSE; + return res; + } + + pt = text_prop_type_by_id(curbuf, prop->tp_type); + start_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL)) || (flags & APC_SUBSTITUTE) || (prop->tp_flags & TP_FLAG_CONT_PREV); - int end_incl = (pt != NULL - && (pt->pt_flags & PT_FLAG_INS_END_INCL)) + end_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL)) || (prop->tp_flags & TP_FLAG_CONT_NEXT); - // Do not drop zero-width props if they later can increase in size. - int droppable = !(start_incl || end_incl); - adjustres_T res = {TRUE, FALSE}; + // do not drop zero-width props if they later can increase in size + droppable = !(start_incl || end_incl); if (added > 0) { -- cgit v1.2.3