summaryrefslogtreecommitdiffstats
path: root/src/ex_cmds.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-01 13:20:31 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-01 13:20:31 +0100
commitbbea47075cc4e7826e9f8c203e4272ba023ed7b0 (patch)
treefbdec3eeea4ca32ada2f309d8c0155087775cfb5 /src/ex_cmds.c
parent9067cd6cdfdc0bb869aa7f5d2a6c607ea8255239 (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.c1246
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.
*/