diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-01-01 13:20:31 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-01-01 13:20:31 +0100 |
commit | bbea47075cc4e7826e9f8c203e4272ba023ed7b0 (patch) | |
tree | fbdec3eeea4ca32ada2f309d8c0155087775cfb5 /src/buffer.c | |
parent | 9067cd6cdfdc0bb869aa7f5d2a6c607ea8255239 (diff) |
patch 8.1.0673: functionality for signs is spread out over several filesv8.1.0673
Problem: Functionality for signs is spread out over several files.
Solution: Move most of the sign functionality into sign.c. (Yegappan
Lakshmanan, closes #3751)
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/src/buffer.c b/src/buffer.c index 07b89e3207..b3bd2aa56b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5864,642 +5864,6 @@ win_found: } #endif -#if defined(FEAT_SIGNS) || defined(PROTO) -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, groupname, hash); - if (HASHITEM_EMPTY(hi)) - { - // new group - group = (signgroup_T *)alloc( - (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); - vim_free(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; - - newsign = (signlist_T *)lalloc_id((long_u)sizeof(signlist_T), FALSE, - aid_insert_sign); - if (newsign != NULL) - { - newsign->id = id; - newsign->lnum = lnum; - newsign->typenr = typenr; - if (group != NULL) - { - newsign->group = sign_group_ref(group); - if (newsign->group == NULL) - { - vim_free(newsign); - return; - } - } - else - newsign->group = NULL; - newsign->priority = prio; - newsign->next = next; - newsign->prev = prev; - if (next != NULL) - next->prev = newsign; - - 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; -#ifdef FEAT_NETBEANS_INTG - if (netbeans_active()) - buf->b_has_sign_column = TRUE; -#endif - } - else - prev->next = newsign; - } -} - -/* - * 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 = dict_alloc_id(aid_sign_getinfo)) == NULL) - return NULL; - dict_add_number(d, "id", sign->id); - dict_add_string(d, "group", (sign->group == NULL) ? - (char_u *)"" : sign->group->sg_name); - dict_add_number(d, "lnum", sign->lnum); - dict_add_string(d, "name", sign_typenr2name(sign->typenr)); - dict_add_number(d, "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 *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) - { - 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); - return; -} - -/* - * 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; -} - -/* - * Return the type number of the sign at line number 'lnum' in buffer 'buf' - * which has the attribute specifed by 'type'. Returns 0 if a sign is not found - * at the line number or it doesn't have the specified attribute. - */ - int -buf_getsigntype( - buf_T *buf, - linenr_T lnum, - int type) /* SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL */ -{ - signlist_T *sign; /* a sign in a b_signlist */ - - FOR_ALL_SIGNS_IN_BUF(buf, sign) - if (sign->lnum == lnum - && (type == SIGN_ANY -# ifdef FEAT_SIGN_ICONS - || (type == SIGN_ICON - && sign_get_image(sign->typenr) != NULL) -# endif - || (type == SIGN_TEXT - && sign_get_text(sign->typenr) != NULL) - || (type == SIGN_LINEHL - && sign_get_attr(sign->typenr, TRUE) != 0))) - return sign->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 - - 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); - vim_free(sign); - update_debug_sign(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 need 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 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; -} - -# if defined(FEAT_NETBEANS_INTG) || defined(PROTO) -/* - * See if a given type of sign exists on a specific line. - */ - int -buf_findsigntype_id( - buf_T *buf, /* buffer whose sign we are searching for */ - linenr_T lnum, /* line number of sign */ - int typenr) /* sign type number */ -{ - signlist_T *sign; /* a sign in the signlist */ - - FOR_ALL_SIGNS_IN_BUF(buf, sign) - if (sign->lnum == lnum && sign->typenr == typenr) - return sign->id; - - return 0; -} - - -# if defined(FEAT_SIGN_ICONS) || defined(PROTO) -/* - * Return the number of icons on the given line. - */ - int -buf_signcount(buf_T *buf, linenr_T lnum) -{ - signlist_T *sign; // a sign in the signlist - int count = 0; - - FOR_ALL_SIGNS_IN_BUF(buf, sign) - if (sign->lnum == lnum) - if (sign_get_image(sign->typenr) != NULL) - count++; - - return count; -} -# endif /* FEAT_SIGN_ICONS */ -# endif /* FEAT_NETBEANS_INTG */ - -/* - * Delete signs in group 'group' in buffer "buf". If 'group' is '*', then - * delete all the signs. - */ - 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); - vim_free(sign); - } - else - lastp = &sign->next; - } -} - -/* - * Delete all the signs in the specified group in all the buffers. - */ - void -buf_delete_all_signs(char_u *groupname) -{ - buf_T *buf; /* buffer we are checking for signs */ - - 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 */ - - FOR_ALL_SIGNS_IN_BUF(curbuf, sign) - { - if (sign->lnum >= line1 && sign->lnum <= line2) - { - if (amount == MAXLNUM) - sign->lnum = line1; - else - sign->lnum += amount; - } - else if (sign->lnum > line2) - sign->lnum += amount_after; - } -} -#endif /* FEAT_SIGNS */ - /* * Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed. */ |