comparison src/textprop.c @ 29560:14b139cbec49 v9.0.0121

patch 9.0.0121: cannot put virtual text after or below a line Commit: https://github.com/vim/vim/commit/b7963df98f9dbbb824713acad2f47c9989fcf8f3 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jul 31 17:12:43 2022 +0100 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.
author Bram Moolenaar <Bram@vim.org>
date Sun, 31 Jul 2022 18:15:03 +0200
parents 89a97f70e8eb
children 4a79bca8a76e
comparison
equal deleted inserted replaced
29559:69ceb540c619 29560:14b139cbec49
161 || check_for_dict_arg(argvars, 2) == FAIL)) 161 || check_for_dict_arg(argvars, 2) == FAIL))
162 return; 162 return;
163 163
164 start_lnum = tv_get_number(&argvars[0]); 164 start_lnum = tv_get_number(&argvars[0]);
165 start_col = tv_get_number(&argvars[1]); 165 start_col = tv_get_number(&argvars[1]);
166 if (start_col < 1)
167 {
168 semsg(_(e_invalid_column_number_nr), (long)start_col);
169 return;
170 }
171 if (argvars[2].v_type != VAR_DICT) 166 if (argvars[2].v_type != VAR_DICT)
172 { 167 {
173 emsg(_(e_dictionary_required)); 168 emsg(_(e_dictionary_required));
174 return; 169 return;
175 } 170 }
188 prop_add_one( 183 prop_add_one(
189 buf_T *buf, 184 buf_T *buf,
190 char_u *type_name, 185 char_u *type_name,
191 int id, 186 int id,
192 char_u *text_arg, 187 char_u *text_arg,
188 int text_flags,
193 linenr_T start_lnum, 189 linenr_T start_lnum,
194 linenr_T end_lnum, 190 linenr_T end_lnum,
195 colnr_T start_col, 191 colnr_T start_col,
196 colnr_T end_col) 192 colnr_T end_col)
197 { 193 {
254 250
255 if (lnum == start_lnum) 251 if (lnum == start_lnum)
256 col = start_col; 252 col = start_col;
257 else 253 else
258 col = 1; 254 col = 1;
259 if (col - 1 > (colnr_T)textlen) 255 if (col - 1 > (colnr_T)textlen && !(col == 0 && text_arg != NULL))
260 { 256 {
261 semsg(_(e_invalid_column_number_nr), (long)start_col); 257 semsg(_(e_invalid_column_number_nr), (long)start_col);
262 goto theend; 258 goto theend;
263 } 259 }
264 260
269 if (length > (long)textlen) 265 if (length > (long)textlen)
270 length = (int)textlen; // can include the end-of-line 266 length = (int)textlen; // can include the end-of-line
271 if (length < 0) 267 if (length < 0)
272 length = 0; // zero-width property 268 length = 0; // zero-width property
273 269
270 if (text_arg != NULL)
271 {
272 length = 1; // text is placed on one character
273 if (col == 0)
274 col = MAXCOL; // after the line
275 }
276
274 // Allocate the new line with space for the new property. 277 // Allocate the new line with space for the new property.
275 newtext = alloc(buf->b_ml.ml_line_len + sizeof(textprop_T)); 278 newtext = alloc(buf->b_ml.ml_line_len + sizeof(textprop_T));
276 if (newtext == NULL) 279 if (newtext == NULL)
277 goto theend; 280 goto theend;
278 // Copy the text, including terminating NUL. 281 // Copy the text, including terminating NUL.
294 297
295 tmp_prop.tp_col = col; 298 tmp_prop.tp_col = col;
296 tmp_prop.tp_len = length; 299 tmp_prop.tp_len = length;
297 tmp_prop.tp_id = id; 300 tmp_prop.tp_id = id;
298 tmp_prop.tp_type = type->pt_id; 301 tmp_prop.tp_type = type->pt_id;
299 tmp_prop.tp_flags = (lnum > start_lnum ? TP_FLAG_CONT_PREV : 0) 302 tmp_prop.tp_flags = text_flags
300 | (lnum < end_lnum ? TP_FLAG_CONT_NEXT : 0); 303 | (lnum > start_lnum ? TP_FLAG_CONT_PREV : 0)
304 | (lnum < end_lnum ? TP_FLAG_CONT_NEXT : 0);
301 mch_memmove(newprops + i * sizeof(textprop_T), &tmp_prop, 305 mch_memmove(newprops + i * sizeof(textprop_T), &tmp_prop,
302 sizeof(textprop_T)); 306 sizeof(textprop_T));
303 307
304 if (i < proplen) 308 if (i < proplen)
305 mch_memmove(newprops + (i + 1) * sizeof(textprop_T), 309 mch_memmove(newprops + (i + 1) * sizeof(textprop_T),
388 || end_lnum <= 0 || end_col <= 0) 392 || end_lnum <= 0 || end_col <= 0)
389 { 393 {
390 emsg(_(e_invalid_argument)); 394 emsg(_(e_invalid_argument));
391 return; 395 return;
392 } 396 }
393 if (prop_add_one(buf, type_name, id, NULL, start_lnum, end_lnum, 397 if (prop_add_one(buf, type_name, id, NULL, 0, start_lnum, end_lnum,
394 start_col, end_col) == FAIL) 398 start_col, end_col) == FAIL)
395 return; 399 return;
396 } 400 }
397 401
398 redraw_buf_later(buf, VALID); 402 redraw_buf_later(buf, VALID);
426 colnr_T end_col; 430 colnr_T end_col;
427 char_u *type_name; 431 char_u *type_name;
428 buf_T *buf = default_buf; 432 buf_T *buf = default_buf;
429 int id = 0; 433 int id = 0;
430 char_u *text = NULL; 434 char_u *text = NULL;
435 int flags = 0;
431 436
432 if (dict == NULL || !dict_has_key(dict, "type")) 437 if (dict == NULL || !dict_has_key(dict, "type"))
433 { 438 {
434 emsg(_(e_missing_property_type_name)); 439 emsg(_(e_missing_property_type_name));
435 goto theend; 440 goto theend;
481 text = dict_get_string(dict, "text", TRUE); 486 text = dict_get_string(dict, "text", TRUE);
482 if (text == NULL) 487 if (text == NULL)
483 goto theend; 488 goto theend;
484 // use a default length of 1 to make multiple props show up 489 // use a default length of 1 to make multiple props show up
485 end_col = start_col + 1; 490 end_col = start_col + 1;
491
492 if (dict_has_key(dict, "text_align"))
493 {
494 char_u *p = dict_get_string(dict, "text_align", FALSE);
495
496 if (p == NULL)
497 goto theend;
498 if (STRCMP(p, "right") == 0)
499 flags |= TP_FLAG_ALIGN_RIGHT;
500 else if (STRCMP(p, "below") == 0)
501 flags |= TP_FLAG_ALIGN_BELOW;
502 else if (STRCMP(p, "after") != 0)
503 {
504 semsg(_(e_invalid_value_for_argument_str_str), "text_align", p);
505 goto theend;
506 }
507 }
508
509 if (dict_has_key(dict, "text_wrap"))
510 {
511 char_u *p = dict_get_string(dict, "text_wrap", FALSE);
512 if (p == NULL)
513 goto theend;
514 if (STRCMP(p, "wrap") == 0)
515 flags |= TP_FLAG_WRAP;
516 else if (STRCMP(p, "truncate") != 0)
517 {
518 semsg(_(e_invalid_value_for_argument_str_str), "text_wrap", p);
519 goto theend;
520 }
521 }
522 }
523
524 // Column must be 1 or more for a normal text property; when "text" is
525 // present zero means it goes after the line.
526 if (start_col < (text == NULL ? 1 : 0))
527 {
528 semsg(_(e_invalid_column_number_nr), (long)start_col);
529 goto theend;
486 } 530 }
487 531
488 if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL) 532 if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
489 goto theend; 533 goto theend;
490 534
499 // This must be done _before_ we add the property because property changes 543 // This must be done _before_ we add the property because property changes
500 // trigger buffer (memline) reorganisation, which needs this flag to be 544 // trigger buffer (memline) reorganisation, which needs this flag to be
501 // correctly set. 545 // correctly set.
502 buf->b_has_textprop = TRUE; // this is never reset 546 buf->b_has_textprop = TRUE; // this is never reset
503 547
504 prop_add_one(buf, type_name, id, text, 548 prop_add_one(buf, type_name, id, text, flags,
505 start_lnum, end_lnum, start_col, end_col); 549 start_lnum, end_lnum, start_col, end_col);
506 text = NULL; 550 text = NULL;
507 551
508 redraw_buf_later(buf, VALID); 552 redraw_buf_later(buf, VALID);
509 553
1736 * "flags" can have: 1780 * "flags" can have:
1737 * APC_SUBSTITUTE: Text is replaced, not inserted. 1781 * APC_SUBSTITUTE: Text is replaced, not inserted.
1738 */ 1782 */
1739 static adjustres_T 1783 static adjustres_T
1740 adjust_prop( 1784 adjust_prop(
1741 textprop_T *prop, 1785 textprop_T *prop,
1742 colnr_T col, 1786 colnr_T col,
1743 int added, 1787 int added,
1744 int flags) 1788 int flags)
1745 { 1789 {
1746 proptype_T *pt = text_prop_type_by_id(curbuf, prop->tp_type); 1790 proptype_T *pt;
1747 int start_incl = (pt != NULL 1791 int start_incl;
1748 && (pt->pt_flags & PT_FLAG_INS_START_INCL)) 1792 int end_incl;
1793 int droppable;
1794 adjustres_T res = {TRUE, FALSE};
1795
1796 // prop after end of the line doesn't move
1797 if (prop->tp_col == MAXCOL)
1798 {
1799 res.dirty = FALSE;
1800 return res;
1801 }
1802
1803 pt = text_prop_type_by_id(curbuf, prop->tp_type);
1804 start_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL))
1749 || (flags & APC_SUBSTITUTE) 1805 || (flags & APC_SUBSTITUTE)
1750 || (prop->tp_flags & TP_FLAG_CONT_PREV); 1806 || (prop->tp_flags & TP_FLAG_CONT_PREV);
1751 int end_incl = (pt != NULL 1807 end_incl = (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL))
1752 && (pt->pt_flags & PT_FLAG_INS_END_INCL))
1753 || (prop->tp_flags & TP_FLAG_CONT_NEXT); 1808 || (prop->tp_flags & TP_FLAG_CONT_NEXT);
1754 // Do not drop zero-width props if they later can increase in size. 1809 // do not drop zero-width props if they later can increase in size
1755 int droppable = !(start_incl || end_incl); 1810 droppable = !(start_incl || end_incl);
1756 adjustres_T res = {TRUE, FALSE};
1757 1811
1758 if (added > 0) 1812 if (added > 0)
1759 { 1813 {
1760 if (col + 1 <= prop->tp_col 1814 if (col + 1 <= prop->tp_col
1761 - (start_incl || (prop->tp_len == 0 && end_incl))) 1815 - (start_incl || (prop->tp_len == 0 && end_incl)))