mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.0.1815: crash with terminal window and with 'lazyredraw' set
Problem: Still a crash with terminal window and with 'lazyredraw' set. (Antoine) Solution: Do not wipe out the buffer when updating the screen.
This commit is contained in:
parent
a10ae5e323
commit
0cb8ac71ae
@ -9,6 +9,7 @@ void redraw_buf_and_status_later(buf_T *buf, int type);
|
|||||||
int redraw_asap(int type);
|
int redraw_asap(int type);
|
||||||
void redraw_after_callback(int call_update_screen);
|
void redraw_after_callback(int call_update_screen);
|
||||||
void redrawWinline(linenr_T lnum, int invalid);
|
void redrawWinline(linenr_T lnum, int invalid);
|
||||||
|
void reset_updating_screen(int may_resize_shell);
|
||||||
void update_curbuf(int type);
|
void update_curbuf(int type);
|
||||||
int update_screen(int type_arg);
|
int update_screen(int type_arg);
|
||||||
int conceal_cursor_line(win_T *wp);
|
int conceal_cursor_line(win_T *wp);
|
||||||
|
@ -20,6 +20,7 @@ void term_win_entered(void);
|
|||||||
int terminal_loop(int blocking);
|
int terminal_loop(int blocking);
|
||||||
void term_job_ended(job_T *job);
|
void term_job_ended(job_T *job);
|
||||||
void term_channel_closed(channel_T *ch);
|
void term_channel_closed(channel_T *ch);
|
||||||
|
void term_check_channel_closed_recently(void);
|
||||||
int term_do_update_window(win_T *wp);
|
int term_do_update_window(win_T *wp);
|
||||||
void term_update_window(win_T *wp);
|
void term_update_window(win_T *wp);
|
||||||
int term_is_finished(buf_T *buf);
|
int term_is_finished(buf_T *buf);
|
||||||
|
22
src/screen.c
22
src/screen.c
@ -512,6 +512,19 @@ redrawWinline(
|
|||||||
curwin->w_lines[i].wl_valid = FALSE;
|
curwin->w_lines[i].wl_valid = FALSE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reset_updating_screen(int may_resize_shell UNUSED)
|
||||||
|
{
|
||||||
|
updating_screen = FALSE;
|
||||||
|
#ifdef FEAT_GUI
|
||||||
|
if (may_resize_shell)
|
||||||
|
gui_may_resize_shell();
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_TERMINAL
|
||||||
|
term_check_channel_closed_recently();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -778,10 +791,7 @@ update_screen(int type_arg)
|
|||||||
FOR_ALL_WINDOWS(wp)
|
FOR_ALL_WINDOWS(wp)
|
||||||
wp->w_buffer->b_mod_set = FALSE;
|
wp->w_buffer->b_mod_set = FALSE;
|
||||||
|
|
||||||
updating_screen = FALSE;
|
reset_updating_screen(TRUE);
|
||||||
#ifdef FEAT_GUI
|
|
||||||
gui_may_resize_shell();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Clear or redraw the command line. Done last, because scrolling may
|
/* Clear or redraw the command line. Done last, because scrolling may
|
||||||
* mess up the command line. */
|
* mess up the command line. */
|
||||||
@ -861,11 +871,9 @@ update_finish(void)
|
|||||||
end_search_hl();
|
end_search_hl();
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
updating_screen = FALSE;
|
reset_updating_screen(TRUE);
|
||||||
|
|
||||||
# ifdef FEAT_GUI
|
# ifdef FEAT_GUI
|
||||||
gui_may_resize_shell();
|
|
||||||
|
|
||||||
/* Redraw the cursor and update the scrollbars when all screen updating is
|
/* Redraw the cursor and update the scrollbars when all screen updating is
|
||||||
* done. */
|
* done. */
|
||||||
if (gui.in_use)
|
if (gui.in_use)
|
||||||
|
119
src/terminal.c
119
src/terminal.c
@ -103,6 +103,8 @@ struct terminal_S {
|
|||||||
|
|
||||||
int tl_normal_mode; /* TRUE: Terminal-Normal mode */
|
int tl_normal_mode; /* TRUE: Terminal-Normal mode */
|
||||||
int tl_channel_closed;
|
int tl_channel_closed;
|
||||||
|
int tl_channel_recently_closed; // still need to handle tl_finish
|
||||||
|
|
||||||
int tl_finish;
|
int tl_finish;
|
||||||
#define TL_FINISH_UNSET NUL
|
#define TL_FINISH_UNSET NUL
|
||||||
#define TL_FINISH_CLOSE 'c' /* ++close or :terminal without argument */
|
#define TL_FINISH_CLOSE 'c' /* ++close or :terminal without argument */
|
||||||
@ -2779,6 +2781,53 @@ static VTermScreenCallbacks screen_callbacks = {
|
|||||||
NULL /* sb_popline */
|
NULL /* sb_popline */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the work after the channel of a terminal was closed.
|
||||||
|
* Must be called only when updating_screen is FALSE.
|
||||||
|
* Returns TRUE when a buffer was closed (list of terminals may have changed).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
term_after_channel_closed(term_T *term)
|
||||||
|
{
|
||||||
|
/* Unless in Terminal-Normal mode: clear the vterm. */
|
||||||
|
if (!term->tl_normal_mode)
|
||||||
|
{
|
||||||
|
int fnum = term->tl_buffer->b_fnum;
|
||||||
|
|
||||||
|
cleanup_vterm(term);
|
||||||
|
|
||||||
|
if (term->tl_finish == TL_FINISH_CLOSE)
|
||||||
|
{
|
||||||
|
aco_save_T aco;
|
||||||
|
|
||||||
|
/* ++close or term_finish == "close" */
|
||||||
|
ch_log(NULL, "terminal job finished, closing window");
|
||||||
|
aucmd_prepbuf(&aco, term->tl_buffer);
|
||||||
|
do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
|
||||||
|
aucmd_restbuf(&aco);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (term->tl_finish == TL_FINISH_OPEN
|
||||||
|
&& term->tl_buffer->b_nwindows == 0)
|
||||||
|
{
|
||||||
|
char buf[50];
|
||||||
|
|
||||||
|
/* TODO: use term_opencmd */
|
||||||
|
ch_log(NULL, "terminal job finished, opening window");
|
||||||
|
vim_snprintf(buf, sizeof(buf),
|
||||||
|
term->tl_opencmd == NULL
|
||||||
|
? "botright sbuf %d"
|
||||||
|
: (char *)term->tl_opencmd, fnum);
|
||||||
|
do_cmdline_cmd((char_u *)buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ch_log(NULL, "terminal job finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw_buf_and_status_later(term->tl_buffer, NOT_VALID);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when a channel has been closed.
|
* Called when a channel has been closed.
|
||||||
* If this was a channel for a terminal window then finish it up.
|
* If this was a channel for a terminal window then finish it up.
|
||||||
@ -2787,9 +2836,12 @@ static VTermScreenCallbacks screen_callbacks = {
|
|||||||
term_channel_closed(channel_T *ch)
|
term_channel_closed(channel_T *ch)
|
||||||
{
|
{
|
||||||
term_T *term;
|
term_T *term;
|
||||||
|
term_T *next_term;
|
||||||
int did_one = FALSE;
|
int did_one = FALSE;
|
||||||
|
|
||||||
for (term = first_term; term != NULL; term = term->tl_next)
|
for (term = first_term; term != NULL; term = next_term)
|
||||||
|
{
|
||||||
|
next_term = term->tl_next;
|
||||||
if (term->tl_job == ch->ch_job)
|
if (term->tl_job == ch->ch_job)
|
||||||
{
|
{
|
||||||
term->tl_channel_closed = TRUE;
|
term->tl_channel_closed = TRUE;
|
||||||
@ -2805,43 +2857,19 @@ term_channel_closed(channel_T *ch)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Unless in Terminal-Normal mode: clear the vterm. */
|
if (updating_screen)
|
||||||
if (!term->tl_normal_mode)
|
|
||||||
{
|
{
|
||||||
int fnum = term->tl_buffer->b_fnum;
|
/* Cannot open or close windows now. Can happen when
|
||||||
|
* 'lazyredraw' is set. */
|
||||||
cleanup_vterm(term);
|
term->tl_channel_recently_closed = TRUE;
|
||||||
|
continue;
|
||||||
if (term->tl_finish == TL_FINISH_CLOSE)
|
|
||||||
{
|
|
||||||
aco_save_T aco;
|
|
||||||
|
|
||||||
/* ++close or term_finish == "close" */
|
|
||||||
ch_log(NULL, "terminal job finished, closing window");
|
|
||||||
aucmd_prepbuf(&aco, term->tl_buffer);
|
|
||||||
do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
|
|
||||||
aucmd_restbuf(&aco);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (term->tl_finish == TL_FINISH_OPEN
|
|
||||||
&& term->tl_buffer->b_nwindows == 0)
|
|
||||||
{
|
|
||||||
char buf[50];
|
|
||||||
|
|
||||||
/* TODO: use term_opencmd */
|
|
||||||
ch_log(NULL, "terminal job finished, opening window");
|
|
||||||
vim_snprintf(buf, sizeof(buf),
|
|
||||||
term->tl_opencmd == NULL
|
|
||||||
? "botright sbuf %d"
|
|
||||||
: (char *)term->tl_opencmd, fnum);
|
|
||||||
do_cmdline_cmd((char_u *)buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ch_log(NULL, "terminal job finished");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw_buf_and_status_later(term->tl_buffer, NOT_VALID);
|
if (term_after_channel_closed(term))
|
||||||
|
next_term = first_term;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (did_one)
|
if (did_one)
|
||||||
{
|
{
|
||||||
redraw_statuslines();
|
redraw_statuslines();
|
||||||
@ -2860,6 +2888,29 @@ term_channel_closed(channel_T *ch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To be called after resetting updating_screen: handle any terminal where the
|
||||||
|
* channel was closed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
term_check_channel_closed_recently()
|
||||||
|
{
|
||||||
|
term_T *term;
|
||||||
|
term_T *next_term;
|
||||||
|
|
||||||
|
for (term = first_term; term != NULL; term = next_term)
|
||||||
|
{
|
||||||
|
next_term = term->tl_next;
|
||||||
|
if (term->tl_channel_recently_closed)
|
||||||
|
{
|
||||||
|
term->tl_channel_recently_closed = FALSE;
|
||||||
|
if (term_after_channel_closed(term))
|
||||||
|
// start over, the list may have changed
|
||||||
|
next_term = first_term;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill one screen line from a line of the terminal.
|
* Fill one screen line from a line of the terminal.
|
||||||
* Advances "pos" to past the last column.
|
* Advances "pos" to past the last column.
|
||||||
|
5
src/ui.c
5
src/ui.c
@ -415,7 +415,10 @@ ui_breakcheck_force(int force)
|
|||||||
#endif
|
#endif
|
||||||
mch_breakcheck(force);
|
mch_breakcheck(force);
|
||||||
|
|
||||||
updating_screen = save_us;
|
if (save_us)
|
||||||
|
updating_screen = save_us;
|
||||||
|
else
|
||||||
|
reset_updating_screen(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -761,6 +761,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1815,
|
||||||
/**/
|
/**/
|
||||||
1814,
|
1814,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user