summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-04-30 19:39:39 +0200
committerBram Moolenaar <Bram@vim.org>2017-04-30 19:39:39 +0200
commit29ae377ea7039874337bc79ace9ab2b37b9056e5 (patch)
treea5465827750a2fd9ee93324138a2157550af62fd
parent45d2cca1ea3f90fc70ad99d0c6812a9d8536303c (diff)
patch 8.0.0592: if a job writes to a buffer screen is not updatedv8.0.0592
Problem: If a job writes to a buffer and the user is typing a command, the screen isn't updated. When a message is displayed the changed buffer may cause it to be cleared. (Ramel Eshed) Solution: Update the screen and then the command line if the screen didn't scroll. Avoid inserting screen lines, as it clears any message. Update the status line when the buffer changed.
-rw-r--r--src/channel.c2
-rw-r--r--src/ex_getln.c9
-rw-r--r--src/globals.h1
-rw-r--r--src/proto/ex_getln.pro1
-rw-r--r--src/proto/screen.pro3
-rw-r--r--src/screen.c72
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h2
8 files changed, 81 insertions, 11 deletions
diff --git a/src/channel.c b/src/channel.c
index 4039b6b25d..ffee334b54 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -2404,7 +2404,7 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
curbuf = curwin->w_buffer;
}
}
- redraw_buf_later(buffer, VALID);
+ redraw_buf_and_status_later(buffer, VALID);
channel_need_redraw = TRUE;
}
diff --git a/src/ex_getln.c b/src/ex_getln.c
index c42abe983f..c7a6d852df 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -3337,10 +3337,17 @@ cmdline_del(int from)
void
redrawcmdline(void)
{
+ redrawcmdline_ex(TRUE);
+}
+
+ void
+redrawcmdline_ex(int do_compute_cmdrow)
+{
if (cmd_silent)
return;
need_wait_return = FALSE;
- compute_cmdrow();
+ if (do_compute_cmdrow)
+ compute_cmdrow();
redrawcmd();
cursorcmd();
}
diff --git a/src/globals.h b/src/globals.h
index 28b71ac851..1d67b0d7af 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -97,6 +97,7 @@ EXTERN int cmdline_row;
EXTERN int redraw_cmdline INIT(= FALSE); /* cmdline must be redrawn */
EXTERN int clear_cmdline INIT(= FALSE); /* cmdline must be cleared */
EXTERN int mode_displayed INIT(= FALSE); /* mode is being displayed */
+EXTERN int no_win_do_lines_ins INIT(= FALSE); /* don't insert lines */
#if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
EXTERN int cmdline_star INIT(= FALSE); /* cmdline is crypted */
#endif
diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro
index 58b635b9fd..6f82904235 100644
--- a/src/proto/ex_getln.pro
+++ b/src/proto/ex_getln.pro
@@ -19,6 +19,7 @@ char_u *save_cmdline_alloc(void);
void restore_cmdline_alloc(char_u *p);
void cmdline_paste_str(char_u *s, int literally);
void redrawcmdline(void);
+void redrawcmdline_ex(int do_compute_cmdrow);
void redrawcmd(void);
void compute_cmdrow(void);
void gotocmdline(int clr);
diff --git a/src/proto/screen.pro b/src/proto/screen.pro
index 5bc3fbaafe..d98e34fd97 100644
--- a/src/proto/screen.pro
+++ b/src/proto/screen.pro
@@ -5,11 +5,12 @@ void redraw_later_clear(void);
void redraw_all_later(int type);
void redraw_curbuf_later(int type);
void redraw_buf_later(buf_T *buf, int type);
+void redraw_buf_and_status_later(buf_T *buf, int type);
int redraw_asap(int type);
void redraw_after_callback(void);
void redrawWinline(linenr_T lnum, int invalid);
void update_curbuf(int type);
-void update_screen(int type);
+void update_screen(int type_arg);
int conceal_cursor_line(win_T *wp);
void conceal_check_cursur_line(void);
void update_single_line(win_T *wp, linenr_T lnum);
diff --git a/src/screen.c b/src/screen.c
index fbfded1a29..43490fb8f6 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -265,6 +265,21 @@ redraw_buf_later(buf_T *buf, int type)
}
}
+ void
+redraw_buf_and_status_later(buf_T *buf, int type)
+{
+ win_T *wp;
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == buf)
+ {
+ redraw_win_later(wp, type);
+ wp->w_redr_status = TRUE;
+ }
+ }
+}
+
/*
* Redraw as soon as possible. When the command line is not scrolled redraw
* right away and restore what was on the command line.
@@ -421,10 +436,29 @@ redraw_after_callback(void)
if (State == HITRETURN || State == ASKMORE)
; /* do nothing */
else if (State & CMDLINE)
- redrawcmdline();
+ {
+ /* Redrawing only works when the screen didn't scroll. */
+ if (msg_scrolled == 0)
+ {
+ update_screen(0);
+ compute_cmdrow();
+ }
+ else
+ {
+ /* Redraw in the same position, so that the user can continue
+ * editing the command. */
+ compute_cmdrow();
+ if (cmdline_row > msg_scrolled)
+ cmdline_row -= msg_scrolled;
+ else
+ cmdline_row = 0;
+ }
+ redrawcmdline_ex(FALSE);
+ }
else if (State & (NORMAL | INSERT))
{
- update_screen(0);
+ /* keep the command line if possible */
+ update_screen(VALID_NO_UPDATE);
setcursor();
}
cursor_on();
@@ -476,7 +510,7 @@ redrawWinline(
}
/*
- * update all windows that are editing the current buffer
+ * Update all windows that are editing the current buffer.
*/
void
update_curbuf(int type)
@@ -490,8 +524,9 @@ update_curbuf(int type)
* of stuff from Filemem to ScreenLines[], and update curwin->w_botline.
*/
void
-update_screen(int type)
+update_screen(int type_arg)
{
+ int type = type_arg;
win_T *wp;
static int did_intro = FALSE;
#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
@@ -502,11 +537,18 @@ update_screen(int type)
int gui_cursor_col;
int gui_cursor_row;
#endif
+ int no_update = FALSE;
/* Don't do anything if the screen structures are (not yet) valid. */
if (!screen_valid(TRUE))
return;
+ if (type == VALID_NO_UPDATE)
+ {
+ no_update = TRUE;
+ type = 0;
+ }
+
if (must_redraw)
{
if (type < must_redraw) /* use maximal type */
@@ -539,6 +581,8 @@ update_screen(int type)
++display_tick; /* let syntax code know we're in a next round of
* display updating */
#endif
+ if (no_update)
+ ++no_win_do_lines_ins;
/*
* if the screen was scrolled up when displaying a message, scroll it down
@@ -576,7 +620,8 @@ update_screen(int type)
}
}
}
- redraw_cmdline = TRUE;
+ if (!no_update)
+ redraw_cmdline = TRUE;
#ifdef FEAT_WINDOWS
redraw_tabline = TRUE;
#endif
@@ -748,6 +793,9 @@ update_screen(int type)
if (clear_cmdline || redraw_cmdline)
showmode();
+ if (no_update)
+ --no_win_do_lines_ins;
+
/* May put up an introductory message when not editing a file */
if (!did_intro)
maybe_intro_message();
@@ -9475,6 +9523,11 @@ win_do_lines(
if (!redrawing() || line_count <= 0)
return FAIL;
+ /* When inserting lines would result in loss of command output, just redraw
+ * the lines. */
+ if (no_win_do_lines_ins && !del)
+ return FAIL;
+
/* only a few lines left: redraw is faster */
if (mayclear && Rows - line_count < 5
#ifdef FEAT_WINDOWS
@@ -9482,7 +9535,8 @@ win_do_lines(
#endif
)
{
- screenclear(); /* will set wp->w_lines_valid to 0 */
+ if (!no_win_do_lines_ins)
+ screenclear(); /* will set wp->w_lines_valid to 0 */
return FAIL;
}
@@ -9498,10 +9552,12 @@ win_do_lines(
}
/*
- * when scrolling, the message on the command line should be cleared,
+ * When scrolling, the message on the command line should be cleared,
* otherwise it will stay there forever.
+ * Don't do this when avoiding to insert lines.
*/
- clear_cmdline = TRUE;
+ if (!no_win_do_lines_ins)
+ clear_cmdline = TRUE;
/*
* If the terminal can set a scroll region, use that.
diff --git a/src/version.c b/src/version.c
index 45f80ee544..fb0d9a56b5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 592,
+/**/
591,
/**/
590,
diff --git a/src/vim.h b/src/vim.h
index 57866ef53e..cbe14e5356 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -630,6 +630,8 @@ extern int (*dyn_libintl_putenv)(const char *envstring);
* flags for update_screen()
* The higher the value, the higher the priority
*/
+#define VALID_NO_UPDATE 5 /* no new changes, keep the command line if
+ possible */
#define VALID 10 /* buffer not changed, or changes marked
with b_mod_* */
#define INVERTED 20 /* redisplay inverted part that changed */