diff options
author | Andrej Zieger <jerdna-regeiz@users.noreply.github.com> | 2019-06-01 12:03:59 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-06-01 12:03:59 +0200 |
commit | 95ece7d046ae3517c60e497be434db88d28891b3 (patch) | |
tree | 7a1db489c5bd35131aa25ff027fee74c4d7935ee /src/nvim/buffer.c | |
parent | ef33500e178e66880795eeaec21d5f6a530c52d5 (diff) | |
download | rneovim-95ece7d046ae3517c60e497be434db88d28891b3.tar.gz rneovim-95ece7d046ae3517c60e497be434db88d28891b3.tar.bz2 rneovim-95ece7d046ae3517c60e497be434db88d28891b3.zip |
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
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 88 |
1 files changed, 12 insertions, 76 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 078d4fe782..0c14656b33 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -5256,92 +5256,28 @@ bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp) 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) { if (buf->b_signcols_max == -1) { 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; + int linesum = 0; + linenr_T curline = 0; - same = 1; - for (i = 1; i < nr_signs; i++) { - if (signs_array[i - 1]->lnum != signs_array[i]->lnum) { - if (buf->b_signcols_max < same) { - buf->b_signcols_max = same; - } - same = 1; - } else { - same++; + FOR_ALL_SIGNS_IN_BUF(buf, sign) { + if (sign->lnum > curline) { + if (linesum > buf->b_signcols_max) { + buf->b_signcols_max = linesum; } + curline = sign->lnum; + linesum = 0; + } + linesum++; } - - if (nr_signs > 0 && buf->b_signcols_max < same) { - 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; + if (linesum > buf->b_signcols_max) { + buf->b_signcols_max = linesum; } - xfree(signs_array); - // Check if we need to redraw if (buf->b_signcols_max != buf->b_signcols) { buf->b_signcols = buf->b_signcols_max; |