summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-08-13 20:06:18 +0200
committerBram Moolenaar <Bram@vim.org>2017-08-13 20:06:18 +0200
commit4f44b886840a90a50575204bc29f72ef309cfaf6 (patch)
treef4a8bfe4b58442ecf4730d55f87c5aed2078241d
parent69905d108be4af86c2d2a9224e2c588723276dc9 (diff)
patch 8.0.0932: terminal may not use right characters for BS and Enterv8.0.0932
Problem: Terminal may not use right characters for BS and Enter. Solution: Get the characters from the tty.
-rw-r--r--src/os_unix.c84
-rw-r--r--src/proto/os_unix.pro1
-rw-r--r--src/terminal.c77
-rw-r--r--src/version.c2
4 files changed, 109 insertions, 55 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index c56de66db2..40e0762ead 100644
--- 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;
+ ttyinfo_T info;
+ 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 */
+ 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 <BS> and <DEL> are now the same, redefine <DEL>. */
+ 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)
+ ioctl(fd, TCGETA, &keys) != -1
# endif
+ )
{
- buf[0] = keys.c_cc[VERASE];
- intr_char = keys.c_cc[VINTR];
+ 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)
+ if (ioctl(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 <BS> and <DEL> are now the same, redefine <DEL>.
- */
- p = find_termcode((char_u *)"kD");
- if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
- do_fixdel(NULL);
+ info->backspace = keys.sg_erase;
+ info->interrupt = keys.sg_kill;
+ info->enter = CAR;
+ info->nl_does_cr = TRUE;
+ return OK;
}
-#if 0
- } /* to keep cindent happy */
#endif
+ return FAIL;
}
#endif /* VMS */
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
index 20765c06fb..80539d34dd 100644
--- 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
index 7e3acf96e1..3171936b19 100644
--- 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 *term, int rows, int cols,
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_u *msg, size_t len)
size_t done;
size_t len_now;
- for (done = 0; done < len; done += len_now)
- {
- 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)
+ 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)
{
- /* Convert NL to CR-NL, that appears to work best. */
- vterm_input_write(vterm, "\r\n", 2);
- ++len_now;
+ 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;
+ }
}
- }
/* 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, char *buf)
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
index 99a01b1d24..850be59f4a 100644
--- 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,