Mercurial > vim
comparison src/drawline.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 | ec5f48ab361b |
children | f7a64755dbe9 |
comparison
equal
deleted
inserted
replaced
29559:69ceb540c619 | 29560:14b139cbec49 |
---|---|
206 | 206 |
207 static int | 207 static int |
208 text_prop_compare(const void *s1, const void *s2) | 208 text_prop_compare(const void *s1, const void *s2) |
209 { | 209 { |
210 int idx1, idx2; | 210 int idx1, idx2; |
211 textprop_T *tp1, *tp2; | |
211 proptype_T *pt1, *pt2; | 212 proptype_T *pt1, *pt2; |
212 colnr_T col1, col2; | 213 colnr_T col1, col2; |
213 | 214 |
214 idx1 = *(int *)s1; | 215 idx1 = *(int *)s1; |
215 idx2 = *(int *)s2; | 216 idx2 = *(int *)s2; |
216 pt1 = text_prop_type_by_id(current_buf, current_text_props[idx1].tp_type); | 217 tp1 = ¤t_text_props[idx1]; |
217 pt2 = text_prop_type_by_id(current_buf, current_text_props[idx2].tp_type); | 218 tp2 = ¤t_text_props[idx2]; |
219 pt1 = text_prop_type_by_id(current_buf, tp1->tp_type); | |
220 pt2 = text_prop_type_by_id(current_buf, tp2->tp_type); | |
218 if (pt1 == pt2) | 221 if (pt1 == pt2) |
219 return 0; | 222 return 0; |
220 if (pt1 == NULL) | 223 if (pt1 == NULL) |
221 return -1; | 224 return -1; |
222 if (pt2 == NULL) | 225 if (pt2 == NULL) |
223 return 1; | 226 return 1; |
224 if (pt1->pt_priority != pt2->pt_priority) | 227 if (pt1->pt_priority != pt2->pt_priority) |
225 return pt1->pt_priority > pt2->pt_priority ? 1 : -1; | 228 return pt1->pt_priority > pt2->pt_priority ? 1 : -1; |
226 col1 = current_text_props[idx1].tp_col; | 229 col1 = tp1->tp_col; |
227 col2 = current_text_props[idx2].tp_col; | 230 col2 = tp2->tp_col; |
231 if (col1 == MAXCOL && col2 == MAXCOL) | |
232 { | |
233 int flags1 = 0; | |
234 int flags2 = 0; | |
235 | |
236 // order on 0: after, 1: right, 2: below | |
237 if (tp1->tp_flags & TP_FLAG_ALIGN_RIGHT) | |
238 flags1 = 1; | |
239 if (tp1->tp_flags & TP_FLAG_ALIGN_BELOW) | |
240 flags1 = 2; | |
241 if (tp2->tp_flags & TP_FLAG_ALIGN_RIGHT) | |
242 flags2 = 1; | |
243 if (tp2->tp_flags & TP_FLAG_ALIGN_BELOW) | |
244 flags2 = 2; | |
245 if (flags1 != flags2) | |
246 return flags1 < flags2 ? 1 : -1; | |
247 } | |
228 return col1 == col2 ? 0 : col1 > col2 ? 1 : -1; | 248 return col1 == col2 ? 0 : col1 > col2 ? 1 : -1; |
229 } | 249 } |
230 #endif | 250 #endif |
231 | 251 |
232 /* | 252 /* |
279 char_u *saved_p_extra = NULL; | 299 char_u *saved_p_extra = NULL; |
280 int saved_c_extra = 0; | 300 int saved_c_extra = 0; |
281 int saved_c_final = 0; | 301 int saved_c_final = 0; |
282 int saved_char_attr = 0; | 302 int saved_char_attr = 0; |
283 | 303 |
284 int n_attr = 0; // chars with special attr | 304 int n_attr = 0; // chars with special attr |
285 int saved_attr2 = 0; // char_attr saved for n_attr | 305 int n_attr_skip = 0; // chars to skip before using extra_attr |
286 int n_attr3 = 0; // chars with overruling special attr | 306 int saved_attr2 = 0; // char_attr saved for n_attr |
287 int saved_attr3 = 0; // char_attr saved for n_attr3 | 307 int n_attr3 = 0; // chars with overruling special attr |
308 int saved_attr3 = 0; // char_attr saved for n_attr3 | |
288 | 309 |
289 int n_skip = 0; // nr of chars to skip for 'nowrap' | 310 int n_skip = 0; // nr of chars to skip for 'nowrap' |
290 | 311 |
291 int fromcol = -10; // start of inverting | 312 int fromcol = -10; // start of inverting |
292 int tocol = MAXCOL; // end of inverting | 313 int tocol = MAXCOL; // end of inverting |
326 int text_props_active = 0; | 347 int text_props_active = 0; |
327 proptype_T *text_prop_type = NULL; | 348 proptype_T *text_prop_type = NULL; |
328 int text_prop_attr = 0; | 349 int text_prop_attr = 0; |
329 int text_prop_id = 0; // active property ID | 350 int text_prop_id = 0; // active property ID |
330 int text_prop_combine = FALSE; | 351 int text_prop_combine = FALSE; |
352 int text_prop_follows = FALSE; // another text prop to display | |
331 #endif | 353 #endif |
332 #ifdef FEAT_SPELL | 354 #ifdef FEAT_SPELL |
333 int has_spell = FALSE; // this buffer has spell checking | 355 int has_spell = FALSE; // this buffer has spell checking |
334 int can_spell = FALSE; | 356 int can_spell = FALSE; |
335 # define SPWORDLEN 150 | 357 # define SPWORDLEN 150 |
1470 // not on the next char yet, don't start another prop | 1492 // not on the next char yet, don't start another prop |
1471 --bcol; | 1493 --bcol; |
1472 # endif | 1494 # endif |
1473 // Add any text property that starts in this column. | 1495 // Add any text property that starts in this column. |
1474 while (text_prop_next < text_prop_count | 1496 while (text_prop_next < text_prop_count |
1475 && bcol >= text_props[text_prop_next].tp_col - 1) | 1497 && (text_props[text_prop_next].tp_col == MAXCOL |
1498 ? *ptr == NUL | |
1499 : bcol >= text_props[text_prop_next].tp_col - 1)) | |
1476 { | 1500 { |
1477 if (bcol <= text_props[text_prop_next].tp_col - 1 | 1501 if (bcol <= text_props[text_prop_next].tp_col - 1 |
1478 + text_props[text_prop_next].tp_len) | 1502 + text_props[text_prop_next].tp_len) |
1479 text_prop_idxs[text_props_active++] = text_prop_next; | 1503 text_prop_idxs[text_props_active++] = text_prop_next; |
1480 ++text_prop_next; | 1504 ++text_prop_next; |
1482 | 1506 |
1483 text_prop_attr = 0; | 1507 text_prop_attr = 0; |
1484 text_prop_combine = FALSE; | 1508 text_prop_combine = FALSE; |
1485 text_prop_type = NULL; | 1509 text_prop_type = NULL; |
1486 text_prop_id = 0; | 1510 text_prop_id = 0; |
1487 if (text_props_active > 0) | 1511 if (text_props_active > 0 && n_extra == 0) |
1488 { | 1512 { |
1489 int used_tpi = -1; | 1513 int used_tpi = -1; |
1490 int used_attr = 0; | 1514 int used_attr = 0; |
1515 int other_tpi = -1; | |
1491 | 1516 |
1492 // Sort the properties on priority and/or starting last. | 1517 // Sort the properties on priority and/or starting last. |
1493 // Then combine the attributes, highest priority last. | 1518 // Then combine the attributes, highest priority last. |
1519 text_prop_follows = FALSE; | |
1494 current_text_props = text_props; | 1520 current_text_props = text_props; |
1495 current_buf = wp->w_buffer; | 1521 current_buf = wp->w_buffer; |
1496 qsort((void *)text_prop_idxs, (size_t)text_props_active, | 1522 qsort((void *)text_prop_idxs, (size_t)text_props_active, |
1497 sizeof(int), text_prop_compare); | 1523 sizeof(int), text_prop_compare); |
1498 | 1524 |
1509 text_prop_type = pt; | 1535 text_prop_type = pt; |
1510 text_prop_attr = | 1536 text_prop_attr = |
1511 hl_combine_attr(text_prop_attr, used_attr); | 1537 hl_combine_attr(text_prop_attr, used_attr); |
1512 text_prop_combine = pt->pt_flags & PT_FLAG_COMBINE; | 1538 text_prop_combine = pt->pt_flags & PT_FLAG_COMBINE; |
1513 text_prop_id = text_props[tpi].tp_id; | 1539 text_prop_id = text_props[tpi].tp_id; |
1540 other_tpi = used_tpi; | |
1514 used_tpi = tpi; | 1541 used_tpi = tpi; |
1515 } | 1542 } |
1516 } | 1543 } |
1517 if (n_extra == 0 && text_prop_id < 0 && used_tpi >= 0 | 1544 if (text_prop_id < 0 && used_tpi >= 0 |
1518 && -text_prop_id | 1545 && -text_prop_id |
1519 <= wp->w_buffer->b_textprop_text.ga_len) | 1546 <= wp->w_buffer->b_textprop_text.ga_len) |
1520 { | 1547 { |
1521 char_u *p = ((char_u **)wp->w_buffer | 1548 char_u *p = ((char_u **)wp->w_buffer |
1522 ->b_textprop_text.ga_data)[ | 1549 ->b_textprop_text.ga_data)[ |
1523 -text_prop_id - 1]; | 1550 -text_prop_id - 1]; |
1524 if (p != NULL) | 1551 if (p != NULL) |
1525 { | 1552 { |
1553 int right = (text_props[used_tpi].tp_flags | |
1554 & TP_FLAG_ALIGN_RIGHT); | |
1555 int below = (text_props[used_tpi].tp_flags | |
1556 & TP_FLAG_ALIGN_BELOW); | |
1557 | |
1526 p_extra = p; | 1558 p_extra = p; |
1527 c_extra = NUL; | 1559 c_extra = NUL; |
1528 c_final = NUL; | 1560 c_final = NUL; |
1529 n_extra = (int)STRLEN(p); | 1561 n_extra = (int)STRLEN(p); |
1530 extra_attr = used_attr; | 1562 extra_attr = used_attr; |
1531 n_attr = n_extra; | 1563 n_attr = n_extra; |
1532 text_prop_attr = 0; | 1564 text_prop_attr = 0; |
1565 if (*ptr == NUL) | |
1566 // don't combine char attr after EOL | |
1567 text_prop_combine = FALSE; | |
1568 | |
1569 // TODO: truncation if it doesn't fit | |
1570 if (right || below) | |
1571 { | |
1572 int added = wp->w_width - col; | |
1573 char_u *l; | |
1574 | |
1575 // Right-align: fill with spaces | |
1576 // TODO: count screen columns | |
1577 if (right) | |
1578 added -= n_extra; | |
1579 if (added < 0 || (below && col == 0)) | |
1580 added = 0; | |
1581 l = alloc(n_extra + added + 1); | |
1582 if (l != NULL) | |
1583 { | |
1584 vim_memset(l, ' ', added); | |
1585 STRCPY(l + added, p); | |
1586 vim_free(p_extra_free); | |
1587 p_extra = p_extra_free = l; | |
1588 n_extra += added; | |
1589 n_attr_skip = added; | |
1590 } | |
1591 } | |
1533 | 1592 |
1534 // If the cursor is on or after this position, | 1593 // If the cursor is on or after this position, |
1535 // move it forward. | 1594 // move it forward. |
1536 if (wp == curwin | 1595 if (wp == curwin |
1537 && lnum == curwin->w_cursor.lnum | 1596 && lnum == curwin->w_cursor.lnum |
1539 curwin->w_cursor.col += n_extra; | 1598 curwin->w_cursor.col += n_extra; |
1540 } | 1599 } |
1541 // reset the ID in the copy to avoid it being used | 1600 // reset the ID in the copy to avoid it being used |
1542 // again | 1601 // again |
1543 text_props[used_tpi].tp_id = -MAXCOL; | 1602 text_props[used_tpi].tp_id = -MAXCOL; |
1603 | |
1604 // If another text prop follows the condition below at | |
1605 // the last window column must know. | |
1606 text_prop_follows = other_tpi != -1; | |
1544 } | 1607 } |
1545 } | 1608 } |
1546 } | 1609 } |
1547 #endif | 1610 #endif |
1548 | 1611 |
2639 curwin->w_flags &= ~(WFLAG_WCOL_OFF_ADDED | WFLAG_WROW_OFF_ADDED); | 2702 curwin->w_flags &= ~(WFLAG_WCOL_OFF_ADDED | WFLAG_WROW_OFF_ADDED); |
2640 # endif | 2703 # endif |
2641 } | 2704 } |
2642 #endif | 2705 #endif |
2643 | 2706 |
2644 // Don't override visual selection highlighting. | 2707 // Use "extra_attr", but don't override visual selection highlighting. |
2645 if (n_attr > 0 | 2708 // Don't use "extra_attr" until n_attr_skip is zero. |
2709 if (n_attr_skip == 0 && n_attr > 0 | |
2646 && draw_state == WL_LINE | 2710 && draw_state == WL_LINE |
2647 && !attr_pri) | 2711 && !attr_pri) |
2648 { | 2712 { |
2649 #ifdef LINE_ATTR | 2713 #ifdef LINE_ATTR |
2650 if (line_attr) | 2714 if (line_attr) |
3186 // restore attributes after "predeces" in 'listchars' | 3250 // restore attributes after "predeces" in 'listchars' |
3187 if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0) | 3251 if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0) |
3188 char_attr = saved_attr3; | 3252 char_attr = saved_attr3; |
3189 | 3253 |
3190 // restore attributes after last 'listchars' or 'number' char | 3254 // restore attributes after last 'listchars' or 'number' char |
3191 if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0) | 3255 if (n_attr > 0 && draw_state == WL_LINE |
3256 && n_attr_skip == 0 && --n_attr == 0) | |
3192 char_attr = saved_attr2; | 3257 char_attr = saved_attr2; |
3258 if (n_attr_skip > 0) | |
3259 --n_attr_skip; | |
3193 | 3260 |
3194 // At end of screen line and there is more to come: Display the line | 3261 // At end of screen line and there is more to come: Display the line |
3195 // so far. If there is no more to display it is caught above. | 3262 // so far. If there is no more to display it is caught above. |
3196 if (( | 3263 if (( |
3197 #ifdef FEAT_RIGHTLEFT | 3264 #ifdef FEAT_RIGHTLEFT |
3200 (col >= wp->w_width)) | 3267 (col >= wp->w_width)) |
3201 && (draw_state != WL_LINE | 3268 && (draw_state != WL_LINE |
3202 || *ptr != NUL | 3269 || *ptr != NUL |
3203 #ifdef FEAT_DIFF | 3270 #ifdef FEAT_DIFF |
3204 || filler_todo > 0 | 3271 || filler_todo > 0 |
3272 #endif | |
3273 #ifdef FEAT_PROP_POPUP | |
3274 || text_prop_follows | |
3205 #endif | 3275 #endif |
3206 || (wp->w_p_list && wp->w_lcs_chars.eol != NUL | 3276 || (wp->w_p_list && wp->w_lcs_chars.eol != NUL |
3207 && p_extra != at_end_str) | 3277 && p_extra != at_end_str) |
3208 || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) | 3278 || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) |
3209 ) | 3279 ) |
3221 | 3291 |
3222 // When not wrapping and finished diff lines, or when displayed | 3292 // When not wrapping and finished diff lines, or when displayed |
3223 // '$' and highlighting until last column, break here. | 3293 // '$' and highlighting until last column, break here. |
3224 if ((!wp->w_p_wrap | 3294 if ((!wp->w_p_wrap |
3225 #ifdef FEAT_DIFF | 3295 #ifdef FEAT_DIFF |
3226 && filler_todo <= 0 | 3296 && filler_todo <= 0 |
3297 #endif | |
3298 #ifdef FEAT_PROP_POPUP | |
3299 && !text_prop_follows | |
3227 #endif | 3300 #endif |
3228 ) || lcs_eol_one == -1) | 3301 ) || lcs_eol_one == -1) |
3229 break; | 3302 break; |
3230 | 3303 |
3231 // When the window is too narrow draw all "@" lines. | 3304 // When the window is too narrow draw all "@" lines. |
3248 } | 3321 } |
3249 | 3322 |
3250 if (screen_cur_row == screen_row - 1 | 3323 if (screen_cur_row == screen_row - 1 |
3251 #ifdef FEAT_DIFF | 3324 #ifdef FEAT_DIFF |
3252 && filler_todo <= 0 | 3325 && filler_todo <= 0 |
3326 #endif | |
3327 #ifdef FEAT_PROP_POPUP | |
3328 && !text_prop_follows | |
3253 #endif | 3329 #endif |
3254 && wp->w_width == Columns) | 3330 && wp->w_width == Columns) |
3255 { | 3331 { |
3256 // Remember that the line wraps, used for modeless copy. | 3332 // Remember that the line wraps, used for modeless copy. |
3257 LineWraps[screen_row - 1] = TRUE; | 3333 LineWraps[screen_row - 1] = TRUE; |