# HG changeset patch # User Christian Brabandt # Date 1502648104 -7200 # Node ID 3bf5fe164a9f9b1894135e6bf38cb64992582279 # Parent a57e00bfee9457a54c5258fdcd81272764fd28dc patch 8.0.0932: terminal may not use right characters for BS and Enter commit https://github.com/vim/vim/commit/4f44b886840a90a50575204bc29f72ef309cfaf6 Author: Bram Moolenaar Date: Sun Aug 13 20:06:18 2017 +0200 patch 8.0.0932: terminal may not use right characters for BS and Enter Problem: Terminal may not use right characters for BS and Enter. Solution: Get the characters from the tty. diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -365,6 +365,11 @@ mch_chdir(char *path) # endif } +/* Why is NeXT excluded here (and not in os_unixx.h)? */ +#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__) +# define NEW_TTY_SYSTEM +#endif + /* * Write s[len] to the screen. */ @@ -3385,11 +3390,7 @@ mch_settmode(int tmode) { static int first = TRUE; - /* Why is NeXT excluded here (and not in os_unixx.h)? */ -#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__) - /* - * for "new" tty systems - */ +#ifdef NEW_TTY_SYSTEM # ifdef HAVE_TERMIOS_H static struct termios told; struct termios tnew; @@ -3451,7 +3452,6 @@ mch_settmode(int tmode) # endif #else - /* * for "old" tty systems */ @@ -3492,48 +3492,72 @@ mch_settmode(int tmode) void get_stty(void) { - char_u buf[2]; - char_u *p; - - /* Why is NeXT excluded here (and not in os_unixx.h)? */ -#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__) - /* for "new" tty systems */ + ttyinfo_T info; + char_u buf[2]; + char_u *p; + + if (get_tty_info(read_cmd_fd, &info) == OK) + { + intr_char = info.interrupt; + buf[0] = info.backspace; + buf[1] = NUL; + add_termcode((char_u *)"kb", buf, FALSE); + + /* If and are now the same, redefine . */ + p = find_termcode((char_u *)"kD"); + if (p != NULL && p[0] == buf[0] && p[1] == buf[1]) + do_fixdel(NULL); + } +} + +/* + * Obtain the characters that Backspace and Enter produce on "fd". + * Returns OK or FAIL. + */ + int +get_tty_info(int fd, ttyinfo_T *info) +{ +#ifdef NEW_TTY_SYSTEM # ifdef HAVE_TERMIOS_H struct termios keys; # else struct termio keys; # endif + if ( # if defined(HAVE_TERMIOS_H) - if (tcgetattr(read_cmd_fd, &keys) != -1) + tcgetattr(fd, &keys) != -1 # else - if (ioctl(read_cmd_fd, TCGETA, &keys) != -1) -# endif - { - buf[0] = keys.c_cc[VERASE]; - intr_char = keys.c_cc[VINTR]; + ioctl(fd, TCGETA, &keys) != -1 +# endif + ) + { + info->backspace = keys.c_cc[VERASE]; + info->interrupt = keys.c_cc[VINTR]; + if (keys.c_iflag & ICRNL) + info->enter = NL; + else + info->enter = CAR; + if (keys.c_oflag & ONLCR) + info->nl_does_cr = TRUE; + else + info->nl_does_cr = FALSE; + return OK; + } #else /* for "old" tty systems */ struct sgttyb keys; - if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1) - { - buf[0] = keys.sg_erase; - intr_char = keys.sg_kill; -#endif - buf[1] = NUL; - add_termcode((char_u *)"kb", buf, FALSE); - - /* - * If and are now the same, redefine . - */ - p = find_termcode((char_u *)"kD"); - if (p != NULL && p[0] == buf[0] && p[1] == buf[1]) - do_fixdel(NULL); - } -#if 0 - } /* to keep cindent happy */ -#endif + if (ioctl(fd, TIOCGETP, &keys) != -1) + { + info->backspace = keys.sg_erase; + info->interrupt = keys.sg_kill; + info->enter = CAR; + info->nl_does_cr = TRUE; + return OK; + } +#endif + return FAIL; } #endif /* VMS */ diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -50,6 +50,7 @@ void mch_free_mem(void); void mch_exit(int r); void mch_settmode(int tmode); void get_stty(void); +int get_tty_info(int fd, ttyinfo_T *info); void mch_setmouse(int on); void check_mouse_termcode(void); int mch_screenmode(char_u *arg); diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -38,11 +38,6 @@ * in tl_scrollback are no longer used. * * TODO: - * - To set BS correctly, check get_stty(); Pass the fd of the pty. - * For the GUI fill termios with default values, perhaps like pangoterm: - * http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134 - * Also get the NL behavior from there. - * - do not store terminal window in viminfo. Or prefix term:// ? * - add a character in :ls output * - add 't' to mode() * - use win_del_lines() to make scroll-up efficient. @@ -52,8 +47,7 @@ * - add test for giving error for invalid 'termsize' value. * - support minimal size when 'termsize' is "rows*cols". * - support minimal size when 'termsize' is empty? - * - implement "term" for job_start(): more job options when starting a - * terminal. Allow: + * - implement job options when starting a terminal. Allow: * "in_io", "in_top", "in_bot", "in_name", "in_buf" "out_io", "out_name", "out_buf", "out_modifiable", "out_msg" "err_io", "err_name", "err_buf", "err_modifiable", "err_msg" @@ -61,6 +55,8 @@ * Test: "cat" reading from a file or buffer * "ls" writing stdout to a file or buffer * shell writing stderr to a file or buffer + * - For the GUI fill termios with default values, perhaps like pangoterm: + * http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134 * - support ":term NONE" to open a terminal with a pty but not running a job * in it. The pty can be passed to gdb to run the executable in. * - if the job in the terminal does not support the mouse, we can use the @@ -168,6 +164,13 @@ static int term_and_job_init(term_T *ter static void term_report_winsize(term_T *term, int rows, int cols); static void term_free_vterm(term_T *term); +/* The characters that we know (or assume) that the terminal expects for the + * backspace and enter keys. */ +static int term_backspace_char = BS; +static int term_enter_char = CAR; +static int term_nl_does_cr = FALSE; + + /************************************** * 1. Generic code for all systems. */ @@ -552,23 +555,26 @@ term_write_job_output(term_T *term, char size_t done; size_t len_now; - for (done = 0; done < len; done += len_now) - { - for (p = msg + done; p < msg + len; ) + if (term_nl_does_cr) + vterm_input_write(vterm, (char *)msg, len); + else + /* need to convert NL to CR-NL */ + for (done = 0; done < len; done += len_now) { - if (*p == NL) - break; - p += utf_ptr2len_len(p, (int)(len - (p - msg))); + for (p = msg + done; p < msg + len; ) + { + if (*p == NL) + break; + p += utf_ptr2len_len(p, (int)(len - (p - msg))); + } + len_now = p - msg - done; + vterm_input_write(vterm, (char *)msg + done, len_now); + if (p < msg + len && *p == NL) + { + vterm_input_write(vterm, "\r\n", 2); + ++len_now; + } } - len_now = p - msg - done; - vterm_input_write(vterm, (char *)msg + done, len_now); - if (p < msg + len && *p == NL) - { - /* Convert NL to CR-NL, that appears to work best. */ - vterm_input_write(vterm, "\r\n", 2); - ++len_now; - } - } /* this invokes the damage callbacks */ vterm_screen_flush_damage(vterm_obtain_screen(vterm)); @@ -654,10 +660,12 @@ term_convert_key(term_T *term, int c, ch switch (c) { - case CAR: key = VTERM_KEY_ENTER; break; + case CAR: c = term_enter_char; break; + /* don't use VTERM_KEY_BACKSPACE, it always + * becomes 0x7f DEL */ + case K_BS: c = term_backspace_char; break; + case ESC: key = VTERM_KEY_ESCAPE; break; - /* VTERM_KEY_BACKSPACE becomes 0x7f DEL */ - case K_BS: c = BS; break; case K_DEL: key = VTERM_KEY_DEL; break; case K_DOWN: key = VTERM_KEY_DOWN; break; case K_S_DOWN: mod = VTERM_MOD_SHIFT; @@ -1321,6 +1329,25 @@ terminal_loop(void) position_cursor(curwin, &curbuf->b_term->tl_cursor_pos); may_set_cursor_props(curbuf->b_term); +#ifdef UNIX + { + int fd = curbuf->b_term->tl_job->jv_channel->ch_part[PART_IN].ch_fd; + + if (isatty(fd)) + { + ttyinfo_T info; + + /* Get the current backspace and enter characters of the pty. */ + if (get_tty_info(fd, &info) == OK) + { + term_backspace_char = info.backspace; + term_enter_char = info.enter; + term_nl_does_cr = info.nl_does_cr; + } + } + } +#endif + for (;;) { /* TODO: skip screen update when handling a sequence of keys. */ 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 */ /**/ + 932, +/**/ 931, /**/ 930,