comparison src/sign.c @ 17264:82b5d981fe59 v8.1.1631

patch 8.1.1631: displaying signs is inefficient commit https://github.com/vim/vim/commit/4e038571aa91521e110187a256b5d16bff8b5820 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jul 4 18:28:35 2019 +0200 patch 8.1.1631: displaying signs is inefficient Problem: Displaying signs is inefficient. Solution: Avoid making multiple calls to get information about a placed sign. (Yegappan Lakshmanan, closes #4586)
author Bram Moolenaar <Bram@vim.org>
date Thu, 04 Jul 2019 18:30:05 +0200
parents cbd0432cf8ff
children 9843fbfa0ee5
comparison
equal deleted inserted replaced
17263:ad5eb560909a 17264:82b5d981fe59
272 272
273 insert_sign(buf, prev, sign, id, group, prio, lnum, typenr); 273 insert_sign(buf, prev, sign, id, group, prio, lnum, typenr);
274 } 274 }
275 275
276 /* 276 /*
277 * Lookup a sign by typenr. Returns NULL if sign is not found.
278 */
279 static sign_T *
280 find_sign_by_typenr(int typenr)
281 {
282 sign_T *sp;
283
284 for (sp = first_sign; sp != NULL; sp = sp->sn_next)
285 if (sp->sn_typenr == typenr)
286 return sp;
287 return NULL;
288 }
289
290 /*
277 * Get the name of a sign by its typenr. 291 * Get the name of a sign by its typenr.
278 */ 292 */
279 static char_u * 293 static char_u *
280 sign_typenr2name(int typenr) 294 sign_typenr2name(int typenr)
281 { 295 {
443 457
444 return (linenr_T)0; 458 return (linenr_T)0;
445 } 459 }
446 460
447 /* 461 /*
448 * Return the type number of the sign at line number 'lnum' in buffer 'buf' 462 * Return the attributes of the first sign placed on line 'lnum' in buffer
449 * which has the attribute specified by 'type'. Returns 0 if a sign is not 463 * 'buf'. Used when refreshing the screen. Returns TRUE if a sign is found on
450 * found at the line number or it doesn't have the specified attribute. 464 * 'lnum', FALSE otherwise.
451 */ 465 */
452 int 466 int
453 buf_getsigntype( 467 buf_get_signattrs(buf_T *buf, linenr_T lnum, sign_attrs_T *sattr)
454 buf_T *buf, 468 {
455 linenr_T lnum, 469 signlist_T *sign;
456 int type) // SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL 470 sign_T *sp;
457 { 471
458 signlist_T *sign; // a sign in a b_signlist 472 vim_memset(sattr, 0, sizeof(sign_attrs_T));
459 473
460 FOR_ALL_SIGNS_IN_BUF(buf, sign) 474 FOR_ALL_SIGNS_IN_BUF(buf, sign)
461 if (sign->lnum == lnum 475 {
462 && (type == SIGN_ANY 476 if (sign->lnum > lnum)
477 // Signs are sorted by line number in the buffer. No need to check
478 // for signs after the specified line number 'lnum'.
479 break;
480
481 if (sign->lnum == lnum)
482 {
483 sattr->typenr = sign->typenr;
484 sp = find_sign_by_typenr(sign->typenr);
485 if (sp == NULL)
486 return FALSE;
487
463 # ifdef FEAT_SIGN_ICONS 488 # ifdef FEAT_SIGN_ICONS
464 || (type == SIGN_ICON 489 sattr->icon = sp->sn_image;
465 && sign_get_image(sign->typenr) != NULL)
466 # endif 490 # endif
467 || (type == SIGN_TEXT 491 sattr->text = sp->sn_text;
468 && sign_get_text(sign->typenr) != NULL) 492 if (sattr->text != NULL && sp->sn_text_hl > 0)
469 || (type == SIGN_LINEHL 493 sattr->texthl = syn_id2attr(sp->sn_text_hl);
470 && sign_get_attr(sign->typenr, TRUE) != 0))) 494 if (sp->sn_line_hl > 0)
471 return sign->typenr; 495 sattr->linehl = syn_id2attr(sp->sn_line_hl);
472 return 0; 496 return TRUE;
497 }
498 }
499 return FALSE;
473 } 500 }
474 501
475 /* 502 /*
476 * Delete sign 'id' in group 'group' from buffer 'buf'. 503 * Delete sign 'id' in group 'group' from buffer 'buf'.
477 * If 'id' is zero, then delete all the signs in group 'group'. Otherwise 504 * If 'id' is zero, then delete all the signs in group 'group'. Otherwise
569 char_u *groupname) // sign group name 596 char_u *groupname) // sign group name
570 { 597 {
571 signlist_T *sign; // a sign in the signlist 598 signlist_T *sign; // a sign in the signlist
572 599
573 FOR_ALL_SIGNS_IN_BUF(buf, sign) 600 FOR_ALL_SIGNS_IN_BUF(buf, sign)
601 {
602 if (sign->lnum > lnum)
603 // Signs are sorted by line number in the buffer. No need to check
604 // for signs after the specified line number 'lnum'.
605 break;
606
574 if (sign->lnum == lnum && sign_in_group(sign, groupname)) 607 if (sign->lnum == lnum && sign_in_group(sign, groupname))
575 return sign; 608 return sign;
609 }
576 610
577 return NULL; 611 return NULL;
578 } 612 }
579 613
580 /* 614 /*
606 int typenr) // sign type number 640 int typenr) // sign type number
607 { 641 {
608 signlist_T *sign; // a sign in the signlist 642 signlist_T *sign; // a sign in the signlist
609 643
610 FOR_ALL_SIGNS_IN_BUF(buf, sign) 644 FOR_ALL_SIGNS_IN_BUF(buf, sign)
645 {
646 if (sign->lnum > lnum)
647 // Signs are sorted by line number in the buffer. No need to check
648 // for signs after the specified line number 'lnum'.
649 break;
650
611 if (sign->lnum == lnum && sign->typenr == typenr) 651 if (sign->lnum == lnum && sign->typenr == typenr)
612 return sign->id; 652 return sign->id;
653 }
613 654
614 return 0; 655 return 0;
615 } 656 }
616 657
617 658
624 { 665 {
625 signlist_T *sign; // a sign in the signlist 666 signlist_T *sign; // a sign in the signlist
626 int count = 0; 667 int count = 0;
627 668
628 FOR_ALL_SIGNS_IN_BUF(buf, sign) 669 FOR_ALL_SIGNS_IN_BUF(buf, sign)
670 {
671 if (sign->lnum > lnum)
672 // Signs are sorted by line number in the buffer. No need to check
673 // for signs after the specified line number 'lnum'.
674 break;
675
629 if (sign->lnum == lnum) 676 if (sign->lnum == lnum)
630 if (sign_get_image(sign->typenr) != NULL) 677 if (sign_get_image(sign->typenr) != NULL)
631 count++; 678 count++;
679 }
632 680
633 return count; 681 return count;
634 } 682 }
635 # endif /* FEAT_SIGN_ICONS */ 683 # endif /* FEAT_SIGN_ICONS */
636 # endif /* FEAT_NETBEANS_INTG */ 684 # endif /* FEAT_NETBEANS_INTG */
1788 if (sp_prev == NULL) 1836 if (sp_prev == NULL)
1789 first_sign = sp->sn_next; 1837 first_sign = sp->sn_next;
1790 else 1838 else
1791 sp_prev->sn_next = sp->sn_next; 1839 sp_prev->sn_next = sp->sn_next;
1792 vim_free(sp); 1840 vim_free(sp);
1793 }
1794
1795 /*
1796 * Get highlighting attribute for sign "typenr".
1797 * If "line" is TRUE: line highl, if FALSE: text highl.
1798 */
1799 int
1800 sign_get_attr(int typenr, int line)
1801 {
1802 sign_T *sp;
1803
1804 for (sp = first_sign; sp != NULL; sp = sp->sn_next)
1805 if (sp->sn_typenr == typenr)
1806 {
1807 if (line)
1808 {
1809 if (sp->sn_line_hl > 0)
1810 return syn_id2attr(sp->sn_line_hl);
1811 }
1812 else
1813 {
1814 if (sp->sn_text_hl > 0)
1815 return syn_id2attr(sp->sn_text_hl);
1816 }
1817 break;
1818 }
1819 return 0;
1820 }
1821
1822 /*
1823 * Get text mark for sign "typenr".
1824 * Returns NULL if there isn't one.
1825 */
1826 char_u *
1827 sign_get_text(int typenr)
1828 {
1829 sign_T *sp;
1830
1831 for (sp = first_sign; sp != NULL; sp = sp->sn_next)
1832 if (sp->sn_typenr == typenr)
1833 return sp->sn_text;
1834 return NULL;
1835 } 1841 }
1836 1842
1837 # if defined(FEAT_SIGN_ICONS) || defined(PROTO) 1843 # if defined(FEAT_SIGN_ICONS) || defined(PROTO)
1838 void * 1844 void *
1839 sign_get_image( 1845 sign_get_image(