]> granicus.if.org Git - vim/commitdiff
patch 8.1.0767: when deleting lines at the bottom signs are misplaced v8.1.0767
authorBram Moolenaar <Bram@vim.org>
Thu, 17 Jan 2019 16:36:45 +0000 (17:36 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 17 Jan 2019 16:36:45 +0000 (17:36 +0100)
Problem:    When deleting lines at the bottom signs are misplaced.
Solution:   Properly update the line number of signs at the end of a buffer
            after a delete/undo operation. (Yegappan Lakshmanan, closes #3798)

src/sign.c
src/testdir/test_signs.vim
src/version.c

index 6f7ead96327c391aba4aecf1a97108c88cf23a95..75f41235e854cebf080759f62b2ab99b68b1bf64 100644 (file)
@@ -660,18 +660,28 @@ sign_mark_adjust(
     long       amount_after)
 {
     signlist_T *sign;          // a sign in a b_signlist
+    linenr_T   new_lnum;
 
     FOR_ALL_SIGNS_IN_BUF(curbuf, sign)
     {
+       // Ignore changes to lines after the sign
+       if (sign->lnum < line1)
+           continue;
+       new_lnum = sign->lnum;
        if (sign->lnum >= line1 && sign->lnum <= line2)
        {
-           if (amount == MAXLNUM)
-               sign->lnum = line1;
-           else
-               sign->lnum += amount;
+           if (amount != MAXLNUM)
+               new_lnum += amount;
        }
        else if (sign->lnum > line2)
-           sign->lnum += amount_after;
+           // Lines inserted or deleted before the sign
+           new_lnum += amount_after;
+
+       // If the new sign line number is past the last line in the buffer,
+       // then don't adjust the line number. Otherwise, it will always be past
+       // the last line and will not be visible.
+       if (new_lnum <= curbuf->b_ml.ml_line_count)
+           sign->lnum = new_lnum;
     }
 }
 
index 5962ab534597bded16c54a443aee0bb4651b87c7..49bd986c35ac700f2650cdf8fb6d5a8f3a5aa6b2 100644 (file)
@@ -1202,13 +1202,13 @@ func Test_sign_lnum_adjust()
   enew! | only!
 
   sign define sign1 text=#> linehl=Comment
-  call setline(1, ['A', 'B', 'C', 'D'])
+  call setline(1, ['A', 'B', 'C', 'D', 'E'])
   exe 'sign place 5 line=3 name=sign1 buffer=' . bufnr('')
   let l = sign_getplaced(bufnr(''))
   call assert_equal(3, l[0].signs[0].lnum)
 
   " Add some lines before the sign and check the sign line number
-  call append(2, ['AA', 'AB', 'AC'])
+  call append(2, ['BA', 'BB', 'BC'])
   let l = sign_getplaced(bufnr(''))
   call assert_equal(6, l[0].signs[0].lnum)
 
@@ -1217,6 +1217,44 @@ func Test_sign_lnum_adjust()
   let l = sign_getplaced(bufnr(''))
   call assert_equal(4, l[0].signs[0].lnum)
 
+  " Insert some lines after the sign and check the sign line number
+  call append(5, ['DA', 'DB'])
+  let l = sign_getplaced(bufnr(''))
+  call assert_equal(4, l[0].signs[0].lnum)
+
+  " Delete some lines after the sign and check the sign line number
+  call deletebufline('', 6, 7)
+  let l = sign_getplaced(bufnr(''))
+  call assert_equal(4, l[0].signs[0].lnum)
+
+  " Break the undo. Otherwise the undo operation below will undo all the
+  " changes made by this function.
+  let &undolevels=&undolevels
+
+  " Delete the line with the sign
+  call deletebufline('', 4)
+  let l = sign_getplaced(bufnr(''))
+  call assert_equal(4, l[0].signs[0].lnum)
+
+  " Undo the delete operation
+  undo
+  let l = sign_getplaced(bufnr(''))
+  call assert_equal(5, l[0].signs[0].lnum)
+
+  " Break the undo
+  let &undolevels=&undolevels
+
+  " Delete few lines at the end of the buffer including the line with the sign
+  " Sign line number should not change (as it is placed outside of the buffer)
+  call deletebufline('', 3, 6)
+  let l = sign_getplaced(bufnr(''))
+  call assert_equal(5, l[0].signs[0].lnum)
+
+  " Undo the delete operation. Sign should be restored to the previous line
+  undo
+  let l = sign_getplaced(bufnr(''))
+  call assert_equal(5, l[0].signs[0].lnum)
+
   sign unplace * group=*
   sign undefine sign1
   enew!
index 4e3c5a20d12b34929c2aa1863a35d7bb0f73b23a..719fd074150af010ff87625151f76c4d7ec65078 100644 (file)
@@ -791,6 +791,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    767,
 /**/
     766,
 /**/