Mercurial > vim
changeset 15557:c0560da7873e v8.1.0786
patch 8.1.0786: ml_get error when updating the status line
commit https://github.com/vim/vim/commit/10772307c4e5299ed45470f92779f089a00d841e
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 20 18:25:54 2019 +0100
patch 8.1.0786: ml_get error when updating the status line
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)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 20 Jan 2019 18:30:06 +0100 |
parents | 83498c37ab4b |
children | 97d57a9349d5 |
files | src/buffer.c src/testdir/test_terminal.vim src/version.c |
diffstat | 3 files changed, 53 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/buffer.c +++ b/src/buffer.c @@ -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);
--- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -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