# HG changeset patch # User Bram Moolenaar # Date 1589824803 -7200 # Node ID 3fe45aa3bbc5ae59e823e585aa11f6d6203bf0ce # Parent 992024e2f885f71ac4c1eb2f0b212f21e7dadaac patch 8.2.0791: a second popup window with terminal causes trouble Commit: https://github.com/vim/vim/commit/b5383b174b2436b556f76f14badb1c1f55d6d8f6 Author: Bram Moolenaar Date: Mon May 18 19:46:48 2020 +0200 patch 8.2.0791: a second popup window with terminal causes trouble Problem: A second popup window with terminal causes trouble. Solution: Disallow opening a second terminal-popup window. (closes https://github.com/vim/vim/issues/6101, closes #6103) Avoid defaulting to an invalid line number. diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -150,7 +150,7 @@ different: *E863* - When the job ends, the popup window closes. - The popup window can be closed with `popup_close()`, the terminal buffer then becomes hidden. -- It is not possible to enter Terminal-Normal mode. +- It is not possible to open a second popup window with a terminal. *E861* - The default Pmenu color is only used for the border and padding. To change the color of the terminal itself set the Terminal highlight group before creating the terminal. Setting 'wincolor' later can work but requires the diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2918,8 +2918,12 @@ parse_cmd_address(exarg_T *eap, char **e { case ADDR_LINES: case ADDR_OTHER: - // default is current line number - eap->line2 = curwin->w_cursor.lnum; + // Default is the cursor line number. Avoid using an invalid + // line number though. + if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) + eap->line2 = curbuf->b_ml.ml_line_count; + else + eap->line2 = curwin->w_cursor.lnum; break; case ADDR_WINDOWS: eap->line2 = CURRENT_WIN_NR; diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1758,6 +1758,25 @@ add_border_left_right_padding(win_T *wp) } /* + * Return TRUE if there is any popup window with a terminal buffer. + */ + static int +popup_terminal_exists(void) +{ + win_T *wp; + tabpage_T *tp; + + FOR_ALL_POPUPWINS(wp) + if (wp->w_buffer->b_term != NULL) + return TRUE; + FOR_ALL_TABPAGES(tp) + FOR_ALL_POPUPWINS_IN_TAB(tp, wp) + if (wp->w_buffer->b_term != NULL) + return TRUE; + return FALSE; +} + +/* * popup_create({text}, {options}) * popup_atcursor({text}, {options}) * etc. @@ -1786,6 +1805,13 @@ popup_create(typval_T *argvars, typval_T semsg(_(e_nobufnr), argvars[0].vval.v_number); return NULL; } +#ifdef FEAT_TERMINAL + if (buf->b_term != NULL && popup_terminal_exists()) + { + emsg(_("E861: Cannot open a second popup with a terminal")); + return NULL; + } +#endif } else if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL) diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2426,10 +2426,10 @@ func Test_popupwin_terminal_buffer() let g:test_is_flaky = 1 let origwin = win_getid() - let ptybuf = term_start(&shell, #{hidden: 1}) - let winid = popup_create(ptybuf, #{minwidth: 40, minheight: 10}) + let termbuf = term_start(&shell, #{hidden: 1}) + let winid = popup_create(termbuf, #{minwidth: 40, minheight: 10}) " Wait for shell to start - call WaitForAssert({-> assert_equal("run", job_status(term_getjob(ptybuf)))}) + call WaitForAssert({-> assert_equal("run", job_status(term_getjob(termbuf)))}) sleep 100m " Check this doesn't crash call assert_equal(winnr(), winnr('j')) @@ -2440,11 +2440,16 @@ func Test_popupwin_terminal_buffer() " Cannot quit while job is running call assert_fails('call feedkeys("\:quit\", "xt")', 'E948:') - " Cannot enter Terminal-Normal mode. + " Cannot enter Terminal-Normal mode. (TODO: but it works...) call feedkeys("xxx\N", 'xt') call assert_fails('call feedkeys("gf", "xt")', 'E863:') call feedkeys("a\", 'xt') + " Cannot open a second one. + let termbuf2 = term_start(&shell, #{hidden: 1}) + call assert_fails('call popup_create(termbuf2, #{})', 'E861:') + call term_sendkeys(termbuf2, "exit\") + " Exiting shell closes popup window call feedkeys("exit\", 'xt') " Wait for shell to exit diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2587,9 +2587,8 @@ func Test_double_popup_terminal() let buf1 = term_start(&shell, #{hidden: 1}) let win1 = popup_create(buf1, {}) let buf2 = term_start(&shell, #{hidden: 1}) - let win2 = popup_create(buf2, {}) + call assert_fails('call popup_create(buf2, {})', 'E861:') call popup_close(win1) - call popup_close(win2) exe buf1 .. 'bwipe!' exe buf2 .. 'bwipe!' endfunc @@ -2619,10 +2618,8 @@ func Test_term_nasty_callback() CheckExecutable sh set hidden - let g:buf0 = term_start('sh', #{hidden: 1}) + let g:buf0 = term_start('sh', #{hidden: 1, term_finish: 'close'}) call popup_create(g:buf0, {}) - let g:buf1 = term_start('sh', #{hidden: 1, term_finish: 'close'}) - call popup_create(g:buf1, {}) call assert_fails("call term_start(['sh', '-c'], #{curwin: 1})", 'E863:') call popup_clear(1) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 791, +/**/ 790, /**/ 789,