Skip to content

Commit 4e03857

Browse files
committed
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)
1 parent e809a4e commit 4e03857

5 files changed

Lines changed: 101 additions & 84 deletions

File tree

src/proto/sign.pro

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* sign.c */
22
void init_signs(void);
3-
int buf_getsigntype(buf_T *buf, linenr_T lnum, int type);
3+
int buf_get_signattrs(buf_T *buf, linenr_T lnum, sign_attrs_T *sattr);
44
linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group);
55
int buf_findsign(buf_T *buf, int id, char_u *group);
66
int buf_findsign_id(buf_T *buf, linenr_T lnum, char_u *groupname);
@@ -13,8 +13,6 @@ int sign_undefine_by_name(char_u *name);
1313
void ex_sign(exarg_T *eap);
1414
void get_buffer_signs(buf_T *buf, list_T *l);
1515
void sign_gui_started(void);
16-
int sign_get_attr(int typenr, int line);
17-
char_u *sign_get_text(int typenr);
1816
void *sign_get_image(int typenr);
1917
void free_signs(void);
2018
char_u *get_sign_name(expand_T *xp, int idx);

src/screen.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,7 +3042,8 @@ text_prop_compare(const void *s1, const void *s2)
30423042
get_sign_display_info(
30433043
int nrcol,
30443044
win_T *wp,
3045-
linenr_T lnum,
3045+
linenr_T lnum UNUSED,
3046+
sign_attrs_T *sattr,
30463047
int wcr_attr,
30473048
int row,
30483049
int startrow,
@@ -3077,9 +3078,9 @@ get_sign_display_info(
30773078
#endif
30783079
)
30793080
{
3080-
text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT);
3081+
text_sign = (sattr->text != NULL) ? sattr->typenr : 0;
30813082
# ifdef FEAT_SIGN_ICONS
3082-
icon_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_ICON);
3083+
icon_sign = (sattr->icon != NULL) ? sattr->typenr : 0;
30833084
if (gui.in_use && icon_sign != 0)
30843085
{
30853086
// Use the image in this position.
@@ -3093,7 +3094,7 @@ get_sign_display_info(
30933094
else
30943095
*c_extrap = SIGN_BYTE;
30953096
# ifdef FEAT_NETBEANS_INTG
3096-
if (buf_signcount(wp->w_buffer, lnum) > 1)
3097+
if (netbeans_active() && (buf_signcount(wp->w_buffer, lnum) > 1))
30973098
{
30983099
if (nrcol)
30993100
{
@@ -3114,7 +3115,7 @@ get_sign_display_info(
31143115
# endif
31153116
if (text_sign != 0)
31163117
{
3117-
*pp_extra = sign_get_text(text_sign);
3118+
*pp_extra = sattr->text;
31183119
if (*pp_extra != NULL)
31193120
{
31203121
if (nrcol)
@@ -3127,7 +3128,7 @@ get_sign_display_info(
31273128
*c_finalp = NUL;
31283129
*n_extrap = (int)STRLEN(*pp_extra);
31293130
}
3130-
*char_attrp = sign_get_attr(text_sign, FALSE);
3131+
*char_attrp = sattr->texthl;
31313132
}
31323133
}
31333134
}
@@ -3264,6 +3265,8 @@ win_line(
32643265
#endif
32653266
#if defined(FEAT_SIGNS) || defined(FEAT_QUICKFIX) \
32663267
|| defined(FEAT_SYN_HL) || defined(FEAT_DIFF)
3268+
int sign_present = FALSE;
3269+
sign_attrs_T sattr;
32673270
# define LINE_ATTR
32683271
int line_attr = 0; /* attribute for the whole line */
32693272
#endif
@@ -3585,12 +3588,15 @@ win_line(
35853588
filler_todo = filler_lines;
35863589
#endif
35873590

3591+
#ifdef FEAT_SIGNS
3592+
sign_present = buf_get_signattrs(wp->w_buffer, lnum, &sattr);
3593+
#endif
3594+
35883595
#ifdef LINE_ATTR
35893596
# ifdef FEAT_SIGNS
35903597
/* If this line has a sign with line highlighting set line_attr. */
3591-
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
3592-
if (v != 0)
3593-
line_attr = sign_get_attr((int)v, TRUE);
3598+
if (sign_present)
3599+
line_attr = sattr.linehl;
35943600
# endif
35953601
# if defined(FEAT_QUICKFIX)
35963602
/* Highlight the current line in the quickfix window. */
@@ -3974,8 +3980,8 @@ win_line(
39743980
/* Show the sign column when there are any signs in this
39753981
* buffer or when using Netbeans. */
39763982
if (signcolumn_on(wp))
3977-
get_sign_display_info(FALSE, wp, lnum, wcr_attr, row,
3978-
startrow, filler_lines, filler_todo, &c_extra,
3983+
get_sign_display_info(FALSE, wp, lnum, &sattr, wcr_attr,
3984+
row, startrow, filler_lines, filler_todo, &c_extra,
39793985
&c_final, extra, &p_extra, &n_extra, &char_attr);
39803986
}
39813987
#endif
@@ -3997,11 +4003,10 @@ win_line(
39974003
// in 'lnum', then display the sign instead of the line
39984004
// number.
39994005
if ((*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')
4000-
&& buf_findsign_id(wp->w_buffer, lnum,
4001-
(char_u *)"*") != 0)
4002-
get_sign_display_info(TRUE, wp, lnum, wcr_attr, row,
4003-
startrow, filler_lines, filler_todo, &c_extra,
4004-
&c_final, extra, &p_extra, &n_extra,
4006+
&& sign_present)
4007+
get_sign_display_info(TRUE, wp, lnum, &sattr, wcr_attr,
4008+
row, startrow, filler_lines, filler_todo,
4009+
&c_extra, &c_final, extra, &p_extra, &n_extra,
40054010
&char_attr);
40064011
else
40074012
#endif

src/sign.c

Lines changed: 66 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,20 @@ insert_sign_by_lnum_prio(
273273
insert_sign(buf, prev, sign, id, group, prio, lnum, typenr);
274274
}
275275

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+
276290
/*
277291
* Get the name of a sign by its typenr.
278292
*/
@@ -445,31 +459,44 @@ buf_change_sign_type(
445459
}
446460

447461
/*
448-
* Return the type number of the sign at line number 'lnum' in buffer 'buf'
449-
* which has the attribute specified by 'type'. Returns 0 if a sign is not
450-
* found at the line number or it doesn't have the specified attribute.
462+
* Return the attributes of the first sign placed on line 'lnum' in buffer
463+
* 'buf'. Used when refreshing the screen. Returns TRUE if a sign is found on
464+
* 'lnum', FALSE otherwise.
451465
*/
452466
int
453-
buf_getsigntype(
454-
buf_T *buf,
455-
linenr_T lnum,
456-
int type) // SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL
467+
buf_get_signattrs(buf_T *buf, linenr_T lnum, sign_attrs_T *sattr)
457468
{
458-
signlist_T *sign; // a sign in a b_signlist
469+
signlist_T *sign;
470+
sign_T *sp;
471+
472+
vim_memset(sattr, 0, sizeof(sign_attrs_T));
459473

460474
FOR_ALL_SIGNS_IN_BUF(buf, sign)
461-
if (sign->lnum == lnum
462-
&& (type == SIGN_ANY
475+
{
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+
463488
# ifdef FEAT_SIGN_ICONS
464-
|| (type == SIGN_ICON
465-
&& sign_get_image(sign->typenr) != NULL)
489+
sattr->icon = sp->sn_image;
466490
# endif
467-
|| (type == SIGN_TEXT
468-
&& sign_get_text(sign->typenr) != NULL)
469-
|| (type == SIGN_LINEHL
470-
&& sign_get_attr(sign->typenr, TRUE) != 0)))
471-
return sign->typenr;
472-
return 0;
491+
sattr->text = sp->sn_text;
492+
if (sattr->text != NULL && sp->sn_text_hl > 0)
493+
sattr->texthl = syn_id2attr(sp->sn_text_hl);
494+
if (sp->sn_line_hl > 0)
495+
sattr->linehl = syn_id2attr(sp->sn_line_hl);
496+
return TRUE;
497+
}
498+
}
499+
return FALSE;
473500
}
474501

475502
/*
@@ -571,8 +598,15 @@ buf_getsign_at_line(
571598
signlist_T *sign; // a sign in the signlist
572599

573600
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+
574607
if (sign->lnum == lnum && sign_in_group(sign, groupname))
575608
return sign;
609+
}
576610

577611
return NULL;
578612
}
@@ -608,8 +642,15 @@ buf_findsigntype_id(
608642
signlist_T *sign; // a sign in the signlist
609643

610644
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+
611651
if (sign->lnum == lnum && sign->typenr == typenr)
612652
return sign->id;
653+
}
613654

614655
return 0;
615656
}
@@ -626,9 +667,16 @@ buf_signcount(buf_T *buf, linenr_T lnum)
626667
int count = 0;
627668

628669
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+
629676
if (sign->lnum == lnum)
630677
if (sign_get_image(sign->typenr) != NULL)
631678
count++;
679+
}
632680

633681
return count;
634682
}
@@ -1792,48 +1840,6 @@ sign_undefine(sign_T *sp, sign_T *sp_prev)
17921840
vim_free(sp);
17931841
}
17941842

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-
}
1836-
18371843
# if defined(FEAT_SIGN_ICONS) || defined(PROTO)
18381844
void *
18391845
sign_get_image(

src/structs.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,17 @@ struct signlist
759759
signlist_T *prev; // previous entry -- for easy reordering
760760
};
761761

762+
/*
763+
* Sign attributes. Used by the screen refresh routines.
764+
*/
765+
typedef struct sign_attrs_S {
766+
int typenr;
767+
void *icon;
768+
char_u *text;
769+
int texthl;
770+
int linehl;
771+
} sign_attrs_T;
772+
762773
#if defined(FEAT_SIGNS) || defined(PROTO)
763774
// Macros to get the sign group structure from the group name
764775
#define SGN_KEY_OFF offsetof(signgroup_T, sg_name)
@@ -767,11 +778,6 @@ struct signlist
767778
// Default sign priority for highlighting
768779
#define SIGN_DEF_PRIO 10
769780

770-
/* type argument for buf_getsigntype() */
771-
#define SIGN_ANY 0
772-
#define SIGN_LINEHL 1
773-
#define SIGN_ICON 2
774-
#define SIGN_TEXT 3
775781
#endif
776782

777783
/*

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,8 @@ static char *(features[]) =
777777

778778
static int included_patches[] =
779779
{ /* Add new patch number below this line */
780+
/**/
781+
1631,
780782
/**/
781783
1630,
782784
/**/

0 commit comments

Comments
 (0)