mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
signs: fix crash in buf_addsign #10091
buf_signcols sorting breaks signlist structure. Remove sorting in buf_signcols, because signlist is already kept sorted and it did not correctly update the double linked list. Fixes #10078
This commit is contained in:
parent
ef33500e17
commit
95ece7d046
@ -5256,92 +5256,28 @@ bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sign_compare(const void *a1, const void *a2)
|
|
||||||
{
|
|
||||||
const signlist_T *s1 = *(const signlist_T **)a1;
|
|
||||||
const signlist_T *s2 = *(const signlist_T **)a2;
|
|
||||||
|
|
||||||
// Sort by line number, priority and id
|
|
||||||
|
|
||||||
if (s1->lnum > s2->lnum) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (s1->lnum < s2->lnum) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (s1->priority > s2->priority) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (s1->priority < s2->priority) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (s1->id > s2->id) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (s1->id < s2->id) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int buf_signcols(buf_T *buf)
|
int buf_signcols(buf_T *buf)
|
||||||
{
|
{
|
||||||
if (buf->b_signcols_max == -1) {
|
if (buf->b_signcols_max == -1) {
|
||||||
signlist_T *sign; // a sign in the signlist
|
signlist_T *sign; // a sign in the signlist
|
||||||
signlist_T **signs_array;
|
|
||||||
signlist_T **prev_sign;
|
|
||||||
int nr_signs = 0, i = 0, same;
|
|
||||||
|
|
||||||
// Count the number of signs
|
|
||||||
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
|
||||||
nr_signs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an array of all the signs
|
|
||||||
signs_array = xcalloc((size_t)nr_signs, sizeof(*sign));
|
|
||||||
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
|
||||||
signs_array[i] = sign;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the array
|
|
||||||
qsort(signs_array, (size_t)nr_signs, sizeof(signlist_T *),
|
|
||||||
sign_compare);
|
|
||||||
|
|
||||||
// Find the maximum amount of signs existing in a single line
|
|
||||||
buf->b_signcols_max = 0;
|
buf->b_signcols_max = 0;
|
||||||
|
int linesum = 0;
|
||||||
|
linenr_T curline = 0;
|
||||||
|
|
||||||
same = 1;
|
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
|
||||||
for (i = 1; i < nr_signs; i++) {
|
if (sign->lnum > curline) {
|
||||||
if (signs_array[i - 1]->lnum != signs_array[i]->lnum) {
|
if (linesum > buf->b_signcols_max) {
|
||||||
if (buf->b_signcols_max < same) {
|
buf->b_signcols_max = linesum;
|
||||||
buf->b_signcols_max = same;
|
|
||||||
}
|
|
||||||
same = 1;
|
|
||||||
} else {
|
|
||||||
same++;
|
|
||||||
}
|
}
|
||||||
|
curline = sign->lnum;
|
||||||
|
linesum = 0;
|
||||||
|
}
|
||||||
|
linesum++;
|
||||||
}
|
}
|
||||||
|
if (linesum > buf->b_signcols_max) {
|
||||||
if (nr_signs > 0 && buf->b_signcols_max < same) {
|
buf->b_signcols_max = linesum;
|
||||||
buf->b_signcols_max = same;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recreate the linked list with the sorted order of the array
|
|
||||||
buf->b_signlist = NULL;
|
|
||||||
prev_sign = &buf->b_signlist;
|
|
||||||
|
|
||||||
for (i = 0; i < nr_signs; i++) {
|
|
||||||
sign = signs_array[i];
|
|
||||||
sign->next = NULL;
|
|
||||||
*prev_sign = sign;
|
|
||||||
|
|
||||||
prev_sign = &sign->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree(signs_array);
|
|
||||||
|
|
||||||
// Check if we need to redraw
|
// Check if we need to redraw
|
||||||
if (buf->b_signcols_max != buf->b_signcols) {
|
if (buf->b_signcols_max != buf->b_signcols) {
|
||||||
buf->b_signcols = buf->b_signcols_max;
|
buf->b_signcols = buf->b_signcols_max;
|
||||||
|
@ -231,9 +231,11 @@ static void insert_sign_by_lnum_prio(
|
|||||||
{
|
{
|
||||||
signlist_T *sign;
|
signlist_T *sign;
|
||||||
|
|
||||||
// keep signs sorted by lnum and by priority: insert new sign at
|
// keep signs sorted by lnum, priority and id: insert new sign at
|
||||||
// the proper position in the list for this lnum.
|
// the proper position in the list for this lnum.
|
||||||
while (prev != NULL && prev->lnum == lnum && prev->priority <= prio) {
|
while (prev != NULL && prev->lnum == lnum
|
||||||
|
&& (prev->priority < prio
|
||||||
|
|| (prev->priority == prio && prev->id <= id))) {
|
||||||
prev = prev->prev;
|
prev = prev->prev;
|
||||||
}
|
}
|
||||||
if (prev == NULL) {
|
if (prev == NULL) {
|
||||||
|
Loading…
Reference in New Issue
Block a user