]> granicus.if.org Git - vim/commitdiff
patch 8.0.0932: terminal may not use right characters for BS and Enter v8.0.0932
authorBram Moolenaar <Bram@vim.org>
Sun, 13 Aug 2017 18:06:18 +0000 (20:06 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 13 Aug 2017 18:06:18 +0000 (20:06 +0200)
Problem:    Terminal may not use right characters for BS and Enter.
Solution:   Get the characters from the tty.

src/os_unix.c
src/proto/os_unix.pro
src/terminal.c
src/version.c

index c56de66db2453115b6bf92241551bc4102106f89..40e0762ead3e3d93575370d362464660606cd103 100644 (file)
@@ -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  */
index 20765c06fb6c29cbfc0d93944b51255fe11572f0..80539d34ddab6587c9530a009170da55a0f442a8 100644 (file)
@@ -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);
index 7e3acf96e1ea618fb181cd261655d69b493961bd..3171936b1968eb83753b1c4eda9729c0601d5b52 100644 (file)
  * 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. */
index 99a01b1d24530d05514301f6966361b9aab46add..850be59f4a1e99bff4a74a6739d7af0b6805406d 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    932,
 /**/
     931,
 /**/