Mercurial > vim
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( |