diff options
author | Andrej Zieger <jerdna-regeiz@users.noreply.github.com> | 2019-05-18 15:35:33 +0200 |
---|---|---|
committer | Andrej Zieger <jerdna-regeiz@users.noreply.github.com> | 2019-05-26 19:32:32 +0200 |
commit | 83025f0028ee5b1b6e09340fa419999643e3f8f6 (patch) | |
tree | ff997a47d6fd08c468b6a384918724c5ffcdb567 /src/nvim/buffer.c | |
parent | ce021baea069df6aae89e0225834b1be7b26c989 (diff) | |
download | rneovim-83025f0028ee5b1b6e09340fa419999643e3f8f6.tar.gz rneovim-83025f0028ee5b1b6e09340fa419999643e3f8f6.tar.bz2 rneovim-83025f0028ee5b1b6e09340fa419999643e3f8f6.zip |
vim-patch:8.1.0673: functionality for signs is spread out over several files
Problem: Functionality for signs is spread out over several files.
Solution: Move most of the sign functionality into sign.c. (Yegappan
Lakshmanan, closes vim/vim#3751)
https://github.com/vim/vim/commit/bbea47075cc4e7826e9f8c203e4272ba023ed7b0
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 618 |
1 files changed, 0 insertions, 618 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 9ccbfa4dd1..1f4a1e0cd1 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -5256,172 +5256,6 @@ bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp) return false; } -static hashtab_T sg_table; // sign group (signgroup_T) hashtable -static int next_sign_id = 1; // next sign id in the global group - -/* - * Initialize data needed for managing signs - */ - void -init_signs(void) -{ - hash_init(&sg_table); // sign group hash table -} - -/* - * A new sign in group 'groupname' is added. If the group is not present, - * create it. Otherwise reference the group. - */ -static signgroup_T * sign_group_ref(char_u *groupname) -{ - hash_T hash; - hashitem_T *hi; - signgroup_T *group; - - hash = hash_hash(groupname); - hi = hash_lookup(&sg_table, S_LEN(groupname), hash); - if (HASHITEM_EMPTY(hi)) - { - // new group - group = (signgroup_T *)xmalloc( - (unsigned)(sizeof(signgroup_T) + STRLEN(groupname))); - if (group == NULL) - return NULL; - STRCPY(group->sg_name, groupname); - group->refcount = 1; - group->next_sign_id = 1; - hash_add_item(&sg_table, hi, group->sg_name, hash); - } - else - { - // existing group - group = HI2SG(hi); - group->refcount++; - } - - return group; -} - -/* - * A sign in group 'groupname' is removed. If all the signs in this group are - * removed, then remove the group. - */ -static void sign_group_unref(char_u *groupname) -{ - hashitem_T *hi; - signgroup_T *group; - - hi = hash_find(&sg_table, groupname); - if (!HASHITEM_EMPTY(hi)) - { - group = HI2SG(hi); - group->refcount--; - if (group->refcount == 0) - { - // All the signs in this group are removed - hash_remove(&sg_table, hi); - xfree(group); - } - } -} - -/* - * Get the next free sign identifier in the specified group - */ - int -sign_group_get_next_signid(buf_T *buf, char_u *groupname) -{ - int id = 1; - signgroup_T *group = NULL; - signlist_T *sign; - hashitem_T *hi; - int found = FALSE; - - if (groupname != NULL) - { - hi = hash_find(&sg_table, groupname); - if (HASHITEM_EMPTY(hi)) - return id; - group = HI2SG(hi); - } - - // Search for the next usuable sign identifier - while (!found) - { - if (group == NULL) - id = next_sign_id++; // global group - else - id = group->next_sign_id++; - - // Check whether this sign is already placed in the buffer - found = TRUE; - FOR_ALL_SIGNS_IN_BUF(buf, sign) - { - if (id == sign->id && sign_in_group(sign, groupname)) - { - found = FALSE; // sign identifier is in use - break; - } - } - } - - return id; -} - -/* - * Insert a new sign into the signlist for buffer 'buf' between the 'prev' and - * 'next' signs. - */ -static void insert_sign( - buf_T *buf, // buffer to store sign in - signlist_T *prev, // previous sign entry - signlist_T *next, // next sign entry - int id, // sign ID - char_u *group, // sign group; NULL for global group - int prio, // sign priority - linenr_T lnum, // line number which gets the mark - int typenr // typenr of sign we are adding -) -{ - signlist_T *newsign = xmalloc(sizeof(signlist_T)); - newsign->id = id; - newsign->lnum = lnum; - newsign->typenr = typenr; - if (group != NULL) - { - newsign->group = sign_group_ref(group); - if (newsign->group == NULL) - { - xfree(newsign); - return; - } - } - else - newsign->group = NULL; - newsign->priority = prio; - newsign->next = next; - newsign->prev = prev; - if (next != NULL) { - next->prev = newsign; - } - buf->b_signcols_max = -1; - - if (prev == NULL) { - // When adding first sign need to redraw the windows to create the - // column for signs. - if (buf->b_signlist == NULL) { - redraw_buf_later(buf, NOT_VALID); - changed_cline_bef_curs(); - } - - // first sign in signlist - buf->b_signlist = newsign; - } - else { - prev->next = newsign; - } -} - static int sign_compare(const void *a1, const void *a2) { const signlist_T *s1 = *(const signlist_T **)a1; @@ -5512,458 +5346,6 @@ int buf_signcols(buf_T *buf) return buf->b_signcols; } -/* - * Insert a new sign sorted by line number and sign priority. - */ -static void insert_sign_by_lnum_prio( - buf_T *buf, // buffer to store sign in - signlist_T *prev, // previous sign entry - int id, // sign ID - char_u *group, // sign group; NULL for global group - int prio, // sign priority - linenr_T lnum, // line number which gets the mark - int typenr // typenr of sign we are adding -) -{ - signlist_T *sign; - - // keep signs sorted by lnum and by priority: insert new sign at - // the proper position in the list for this lnum. - while (prev != NULL && prev->lnum == lnum && prev->priority <= prio) { - prev = prev->prev; - } - if (prev == NULL) { - sign = buf->b_signlist; - } else { - sign = prev->next; - } - - insert_sign(buf, prev, sign, id, group, prio, lnum, typenr); -} - -/* - * Returns TRUE if 'sign' is in 'group'. - * A sign can either be in the global group (sign->group == NULL) - * or in a named group. If 'group' is '*', then the sign is part of the group. - */ -int sign_in_group(signlist_T *sign, char_u *group) -{ - return ((group != NULL && STRCMP(group, "*") == 0) - || (group == NULL && sign->group == NULL) - || (group != NULL && sign->group != NULL - && STRCMP(group, sign->group->sg_name) == 0)); -} - -/* - * Return information about a sign in a Dict - */ -dict_T * sign_get_info(signlist_T *sign) -{ - dict_T *d; - - if ((d = tv_dict_alloc()) == NULL) { - return NULL; - } - tv_dict_add_nr(d, S_LEN("id"), sign->id); - tv_dict_add_str(d, S_LEN("group"), (sign->group == NULL) ? (char_u *)"" : sign->group->sg_name); - tv_dict_add_nr(d, S_LEN("lnum"), sign->lnum); - tv_dict_add_str(d, S_LEN("name"), sign_typenr2name(sign->typenr)); - tv_dict_add_nr(d, S_LEN("priority"), sign->priority); - - return d; -} - -/* - * Add the sign into the signlist. Find the right spot to do it though. - */ -void buf_addsign( - buf_T *buf, // buffer to store sign in - int id, // sign ID - char_u *groupname, // sign group - int prio, // sign priority - linenr_T lnum, // line number which gets the mark - int typenr // typenr of sign we are adding -) -{ - signlist_T **lastp; // pointer to pointer to current sign - signlist_T *sign; // a sign in the signlist - signlist_T *prev; // the previous sign - - prev = NULL; - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (lnum == sign->lnum && id == sign->id && - sign_in_group(sign, groupname)) { - // Update an existing sign - sign->typenr = typenr; - return; - } else if ((lnum == sign->lnum && id != sign->id) - || (id < 0 && lnum < sign->lnum)) { - insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr); - return; - } - prev = sign; - } - - insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr); - - // Having more than one sign with _the same type_ and on the _same line_ is - // unwanted, let's prevent it. - - lastp = &buf->b_signlist; - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { - if (lnum == sign->lnum && sign->typenr == typenr && id != sign->id) { - *lastp = sign->next; - xfree(sign); - } else { - lastp = &sign->next; - } - } -} - -// For an existing, placed sign "markId" change the type to "typenr". -// Returns the line number of the sign, or zero if the sign is not found. -linenr_T buf_change_sign_type( - buf_T *buf, // buffer to store sign in - int markId, // sign ID - char_u *group, // sign group - int typenr // typenr of sign we are adding -) -{ - signlist_T *sign; // a sign in the signlist - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->id == markId && sign_in_group(sign, group)) { - sign->typenr = typenr; - return sign->lnum; - } - } - - return (linenr_T)0; -} - - -/// Gets a sign from a given line. -/// -/// @param buf Buffer in which to search -/// @param lnum Line in which to search -/// @param type Type of sign to look for -/// @param idx if there multiple signs, this index will pick the n-th -// out of the most `max_signs` sorted ascending by Id. -/// @param max_signs the number of signs, with priority for the ones -// with the highest Ids. -/// @return Identifier of the matching sign, or 0 -int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type, - int idx, int max_signs) -{ - signlist_T *sign; // a sign in a b_signlist - signlist_T *matches[9]; - int nr_matches = 0; - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->lnum == lnum - && (type == SIGN_ANY - || (type == SIGN_TEXT - && sign_get_text(sign->typenr) != NULL) - || (type == SIGN_LINEHL - && sign_get_attr(sign->typenr, SIGN_LINEHL) != 0) - || (type == SIGN_NUMHL - && sign_get_attr(sign->typenr, SIGN_NUMHL) != 0))) { - matches[nr_matches] = sign; - nr_matches++; - - if (nr_matches == ARRAY_SIZE(matches)) { - break; - } - } - } - - if (nr_matches > 0) { - if (nr_matches > max_signs) { - idx += nr_matches - max_signs; - } - - if (idx >= nr_matches) { - return 0; - } - - return matches[idx]->typenr; - } - - return 0; -} - -/* - * Delete sign 'id' in group 'group' from buffer 'buf'. - * If 'id' is zero, then delete all the signs in group 'group'. Otherwise - * delete only the specified sign. - * If 'group' is '*', then delete the sign in all the groups. If 'group' is - * NULL, then delete the sign in the global group. Otherwise delete the sign in - * the specified group. - * Returns the line number of the deleted sign. If multiple signs are deleted, - * then returns the line number of the last sign deleted. - */ -linenr_T buf_delsign( - buf_T *buf, // buffer sign is stored in - linenr_T atlnum, // sign at this line, 0 - at any line - int id, // sign id - char_u *group// sign group - ) -{ - signlist_T **lastp; // pointer to pointer to current sign - signlist_T *sign; // a sign in a b_signlist - signlist_T *next; // the next sign in a b_signlist - linenr_T lnum; // line number whose sign was deleted - - buf->b_signcols_max = -1; - lastp = &buf->b_signlist; - lnum = 0; - for (sign = buf->b_signlist; sign != NULL; sign = next) { - next = sign->next; - if ((id == 0 || sign->id == id) && - (atlnum == 0 || sign->lnum == atlnum) && - sign_in_group(sign, group)) { - *lastp = next; - if (next != NULL) { - next->prev = sign->prev; - } - lnum = sign->lnum; - if (sign->group != NULL) - sign_group_unref(sign->group->sg_name); - xfree(sign); - redraw_buf_line_later(buf, lnum); - // Check whether only one sign needs to be deleted - // If deleting a sign with a specific identifer in a particular - // group or deleting any sign at a particular line number, delete - // only one sign. - if (group == NULL - || (*group != '*' && id != 0) - || (*group == '*' && atlnum != 0)) { - break; - } - } else { - lastp = &sign->next; - } - } - - /* When deleted the last sign needs to redraw the windows to remove the - * sign column. */ - if (buf->b_signlist == NULL) { - redraw_buf_later(buf, NOT_VALID); - changed_cline_bef_curs(); - } - - return lnum; -} - - -/* - * Find the line number of the sign with the requested id in group 'group'. If - * the sign does not exist, return 0 as the line number. This will still let - * the correct file get loaded. - */ -int buf_findsign( - buf_T *buf, // buffer to store sign in - int id, // sign ID - char_u *group // sign group -) -{ - signlist_T *sign; // a sign in the signlist - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->id == id && sign_in_group(sign, group)){ - return (int)sign->lnum; - } - } - - return 0; -} - -/* - * Return the sign at line 'lnum' in buffer 'buf'. Returns NULL if a sign is - * not found at the line. If 'groupname' is NULL, searches in the global group. - */ -static signlist_T * buf_getsign_at_line( - buf_T *buf, // buffer whose sign we are searching for - linenr_T lnum, // line number of sign - char_u *groupname // sign group name -) -{ - signlist_T *sign; // a sign in the signlist - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->lnum == lnum && sign_in_group(sign, groupname)) { - return sign; - } - } - - return NULL; -} - -/* - * Return the sign with identifier 'id' in group 'group' placed in buffer 'buf' - */ -signlist_T *buf_getsign_with_id( - buf_T *buf, // buffer whose sign we are searching for - int id, // sign identifier - char_u *group// sign group -) -{ - signlist_T *sign; // a sign in the signlist - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->id == id && sign_in_group(sign, group)) { - return sign; - } - } - - return NULL; -} - -/* - * Return the identifier of the sign at line number 'lnum' in buffer 'buf'. - */ -int buf_findsign_id( - buf_T *buf, // buffer whose sign we are searching for - linenr_T lnum, // line number of sign - char_u *groupname // sign group name -) -{ - signlist_T *sign; // a sign in the signlist - - sign = buf_getsign_at_line(buf, lnum, groupname); - if (sign != NULL) { - return sign->id; - } - - return 0; -} - - -/* - * Delete signs in buffer "buf". - */ -void buf_delete_signs(buf_T *buf, char_u *group) -{ - signlist_T *sign; - signlist_T **lastp; // pointer to pointer to current sign - signlist_T *next; - - // When deleting the last sign need to redraw the windows to remove the - // sign column. Not when curwin is NULL (this means we're exiting). - if (buf->b_signlist != NULL && curwin != NULL){ - redraw_buf_later(buf, NOT_VALID); - changed_cline_bef_curs(); - } - - lastp = &buf->b_signlist; - for (sign = buf->b_signlist; sign != NULL; sign = next) { - next = sign->next; - if (sign_in_group(sign, group)) { - *lastp = next; - if (next != NULL) { - next->prev = sign->prev; - } - if (sign->group != NULL) { - sign_group_unref(sign->group->sg_name); - } - xfree(sign); - } else { - lastp = &sign->next; - } - } - buf->b_signcols_max = -1; -} - -/* - * Delete all signs in all buffers. - */ -void buf_delete_all_signs(char_u *groupname) -{ - FOR_ALL_BUFFERS(buf) { - if (buf->b_signlist != NULL) { - buf_delete_signs(buf, groupname); - } - } -} - -/* - * List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers. - */ -void sign_list_placed(buf_T *rbuf, char_u *sign_group) -{ - buf_T *buf; - signlist_T *sign; - char lbuf[BUFSIZ]; - char group[BUFSIZ]; - - MSG_PUTS_TITLE(_("\n--- Signs ---")); - msg_putchar('\n'); - if (rbuf == NULL) { - buf = firstbuf; - } else { - buf = rbuf; - } - while (buf != NULL && !got_int) { - if (buf->b_signlist != NULL) { - vim_snprintf(lbuf, BUFSIZ, _("Signs for %s:"), buf->b_fname); - MSG_PUTS_ATTR(lbuf, HL_ATTR(HLF_D)); - msg_putchar('\n'); - } - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (got_int) { - break; - } - if (!sign_in_group(sign, sign_group)) { - continue; - } - if (sign->group != NULL) { - vim_snprintf(group, BUFSIZ, " group=%s", sign->group->sg_name); - } else { - group[0] = '\0'; - } - vim_snprintf(lbuf, BUFSIZ, _(" line=%ld id=%d%s name=%s " - "priority=%d"), - (long)sign->lnum, sign->id, group, - sign_typenr2name(sign->typenr), sign->priority); - MSG_PUTS(lbuf); - msg_putchar('\n'); - } - if (rbuf != NULL) { - break; - } - buf = buf->b_next; - } -} - -/* - * Adjust a placed sign for inserted/deleted lines. - */ -void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) -{ - signlist_T *sign; // a sign in a b_signlist - signlist_T *next; // the next sign in a b_signlist - signlist_T **lastp; // pointer to pointer to current sign - - curbuf->b_signcols_max = -1; - lastp = &curbuf->b_signlist; - - FOR_ALL_SIGNS_IN_BUF(curbuf, sign) { - next = sign->next; - if (sign->lnum >= line1 && sign->lnum <= line2) { - if (amount == MAXLNUM) { - *lastp = next; - xfree(sign); - continue; - } else { - sign->lnum += amount; - } - } else if (sign->lnum > line2) { - sign->lnum += amount_after; - } - lastp = &sign->next; - } -} - // bufhl: plugin highlights associated with a buffer /// Get reference to line in kbtree_t |