diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-06-07 21:37:13 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-06-07 21:37:13 +0200 |
commit | 64416127fc184b5544530afe818722679158f059 (patch) | |
tree | 1e40693c42ae723795302899e98b4c8b2314c808 /src/sign.c | |
parent | 150f0550f45b836200a189e4d34417f4d3467455 (diff) | |
download | vim-git-64416127fc184b5544530afe818722679158f059.tar.gz |
patch 8.1.1489: sign order wrong when priority was changedv8.1.1489
Problem: Sign order wrong when priority was changed.
Solution: Reorder signs when priority is changed. (Yegappan Lakshmanan,
closes #4502)
Diffstat (limited to 'src/sign.c')
-rw-r--r-- | src/sign.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/sign.c b/src/sign.c index 8f1de4af1..e8288d628 100644 --- a/src/sign.c +++ b/src/sign.c @@ -308,6 +308,78 @@ sign_get_info(signlist_T *sign) } /* + * Sort the signs placed on the same line as "sign" by priority. Invoked after + * changing the priority of an already placed sign. Assumes the signs in the + * buffer are sorted by line number and priority. + */ + static void +sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign) +{ + signlist_T *p = NULL; + + // If there is only one sign in the buffer or only one sign on the line or + // the sign is already sorted by priority, then return. + if ((sign->prev == NULL + || sign->prev->lnum != sign->lnum + || sign->prev->priority > sign->priority) + && (sign->next == NULL + || sign->next->lnum != sign->lnum + || sign->next->priority < sign->priority)) + return; + + // One or more signs on the same line as 'sign' + // Find a sign after which 'sign' should be inserted + + // First search backward for a sign with higher priority on the same line + p = sign; + while (p->prev != NULL && p->prev->lnum == sign->lnum + && p->prev->priority <= sign->priority) + p = p->prev; + + if (p == sign) + { + // Sign not found. Search forward for a sign with priority just before + // 'sign'. + p = sign->next; + while (p->next != NULL && p->next->lnum == sign->lnum + && p->next->priority > sign->priority) + p = p->next; + } + + // Remove 'sign' from the list + if (buf->b_signlist == sign) + buf->b_signlist = sign->next; + if (sign->prev != NULL) + sign->prev->next = sign->next; + if (sign->next != NULL) + sign->next->prev = sign->prev; + sign->prev = NULL; + sign->next = NULL; + + // Re-insert 'sign' at the right place + if (p->priority <= sign->priority) + { + // 'sign' has a higher priority and should be inserted before 'p' + sign->prev = p->prev; + sign->next = p; + p->prev = sign; + if (sign->prev != NULL) + sign->prev->next = sign; + if (buf->b_signlist == p) + buf->b_signlist = sign; + } + else + { + // 'sign' has a lower priority and should be inserted after 'p' + sign->prev = p; + sign->next = p->next; + p->next = sign; + if (sign->next != NULL) + sign->next->prev = sign; + } +} + +/* * Add the sign into the signlist. Find the right spot to do it though. */ static void @@ -331,6 +403,7 @@ buf_addsign( // Update an existing sign sign->typenr = typenr; sign->priority = prio; + sign_sort_by_prio_on_line(buf, sign); return; } else if (lnum < sign->lnum) |