# HG changeset patch # User Christian Brabandt # Date 1500585303 -7200 # Node ID 2ec27561dd763e6356413e740d47c9b89b10739f # Parent 1347bc230b5f9db85754747236c94f3a80e2a23e patch 8.0.0739: terminal resizing doesn't work well. commit https://github.com/vim/vim/commit/58556cd0e592cba75bf60310d822a20e41f6b02e Author: Bram Moolenaar Date: Thu Jul 20 23:04:46 2017 +0200 patch 8.0.0739: terminal resizing doesn't work well. Problem: Terminal resizing doesn't work well. Solution: Resize the terminal to the Vim window and the other way around. Avoid mapping typed keys. Set the environment properly. diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4054,38 +4054,48 @@ mch_parse_cmd(char_u *cmd, int use_shcf, #if !defined(USE_SYSTEM) || defined(FEAT_JOB_CHANNEL) static void -set_child_environment(void) +set_child_environment(long rows, long columns, char *term) { # ifdef HAVE_SETENV char envbuf[50]; # else + static char envbuf_TERM[30]; static char envbuf_Rows[20]; + static char envbuf_Lines[20]; static char envbuf_Columns[20]; # endif /* Simulate to have a dumb terminal (for now) */ # ifdef HAVE_SETENV - setenv("TERM", "dumb", 1); - sprintf((char *)envbuf, "%ld", Rows); + setenv("TERM", term, 1); + sprintf((char *)envbuf, "%ld", rows); setenv("ROWS", (char *)envbuf, 1); - sprintf((char *)envbuf, "%ld", Rows); + sprintf((char *)envbuf, "%ld", rows); setenv("LINES", (char *)envbuf, 1); - sprintf((char *)envbuf, "%ld", Columns); + sprintf((char *)envbuf, "%ld", columns); setenv("COLUMNS", (char *)envbuf, 1); # else /* * Putenv does not copy the string, it has to remain valid. * Use a static array to avoid losing allocated memory. */ - putenv("TERM=dumb"); - sprintf(envbuf_Rows, "ROWS=%ld", Rows); + vim_snprintf(envbuf_Term, sizeof(envbuf_Term), "TERM=%s", term); + putenv(envbuf_Term); + vim_snprintf(envbuf_Rows, sizeof(envbuf_Rows), "ROWS=%ld", rows); putenv(envbuf_Rows); - sprintf(envbuf_Rows, "LINES=%ld", Rows); - putenv(envbuf_Rows); - sprintf(envbuf_Columns, "COLUMNS=%ld", Columns); + vim_snprintf(envbuf_Lines, sizeof(envbuf_Lines), "LINES=%ld", rows); + putenv(envbuf_Lines); + vim_snprintf(envbuf_Columns, sizeof(envbuf_Columns), + "COLUMNS=%ld", columns); putenv(envbuf_Columns); # endif } + + static void +set_default_child_environment(void) +{ + set_child_environment(Rows, Columns, "dumb"); +} #endif int @@ -4417,7 +4427,7 @@ mch_call_shell( # endif } # endif - set_child_environment(); + set_default_child_environment(); /* * stderr is only redirected when using the GUI, so that a @@ -5090,7 +5100,7 @@ error: #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) void -mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED) +mch_start_job(char **argv, job_T *job, jobopt_T *options) { pid_t pid; int fd_in[2]; /* for stdin */ @@ -5200,7 +5210,15 @@ mch_start_job(char **argv, job_T *job, j (void)setsid(); # endif - set_child_environment(); +# ifdef FEAT_TERMINAL + if (options->jo_term_rows > 0) + set_child_environment( + (long)options->jo_term_rows, + (long)options->jo_term_cols, + "xterm"); + else +# endif + set_default_child_environment(); if (use_null_for_in || use_null_for_out || use_null_for_err) null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1732,6 +1732,12 @@ typedef struct int jo_id; char_u jo_soe_buf[NUMBUFLEN]; char_u *jo_stoponexit; + +#ifdef FEAT_TERMINAL + /* when non-zero run the job in a terminal window of this size */ + int jo_term_rows; + int jo_term_cols; +#endif } jobopt_T; diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -184,6 +184,8 @@ ex_terminal(exarg_T *eap) opt.jo_io_buf[PART_OUT] = curbuf->b_fnum; opt.jo_io_buf[PART_ERR] = curbuf->b_fnum; opt.jo_set |= JO_OUT_BUF + (JO_OUT_BUF << (PART_ERR - PART_OUT)); + opt.jo_term_rows = rows; + opt.jo_term_cols = cols; term->tl_job = job_start(argvars, &opt); } @@ -267,7 +269,11 @@ terminal_loop(void) update_screen(0); setcursor(); out_flush(); + ++no_mapping; + ++allow_keys; c = vgetc(); + --no_mapping; + --allow_keys; /* Catch keys that need to be handled as in Normal mode. */ switch (c) @@ -331,6 +337,13 @@ term_update_window(win_T *wp) term_update_lines(wp); } + static void +position_cursor(win_T *wp, VTermPos *pos) +{ + wp->w_wrow = MIN(pos->row, MAX(0, wp->w_height - 1)); + wp->w_wcol = MIN(pos->col, MAX(0, wp->w_width - 1)); +} + #ifdef WIN3264 /************************************** @@ -486,7 +499,7 @@ handle_damage(VTermRect rect, void *user } static int -handle_moverect(VTermRect dest, VTermRect src, void *user) +handle_moverect(VTermRect dest UNUSED, VTermRect src UNUSED, void *user) { term_T *term = (term_T *)user; @@ -496,7 +509,11 @@ handle_moverect(VTermRect dest, VTermRec } static int -handle_movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user) +handle_movecursor( + VTermPos pos, + VTermPos oldpos UNUSED, + int visible UNUSED, + void *user) { term_T *term = (term_T *)user; win_T *wp; @@ -506,9 +523,7 @@ handle_movecursor(VTermPos pos, VTermPos { if (wp->w_buffer == term->tl_buffer) { - /* TODO: limit to window size? */ - wp->w_wrow = pos.row; - wp->w_wcol = pos.col; + position_cursor(wp, &pos); if (wp == curwin) is_current = TRUE; } @@ -527,8 +542,17 @@ handle_movecursor(VTermPos pos, VTermPos handle_resize(int rows, int cols, void *user) { term_T *term = (term_T *)user; + win_T *wp; - /* TODO: handle terminal resize. */ + FOR_ALL_WINDOWS(wp) + { + if (wp->w_buffer == term->tl_buffer) + { + win_setheight_win(rows, wp); + win_setwidth_win(cols, wp); + } + } + redraw_buf_later(term->tl_buffer, NOT_VALID); return 1; } @@ -648,10 +672,23 @@ term_update_lines(win_T *wp) int vterm_cols; VTerm *vterm = wp->w_buffer->b_term->tl_vterm; VTermScreen *screen = vterm_obtain_screen(vterm); + VTermState *state = vterm_obtain_state(vterm); VTermPos pos; vterm_get_size(vterm, &vterm_rows, &vterm_cols); + if (*wp->w_p_tms == NUL + && (vterm_rows != wp->w_height || vterm_cols != wp->w_width)) + { + vterm_set_size(vterm, wp->w_height, wp->w_width); + /* Get the size again, in case setting the didn't work. */ + vterm_get_size(vterm, &vterm_rows, &vterm_cols); + } + + /* The cursor may have been moved when resizing. */ + vterm_state_get_cursorpos(state, &pos); + position_cursor(wp, &pos); + /* TODO: Only redraw what changed. */ for (pos.row = 0; pos.row < wp->w_height; ++pos.row) { diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 739, +/**/ 738, /**/ 737,