diff options
Diffstat (limited to 'data/vim/patches/8.1.0673')
-rw-r--r-- | data/vim/patches/8.1.0673 | 4323 |
1 files changed, 4323 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0673 b/data/vim/patches/8.1.0673 new file mode 100644 index 000000000..1e98b0e1d --- /dev/null +++ b/data/vim/patches/8.1.0673 @@ -0,0 +1,4323 @@ +To: vim_dev@googlegroups.com +Subject: Patch 8.1.0673 +Fcc: outbox +From: Bram Moolenaar <Bram@moolenaar.net> +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 8.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) +Files: Filelist, src/Make_bc5.mak, src/Make_cyg_ming.mak, + src/Make_dice.mak, src/Make_ivc.mak, src/Make_manx.mak, + src/Make_morph.mak, src/Make_mvc.mak, src/Make_sas.mak, + src/Make_vms.mms, src/Makefile, src/README.txt, src/buffer.c, + src/evalfunc.c, src/ex_cmds.c, src/proto.h, src/proto/buffer.pro, + src/proto/ex_cmds.pro, src/proto/sign.pro, src/sign.c + + +*** ../vim-8.1.0672/Filelist 2018-12-26 00:59:53.449011480 +0100 +--- Filelist 2019-01-01 13:01:50.678246698 +0100 +*************** +*** 81,90 **** + src/screen.c \ + src/search.c \ + src/sha256.c \ +! src/structs.h \ + src/spell.c \ + src/spell.h \ + src/spellfile.c \ + src/syntax.c \ + src/tag.c \ + src/term.c \ +--- 81,91 ---- + src/screen.c \ + src/search.c \ + src/sha256.c \ +! src/sign.c \ + src/spell.c \ + src/spell.h \ + src/spellfile.c \ ++ src/structs.h \ + src/syntax.c \ + src/tag.c \ + src/term.c \ +*************** +*** 192,197 **** +--- 193,199 ---- + src/proto/screen.pro \ + src/proto/search.pro \ + src/proto/sha256.pro \ ++ src/proto/sign.pro \ + src/proto/spell.pro \ + src/proto/spellfile.pro \ + src/proto/syntax.pro \ +*** ../vim-8.1.0672/src/Make_bc5.mak 2018-10-14 16:25:04.904583951 +0200 +--- src/Make_bc5.mak 2019-01-01 12:47:49.509502791 +0100 +*************** +*** 581,586 **** +--- 581,587 ---- + $(OBJDIR)\screen.obj \ + $(OBJDIR)\search.obj \ + $(OBJDIR)\sha256.obj \ ++ $(OBJDIR)\sign.obj \ + $(OBJDIR)\spell.obj \ + $(OBJDIR)\spellfile.obj \ + $(OBJDIR)\syntax.obj \ +*** ../vim-8.1.0672/src/Make_cyg_ming.mak 2018-12-19 21:05:53.912800490 +0100 +--- src/Make_cyg_ming.mak 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 746,751 **** +--- 746,752 ---- + $(OUTDIR)/screen.o \ + $(OUTDIR)/search.o \ + $(OUTDIR)/sha256.o \ ++ $(OUTDIR)/sign.o \ + $(OUTDIR)/spell.o \ + $(OUTDIR)/spellfile.o \ + $(OUTDIR)/syntax.o \ +*** ../vim-8.1.0672/src/Make_dice.mak 2016-07-19 13:51:24.000000000 +0200 +--- src/Make_dice.mak 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 71,76 **** +--- 71,77 ---- + screen.c \ + search.c \ + sha256.c \ ++ sign.c \ + spell.c \ + spellfile.c \ + syntax.c \ +*************** +*** 127,132 **** +--- 128,134 ---- + o/screen.o \ + o/search.o \ + o/sha256.o \ ++ o/sign.o \ + o/spell.o \ + o/spellfile.o \ + o/syntax.o \ +*************** +*** 252,257 **** +--- 254,261 ---- + + o/sha256.o: sha256.c $(SYMS) + ++ o/sign.o: sign.c $(SYMS) ++ + o/spell.o: spell.c $(SYMS) spell.h + + o/spellfile.o: spellfile.c $(SYMS) spell.h +*** ../vim-8.1.0672/src/Make_ivc.mak 2018-06-19 18:58:04.006489842 +0200 +--- src/Make_ivc.mak 2019-01-01 12:55:40.869451744 +0100 +*************** +*** 257,262 **** +--- 257,263 ---- + "$(INTDIR)/screen.obj" \ + "$(INTDIR)/search.obj" \ + "$(INTDIR)/sha256.obj" \ ++ "$(INTDIR)/sign.obj" \ + "$(INTDIR)/spell.obj" \ + "$(INTDIR)/spellfile.obj" \ + "$(INTDIR)/syntax.obj" \ +*************** +*** 675,680 **** +--- 676,685 ---- + # End Source File + # Begin Source File + ++ SOURCE=.\sign.c ++ # End Source File ++ # Begin Source File ++ + SOURCE=.\spell.c + # End Source File + # Begin Source File +*** ../vim-8.1.0672/src/Make_manx.mak 2016-07-19 13:52:17.000000000 +0200 +--- src/Make_manx.mak 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 81,86 **** +--- 81,87 ---- + screen.c \ + search.c \ + sha256.c \ ++ sign.c \ + spell.c \ + spellfile.c \ + syntax.c \ +*************** +*** 139,144 **** +--- 140,146 ---- + obj/screen.o \ + obj/search.o \ + obj/sha256.o \ ++ obj/sign.o \ + obj/spell.o \ + obj/spellfile.o \ + obj/syntax.o \ +*************** +*** 195,200 **** +--- 197,203 ---- + proto/screen.pro \ + proto/search.pro \ + proto/sha256.pro \ ++ proto/sign.pro \ + proto/spell.pro \ + proto/spellfile.pro \ + proto/syntax.pro \ +*************** +*** 389,394 **** +--- 392,400 ---- + obj/sha256.o: sha256.c + $(CCSYM) $@ sha256.c + ++ obj/sign.o: sign.c ++ $(CCSYM) $@ sign.c ++ + obj/spell.o: spell.c + $(CCSYM) $@ spell.c + +*** ../vim-8.1.0672/src/Make_morph.mak 2016-07-19 13:52:32.000000000 +0200 +--- src/Make_morph.mak 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 69,74 **** +--- 69,75 ---- + screen.c \ + search.c \ + sha256.c \ ++ sign.c \ + spell.c \ + spellfile.c \ + syntax.c \ +*** ../vim-8.1.0672/src/Make_mvc.mak 2018-12-19 21:05:53.912800490 +0100 +--- src/Make_mvc.mak 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 749,754 **** +--- 749,755 ---- + $(OUTDIR)\screen.obj \ + $(OUTDIR)\search.obj \ + $(OUTDIR)\sha256.obj \ ++ $(OUTDIR)\sign.obj \ + $(OUTDIR)\spell.obj \ + $(OUTDIR)\spellfile.obj \ + $(OUTDIR)\syntax.obj \ +*************** +*** 1519,1524 **** +--- 1520,1527 ---- + + $(OUTDIR)/sha256.obj: $(OUTDIR) sha256.c $(INCL) + ++ $(OUTDIR)/sign.obj: $(OUTDIR) sign.c $(INCL) ++ + $(OUTDIR)/spell.obj: $(OUTDIR) spell.c $(INCL) + + $(OUTDIR)/spellfile.obj: $(OUTDIR) spellfile.c $(INCL) +*************** +*** 1664,1669 **** +--- 1667,1673 ---- + proto/screen.pro \ + proto/search.pro \ + proto/sha256.pro \ ++ proto/sign.pro \ + proto/spell.pro \ + proto/spellfile.pro \ + proto/syntax.pro \ +*** ../vim-8.1.0672/src/Make_sas.mak 2016-07-19 13:53:24.000000000 +0200 +--- src/Make_sas.mak 2019-01-01 12:57:19.092606414 +0100 +*************** +*** 134,139 **** +--- 134,140 ---- + screen.c \ + search.c \ + sha256.c \ ++ sign.c \ + spell.c \ + spellfile.c \ + syntax.c \ +*************** +*** 191,196 **** +--- 192,198 ---- + screen.o \ + search.o \ + sha256.o \ ++ sign.o \ + spell.o \ + spellfile.o \ + syntax.o \ +*************** +*** 248,253 **** +--- 250,256 ---- + proto/screen.pro \ + proto/search.pro \ + proto/sha256.pro \ ++ proto/sign.pro \ + proto/spell.pro \ + proto/spellfile.pro \ + proto/syntax.pro \ +*************** +*** 404,409 **** +--- 407,414 ---- + proto/search.pro: search.c + sha256.o: sha256.c + proto/sha256.pro: sha256.c ++ sign.o: sign.c ++ proto/sign.pro: sign.c + spell.o: spell.c + proto/spell.pro: spell.c + spellfile.o: spellfile.c +*** ../vim-8.1.0672/src/Make_vms.mms 2017-11-18 21:08:23.000000000 +0100 +--- src/Make_vms.mms 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 302,308 **** + SRC = arabic.c beval.obj blowfish.c buffer.c charset.c crypt.c crypt_zip.c dict.c diff.c digraph.c edit.c eval.c evalfunc.c \ + ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c if_cscope.c if_xcmdsrv.c farsi.c fileio.c fold.c getchar.c \ + hardcopy.c hashtab.c json.c list.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \ +! misc2.c move.c normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c\ + spell.c spellfile.c syntax.c tag.c term.c termlib.c ui.c undo.c userfunc.c version.c screen.c \ + window.c os_unix.c os_vms.c pathdef.c \ + $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) \ +--- 302,308 ---- + SRC = arabic.c beval.obj blowfish.c buffer.c charset.c crypt.c crypt_zip.c dict.c diff.c digraph.c edit.c eval.c evalfunc.c \ + ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c if_cscope.c if_xcmdsrv.c farsi.c fileio.c fold.c getchar.c \ + hardcopy.c hashtab.c json.c list.c main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \ +! misc2.c move.c normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c sign.c \ + spell.c spellfile.c syntax.c tag.c term.c termlib.c ui.c undo.c userfunc.c version.c screen.c \ + window.c os_unix.c os_vms.c pathdef.c \ + $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) \ +*************** +*** 313,319 **** + if_xcmdsrv.obj farsi.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj json.obj list.obj main.obj mark.obj \ + menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \ + move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj quickfix.obj \ +! regexp.obj search.obj sha256.obj spell.obj spellfile.obj syntax.obj tag.obj term.obj termlib.obj \ + ui.obj undo.obj userfunc.obj screen.obj version.obj window.obj os_unix.obj \ + os_vms.obj pathdef.obj if_mzsch.obj\ + $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \ +--- 313,319 ---- + if_xcmdsrv.obj farsi.obj fileio.obj fold.obj getchar.obj hardcopy.obj hashtab.obj json.obj list.obj main.obj mark.obj \ + menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \ + move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj quickfix.obj \ +! regexp.obj search.obj sha256.obj sign.obj spell.obj spellfile.obj syntax.obj tag.obj term.obj termlib.obj \ + ui.obj undo.obj userfunc.obj screen.obj version.obj window.obj os_unix.obj \ + os_vms.obj pathdef.obj if_mzsch.obj\ + $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \ +*************** +*** 677,682 **** +--- 677,686 ---- + ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \ + beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h proto.h \ + globals.h farsi.h arabic.h ++ sign.obj : sign.c vim.h [.auto]config.h feature.h os_unix.h \ ++ ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \ ++ beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h proto.h \ ++ globals.h farsi.h arabic.h + spell.obj : spell.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ +*** ../vim-8.1.0672/src/Makefile 2018-12-22 17:27:08.982517207 +0100 +--- src/Makefile 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 1626,1631 **** +--- 1628,1634 ---- + screen.c \ + search.c \ + sha256.c \ ++ sign.c \ + spell.c \ + spellfile.c \ + syntax.c \ +*************** +*** 1736,1741 **** +--- 1739,1745 ---- + objects/screen.o \ + objects/search.o \ + objects/sha256.o \ ++ objects/sign.o \ + objects/spell.o \ + objects/spellfile.o \ + objects/syntax.o \ +*************** +*** 1870,1875 **** +--- 1874,1880 ---- + screen.pro \ + search.pro \ + sha256.pro \ ++ sign.pro \ + spell.pro \ + spellfile.pro \ + syntax.pro \ +*************** +*** 3200,3205 **** +--- 3205,3213 ---- + objects/sha256.o: sha256.c + $(CCC) -o $@ sha256.c + ++ objects/sign.o: sign.c ++ $(CCC) -o $@ sign.c ++ + objects/spell.o: spell.c + $(CCC) -o $@ spell.c + +*************** +*** 3586,3591 **** +--- 3594,3603 ---- + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h farsi.h arabic.h ++ objects/sign.o: sign.c vim.h protodef.h auto/config.h feature.h os_unix.h \ ++ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ ++ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ ++ proto.h globals.h farsi.h arabic.h + objects/spell.o: spell.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ +*** ../vim-8.1.0672/src/README.txt 2017-11-12 16:49:36.000000000 +0100 +--- src/README.txt 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 35,40 **** +--- 35,41 ---- + regexp.c pattern matching + screen.c updating the windows + search.c pattern searching ++ sign.c signs + spell.c spell checking + syntax.c syntax and other highlighting + tag.c tags +*** ../vim-8.1.0672/src/buffer.c 2018-12-29 18:53:07.839607468 +0100 +--- src/buffer.c 2019-01-01 12:47:49.513502757 +0100 +*************** +*** 5864,6505 **** + } + #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. + */ +--- 5864,5869 ---- +*** ../vim-8.1.0672/src/evalfunc.c 2018-12-29 21:00:20.953498877 +0100 +--- src/evalfunc.c 2019-01-01 12:47:49.517502724 +0100 +*************** +*** 4424,4447 **** + copy_tv(tv, rettv); + } + +- #ifdef FEAT_SIGNS +- /* +- * Returns information about signs placed in a buffer as list of dicts. +- */ +- static void +- get_buffer_signs(buf_T *buf, list_T *l) +- { +- signlist_T *sign; +- dict_T *d; +- +- FOR_ALL_SIGNS_IN_BUF(buf, sign) +- { +- if ((d = sign_get_info(sign)) != NULL) +- list_append_dict(l, d); +- } +- } +- #endif +- + /* + * Returns buffer options, variables and other attributes in a dictionary. + */ +--- 4424,4429 ---- +*** ../vim-8.1.0672/src/ex_cmds.c 2018-12-31 22:02:24.081890522 +0100 +--- src/ex_cmds.c 2019-01-01 12:47:49.517502724 +0100 +*************** +*** 7579,8830 **** + } + } + +- #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. + */ +--- 7579,7584 ---- +*** ../vim-8.1.0672/src/proto.h 2018-12-13 22:17:52.877941474 +0100 +--- src/proto.h 2019-01-01 12:47:49.517502724 +0100 +*************** +*** 172,177 **** +--- 172,180 ---- + # include "sha256.pro" + # endif + # include "search.pro" ++ # ifdef FEAT_SIGNS ++ # include "sign.pro" ++ # endif + # include "spell.pro" + # include "spellfile.pro" + # include "syntax.pro" +*** ../vim-8.1.0672/src/proto/buffer.pro 2018-12-29 18:53:07.843607433 +0100 +--- src/proto/buffer.pro 2019-01-01 13:07:45.075144726 +0100 +*************** +*** 69,91 **** + void switch_to_win_for_buf(buf_T *buf, win_T **save_curwinp, tabpage_T **save_curtabp, bufref_T *save_curbuf); + void restore_win_for_buf(win_T *save_curwin, tabpage_T *save_curtab, bufref_T *save_curbuf); + int find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp); +- void init_signs(void); +- int sign_group_get_next_signid(buf_T *buf, char_u *groupname); +- int sign_in_group(signlist_T *sign, char_u *group); +- dict_T *sign_get_info(signlist_T *sign); +- void buf_addsign(buf_T *buf, int id, char_u *groupname, int prio, linenr_T lnum, int typenr); +- linenr_T buf_change_sign_type(buf_T *buf, int markId, char_u *group, int typenr); +- int buf_getsigntype(buf_T *buf, linenr_T lnum, int type); +- linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group); +- int buf_findsign(buf_T *buf, int id, char_u *group); +- signlist_T *buf_getsign_with_id(buf_T *buf, int id, char_u *group); +- int buf_findsign_id(buf_T *buf, linenr_T lnum, char_u *groupname); +- int buf_findsigntype_id(buf_T *buf, linenr_T lnum, int typenr); +- int buf_signcount(buf_T *buf, linenr_T lnum); +- void buf_delete_signs(buf_T *buf, char_u *group); +- void buf_delete_all_signs(char_u *groupname); +- void sign_list_placed(buf_T *rbuf, char_u *sign_group); +- void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after); + void set_buflisted(int on); + int buf_contents_changed(buf_T *buf); + void wipe_buffer(buf_T *buf, int aucmd); +--- 69,74 ---- +*** ../vim-8.1.0672/src/proto/ex_cmds.pro 2018-12-29 18:53:07.843607433 +0100 +--- src/proto/ex_cmds.pro 2019-01-01 12:47:49.517502724 +0100 +*************** +*** 54,74 **** + void ex_exusage(exarg_T *eap); + void ex_viusage(exarg_T *eap); + void ex_helptags(exarg_T *eap); +- int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl); +- int sign_undefine_by_name(char_u *name); +- int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio); +- int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum); +- void ex_sign(exarg_T *eap); +- void sign_getlist(char_u *name, list_T *retlist); +- void sign_get_placed(buf_T *buf, linenr_T lnum, int sign_id, char_u *sign_group, list_T *retlist); +- void sign_gui_started(void); +- int sign_get_attr(int typenr, int line); +- char_u *sign_get_text(int typenr); +- void *sign_get_image(int typenr); +- char_u *sign_typenr2name(int typenr); +- void free_signs(void); +- char_u *get_sign_name(expand_T *xp, int idx); +- void set_context_in_sign_cmd(expand_T *xp, char_u *arg); + void ex_smile(exarg_T *eap); + void ex_drop(exarg_T *eap); + char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags); +--- 54,59 ---- +*** ../vim-8.1.0672/src/proto/sign.pro 2019-01-01 13:18:57.745301984 +0100 +--- src/proto/sign.pro 2019-01-01 12:47:49.517502724 +0100 +*************** +*** 0 **** +--- 1,25 ---- ++ /* sign.c */ ++ void init_signs(void); ++ int buf_getsigntype(buf_T *buf, linenr_T lnum, int type); ++ linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group); ++ int buf_findsign(buf_T *buf, int id, char_u *group); ++ int buf_findsign_id(buf_T *buf, linenr_T lnum, char_u *groupname); ++ int buf_findsigntype_id(buf_T *buf, linenr_T lnum, int typenr); ++ int buf_signcount(buf_T *buf, linenr_T lnum); ++ void buf_delete_signs(buf_T *buf, char_u *group); ++ void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after); ++ int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl); ++ int sign_undefine_by_name(char_u *name); ++ int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio); ++ int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum); ++ void ex_sign(exarg_T *eap); ++ void sign_getlist(char_u *name, list_T *retlist); ++ void get_buffer_signs(buf_T *buf, list_T *l); ++ void sign_get_placed(buf_T *buf, linenr_T lnum, int sign_id, char_u *sign_group, list_T *retlist); ++ void sign_gui_started(void); ++ int sign_get_attr(int typenr, int line); ++ char_u *sign_get_text(int typenr); ++ void *sign_get_image(int typenr); ++ void free_signs(void); ++ char_u *get_sign_name(expand_T *xp, int idx); ++ void set_context_in_sign_cmd(expand_T *xp, char_u *arg); +*** ../vim-8.1.0672/src/sign.c 2019-01-01 13:18:57.749301949 +0100 +--- src/sign.c 2019-01-01 12:47:49.517502724 +0100 +*************** +*** 0 **** +--- 1,1880 ---- ++ /* vi:set ts=8 sts=4 sw=4 noet: ++ * ++ * VIM - Vi IMproved by Bram Moolenaar ++ * ++ * Do ":help uganda" in Vim to read copying and usage conditions. ++ * Do ":help credits" in Vim to see a list of people who contributed. ++ * See README.txt for an overview of the Vim source code. ++ */ ++ ++ /* ++ * sign.c: functions for managing signs ++ */ ++ ++ #include "vim.h" ++ ++ #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 ++ }; ++ ++ 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); ++ } ++ } ++ } ++ ++ /* ++ * 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. ++ */ ++ static 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)); ++ } ++ ++ /* ++ * Get the next free sign identifier in the specified group ++ */ ++ static 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); ++ } ++ ++ /* ++ * Get the name of a sign by its typenr. ++ */ ++ static 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]"); ++ } ++ ++ /* ++ * Return information about a sign in a Dict ++ */ ++ static 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. ++ */ ++ static 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. ++ */ ++ static 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 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; ++ } ++ } ++ ++ /* ++ * List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers. ++ */ ++ static 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; ++ } ++ } ++ ++ /* ++ * 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; ++ } ++ } ++ ++ /* ++ * Returns information about signs placed in a buffer as list of dicts. ++ */ ++ void ++ get_buffer_signs(buf_T *buf, list_T *l) ++ { ++ signlist_T *sign; ++ dict_T *d; ++ ++ FOR_ALL_SIGNS_IN_BUF(buf, sign) ++ { ++ if ((d = sign_get_info(sign)) != NULL) ++ list_append_dict(l, d); ++ } ++ } ++ ++ /* ++ * 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 ++ ++ /* ++ * 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 /* FEAT_SIGNS */ +*** ../vim-8.1.0672/src/version.c 2019-01-01 00:41:50.040176062 +0100 +--- src/version.c 2019-01-01 12:50:56.371898216 +0100 +*************** +*** 801,802 **** +--- 801,804 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 673, + /**/ + +-- +From "know your smileys": + 8-O "Omigod!!" (done "rm -rf *" ?) + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |