From 69e056915c4145b7b64c60963797692a5b293561 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 14:11:52 +0200 Subject: [PATCH 1/7] patch 8.0.1807: function to set terminal name is too long Problem: Function to set terminal name is too long. Solution: Refactor the function. Fix typo in test. --- src/term.c | 285 ++++++++++++++++++----------------- src/testdir/test_options.vim | 4 +- src/version.c | 2 + 3 files changed, 151 insertions(+), 140 deletions(-) diff --git a/src/term.c b/src/term.c index 49dee03013..37caf2b26c 100644 --- a/src/term.c +++ b/src/term.c @@ -1544,6 +1544,150 @@ static char *(key_names[]) = }; #endif + static void +get_term_entries(int *height, int *width) +{ + static struct { + enum SpecialKey dest; /* index in term_strings[] */ + char *name; /* termcap name for string */ + } string_names[] = + { {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"}, + {KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"}, + {KS_CL, "cl"}, {KS_CD, "cd"}, + {KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"}, + {KS_ME, "me"}, {KS_MR, "mr"}, + {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"}, + {KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"}, + {KS_US, "us"}, {KS_UCE, "Ce"}, {KS_UCS, "Cs"}, + {KS_STE,"Te"}, {KS_STS,"Ts"}, + {KS_CM, "cm"}, {KS_SR, "sr"}, + {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, + {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, + {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"}, + {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"}, + {KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"}, + {KS_VS, "vs"}, {KS_CVS, "VS"}, + {KS_CIS, "IS"}, {KS_CIE, "IE"}, + {KS_CSC, "SC"}, {KS_CEC, "EC"}, + {KS_TS, "ts"}, {KS_FS, "fs"}, + {KS_CWP, "WP"}, {KS_CWS, "WS"}, + {KS_CSI, "SI"}, {KS_CEI, "EI"}, + {KS_U7, "u7"}, {KS_RFG, "RF"}, {KS_RBG, "RB"}, + {KS_8F, "8f"}, {KS_8B, "8b"}, + {KS_CBE, "BE"}, {KS_CBD, "BD"}, + {KS_CPS, "PS"}, {KS_CPE, "PE"}, + {(enum SpecialKey)0, NULL} + }; + int i; + char_u *p; + static char_u tstrbuf[TBUFSZ]; + char_u *tp = tstrbuf; + + /* + * get output strings + */ + for (i = 0; string_names[i].name != NULL; ++i) + { + if (TERM_STR(string_names[i].dest) == NULL + || TERM_STR(string_names[i].dest) == empty_option) + TERM_STR(string_names[i].dest) = TGETSTR(string_names[i].name, &tp); + } + + /* tgetflag() returns 1 if the flag is present, 0 if not and + * possibly -1 if the flag doesn't exist. */ + if ((T_MS == NULL || T_MS == empty_option) && tgetflag("ms") > 0) + T_MS = (char_u *)"y"; + if ((T_XS == NULL || T_XS == empty_option) && tgetflag("xs") > 0) + T_XS = (char_u *)"y"; + if ((T_XN == NULL || T_XN == empty_option) && tgetflag("xn") > 0) + T_XN = (char_u *)"y"; + if ((T_DB == NULL || T_DB == empty_option) && tgetflag("db") > 0) + T_DB = (char_u *)"y"; + if ((T_DA == NULL || T_DA == empty_option) && tgetflag("da") > 0) + T_DA = (char_u *)"y"; + if ((T_UT == NULL || T_UT == empty_option) && tgetflag("ut") > 0) + T_UT = (char_u *)"y"; + + /* + * get key codes + */ + for (i = 0; key_names[i] != NULL; ++i) + if (find_termcode((char_u *)key_names[i]) == NULL) + { + p = TGETSTR(key_names[i], &tp); + /* if cursor-left == backspace, ignore it (televideo 925) */ + if (p != NULL + && (*p != Ctrl_H + || key_names[i][0] != 'k' + || key_names[i][1] != 'l')) + add_termcode((char_u *)key_names[i], p, FALSE); + } + + if (*height == 0) + *height = tgetnum("li"); + if (*width == 0) + *width = tgetnum("co"); + + /* + * Get number of colors (if not done already). + */ + if (TERM_STR(KS_CCO) == NULL || TERM_STR(KS_CCO) == empty_option) + set_color_count(tgetnum("Co")); + +# ifndef hpux + BC = (char *)TGETSTR("bc", &tp); + UP = (char *)TGETSTR("up", &tp); + p = TGETSTR("pc", &tp); + if (p) + PC = *p; +# endif +} + + static void +report_term_error(char_u *error_msg, char_u *term) +{ + struct builtin_term *termp; + + mch_errmsg("\r\n"); + if (error_msg != NULL) + { + mch_errmsg((char *)error_msg); + mch_errmsg("\r\n"); + } + mch_errmsg("'"); + mch_errmsg((char *)term); + mch_errmsg(_("' not known. Available builtin terminals are:")); + mch_errmsg("\r\n"); + for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL; ++termp) + { + if (termp->bt_entry == (int)KS_NAME) + { +#ifdef HAVE_TGETENT + mch_errmsg(" builtin_"); +#else + mch_errmsg(" "); +#endif + mch_errmsg(termp->bt_string); + mch_errmsg("\r\n"); + } + } +} + + static void +report_default_term(char_u *term) +{ + mch_errmsg(_("defaulting to '")); + mch_errmsg((char *)term); + mch_errmsg("'\r\n"); + if (emsg_silent == 0) + { + screen_start(); /* don't know where cursor is now */ + out_flush(); + if (!is_not_a_term()) + ui_delay(2000L, TRUE); + } +} + /* * Set terminal options for terminal "term". * Return OK if terminal 'term' was found in a termcap, FAIL otherwise. @@ -1595,42 +1739,7 @@ set_termname(char_u *term) */ if (try == 1) { - char_u *p; - static char_u tstrbuf[TBUFSZ]; - int i; char_u tbuf[TBUFSZ]; - char_u *tp; - static struct { - enum SpecialKey dest; /* index in term_strings[] */ - char *name; /* termcap name for string */ - } string_names[] = - { {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL,"AL"}, - {KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"}, - {KS_CL, "cl"}, {KS_CD, "cd"}, - {KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"}, - {KS_ME, "me"}, {KS_MR, "mr"}, - {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"}, - {KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"}, - {KS_US, "us"}, {KS_UCE, "Ce"}, {KS_UCS, "Cs"}, - {KS_STE,"Te"}, {KS_STS,"Ts"}, - {KS_CM, "cm"}, {KS_SR, "sr"}, - {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, - {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, - {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"}, - {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"}, - {KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"}, - {KS_VS, "vs"}, {KS_CVS, "VS"}, - {KS_CIS, "IS"}, {KS_CIE, "IE"}, - {KS_CSC, "SC"}, {KS_CEC, "EC"}, - {KS_TS, "ts"}, {KS_FS, "fs"}, - {KS_CWP, "WP"}, {KS_CWS, "WS"}, - {KS_CSI, "SI"}, {KS_CEI, "EI"}, - {KS_U7, "u7"}, {KS_RFG, "RF"}, {KS_RBG, "RB"}, - {KS_8F, "8f"}, {KS_8B, "8b"}, - {KS_CBE, "BE"}, {KS_CBD, "BD"}, - {KS_CPS, "PS"}, {KS_CPE, "PE"}, - {(enum SpecialKey)0, NULL} - }; /* * If the external termcap does not have a matching entry, try the @@ -1638,81 +1747,13 @@ set_termname(char_u *term) */ if ((error_msg = tgetent_error(tbuf, term)) == NULL) { - tp = tstrbuf; if (!termcap_cleared) { clear_termoptions(); /* clear old options */ termcap_cleared = TRUE; } - /* get output strings */ - for (i = 0; string_names[i].name != NULL; ++i) - { - if (TERM_STR(string_names[i].dest) == NULL - || TERM_STR(string_names[i].dest) == empty_option) - TERM_STR(string_names[i].dest) = - TGETSTR(string_names[i].name, &tp); - } - - /* tgetflag() returns 1 if the flag is present, 0 if not and - * possibly -1 if the flag doesn't exist. */ - if ((T_MS == NULL || T_MS == empty_option) - && tgetflag("ms") > 0) - T_MS = (char_u *)"y"; - if ((T_XS == NULL || T_XS == empty_option) - && tgetflag("xs") > 0) - T_XS = (char_u *)"y"; - if ((T_XN == NULL || T_XN == empty_option) - && tgetflag("xn") > 0) - T_XN = (char_u *)"y"; - if ((T_DB == NULL || T_DB == empty_option) - && tgetflag("db") > 0) - T_DB = (char_u *)"y"; - if ((T_DA == NULL || T_DA == empty_option) - && tgetflag("da") > 0) - T_DA = (char_u *)"y"; - if ((T_UT == NULL || T_UT == empty_option) - && tgetflag("ut") > 0) - T_UT = (char_u *)"y"; - - - /* - * get key codes - */ - for (i = 0; key_names[i] != NULL; ++i) - { - if (find_termcode((char_u *)key_names[i]) == NULL) - { - p = TGETSTR(key_names[i], &tp); - /* if cursor-left == backspace, ignore it (televideo - * 925) */ - if (p != NULL - && (*p != Ctrl_H - || key_names[i][0] != 'k' - || key_names[i][1] != 'l')) - add_termcode((char_u *)key_names[i], p, FALSE); - } - } - - if (height == 0) - height = tgetnum("li"); - if (width == 0) - width = tgetnum("co"); - - /* - * Get number of colors (if not done already). - */ - if (TERM_STR(KS_CCO) == NULL - || TERM_STR(KS_CCO) == empty_option) - set_color_count(tgetnum("Co")); - -# ifndef hpux - BC = (char *)TGETSTR("bc", &tp); - UP = (char *)TGETSTR("up", &tp); - p = TGETSTR("pc", &tp); - if (p) - PC = *p; -# endif /* hpux */ + get_term_entries(&height, &width); } } else /* try == 0 || try == 2 */ @@ -1748,31 +1789,8 @@ set_termname(char_u *term) if (termcap_cleared) /* found in external termcap */ break; #endif + report_term_error(error_msg, term); - mch_errmsg("\r\n"); - if (error_msg != NULL) - { - mch_errmsg((char *)error_msg); - mch_errmsg("\r\n"); - } - mch_errmsg("'"); - mch_errmsg((char *)term); - mch_errmsg(_("' not known. Available builtin terminals are:")); - mch_errmsg("\r\n"); - for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL; - ++termp) - { - if (termp->bt_entry == (int)KS_NAME) - { -#ifdef HAVE_TGETENT - mch_errmsg(" builtin_"); -#else - mch_errmsg(" "); -#endif - mch_errmsg(termp->bt_string); - mch_errmsg("\r\n"); - } - } /* when user typed :set term=xxx, quit here */ if (starting != NO_SCREEN) { @@ -1781,16 +1799,7 @@ set_termname(char_u *term) return FAIL; } term = DEFAULT_TERM; - mch_errmsg(_("defaulting to '")); - mch_errmsg((char *)term); - mch_errmsg("'\r\n"); - if (emsg_silent == 0) - { - screen_start(); /* don't know where cursor is now */ - out_flush(); - if (!is_not_a_term()) - ui_delay(2000L, TRUE); - } + report_default_term(term); set_string_option_direct((char_u *)"term", -1, term, OPT_FREE, 0); display_errors(); diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 0f2908fcb3..8fa5f8b7bf 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -284,7 +284,7 @@ func Test_set_ttytype() " in travis on some builds. Why? Catch both for now try set ttytype= - call assert_report('set ttype= did not fail') + call assert_report('set ttytype= did not fail') catch /E529\|E522/ endtry @@ -292,7 +292,7 @@ func Test_set_ttytype() " check for failure of finding the entry and for missing 'cm' entry. try set ttytype=xxx - call assert_report('set ttype=xxx did not fail') + call assert_report('set ttytype=xxx did not fail') catch /E522\|E437/ endtry diff --git a/src/version.c b/src/version.c index 5ebf701848..147f4ed077 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1807, /**/ 1806, /**/ From 9289df5ca9546bda0e0046a45ceb66c6bb7a838f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 14:40:57 +0200 Subject: [PATCH 2/7] patch 8.0.1808: can't build without TGETENT Problem: Can't build without TGETENT. Solution: Add #ifdef --- src/term.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/term.c b/src/term.c index 37caf2b26c..8b69cc41a5 100644 --- a/src/term.c +++ b/src/term.c @@ -1544,6 +1544,7 @@ static char *(key_names[]) = }; #endif +#ifdef HAVE_TGETENT static void get_term_entries(int *height, int *width) { @@ -1642,6 +1643,7 @@ get_term_entries(int *height, int *width) PC = *p; # endif } +#endif static void report_term_error(char_u *error_msg, char_u *term) diff --git a/src/version.c b/src/version.c index 147f4ed077..db47bea9eb 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1808, /**/ 1807, /**/ From b9464821901623f983528acaed9e4dc2cea7387b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 15:09:49 +0200 Subject: [PATCH 3/7] patch 8.0.1809: various typos Problem: Various typos. Solution: Correct the mistakes, change "cursur" to "cursor". (closes #2887) --- src/edit.c | 2 +- src/normal.c | 4 ++-- src/proto/screen.pro | 2 +- src/screen.c | 2 +- src/ui.c | 2 +- src/version.c | 2 ++ 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/edit.c b/src/edit.c index 9b7206410e..ef4c98d29b 100644 --- a/src/edit.c +++ b/src/edit.c @@ -431,7 +431,7 @@ edit( #ifdef FEAT_CONCEAL /* Check if the cursor line needs redrawing before changing State. If * 'concealcursor' is "n" it needs to be redrawn without concealing. */ - conceal_check_cursur_line(); + conceal_check_cursor_line(); #endif #ifdef FEAT_MOUSE diff --git a/src/normal.c b/src/normal.c index be0e75e7e3..3b958a5b59 100644 --- a/src/normal.c +++ b/src/normal.c @@ -7797,7 +7797,7 @@ n_start_visual_mode(int c) { #ifdef FEAT_CONCEAL /* Check for redraw before changing the state. */ - conceal_check_cursur_line(); + conceal_check_cursor_line(); #endif VIsual_mode = c; @@ -7824,7 +7824,7 @@ n_start_visual_mode(int c) #endif #ifdef FEAT_CONCEAL /* Check for redraw after changing the state. */ - conceal_check_cursur_line(); + conceal_check_cursor_line(); #endif if (p_smd && msg_silent == 0) diff --git a/src/proto/screen.pro b/src/proto/screen.pro index f04fda51e4..f690f93d62 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -12,7 +12,7 @@ void redrawWinline(linenr_T lnum, int invalid); void update_curbuf(int type); int update_screen(int type_arg); int conceal_cursor_line(win_T *wp); -void conceal_check_cursur_line(void); +void conceal_check_cursor_line(void); void update_single_line(win_T *wp, linenr_T lnum); void update_debug_sign(buf_T *buf, linenr_T lnum); void updateWindow(win_T *wp); diff --git a/src/screen.c b/src/screen.c index cff6ae5d3d..cac5a3a1f8 100644 --- a/src/screen.c +++ b/src/screen.c @@ -906,7 +906,7 @@ conceal_cursor_line(win_T *wp) * Check if the cursor line needs to be redrawn because of 'concealcursor'. */ void -conceal_check_cursur_line(void) +conceal_check_cursor_line(void) { if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin)) { diff --git a/src/ui.c b/src/ui.c index bb038801ac..05e82e6c74 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1971,7 +1971,7 @@ ui_cursor_shape_forced(int forced) # endif # ifdef FEAT_CONCEAL - conceal_check_cursur_line(); + conceal_check_cursor_line(); # endif } diff --git a/src/version.c b/src/version.c index db47bea9eb..b71b384f1b 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1809, /**/ 1808, /**/ From 56bc8e299cdae1b4606897749ef54a0161381a4a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 18:05:56 +0200 Subject: [PATCH 4/7] patch 8.0.1810: buffer of a terminal only updated in Terminal-Normal mode Problem: Buffer of a terminal only updated in Terminal-Normal mode. Solution: Copy the terminal window content to the buffer when in Terminal-Job mode. --- src/ex_cmds2.c | 6 +- src/proto/ex_cmds2.pro | 3 +- src/proto/terminal.pro | 1 + src/terminal.c | 123 +++++++++++++++++++++++++++++++++++------ src/version.c | 2 + 5 files changed, 115 insertions(+), 20 deletions(-) diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 7fa4907bda..d27d0cdf59 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1206,7 +1206,7 @@ profile_zero(proftime_T *tm) static timer_T *first_timer = NULL; static long last_timer_id = 0; - static long + long proftime_time_left(proftime_T *due, proftime_T *now) { # ifdef WIN3264 @@ -1424,6 +1424,10 @@ check_due_timer(void) next_due = this_due; } #endif +#ifdef FEAT_TERMINAL + /* Some terminal windows may need their buffer updated. */ + next_due = term_check_timers(next_due, &now); +#endif return current_id != last_timer_id ? 1 : next_due; } diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro index a7d19d768f..ac9b291e5c 100644 --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -1,5 +1,5 @@ /* ex_cmds2.c */ -int has_watchexpr (void); +int has_watchexpr(void); void do_debug(char_u *cmd); void ex_debug(exarg_T *eap); void dbg_check_breakpoint(exarg_T *eap); @@ -19,6 +19,7 @@ float_T profile_float(proftime_T *tm); void profile_setlimit(long msec, proftime_T *tm); int profile_passed_limit(proftime_T *tm); void profile_zero(proftime_T *tm); +long proftime_time_left(proftime_T *due, proftime_T *now); timer_T *create_timer(long msec, int repeat); long check_due_timer(void); timer_T *find_timer(long id); diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro index f97f025d58..93c6ab53c6 100644 --- a/src/proto/terminal.pro +++ b/src/proto/terminal.pro @@ -9,6 +9,7 @@ void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel); int term_job_running(term_T *term); int term_none_open(term_T *term); int term_try_stop_job(buf_T *buf); +int term_check_timers(int next_due_arg, proftime_T *now); int term_in_normal_mode(void); void term_enter_job_mode(void); int send_keys_to_term(term_T *term, int c, int typed); diff --git a/src/terminal.c b/src/terminal.c index 0c483e140c..6e5b1002c2 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -43,8 +43,6 @@ * - Win32: Redirecting output works but includes escape sequences. * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for * redirection. - * - Copy text in the vterm to the Vim buffer once in a while, so that - * completion works. * - When the job only outputs lines, we could handle resizing the terminal * better: store lines separated by line breaks, instead of screen lines, * then when the window is resized redraw those lines. @@ -131,7 +129,11 @@ struct terminal_S { /* Range of screen rows to update. Zero based. */ int tl_dirty_row_start; /* MAX_ROW if nothing dirty */ int tl_dirty_row_end; /* row below last one to update */ - + int tl_dirty_snapshot; /* text updated after making snapshot */ +#ifdef FEAT_TIMERS + int tl_timer_set; + proftime_T tl_timer_due; +#endif int tl_postponed_scroll; /* to be scrolled up */ garray_T tl_scrollback; @@ -1441,6 +1443,29 @@ add_empty_scrollback(term_T *term, cellattr_T *fill_attr, int lnum) return FALSE; } +/* + * Remove the terminal contents from the scrollback and the buffer. + * Used before adding a new scrollback line or updating the buffer for lines + * displayed in the terminal. + */ + static void +cleanup_scrollback(term_T *term) +{ + sb_line_T *line; + garray_T *gap; + + gap = &term->tl_scrollback; + while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled + && gap->ga_len > 0) + { + ml_delete(curbuf->b_ml.ml_line_count, FALSE); + line = (sb_line_T *)gap->ga_data + gap->ga_len - 1; + vim_free(line->sb_cells); + --gap->ga_len; + } + check_cursor(); +} + /* * Add the current lines of the terminal to scrollback and to the buffer. * Called after the job has ended and when switching to Terminal-Normal mode. @@ -1459,9 +1484,22 @@ move_terminal_to_buffer(term_T *term) if (term->tl_vterm == NULL) return; + + /* Nothing to do if the buffer already has the lines and nothing was + * changed. */ + if (!term->tl_dirty_snapshot + && curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled) + return; + + ch_log(term->tl_job == NULL ? NULL : term->tl_job->jv_channel, + "Adding terminal window snapshot to buffer"); + + /* First remove the lines that were appended before, they might be + * outdated. */ + cleanup_scrollback(term); + screen = vterm_obtain_screen(term->tl_vterm); fill_attr = new_fill_attr = term->tl_default_color; - for (pos.row = 0; pos.row < term->tl_rows; ++pos.row) { len = 0; @@ -1548,6 +1586,11 @@ move_terminal_to_buffer(term_T *term) } } + term->tl_dirty_snapshot = FALSE; +#ifdef FEAT_TIMERS + term->tl_timer_set = FALSE; +#endif + /* Obtain the current background color. */ vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), &term->tl_default_color.fg, &term->tl_default_color.bg); @@ -1571,6 +1614,38 @@ move_terminal_to_buffer(term_T *term) } } +#if defined(FEAT_TIMERS) || defined(PROTO) +/* + * Check if any terminal timer expired. If so, copy text from the terminal to + * the buffer. + * Return the time until the next timer will expire. + */ + int +term_check_timers(int next_due_arg, proftime_T *now) +{ + term_T *term; + int next_due = next_due_arg; + + for (term = first_term; term != NULL; term = term->tl_next) + { + if (term->tl_timer_set && !term->tl_normal_mode) + { + long this_due = proftime_time_left(&term->tl_timer_due, now); + + if (this_due <= 1) + { + term->tl_timer_set = FALSE; + move_terminal_to_buffer(term); + } + else if (next_due == -1 || next_due > this_due) + next_due = this_due; + } + } + + return next_due; +} +#endif + static void set_terminal_mode(term_T *term, int normal_mode) { @@ -1638,20 +1713,6 @@ term_in_normal_mode(void) term_enter_job_mode() { term_T *term = curbuf->b_term; - sb_line_T *line; - garray_T *gap; - - /* Remove the terminal contents from the scrollback and the buffer. */ - gap = &term->tl_scrollback; - while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled - && gap->ga_len > 0) - { - ml_delete(curbuf->b_ml.ml_line_count, FALSE); - line = (sb_line_T *)gap->ga_data + gap->ga_len - 1; - vim_free(line->sb_cells); - --gap->ga_len; - } - check_cursor(); set_terminal_mode(term, FALSE); @@ -2174,6 +2235,12 @@ theend: in_terminal_loop = NULL; if (restore_cursor) prepare_restore_cursor_props(); + + /* Move a snapshot of the screen contents to the buffer, so that completion + * works in other buffers. */ + if (curbuf->b_term != NULL) + move_terminal_to_buffer(curbuf->b_term); + return ret; } @@ -2390,6 +2457,20 @@ cell2attr(VTermScreenCellAttrs cellattrs, VTermColor cellfg, VTermColor cellbg) return 0; } + static void +set_dirty_snapshot(term_T *term) +{ + term->tl_dirty_snapshot = TRUE; +#ifdef FEAT_TIMERS + if (!term->tl_normal_mode) + { + /* Update the snapshot after 100 msec of not getting updates. */ + profile_setlimit(100L, &term->tl_timer_due); + term->tl_timer_set = TRUE; + } +#endif +} + static int handle_damage(VTermRect rect, void *user) { @@ -2397,6 +2478,7 @@ handle_damage(VTermRect rect, void *user) term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row); term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row); + set_dirty_snapshot(term); redraw_buf_later(term->tl_buffer, SOME_VALID); return 1; } @@ -2443,6 +2525,7 @@ handle_moverect(VTermRect dest, VTermRect src, void *user) term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row); term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row); + set_dirty_snapshot(term); /* Note sure if the scrolling will work correctly, let's do a complete * redraw later. */ @@ -2594,6 +2677,10 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user) { term_T *term = (term_T *)user; + /* First remove the lines that were appended before, the pushed line goes + * above it. */ + cleanup_scrollback(term); + /* If the number of lines that are stored goes over 'termscrollback' then * delete the first 10%. */ if (term->tl_scrollback.ga_len >= term->tl_buffer->b_p_twsl) diff --git a/src/version.c b/src/version.c index b71b384f1b..59b25bf921 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1810, /**/ 1809, /**/ From 72cf47a279f7261abf4ae6c9c3ee54024ee87a12 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 18:23:29 +0200 Subject: [PATCH 5/7] patch 8.0.1811: no test for winrestcmd() Problem: No test for winrestcmd(). Solution: Add a test. (Dominique Pelle, closes #2894) --- src/testdir/test_window_cmd.vim | 23 +++++++++++++++++++---- src/version.c | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 296cba2fd8..423d6f8d2c 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -17,7 +17,7 @@ func Test_window_cmd_ls0_with_split() endfunc func Test_window_cmd_cmdwin_with_vsp() - let efmt='Expected 0 but got %d (in ls=%d, %s window)' + let efmt = 'Expected 0 but got %d (in ls=%d, %s window)' for v in range(0, 2) exec "set ls=" . v vsplit @@ -444,21 +444,21 @@ func Test_window_contents() exe "norm! \t\=1Gzt\w\+" redraw - let s3=GetScreenStr(1) + let s3 = GetScreenStr(1) wincmd p call assert_equal(1, line("w0")) call assert_equal('1 ', s3) exe "norm! \t\=50Gzt\w\+" redraw - let s3=GetScreenStr(1) + let s3 = GetScreenStr(1) wincmd p call assert_equal(50, line("w0")) call assert_equal('50 ', s3) exe "norm! \t\=59Gzt\w\+" redraw - let s3=GetScreenStr(1) + let s3 = GetScreenStr(1) wincmd p call assert_equal(59, line("w0")) call assert_equal('59 ', s3) @@ -507,4 +507,19 @@ func Test_visual_cleared_after_window_split() bwipe! endfunc +func Test_winrestcmd() + 2split + 3vsplit + let a = winrestcmd() + call assert_equal(2, winheight(0)) + call assert_equal(3, winwidth(0)) + wincmd = + call assert_notequal(2, winheight(0)) + call assert_notequal(3, winwidth(0)) + exe a + call assert_equal(2, winheight(0)) + call assert_equal(3, winwidth(0)) + only +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 59b25bf921..d8819ae5b4 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1811, /**/ 1810, /**/ From 7a2b0e55e9460493c4a949bda8be70950dbb8f85 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 18:55:28 +0200 Subject: [PATCH 6/7] patch 8.0.1812: the qf_jump_to_usable_window() function is too long Problem: The qf_jump_to_usable_window() function is too long. Solution: Split it in parts. (Yegappan Lakshmanan, closes #2891) --- src/quickfix.c | 341 +++++++++++++++++++++++++++++-------------------- src/version.c | 2 + 2 files changed, 208 insertions(+), 135 deletions(-) diff --git a/src/quickfix.c b/src/quickfix.c index dbd42ee4a1..9e21191e70 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -2027,7 +2027,7 @@ qf_clean_dir_stack(struct dir_stack_T **stackptr) * Cleans up intermediate directory entries. * * TODO: How to solve the following problem? - * If we have the this directory tree: + * If we have this directory tree: * ./ * ./aa * ./aa/bb @@ -2079,7 +2079,7 @@ qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *filename) vim_free(ds_tmp); } - return ds_ptr==NULL? NULL: ds_ptr->dirname; + return ds_ptr == NULL ? NULL : ds_ptr->dirname; } /* @@ -2108,7 +2108,7 @@ qflist_valid (win_T *wp, int_u qf_id) /* * When loading a file from the quickfix, the auto commands may modify it. * This may invalidate the current quickfix entry. This function checks - * whether a entry is still present in the quickfix. + * whether an entry is still present in the quickfix list. * Similar to location list. */ static int @@ -2272,6 +2272,21 @@ get_nth_entry( return qf_ptr; } +/* + * Find a window displaying a Vim help file. + */ + static win_T * +qf_find_help_win(void) +{ + win_T *wp; + + FOR_ALL_WINDOWS(wp) + if (bt_help(wp->w_buffer)) + return wp; + + return NULL; +} + /* * Find a help window or open one. */ @@ -2284,9 +2299,7 @@ jump_to_help_window(qf_info_T *qi, int *opened_window) if (cmdmod.tab != 0) wp = NULL; else - FOR_ALL_WINDOWS(wp) - if (bt_help(wp->w_buffer)) - break; + wp = qf_find_help_win(); if (wp != NULL && wp->w_buffer->b_nwindows > 0) win_enter(wp, TRUE); else @@ -2325,8 +2338,175 @@ jump_to_help_window(qf_info_T *qi, int *opened_window) } /* - * Find a suitable window for opening a file (qf_fnum) and jump to it. - * If the file is already opened in a window, jump to it. + * Find a non-quickfix window using the given location list. + * Returns NULL if a matching window is not found. + */ + static win_T * +qf_find_win_with_loclist(qf_info_T *ll) +{ + win_T *wp; + + FOR_ALL_WINDOWS(wp) + if (wp->w_llist == ll && !bt_quickfix(wp->w_buffer)) + return wp; + + return NULL; +} + +/* + * Find a window containing a normal buffer + */ + static win_T * +qf_find_win_with_normal_buf(void) +{ + win_T *wp; + + FOR_ALL_WINDOWS(wp) + if (wp->w_buffer->b_p_bt[0] == NUL) + return wp; + + return NULL; +} + +/* + * Go to a window in any tabpage containing the specified file. Returns TRUE + * if successfully jumped to the window. Otherwise returns FALSE. + */ + static int +qf_goto_tabwin_with_file(int fnum) +{ + tabpage_T *tp; + win_T *wp; + + FOR_ALL_TAB_WINDOWS(tp, wp) + if (wp->w_buffer->b_fnum == fnum) + { + goto_tabpage_win(tp, wp); + return TRUE; + } + + return FALSE; +} + +/* + * Create a new window to show a file above the quickfix window. Called when + * only the quickfix window is present. + */ + static int +qf_open_new_file_win(qf_info_T *ll_ref) +{ + int flags; + + flags = WSP_ABOVE; + if (ll_ref != NULL) + flags |= WSP_NEWLOC; + if (win_split(0, flags) == FAIL) + return FAIL; /* not enough room for window */ + p_swb = empty_option; /* don't split again */ + swb_flags = 0; + RESET_BINDING(curwin); + if (ll_ref != NULL) + { + /* The new window should use the location list from the + * location list window */ + curwin->w_llist = ll_ref; + ll_ref->qf_refcount++; + } + return OK; +} + +/* + * Go to a window that shows the right buffer. If the window is not found, go + * to the window just above the location list window. This is used for opening + * a file from a location window and not from a quickfix window. If some usable + * window is previously found, then it is supplied in 'use_win'. + */ + static void +qf_goto_win_with_ll_file(win_T *use_win, int qf_fnum, qf_info_T *ll_ref) +{ + win_T *win = use_win; + + if (win == NULL) + { + /* Find the window showing the selected file */ + FOR_ALL_WINDOWS(win) + if (win->w_buffer->b_fnum == qf_fnum) + break; + if (win == NULL) + { + /* Find a previous usable window */ + win = curwin; + do + { + if (win->w_buffer->b_p_bt[0] == NUL) + break; + if (win->w_prev == NULL) + win = lastwin; /* wrap around the top */ + else + win = win->w_prev; /* go to previous window */ + } while (win != curwin); + } + } + win_goto(win); + + /* If the location list for the window is not set, then set it + * to the location list from the location window */ + if (win->w_llist == NULL) + { + win->w_llist = ll_ref; + ll_ref->qf_refcount++; + } +} + +/* + * Go to a window that shows the specified file. If a window is not found, go + * to the window just above the quickfix window. This is used for opening a + * file from a quickfix window and not from a location window. + */ + static void +qf_goto_win_with_qfl_file(int qf_fnum) +{ + win_T *win; + win_T *altwin; + + win = curwin; + altwin = NULL; + for (;;) + { + if (win->w_buffer->b_fnum == qf_fnum) + break; + if (win->w_prev == NULL) + win = lastwin; /* wrap around the top */ + else + win = win->w_prev; /* go to previous window */ + + if (IS_QF_WINDOW(win)) + { + /* Didn't find it, go to the window before the quickfix + * window. */ + if (altwin != NULL) + win = altwin; + else if (curwin->w_prev != NULL) + win = curwin->w_prev; + else + win = curwin->w_next; + break; + } + + /* Remember a usable window. */ + if (altwin == NULL && !win->w_p_pvw + && win->w_buffer->b_p_bt[0] == NUL) + altwin = win; + } + + win_goto(win); +} + +/* + * Find a suitable window for opening a file (qf_fnum) from the + * quickfix/location list and jump to it. If the file is already opened in a + * window, jump to it. Otherwise open a new window to display the file. This is + * called from either a quickfix or a location list window. */ static int qf_jump_to_usable_window(int qf_fnum, int *opened_window) @@ -2334,35 +2514,25 @@ qf_jump_to_usable_window(int qf_fnum, int *opened_window) win_T *usable_win_ptr = NULL; int usable_win; qf_info_T *ll_ref; - int flags; win_T *win; - win_T *altwin; usable_win = 0; ll_ref = curwin->w_llist_ref; if (ll_ref != NULL) { - /* Find a window using the same location list that is not a - * quickfix window. */ - FOR_ALL_WINDOWS(usable_win_ptr) - if (usable_win_ptr->w_llist == ll_ref - && !bt_quickfix(usable_win_ptr->w_buffer)) - { - usable_win = 1; - break; - } + /* Find a non-quickfix window with this location list */ + usable_win_ptr = qf_find_win_with_loclist(ll_ref); + if (usable_win_ptr != NULL) + usable_win = 1; } if (!usable_win) { /* Locate a window showing a normal buffer */ - FOR_ALL_WINDOWS(win) - if (win->w_buffer->b_p_bt[0] == NUL) - { - usable_win = 1; - break; - } + win = qf_find_win_with_normal_buf(); + if (win != NULL) + usable_win = 1; } /* @@ -2370,21 +2540,7 @@ qf_jump_to_usable_window(int qf_fnum, int *opened_window) * then search in other tabs. */ if (!usable_win && (swb_flags & SWB_USETAB)) - { - tabpage_T *tp; - win_T *wp; - - FOR_ALL_TAB_WINDOWS(tp, wp) - { - if (wp->w_buffer->b_fnum == qf_fnum) - { - goto_tabpage_win(tp, wp); - usable_win = 1; - goto win_found; - } - } - } -win_found: + usable_win = qf_goto_tabwin_with_file(qf_fnum); /* * If there is only one window and it is the quickfix window, create a @@ -2392,99 +2548,16 @@ win_found: */ if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) { - flags = WSP_ABOVE; - if (ll_ref != NULL) - flags |= WSP_NEWLOC; - if (win_split(0, flags) == FAIL) - return FAIL; /* not enough room for window */ + if (qf_open_new_file_win(ll_ref) != OK) + return FAIL; *opened_window = TRUE; /* close it when fail */ - p_swb = empty_option; /* don't split again */ - swb_flags = 0; - RESET_BINDING(curwin); - if (ll_ref != NULL) - { - /* The new window should use the location list from the - * location list window */ - curwin->w_llist = ll_ref; - ll_ref->qf_refcount++; - } } else { - if (curwin->w_llist_ref != NULL) - { - /* In a location window */ - win = usable_win_ptr; - if (win == NULL) - { - /* Find the window showing the selected file */ - FOR_ALL_WINDOWS(win) - if (win->w_buffer->b_fnum == qf_fnum) - break; - if (win == NULL) - { - /* Find a previous usable window */ - win = curwin; - do - { - if (win->w_buffer->b_p_bt[0] == NUL) - break; - if (win->w_prev == NULL) - win = lastwin; /* wrap around the top */ - else - win = win->w_prev; /* go to previous window */ - } while (win != curwin); - } - } - win_goto(win); - - /* If the location list for the window is not set, then set it - * to the location list from the location window */ - if (win->w_llist == NULL) - { - win->w_llist = ll_ref; - ll_ref->qf_refcount++; - } - } - else - { - - /* - * Try to find a window that shows the right buffer. - * Default to the window just above the quickfix buffer. - */ - win = curwin; - altwin = NULL; - for (;;) - { - if (win->w_buffer->b_fnum == qf_fnum) - break; - if (win->w_prev == NULL) - win = lastwin; /* wrap around the top */ - else - win = win->w_prev; /* go to previous window */ - - if (IS_QF_WINDOW(win)) - { - /* Didn't find it, go to the window before the quickfix - * window. */ - if (altwin != NULL) - win = altwin; - else if (curwin->w_prev != NULL) - win = curwin->w_prev; - else - win = curwin->w_next; - break; - } - - /* Remember a usable window. */ - if (altwin == NULL && !win->w_p_pvw - && win->w_buffer->b_p_bt[0] == NUL) - altwin = win; - } - - win_goto(win); - } + if (curwin->w_llist_ref != NULL) /* In a location window */ + qf_goto_win_with_ll_file(usable_win_ptr, qf_fnum, ll_ref); + else /* In a quickfix window */ + qf_goto_win_with_qfl_file(qf_fnum); } return OK; @@ -2562,8 +2635,8 @@ qf_jump_edit_buffer( } /* - * Goto the error line in the current file using either line/column number or a - * search pattern. + * Go to the error line in the current file using either line/column number or + * a search pattern. */ static void qf_jump_goto_line( @@ -5779,7 +5852,7 @@ qf_setprop_context(qf_info_T *qi, int qf_idx, dictitem_T *di) /* * Set quickfix/location list properties (title, items, context). * Also used to add items from parsing a list of lines. - * Used by the setqflist() and setloclist() VimL functions. + * Used by the setqflist() and setloclist() Vim script functions. */ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title) @@ -6162,9 +6235,7 @@ hgr_get_ll(int *new_ll) wp = curwin; else /* Find an existing help window */ - FOR_ALL_WINDOWS(wp) - if (bt_help(wp->w_buffer)) - break; + wp = qf_find_help_win(); if (wp == NULL) /* Help window not found */ qi = NULL; diff --git a/src/version.c b/src/version.c index d8819ae5b4..a2644f1a37 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1812, /**/ 1811, /**/ From 38623c8512ae3d1bd9556a7b99fc6f7b3a9b1cda Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 10 May 2018 21:24:35 +0200 Subject: [PATCH 7/7] patch 8.0.1813: Windows installer doesn't install terminal debugger Problem: Windows installer doesn't install terminal debugger. Solution: Add the package to the list of files to install. --- nsis/gvim.nsi | 3 +++ src/version.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/nsis/gvim.nsi b/nsis/gvim.nsi index a1820f449f..55bb4ce007 100644 --- a/nsis/gvim.nsi +++ b/nsis/gvim.nsi @@ -267,6 +267,9 @@ Section "Vim executables and runtime files" SetOutPath $0\pack\dist\opt\swapmouse\plugin File ${VIMRT}\pack\dist\opt\swapmouse\plugin\*.* + SetOutPath $0\pack\dist\opt\termdebug\plugin + File ${VIMRT}\pack\dist\opt\termdebug\plugin\*.* + SetOutPath $0\plugin File ${VIMRT}\plugin\*.* diff --git a/src/version.c b/src/version.c index a2644f1a37..966463a49e 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1813, /**/ 1812, /**/