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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui