]> granicus.if.org Git - vim/commitdiff
patch 8.1.0786: ml_get error when updating the status line v8.1.0786
authorBram Moolenaar <Bram@vim.org>
Sun, 20 Jan 2019 17:25:54 +0000 (18:25 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 20 Jan 2019 17:25:54 +0000 (18:25 +0100)
Problem:    ml_get error when updating the status line and a terminal had its
            scrollback cleared.  (Chris Patuzzo)
Solution:   Check the cursor position when drawing the status line.
            (closes #3830)

src/buffer.c
src/testdir/test_terminal.vim
src/version.c

index 33df710674775e73cdaeb7ee2a63a5ecb92e370f..fa2e6524b766863d66cd486edc0e695b698f5f96 100644 (file)
@@ -3869,6 +3869,8 @@ build_stl_str_hl(
     struct stl_hlrec *hltab,   /* return: HL attributes (can be NULL) */
     struct stl_hlrec *tabtab)  /* return: tab page nrs (can be NULL) */
 {
+    linenr_T   lnum;
+    size_t     len;
     char_u     *p;
     char_u     *s;
     char_u     *t;
@@ -3943,15 +3945,33 @@ build_stl_str_hl(
        fillchar = '-';
 #endif
 
-    /* Get line & check if empty (cursorpos will show "0-1").  Note that
-     * p will become invalid when getting another buffer line. */
-    p = ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE);
+    // The cursor in windows other than the current one isn't always
+    // up-to-date, esp. because of autocommands and timers.
+    lnum = wp->w_cursor.lnum;
+    if (lnum > wp->w_buffer->b_ml.ml_line_count)
+    {
+       lnum = wp->w_buffer->b_ml.ml_line_count;
+       wp->w_cursor.lnum = lnum;
+    }
+
+    // Get line & check if empty (cursorpos will show "0-1").  Note that
+    // p will become invalid when getting another buffer line.
+    p = ml_get_buf(wp->w_buffer, lnum, FALSE);
     empty_line = (*p == NUL);
 
-    /* Get the byte value now, in case we need it below. This is more
-     * efficient than making a copy of the line. */
-    if (wp->w_cursor.col > (colnr_T)STRLEN(p))
+    // Get the byte value now, in case we need it below. This is more efficient
+    // than making a copy of the line.
+    len = STRLEN(p);
+    if (wp->w_cursor.col > (colnr_T)len)
+    {
+       // Line may have changed since checking the cursor column, or the lnum
+       // was adjusted above.
+       wp->w_cursor.col = (colnr_T)len;
+#ifdef FEAT_VIRTUALEDIT
+       wp->w_cursor.coladd = 0;
+#endif
        byteval = 0;
+    }
     else
 #ifdef FEAT_MBYTE
        byteval = (*mb_ptr2char)(p + wp->w_cursor.col);
index f78d66ca2c4e7c8700b67dfd9a86dca1d0297935..960a85e978c4af07a7aface04d2aa3f1c3954bae 100644 (file)
@@ -1719,3 +1719,28 @@ func Test_term_gettitle()
 
   exe term . 'bwipe!'
 endfunc
+
+" When drawing the statusline the cursor position may not have been updated
+" yet.
+" 1. create a terminal, make it show 2 lines
+" 2. 0.5 sec later: leave terminal window, execute "i"
+" 3. 0.5 sec later: clear terminal window, now it's 1 line
+" 4. 0.5 sec later: redraw, including statusline (used to trigger bug)
+" 4. 0.5 sec later: should be done, clean up
+func Test_terminal_statusline()
+  if !has('unix')
+    return
+  endif
+  set statusline=x
+  terminal
+  let tbuf = bufnr('')
+  call term_sendkeys(tbuf, "clear; echo a; echo b; sleep 1; clear\n")
+  call timer_start(500, { tid -> feedkeys("\<C-w>j", 'tx') })
+  call timer_start(1500, { tid -> feedkeys("\<C-l>", 'tx') })
+  au BufLeave * if &buftype == 'terminal' | silent! normal i | endif
+
+  sleep 2
+  exe tbuf . 'bwipe!'
+  au! BufLeave
+  set statusline=
+endfunc
index 0ef836e9bf896f27be2dfafa8709ff36ff847584..8f1c8bc752e1001612fd6c88362aab5a2ea3dc52 100644 (file)
@@ -791,6 +791,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    786,
 /**/
     785,
 /**/