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/ex_cmds.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/ex_cmds.c')
-rw-r--r-- | src/ex_cmds.c | 1246 |
1 files changed, 0 insertions, 1246 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 208f2b5766..52c0e5bedd 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -7579,1252 +7579,6 @@ ex_helptags(exarg_T *eap) } } -#if defined(FEAT_SIGNS) || defined(PROTO) - -/* - * Struct to hold the sign properties. - */ -typedef struct sign sign_T; - -struct sign -{ - sign_T *sn_next; /* next sign in list */ - int sn_typenr; /* type number of sign */ - char_u *sn_name; /* name of sign */ - char_u *sn_icon; /* name of pixmap */ -# ifdef FEAT_SIGN_ICONS - void *sn_image; /* icon image */ -# endif - char_u *sn_text; /* text used instead of pixmap */ - int sn_line_hl; /* highlight ID for line */ - int sn_text_hl; /* highlight ID for text */ -}; - -static sign_T *first_sign = NULL; -static int next_sign_typenr = 1; - -static void sign_list_defined(sign_T *sp); -static void sign_undefine(sign_T *sp, sign_T *sp_prev); - -static char *cmds[] = { - "define", -# define SIGNCMD_DEFINE 0 - "undefine", -# define SIGNCMD_UNDEFINE 1 - "list", -# define SIGNCMD_LIST 2 - "place", -# define SIGNCMD_PLACE 3 - "unplace", -# define SIGNCMD_UNPLACE 4 - "jump", -# define SIGNCMD_JUMP 5 - NULL -# define SIGNCMD_LAST 6 -}; - -/* - * Find index of a ":sign" subcmd from its name. - * "*end_cmd" must be writable. - */ - static int -sign_cmd_idx( - char_u *begin_cmd, /* begin of sign subcmd */ - char_u *end_cmd) /* just after sign subcmd */ -{ - int idx; - char save = *end_cmd; - - *end_cmd = NUL; - for (idx = 0; ; ++idx) - if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) - break; - *end_cmd = save; - return idx; -} - -/* - * Find a sign by name. Also returns pointer to the previous sign. - */ - static sign_T * -sign_find(char_u *name, sign_T **sp_prev) -{ - sign_T *sp; - - if (sp_prev != NULL) - *sp_prev = NULL; - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - { - if (STRCMP(sp->sn_name, name) == 0) - break; - if (sp_prev != NULL) - *sp_prev = sp; - } - - return sp; -} - -/* - * Define a new sign or update an existing sign - */ - int -sign_define_by_name( - char_u *name, - char_u *icon, - char_u *linehl, - char_u *text, - char_u *texthl) -{ - sign_T *sp_prev; - sign_T *sp; - - sp = sign_find(name, &sp_prev); - if (sp == NULL) - { - sign_T *lp; - int start = next_sign_typenr; - - // Allocate a new sign. - sp = (sign_T *)alloc_clear_id((unsigned)sizeof(sign_T), - aid_sign_define_by_name); - if (sp == NULL) - return FAIL; - - // Check that next_sign_typenr is not already being used. - // This only happens after wrapping around. Hopefully - // another one got deleted and we can use its number. - for (lp = first_sign; lp != NULL; ) - { - if (lp->sn_typenr == next_sign_typenr) - { - ++next_sign_typenr; - if (next_sign_typenr == MAX_TYPENR) - next_sign_typenr = 1; - if (next_sign_typenr == start) - { - vim_free(sp); - EMSG(_("E612: Too many signs defined")); - return FAIL; - } - lp = first_sign; // start all over - continue; - } - lp = lp->sn_next; - } - - sp->sn_typenr = next_sign_typenr; - if (++next_sign_typenr == MAX_TYPENR) - next_sign_typenr = 1; // wrap around - - sp->sn_name = vim_strsave(name); - if (sp->sn_name == NULL) // out of memory - { - vim_free(sp); - return FAIL; - } - - // add the new sign to the list of signs - if (sp_prev == NULL) - first_sign = sp; - else - sp_prev->sn_next = sp; - } - - // set values for a defined sign. - if (icon != NULL) - { - vim_free(sp->sn_icon); - sp->sn_icon = vim_strsave(icon); - backslash_halve(sp->sn_icon); -# ifdef FEAT_SIGN_ICONS - if (gui.in_use) - { - out_flush(); - if (sp->sn_image != NULL) - gui_mch_destroy_sign(sp->sn_image); - sp->sn_image = gui_mch_register_sign(sp->sn_icon); - } -# endif - } - - if (text != NULL) - { - char_u *s; - char_u *endp; - int cells; - int len; - - endp = text + (int)STRLEN(text); - for (s = text; s + 1 < endp; ++s) - if (*s == '\\') - { - // Remove a backslash, so that it is possible - // to use a space. - STRMOVE(s, s + 1); - --endp; - } -# ifdef FEAT_MBYTE - // Count cells and check for non-printable chars - if (has_mbyte) - { - cells = 0; - for (s = text; s < endp; s += (*mb_ptr2len)(s)) - { - if (!vim_isprintc((*mb_ptr2char)(s))) - break; - cells += (*mb_ptr2cells)(s); - } - } - else -# endif - { - for (s = text; s < endp; ++s) - if (!vim_isprintc(*s)) - break; - cells = (int)(s - text); - } - // Currently must be one or two display cells - if (s != endp || cells < 1 || cells > 2) - { - EMSG2(_("E239: Invalid sign text: %s"), text); - return FAIL; - } - - vim_free(sp->sn_text); - // Allocate one byte more if we need to pad up - // with a space. - len = (int)(endp - text + ((cells == 1) ? 1 : 0)); - sp->sn_text = vim_strnsave(text, len); - - if (sp->sn_text != NULL && cells == 1) - STRCPY(sp->sn_text + len - 1, " "); - } - - if (linehl != NULL) - sp->sn_line_hl = syn_check_group(linehl, (int)STRLEN(linehl)); - - if (texthl != NULL) - sp->sn_text_hl = syn_check_group(texthl, (int)STRLEN(texthl)); - - return OK; -} - -/* - * Free the sign specified by 'name'. - */ - int -sign_undefine_by_name(char_u *name) -{ - sign_T *sp_prev; - sign_T *sp; - - sp = sign_find(name, &sp_prev); - if (sp == NULL) - { - EMSG2(_("E155: Unknown sign: %s"), name); - return FAIL; - } - sign_undefine(sp, sp_prev); - - return OK; -} - -/* - * List the signs matching 'name' - */ - static void -sign_list_by_name(char_u *name) -{ - sign_T *sp; - - sp = sign_find(name, NULL); - if (sp != NULL) - sign_list_defined(sp); - else - EMSG2(_("E155: Unknown sign: %s"), name); -} - -/* - * Place a sign at the specifed file location or update a sign. - */ - int -sign_place( - int *sign_id, - char_u *sign_group, - char_u *sign_name, - buf_T *buf, - linenr_T lnum, - int prio) -{ - sign_T *sp; - - // Check for reserved character '*' in group name - if (sign_group != NULL && (*sign_group == '*' || *sign_group == '\0')) - return FAIL; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (STRCMP(sp->sn_name, sign_name) == 0) - break; - if (sp == NULL) - { - EMSG2(_("E155: Unknown sign: %s"), sign_name); - return FAIL; - } - if (*sign_id == 0) - *sign_id = sign_group_get_next_signid(buf, sign_group); - - if (lnum > 0) - // ":sign place {id} line={lnum} name={name} file={fname}": - // place a sign - buf_addsign(buf, *sign_id, sign_group, prio, lnum, sp->sn_typenr); - else - // ":sign place {id} file={fname}": change sign type - lnum = buf_change_sign_type(buf, *sign_id, sign_group, sp->sn_typenr); - if (lnum > 0) - update_debug_sign(buf, lnum); - else - { - EMSG2(_("E885: Not possible to change sign %s"), sign_name); - return FAIL; - } - - return OK; -} - -/* - * Unplace the specified sign - */ - int -sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum) -{ - if (buf->b_signlist == NULL) // No signs in the buffer - return OK; - - if (sign_id == 0) - { - // Delete all the signs in the specified buffer - redraw_buf_later(buf, NOT_VALID); - buf_delete_signs(buf, sign_group); - } - else - { - linenr_T lnum; - - // Delete only the specified signs - lnum = buf_delsign(buf, atlnum, sign_id, sign_group); - if (lnum == 0) - return FAIL; - } - - return OK; -} - -/* - * Unplace the sign at the current cursor line. - */ - static void -sign_unplace_at_cursor(char_u *groupname) -{ - int id = -1; - - id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum, groupname); - if (id > 0) - sign_unplace(id, groupname, curwin->w_buffer, curwin->w_cursor.lnum); - else - EMSG(_("E159: Missing sign number")); -} - -/* - * sign define command - * ":sign define {name} ..." - */ - static void -sign_define_cmd(char_u *sign_name, char_u *cmdline) -{ - char_u *arg; - char_u *p = cmdline; - char_u *icon = NULL; - char_u *text = NULL; - char_u *linehl = NULL; - char_u *texthl = NULL; - int failed = FALSE; - - // set values for a defined sign. - for (;;) - { - arg = skipwhite(p); - if (*arg == NUL) - break; - p = skiptowhite_esc(arg); - if (STRNCMP(arg, "icon=", 5) == 0) - { - arg += 5; - icon = vim_strnsave(arg, (int)(p - arg)); - } - else if (STRNCMP(arg, "text=", 5) == 0) - { - arg += 5; - text = vim_strnsave(arg, (int)(p - arg)); - } - else if (STRNCMP(arg, "linehl=", 7) == 0) - { - arg += 7; - linehl = vim_strnsave(arg, (int)(p - arg)); - } - else if (STRNCMP(arg, "texthl=", 7) == 0) - { - arg += 7; - texthl = vim_strnsave(arg, (int)(p - arg)); - } - else - { - EMSG2(_(e_invarg2), arg); - failed = TRUE; - break; - } - } - - if (!failed) - sign_define_by_name(sign_name, icon, linehl, text, texthl); - - vim_free(icon); - vim_free(text); - vim_free(linehl); - vim_free(texthl); -} - -/* - * :sign place command - */ - static void -sign_place_cmd( - buf_T *buf, - linenr_T lnum, - char_u *sign_name, - int id, - char_u *group, - int prio) -{ - if (id <= 0) - { - // List signs placed in a file/buffer - // :sign place file={fname} - // :sign place group={group} file={fname} - // :sign place group=* file={fname} - // :sign place buffer={nr} - // :sign place group={group} buffer={nr} - // :sign place group=* buffer={nr} - // :sign place - // :sign place group={group} - // :sign place group=* - if (lnum >= 0 || sign_name != NULL || - (group != NULL && *group == '\0')) - EMSG(_(e_invarg)); - else - sign_list_placed(buf, group); - } - else - { - // Place a new sign - if (sign_name == NULL || buf == NULL || - (group != NULL && *group == '\0')) - { - EMSG(_(e_invarg)); - return; - } - - sign_place(&id, group, sign_name, buf, lnum, prio); - } -} - -/* - * :sign unplace command - */ - static void -sign_unplace_cmd( - buf_T *buf, - linenr_T lnum, - char_u *sign_name, - int id, - char_u *group) -{ - if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) - { - EMSG(_(e_invarg)); - return; - } - - if (id == -2) - { - if (buf != NULL) - // :sign unplace * file={fname} - // :sign unplace * group={group} file={fname} - // :sign unplace * group=* file={fname} - // :sign unplace * buffer={nr} - // :sign unplace * group={group} buffer={nr} - // :sign unplace * group=* buffer={nr} - sign_unplace(0, group, buf, 0); - else - // :sign unplace * - // :sign unplace * group={group} - // :sign unplace * group=* - FOR_ALL_BUFFERS(buf) - if (buf->b_signlist != NULL) - buf_delete_signs(buf, group); - } - else - { - if (buf != NULL) - // :sign unplace {id} file={fname} - // :sign unplace {id} group={group} file={fname} - // :sign unplace {id} group=* file={fname} - // :sign unplace {id} buffer={nr} - // :sign unplace {id} group={group} buffer={nr} - // :sign unplace {id} group=* buffer={nr} - sign_unplace(id, group, buf, 0); - else - { - if (id == -1) - { - // :sign unplace group={group} - // :sign unplace group=* - sign_unplace_at_cursor(group); - } - else - { - // :sign unplace {id} - // :sign unplace {id} group={group} - // :sign unplace {id} group=* - FOR_ALL_BUFFERS(buf) - sign_unplace(id, group, buf, 0); - } - } - } -} - -/* - * Jump to a placed sign - * :sign jump {id} file={fname} - * :sign jump {id} buffer={nr} - * :sign jump {id} group={group} file={fname} - * :sign jump {id} group={group} buffer={nr} - */ - static void -sign_jump_cmd( - buf_T *buf, - linenr_T lnum, - char_u *sign_name, - int id, - char_u *group) -{ - if (buf == NULL && sign_name == NULL && group == NULL && id == -1) - { - EMSG(_(e_argreq)); - return; - } - - if (buf == NULL || (group != NULL && *group == '\0') || - lnum >= 0 || sign_name != NULL) - { - // File or buffer is not specified or an empty group is used - // or a line number or a sign name is specified. - EMSG(_(e_invarg)); - return; - } - - if ((lnum = buf_findsign(buf, id, group)) <= 0) - { - EMSGN(_("E157: Invalid sign ID: %ld"), id); - return; - } - - // goto a sign ... - if (buf_jump_open_win(buf) != NULL) - { // ... in a current window - curwin->w_cursor.lnum = lnum; - check_cursor_lnum(); - beginline(BL_WHITE); - } - else - { // ... not currently in a window - char_u *cmd; - - if (buf->b_fname == NULL) - { - EMSG(_("E934: Cannot jump to a buffer that does not have a name")); - return; - } - cmd = alloc((unsigned)STRLEN(buf->b_fname) + 25); - if (cmd == NULL) - return; - sprintf((char *)cmd, "e +%ld %s", (long)lnum, buf->b_fname); - do_cmdline_cmd(cmd); - vim_free(cmd); - } -# ifdef FEAT_FOLDING - foldOpenCursor(); -# endif -} - -/* - * Parse the command line arguments for the ":sign place", ":sign unplace" and - * ":sign jump" commands. - * The supported arguments are: line={lnum} name={name} group={group} - * priority={prio} and file={fname} or buffer={nr}. - */ - static int -parse_sign_cmd_args( - int cmd, - char_u *arg, - char_u **sign_name, - int *signid, - char_u **group, - int *prio, - buf_T **buf, - linenr_T *lnum) -{ - char_u *arg1; - char_u *name; - char_u *filename = NULL; - - // first arg could be placed sign id - arg1 = arg; - if (VIM_ISDIGIT(*arg)) - { - *signid = getdigits(&arg); - if (!VIM_ISWHITE(*arg) && *arg != NUL) - { - *signid = -1; - arg = arg1; - } - else - arg = skipwhite(arg); - } - - while (*arg != NUL) - { - if (STRNCMP(arg, "line=", 5) == 0) - { - arg += 5; - *lnum = atoi((char *)arg); - arg = skiptowhite(arg); - } - else if (STRNCMP(arg, "*", 1) == 0 && cmd == SIGNCMD_UNPLACE) - { - if (*signid != -1) - { - EMSG(_(e_invarg)); - return FAIL; - } - *signid = -2; - arg = skiptowhite(arg + 1); - } - else if (STRNCMP(arg, "name=", 5) == 0) - { - arg += 5; - name = arg; - arg = skiptowhite(arg); - if (*arg != NUL) - *arg++ = NUL; - while (name[0] == '0' && name[1] != NUL) - ++name; - *sign_name = name; - } - else if (STRNCMP(arg, "group=", 6) == 0) - { - arg += 6; - *group = arg; - arg = skiptowhite(arg); - if (*arg != NUL) - *arg++ = NUL; - } - else if (STRNCMP(arg, "priority=", 9) == 0) - { - arg += 9; - *prio = atoi((char *)arg); - arg = skiptowhite(arg); - } - else if (STRNCMP(arg, "file=", 5) == 0) - { - arg += 5; - filename = arg; - *buf = buflist_findname_exp(arg); - break; - } - else if (STRNCMP(arg, "buffer=", 7) == 0) - { - arg += 7; - filename = arg; - *buf = buflist_findnr((int)getdigits(&arg)); - if (*skipwhite(arg) != NUL) - EMSG(_(e_trailing)); - break; - } - else - { - EMSG(_(e_invarg)); - return FAIL; - } - arg = skipwhite(arg); - } - - if (filename != NULL && *buf == NULL) - { - EMSG2(_("E158: Invalid buffer name: %s"), filename); - return FAIL; - } - - return OK; -} - -/* - * ":sign" command - */ - void -ex_sign(exarg_T *eap) -{ - char_u *arg = eap->arg; - char_u *p; - int idx; - sign_T *sp; - buf_T *buf = NULL; - - // Parse the subcommand. - p = skiptowhite(arg); - idx = sign_cmd_idx(arg, p); - if (idx == SIGNCMD_LAST) - { - EMSG2(_("E160: Unknown sign command: %s"), arg); - return; - } - arg = skipwhite(p); - - if (idx <= SIGNCMD_LIST) - { - // Define, undefine or list signs. - if (idx == SIGNCMD_LIST && *arg == NUL) - { - // ":sign list": list all defined signs - for (sp = first_sign; sp != NULL && !got_int; sp = sp->sn_next) - sign_list_defined(sp); - } - else if (*arg == NUL) - EMSG(_("E156: Missing sign name")); - else - { - char_u *name; - - // Isolate the sign name. If it's a number skip leading zeroes, - // so that "099" and "99" are the same sign. But keep "0". - p = skiptowhite(arg); - if (*p != NUL) - *p++ = NUL; - while (arg[0] == '0' && arg[1] != NUL) - ++arg; - name = vim_strsave(arg); - - if (idx == SIGNCMD_DEFINE) - sign_define_cmd(name, p); - else if (idx == SIGNCMD_LIST) - // ":sign list {name}" - sign_list_by_name(name); - else - // ":sign undefine {name}" - sign_undefine_by_name(name); - - vim_free(name); - return; - } - } - else - { - int id = -1; - linenr_T lnum = -1; - char_u *sign_name = NULL; - char_u *group = NULL; - int prio = SIGN_DEF_PRIO; - - // Parse command line arguments - if (parse_sign_cmd_args(idx, arg, &sign_name, &id, &group, &prio, - &buf, &lnum) == FAIL) - return; - - if (idx == SIGNCMD_PLACE) - sign_place_cmd(buf, lnum, sign_name, id, group, prio); - else if (idx == SIGNCMD_UNPLACE) - sign_unplace_cmd(buf, lnum, sign_name, id, group); - else if (idx == SIGNCMD_JUMP) - sign_jump_cmd(buf, lnum, sign_name, id, group); - } -} - -/* - * Return information about a specified sign - */ - static void -sign_getinfo(sign_T *sp, dict_T *retdict) -{ - char_u *p; - - dict_add_string(retdict, "name", (char_u *)sp->sn_name); - if (sp->sn_icon != NULL) - dict_add_string(retdict, "icon", (char_u *)sp->sn_icon); - if (sp->sn_text != NULL) - dict_add_string(retdict, "text", (char_u *)sp->sn_text); - if (sp->sn_line_hl > 0) - { - p = get_highlight_name_ext(NULL, sp->sn_line_hl - 1, FALSE); - if (p == NULL) - p = (char_u *)"NONE"; - dict_add_string(retdict, "linehl", (char_u *)p); - } - if (sp->sn_text_hl > 0) - { - p = get_highlight_name_ext(NULL, sp->sn_text_hl - 1, FALSE); - if (p == NULL) - p = (char_u *)"NONE"; - dict_add_string(retdict, "texthl", (char_u *)p); - } -} - -/* - * If 'name' is NULL, return a list of all the defined signs. - * Otherwise, return information about the specified sign. - */ - void -sign_getlist(char_u *name, list_T *retlist) -{ - sign_T *sp = first_sign; - dict_T *dict; - - if (name != NULL) - { - sp = sign_find(name, NULL); - if (sp == NULL) - return; - } - - for (; sp != NULL && !got_int; sp = sp->sn_next) - { - if ((dict = dict_alloc_id(aid_sign_getlist)) == NULL) - return; - if (list_append_dict(retlist, dict) == FAIL) - return; - sign_getinfo(sp, dict); - - if (name != NULL) // handle only the specified sign - break; - } -} - -/* - * Return information about all the signs placed in a buffer - */ - static void -sign_get_placed_in_buf( - buf_T *buf, - linenr_T lnum, - int sign_id, - char_u *sign_group, - list_T *retlist) -{ - dict_T *d; - list_T *l; - signlist_T *sign; - dict_T *sdict; - - if ((d = dict_alloc_id(aid_sign_getplaced_dict)) == NULL) - return; - list_append_dict(retlist, d); - - dict_add_number(d, "bufnr", (long)buf->b_fnum); - - if ((l = list_alloc_id(aid_sign_getplaced_list)) == NULL) - return; - dict_add_list(d, "signs", l); - - FOR_ALL_SIGNS_IN_BUF(buf, sign) - { - if (!sign_in_group(sign, sign_group)) - continue; - if ((lnum == 0 && sign_id == 0) || - (sign_id == 0 && lnum == sign->lnum) || - (lnum == 0 && sign_id == sign->id) || - (lnum == sign->lnum && sign_id == sign->id)) - { - if ((sdict = sign_get_info(sign)) != NULL) - list_append_dict(l, sdict); - } - } -} - -/* - * Get a list of signs placed in buffer 'buf'. If 'num' is non-zero, return the - * sign placed at the line number. If 'lnum' is zero, return all the signs - * placed in 'buf'. If 'buf' is NULL, return signs placed in all the buffers. - */ - void -sign_get_placed( - buf_T *buf, - linenr_T lnum, - int sign_id, - char_u *sign_group, - list_T *retlist) -{ - if (buf != NULL) - sign_get_placed_in_buf(buf, lnum, sign_id, sign_group, retlist); - else - { - FOR_ALL_BUFFERS(buf) - { - if (buf->b_signlist != NULL) - sign_get_placed_in_buf(buf, 0, sign_id, sign_group, retlist); - } - } -} - -# if defined(FEAT_SIGN_ICONS) || defined(PROTO) -/* - * Allocate the icons. Called when the GUI has started. Allows defining - * signs before it starts. - */ - void -sign_gui_started(void) -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_icon != NULL) - sp->sn_image = gui_mch_register_sign(sp->sn_icon); -} -# endif - -/* - * List one sign. - */ - static void -sign_list_defined(sign_T *sp) -{ - char_u *p; - - smsg((char_u *)"sign %s", sp->sn_name); - if (sp->sn_icon != NULL) - { - MSG_PUTS(" icon="); - msg_outtrans(sp->sn_icon); -# ifdef FEAT_SIGN_ICONS - if (sp->sn_image == NULL) - MSG_PUTS(_(" (NOT FOUND)")); -# else - MSG_PUTS(_(" (not supported)")); -# endif - } - if (sp->sn_text != NULL) - { - MSG_PUTS(" text="); - msg_outtrans(sp->sn_text); - } - if (sp->sn_line_hl > 0) - { - MSG_PUTS(" linehl="); - p = get_highlight_name_ext(NULL, sp->sn_line_hl - 1, FALSE); - if (p == NULL) - MSG_PUTS("NONE"); - else - msg_puts(p); - } - if (sp->sn_text_hl > 0) - { - MSG_PUTS(" texthl="); - p = get_highlight_name_ext(NULL, sp->sn_text_hl - 1, FALSE); - if (p == NULL) - MSG_PUTS("NONE"); - else - msg_puts(p); - } -} - -/* - * Undefine a sign and free its memory. - */ - static void -sign_undefine(sign_T *sp, sign_T *sp_prev) -{ - vim_free(sp->sn_name); - vim_free(sp->sn_icon); -# ifdef FEAT_SIGN_ICONS - if (sp->sn_image != NULL) - { - out_flush(); - gui_mch_destroy_sign(sp->sn_image); - } -# endif - vim_free(sp->sn_text); - if (sp_prev == NULL) - first_sign = sp->sn_next; - else - sp_prev->sn_next = sp->sn_next; - vim_free(sp); -} - -/* - * Get highlighting attribute for sign "typenr". - * If "line" is TRUE: line highl, if FALSE: text highl. - */ - int -sign_get_attr(int typenr, int line) -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_typenr == typenr) - { - if (line) - { - if (sp->sn_line_hl > 0) - return syn_id2attr(sp->sn_line_hl); - } - else - { - if (sp->sn_text_hl > 0) - return syn_id2attr(sp->sn_text_hl); - } - break; - } - return 0; -} - -/* - * Get text mark for sign "typenr". - * Returns NULL if there isn't one. - */ - char_u * -sign_get_text(int typenr) -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_typenr == typenr) - return sp->sn_text; - return NULL; -} - -# if defined(FEAT_SIGN_ICONS) || defined(PROTO) - void * -sign_get_image( - int typenr) /* the attribute which may have a sign */ -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_typenr == typenr) - return sp->sn_image; - return NULL; -} -# endif - -/* - * Get the name of a sign by its typenr. - */ - char_u * -sign_typenr2name(int typenr) -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_typenr == typenr) - return sp->sn_name; - return (char_u *)_("[Deleted]"); -} - -/* - * Undefine/free all signs. - */ - void -free_signs(void) -{ - while (first_sign != NULL) - sign_undefine(first_sign, NULL); -} - -# if defined(FEAT_CMDL_COMPL) || defined(PROTO) -static enum -{ - EXP_SUBCMD, /* expand :sign sub-commands */ - EXP_DEFINE, /* expand :sign define {name} args */ - EXP_PLACE, /* expand :sign place {id} args */ - EXP_UNPLACE, /* expand :sign unplace" */ - EXP_SIGN_NAMES /* expand with name of placed signs */ -} expand_what; - -/* - * Function given to ExpandGeneric() to obtain the sign command - * expansion. - */ - char_u * -get_sign_name(expand_T *xp UNUSED, int idx) -{ - sign_T *sp; - int current_idx; - - switch (expand_what) - { - case EXP_SUBCMD: - return (char_u *)cmds[idx]; - case EXP_DEFINE: - { - char *define_arg[] = - { - "icon=", "linehl=", "text=", "texthl=", NULL - }; - return (char_u *)define_arg[idx]; - } - case EXP_PLACE: - { - char *place_arg[] = - { - "line=", "name=", "group=", "priority=", "file=", - "buffer=", NULL - }; - return (char_u *)place_arg[idx]; - } - case EXP_UNPLACE: - { - char *unplace_arg[] = { "group=", "file=", "buffer=", NULL }; - return (char_u *)unplace_arg[idx]; - } - case EXP_SIGN_NAMES: - /* Complete with name of signs already defined */ - current_idx = 0; - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (current_idx++ == idx) - return sp->sn_name; - return NULL; - default: - return NULL; - } -} - -/* - * Handle command line completion for :sign command. - */ - void -set_context_in_sign_cmd(expand_T *xp, char_u *arg) -{ - char_u *p; - char_u *end_subcmd; - char_u *last; - int cmd_idx; - char_u *begin_subcmd_args; - - /* Default: expand subcommands. */ - xp->xp_context = EXPAND_SIGN; - expand_what = EXP_SUBCMD; - xp->xp_pattern = arg; - - end_subcmd = skiptowhite(arg); - if (*end_subcmd == NUL) - /* expand subcmd name - * :sign {subcmd}<CTRL-D>*/ - return; - - cmd_idx = sign_cmd_idx(arg, end_subcmd); - - /* :sign {subcmd} {subcmd_args} - * | - * begin_subcmd_args */ - begin_subcmd_args = skipwhite(end_subcmd); - p = skiptowhite(begin_subcmd_args); - if (*p == NUL) - { - /* - * Expand first argument of subcmd when possible. - * For ":jump {id}" and ":unplace {id}", we could - * possibly expand the ids of all signs already placed. - */ - xp->xp_pattern = begin_subcmd_args; - switch (cmd_idx) - { - case SIGNCMD_LIST: - case SIGNCMD_UNDEFINE: - /* :sign list <CTRL-D> - * :sign undefine <CTRL-D> */ - expand_what = EXP_SIGN_NAMES; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - return; - } - - /* expand last argument of subcmd */ - - /* :sign define {name} {args}... - * | - * p */ - - /* Loop until reaching last argument. */ - do - { - p = skipwhite(p); - last = p; - p = skiptowhite(p); - } while (*p != NUL); - - p = vim_strchr(last, '='); - - /* :sign define {name} {args}... {last}= - * | | - * last p */ - if (p == NULL) - { - /* Expand last argument name (before equal sign). */ - xp->xp_pattern = last; - switch (cmd_idx) - { - case SIGNCMD_DEFINE: - expand_what = EXP_DEFINE; - break; - case SIGNCMD_PLACE: - expand_what = EXP_PLACE; - break; - case SIGNCMD_JUMP: - case SIGNCMD_UNPLACE: - expand_what = EXP_UNPLACE; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - } - else - { - /* Expand last argument value (after equal sign). */ - xp->xp_pattern = p + 1; - switch (cmd_idx) - { - case SIGNCMD_DEFINE: - if (STRNCMP(last, "texthl", p - last) == 0 || - STRNCMP(last, "linehl", p - last) == 0) - xp->xp_context = EXPAND_HIGHLIGHT; - else if (STRNCMP(last, "icon", p - last) == 0) - xp->xp_context = EXPAND_FILES; - else - xp->xp_context = EXPAND_NOTHING; - break; - case SIGNCMD_PLACE: - if (STRNCMP(last, "name", p - last) == 0) - expand_what = EXP_SIGN_NAMES; - else - xp->xp_context = EXPAND_NOTHING; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - } -} -# endif -#endif - /* * Make the user happy. */ |