Patch 8.0.0730
Problem:    Terminal feature only supports Unix-like systems.
Solution:   Prepare for adding an MS-Windows implementaiton.
Files:      src/terminal.c


*** ../vim-8.0.0729/src/terminal.c      2017-07-17 23:20:18.335903533 +0200
--- src/terminal.c      2017-07-18 22:48:15.997398685 +0200
***************
*** 10,27 ****
  /*
   * Terminal window support, see ":help :terminal".
   *
!  * For a terminal one VTerm is constructed.  This uses libvterm.  A copy of
!  * that library is in the libvterm directory.
   *
!  * The VTerm invokes callbacks when its screen contents changes.  The line
!  * range is stored in tl_dirty_row_start and tl_dirty_row_end.  Once in a
!  * while, if the terminal window is visible, the screen contents is drawn.
   *
   * If the terminal window has keyboard focus, typed keys are converted to the
   * terminal encoding and writting to the job over a channel.
   *
!  * If the job produces output, it is written to the VTerm.
!  * This will result in screen updates.
   *
   * TODO:
   * - pressing Enter sends two CR and/or NL characters to "bash -i"?
--- 10,32 ----
  /*
   * Terminal window support, see ":help :terminal".
   *
!  * There are three parts:
!  * 1. Generic code for all systems.
!  * 2. The MS-Windows implementation.
!  *    Uses a hidden console for the terminal emulator.
!  * 3. The Unix-like implementation.
!  *    Uses libvterm for the terminal emulator.
   *
!  * When a terminal window is opened, a job is started that will be connected 
to
!  * the terminal emulator.
   *
   * If the terminal window has keyboard focus, typed keys are converted to the
   * terminal encoding and writting to the job over a channel.
   *
!  * If the job produces output, it is written to the terminal emulator.  The
!  * terminal emulator invokes callbacks when its screen content changes.  The
!  * line range is stored in tl_dirty_row_start and tl_dirty_row_end.  Once in a
!  * while, if the terminal window is visible, the screen contents is drawn.
   *
   * TODO:
   * - pressing Enter sends two CR and/or NL characters to "bash -i"?
***************
*** 29,42 ****
   * - set buffer options to be scratch, hidden, nomodifiable, etc.
   * - set buffer name to command, add (1) to avoid duplicates.
   * - If [command] is not given the 'shell' option is used.
!  * - if the job ends, write "-- JOB ENDED --" in the terminal
!  * - when closing window and job ended, delete the terminal
   * - when closing window and job has not ended, make terminal hidden?
   * - Use a pty for I/O with the job.
   * - Windows implementation:
   *   (WiP): https://github.com/mattn/vim/tree/terminal
   *    src/os_win32.c  mch_open_terminal()
!      Using winpty ?
   * - command line completion for :terminal
   * - support fixed size when 'termsize' is "rowsXcols".
   * - support minimal size when 'termsize' is "rows*cols".
--- 34,54 ----
   * - set buffer options to be scratch, hidden, nomodifiable, etc.
   * - set buffer name to command, add (1) to avoid duplicates.
   * - If [command] is not given the 'shell' option is used.
!  * - Add a scrollback buffer (contains lines to scroll off the top).
!  *   Can use the buf_T lines, store attributes somewhere else?
!  * - When the job ends:
!  *   - Write "-- JOB ENDED --" in the terminal.
!  *   - Put the terminal contents in the scrollback buffer.
!  *   - Free the terminal emulator.
!  *   - Display the scrollback buffer (but with attributes).
!  *     Make the buffer not modifiable, drop attributes when making changes.
   * - when closing window and job has not ended, make terminal hidden?
   * - Use a pty for I/O with the job.
   * - Windows implementation:
   *   (WiP): https://github.com/mattn/vim/tree/terminal
   *    src/os_win32.c  mch_open_terminal()
!  *   Using winpty ?
!  * - use win_del_lines() to make scroll-up efficient.
   * - command line completion for :terminal
   * - support fixed size when 'termsize' is "rowsXcols".
   * - support minimal size when 'termsize' is "rows*cols".
***************
*** 57,69 ****
  
  #ifdef FEAT_TERMINAL
  
! #include "libvterm/include/vterm.h"
  
  /* typedef term_T in structs.h */
  struct terminal_S {
      term_T    *tl_next;
  
      VTerm     *tl_vterm;
      job_T     *tl_job;
      buf_T     *tl_buffer;
  
--- 69,90 ----
  
  #ifdef FEAT_TERMINAL
  
! #ifdef WIN3264
! /* MS-Windows: use a native console. */
! #else
! /* Unix-like: use libvterm. */
! # include "libvterm/include/vterm.h"
! #endif
  
  /* typedef term_T in structs.h */
  struct terminal_S {
      term_T    *tl_next;
  
+ #ifdef WIN3264
+     /* console handle? */
+ #else
      VTerm     *tl_vterm;
+ #endif
      job_T     *tl_job;
      buf_T     *tl_buffer;
  
***************
*** 75,101 ****
  };
  
  #define MAX_ROW 999999            /* used for tl_dirty_row_end to update all 
rows */
  
  /*
   * List of all active terminals.
   */
  static term_T *first_term = NULL;
  
! static int handle_damage(VTermRect rect, void *user);
! static int handle_moverect(VTermRect dest, VTermRect src, void *user);
! static int handle_movecursor(VTermPos pos, VTermPos oldpos, int visible, void 
*user);
! static int handle_resize(int rows, int cols, void *user);
! 
! static VTermScreenCallbacks screen_callbacks = {
!   handle_damage,      /* damage */
!   handle_moverect,    /* moverect */
!   handle_movecursor,  /* movecursor */
!   NULL,                       /* settermprop */
!   NULL,                       /* bell */
!   handle_resize,      /* resize */
!   NULL,                       /* sb_pushline */
!   NULL                        /* sb_popline */
! };
  
  /*
   * ":terminal": open a terminal window and execute a job in it.
--- 96,118 ----
  };
  
  #define MAX_ROW 999999            /* used for tl_dirty_row_end to update all 
rows */
+ #define KEY_BUF_LEN 200
+ 
+ /* Functions implemented for MS-Windows and Unix-like systems. */
+ static int term_init(term_T *term, int rows, int cols);
+ static void term_free(term_T *term);
+ static void term_write_job_output(term_T *term, char_u *msg, size_t len);
+ static int term_convert_key(int c, char *buf);
+ static void term_update_lines(win_T *wp);
  
  /*
   * List of all active terminals.
   */
  static term_T *first_term = NULL;
  
! /**************************************
!  * 1. Generic code for all systems.
!  */
  
  /*
   * ":terminal": open a terminal window and execute a job in it.
***************
*** 109,116 ****
      win_T     *old_curwin = curwin;
      typval_T  argvars[2];
      term_T    *term;
-     VTerm     *vterm;
-     VTermScreen *screen;
      jobopt_T  opt;
  
      if (check_restricted() || check_secure())
--- 126,131 ----
***************
*** 155,194 ****
        cols = curwin->w_width;
      }
  
!     vterm = vterm_new(rows, cols);
!     term->tl_vterm = vterm;
!     screen = vterm_obtain_screen(vterm);
!     vterm_screen_set_callbacks(screen, &screen_callbacks, term);
!     /* TODO: depends on 'encoding'. */
!     vterm_set_utf8(vterm, 1);
!     /* Required to initialize most things. */
!     vterm_screen_reset(screen, 1 /* hard */);
! 
!     /* By default NL means CR-NL. */
!     vterm_input_write(vterm, "\x1b[20h", 5);
! 
!     argvars[0].v_type = VAR_STRING;
!     argvars[0].vval.v_string = eap->arg;
  
!     clear_job_options(&opt);
!     opt.jo_mode = MODE_RAW;
!     opt.jo_out_mode = MODE_RAW;
!     opt.jo_err_mode = MODE_RAW;
!     opt.jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE;
!     opt.jo_io[PART_OUT] = JIO_BUFFER;
!     opt.jo_io[PART_ERR] = JIO_BUFFER;
!     opt.jo_set |= JO_OUT_IO + (JO_OUT_IO << (PART_ERR - PART_OUT));
!     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));
  
!     term->tl_job = job_start(argvars, &opt);
  
      if (term->tl_job == NULL)
        /* Wiping out the buffer will also close the window. */
        do_buffer(DOBUF_WIPE, DOBUF_CURRENT, FORWARD, 0, TRUE);
  
!     /* Setup pty, see mch_call_shell(). */
  }
  
  /*
--- 170,200 ----
        cols = curwin->w_width;
      }
  
!     if (term_init(term, rows, cols) == OK)
!     {
!       argvars[0].v_type = VAR_STRING;
!       argvars[0].vval.v_string = eap->arg;
  
!       clear_job_options(&opt);
!       opt.jo_mode = MODE_RAW;
!       opt.jo_out_mode = MODE_RAW;
!       opt.jo_err_mode = MODE_RAW;
!       opt.jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE;
!       opt.jo_io[PART_OUT] = JIO_BUFFER;
!       opt.jo_io[PART_ERR] = JIO_BUFFER;
!       opt.jo_set |= JO_OUT_IO + (JO_OUT_IO << (PART_ERR - PART_OUT));
!       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));
  
!       term->tl_job = job_start(argvars, &opt);
!     }
  
      if (term->tl_job == NULL)
        /* Wiping out the buffer will also close the window. */
        do_buffer(DOBUF_WIPE, DOBUF_CURRENT, FORWARD, 0, TRUE);
  
!     /* TODO: Setup pty, see mch_call_shell(). */
  }
  
  /*
***************
*** 220,226 ****
        job_unref(term->tl_job);
      }
  
!     vterm_free(term->tl_vterm);
      vim_free(term);
  }
  
--- 226,232 ----
        job_unref(term->tl_job);
      }
  
!     term_free(term);
      vim_free(term);
  }
  
***************
*** 232,242 ****
  write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
  {
      size_t    len = STRLEN(msg);
!     VTerm     *vterm = buffer->b_term->tl_vterm;
  
      ch_logn(channel, "writing %d bytes to terminal", (int)len);
!     vterm_input_write(vterm, (char *)msg, len);
!     vterm_screen_flush_damage(vterm_obtain_screen(vterm));
  
      /* TODO: only update once in a while. */
      update_screen(0);
--- 238,247 ----
  write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
  {
      size_t    len = STRLEN(msg);
!     term_T    *term = buffer->b_term;
  
      ch_logn(channel, "writing %d bytes to terminal", (int)len);
!     term_write_job_output(term, msg, len);
  
      /* TODO: only update once in a while. */
      update_screen(0);
***************
*** 245,288 ****
  }
  
  /*
   * Called to update the window that contains the terminal.
   */
      void
  term_update_window(win_T *wp)
  {
!     int vterm_rows;
!     int vterm_cols;
!     VTerm *vterm = wp->w_buffer->b_term->tl_vterm;
!     VTermScreen *screen = vterm_obtain_screen(vterm);
!     VTermPos pos;
  
!     vterm_get_size(vterm, &vterm_rows, &vterm_cols);
  
!     /* TODO: Only redraw what changed. */
!     for (pos.row = 0; pos.row < wp->w_height; ++pos.row)
!     {
!       int off = screen_get_current_line_off();
  
!       if (pos.row < vterm_rows)
!           for (pos.col = 0; pos.col < wp->w_width && pos.col < vterm_cols;
!                                                                    ++pos.col)
!           {
!               VTermScreenCell cell;
!               int c;
  
!               vterm_screen_get_cell(screen, pos, &cell);
!               /* TODO: use cell.attrs and colors */
!               /* TODO: use cell.width */
!               /* TODO: multi-byte chars */
!               c = cell.chars[0];
!               ScreenLines[off] = c == NUL ? ' ' : c;
!               ScreenAttrs[off] = 0;
!               ++off;
!           }
  
!       screen_line(wp->w_winrow + pos.row, wp->w_wincol, pos.col, wp->w_width,
!                                                                       FALSE);
!     }
  }
  
      static int
--- 250,422 ----
  }
  
  /*
+  * Wait for input and send it to the job.
+  * Return when a CTRL-W command is typed that moves to another window.
+  */
+     void
+ terminal_loop(void)
+ {
+     char      buf[KEY_BUF_LEN];
+     int               c;
+     size_t    len;
+ 
+     for (;;)
+     {
+       /* TODO: skip screen update when handling a sequence of keys. */
+       update_screen(0);
+       setcursor();
+       out_flush();
+       c = vgetc();
+ 
+       if (c == Ctrl_W)
+       {
+           stuffcharReadbuff(Ctrl_W);
+           return;
+       }
+ 
+       /* Convert the typed key to a sequence of bytes for the job. */
+       len = term_convert_key(c, buf);
+       if (len > 0)
+           /* TODO: if FAIL is returned, stop? */
+           channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
+                                                    (char_u *)buf, len, NULL);
+     }
+ }
+ 
+ /*
   * Called to update the window that contains the terminal.
   */
      void
  term_update_window(win_T *wp)
  {
!     term_update_lines(wp);
! }
  
! #ifdef WIN3264
  
! /**************************************
!  * 2. MS-Windows implementation.
!  */
  
! /*
!  * Create a new terminal of "rows" by "cols" cells.
!  * Store a reference in "term".
!  * Return OK or FAIL.
!  */
!     static int
! term_init(term_T *term, int rows, int cols)
! {
!     /* TODO: Create a hidden console */
!     return FAIL;
! }
  
! /*
!  * Free the terminal emulator part of "term".
!  */
!     static void
! term_free(term_T *term)
! {
!     /* TODO */
! }
  
! /*
!  * Write job output "msg[len]" to the terminal.
!  */
!     static void
! term_write_job_output(term_T *term, char_u *msg, size_t len)
! {
!     /* TODO */
! }
! 
! /*
!  * Convert typed key "c" into bytes to send to the job.
!  * Return the number of bytes in "buf".
!  */
!     static int
! term_convert_key(int c, char *buf)
! {
!     /* TODO */
!     return 0;
! }
! 
! /*
!  * Called to update the window that contains the terminal.
!  */
!     static void
! term_update_lines(win_T *wp)
! {
!     /* TODO */
! }
! 
! #else
! 
! /**************************************
!  * 3. Unix-like implementation.
!  *
!  * For a terminal one VTerm is constructed.  This uses libvterm.  A copy of
!  * that library is in the libvterm directory.
!  */
! 
! static int handle_damage(VTermRect rect, void *user);
! static int handle_moverect(VTermRect dest, VTermRect src, void *user);
! static int handle_movecursor(VTermPos pos, VTermPos oldpos, int visible, void 
*user);
! static int handle_resize(int rows, int cols, void *user);
! 
! static VTermScreenCallbacks screen_callbacks = {
!   handle_damage,      /* damage */
!   handle_moverect,    /* moverect */
!   handle_movecursor,  /* movecursor */
!   NULL,                       /* settermprop */
!   NULL,                       /* bell */
!   handle_resize,      /* resize */
!   NULL,                       /* sb_pushline */
!   NULL                        /* sb_popline */
! };
! 
! /*
!  * Create a new terminal of "rows" by "cols" cells.
!  * Store a reference in "term".
!  * Return OK or FAIL.
!  */
!     static int
! term_init(term_T *term, int rows, int cols)
! {
!     VTerm *vterm = vterm_new(rows, cols);
!     VTermScreen *screen;
! 
!     term->tl_vterm = vterm;
!     screen = vterm_obtain_screen(vterm);
!     vterm_screen_set_callbacks(screen, &screen_callbacks, term);
!     /* TODO: depends on 'encoding'. */
!     vterm_set_utf8(vterm, 1);
!     /* Required to initialize most things. */
!     vterm_screen_reset(screen, 1 /* hard */);
! 
!     /* By default NL means CR-NL. */
!     vterm_input_write(vterm, "\x1b[20h", 5);
! 
!     return OK;
! }
! 
! /*
!  * Free the terminal emulator part of "term".
!  */
!     static void
! term_free(term_T *term)
! {
!     vterm_free(term->tl_vterm);
! }
! 
! /*
!  * Write job output "msg[len]" to the terminal.
!  */
!     static void
! term_write_job_output(term_T *term, char_u *msg, size_t len)
! {
!     VTerm     *vterm = term->tl_vterm;
! 
!     vterm_input_write(vterm, (char *)msg, len);
!     vterm_screen_flush_damage(vterm_obtain_screen(vterm));
  }
  
      static int
***************
*** 344,454 ****
      return 1;
  }
  
- /* TODO: Use win_del_lines() to make scroll up efficient. */
- 
- 
  /*
!  * Wait for input and send it to the job.
!  * Return when a CTRL-W command is typed that moves to another window.
   */
!     void
! terminal_loop(void)
  {
!     VTerm   *vterm = curbuf->b_term->tl_vterm;
!     char    buf[200];
  
!     for (;;)
      {
!       int c;
!       VTermKey key = VTERM_KEY_NONE;
!       VTermModifier mod = VTERM_MOD_NONE;
!       size_t len;
! 
!       update_screen(0);
!       setcursor();
!       out_flush();
! 
!       c = vgetc();
!       switch (c)
!       {
!           case Ctrl_W:
!               stuffcharReadbuff(Ctrl_W);
!               return;
! 
!           /* TODO: which of these two should be used? */
  #if 0
!           case CAR:           key = VTERM_KEY_ENTER; break;
  #else
!           case CAR:           c = NL; break;
  #endif
!           case ESC:           key = VTERM_KEY_ESCAPE; break;
!           case K_BS:          key = VTERM_KEY_BACKSPACE; break;
!           case K_DEL:         key = VTERM_KEY_DEL; break;
!           case K_DOWN:        key = VTERM_KEY_DOWN; break;
!           case K_END:         key = VTERM_KEY_END; break;
!           case K_F10:         key = VTERM_KEY_FUNCTION(10); break;
!           case K_F11:         key = VTERM_KEY_FUNCTION(11); break;
!           case K_F12:         key = VTERM_KEY_FUNCTION(12); break;
!           case K_F1:          key = VTERM_KEY_FUNCTION(1); break;
!           case K_F2:          key = VTERM_KEY_FUNCTION(2); break;
!           case K_F3:          key = VTERM_KEY_FUNCTION(3); break;
!           case K_F4:          key = VTERM_KEY_FUNCTION(4); break;
!           case K_F5:          key = VTERM_KEY_FUNCTION(5); break;
!           case K_F6:          key = VTERM_KEY_FUNCTION(6); break;
!           case K_F7:          key = VTERM_KEY_FUNCTION(7); break;
!           case K_F8:          key = VTERM_KEY_FUNCTION(8); break;
!           case K_F9:          key = VTERM_KEY_FUNCTION(9); break;
!           case K_HOME:        key = VTERM_KEY_HOME; break;
!           case K_INS:         key = VTERM_KEY_INS; break;
!           case K_K0:          key = VTERM_KEY_KP_0; break;
!           case K_K1:          key = VTERM_KEY_KP_1; break;
!           case K_K2:          key = VTERM_KEY_KP_2; break;
!           case K_K3:          key = VTERM_KEY_KP_3; break;
!           case K_K4:          key = VTERM_KEY_KP_4; break;
!           case K_K5:          key = VTERM_KEY_KP_5; break;
!           case K_K6:          key = VTERM_KEY_KP_6; break;
!           case K_K7:          key = VTERM_KEY_KP_7; break;
!           case K_K8:          key = VTERM_KEY_KP_8; break;
!           case K_K9:          key = VTERM_KEY_KP_9; break;
!           case K_KDEL:        key = VTERM_KEY_DEL; break; /* TODO */
!           case K_KDIVIDE:     key = VTERM_KEY_KP_DIVIDE; break;
!           case K_KEND:        key = VTERM_KEY_KP_1; break; /* TODO */
!           case K_KENTER:      key = VTERM_KEY_KP_ENTER; break;
!           case K_KHOME:       key = VTERM_KEY_KP_7; break; /* TODO */
!           case K_KINS:        key = VTERM_KEY_KP_0; break; /* TODO */
!           case K_KMINUS:      key = VTERM_KEY_KP_MINUS; break;
!           case K_KMULTIPLY:   key = VTERM_KEY_KP_MULT; break;
!           case K_KPAGEDOWN:   key = VTERM_KEY_KP_3; break; /* TODO */
!           case K_KPAGEUP:     key = VTERM_KEY_KP_9; break; /* TODO */
!           case K_KPLUS:       key = VTERM_KEY_KP_PLUS; break;
!           case K_KPOINT:      key = VTERM_KEY_KP_PERIOD; break;
!           case K_LEFT:        key = VTERM_KEY_LEFT; break;
!           case K_PAGEDOWN:    key = VTERM_KEY_PAGEDOWN; break;
!           case K_PAGEUP:      key = VTERM_KEY_PAGEUP; break;
!           case K_RIGHT:       key = VTERM_KEY_RIGHT; break;
!           case K_UP:          key = VTERM_KEY_UP; break;
!           case TAB:           key = VTERM_KEY_TAB; break;
!       }
  
!       /*
!        * Convert special keys to vterm keys:
!        * - Write keys to vterm: vterm_keyboard_key()
!        * - Write output to channel.
!        */
!       if (key != VTERM_KEY_NONE)
!           /* Special key, let vterm convert it. */
!           vterm_keyboard_key(vterm, key, mod);
!       else
!           /* Normal character, let vterm convert it. */
!           vterm_keyboard_unichar(vterm, c, mod);
  
!       /* Read back the converted escape sequence. */
!       len = vterm_output_read(vterm, buf, sizeof(buf));
  
!       /* TODO: if FAIL is returned, stop? */
!       channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
!                                                    (char_u *)buf, len, NULL);
      }
  }
  
  #endif /* FEAT_TERMINAL */
--- 478,608 ----
      return 1;
  }
  
  /*
!  * Convert typed key "c" into bytes to send to the job.
!  * Return the number of bytes in "buf".
   */
!     static int
! term_convert_key(int c, char *buf)
  {
!     VTerm         *vterm = curbuf->b_term->tl_vterm;
!     VTermKey      key = VTERM_KEY_NONE;
!     VTermModifier   mod = VTERM_MOD_NONE;
  
!     switch (c)
      {
!       /* TODO: which of these two should be used? */
  #if 0
!       case CAR:               key = VTERM_KEY_ENTER; break;
  #else
!       case CAR:               c = NL; break;
  #endif
!       case ESC:               key = VTERM_KEY_ESCAPE; break;
!       case K_BS:              key = VTERM_KEY_BACKSPACE; break;
!       case K_DEL:             key = VTERM_KEY_DEL; break;
!       case K_DOWN:            key = VTERM_KEY_DOWN; break;
!       case K_END:             key = VTERM_KEY_END; break;
!       case K_F10:             key = VTERM_KEY_FUNCTION(10); break;
!       case K_F11:             key = VTERM_KEY_FUNCTION(11); break;
!       case K_F12:             key = VTERM_KEY_FUNCTION(12); break;
!       case K_F1:              key = VTERM_KEY_FUNCTION(1); break;
!       case K_F2:              key = VTERM_KEY_FUNCTION(2); break;
!       case K_F3:              key = VTERM_KEY_FUNCTION(3); break;
!       case K_F4:              key = VTERM_KEY_FUNCTION(4); break;
!       case K_F5:              key = VTERM_KEY_FUNCTION(5); break;
!       case K_F6:              key = VTERM_KEY_FUNCTION(6); break;
!       case K_F7:              key = VTERM_KEY_FUNCTION(7); break;
!       case K_F8:              key = VTERM_KEY_FUNCTION(8); break;
!       case K_F9:              key = VTERM_KEY_FUNCTION(9); break;
!       case K_HOME:            key = VTERM_KEY_HOME; break;
!       case K_INS:             key = VTERM_KEY_INS; break;
!       case K_K0:              key = VTERM_KEY_KP_0; break;
!       case K_K1:              key = VTERM_KEY_KP_1; break;
!       case K_K2:              key = VTERM_KEY_KP_2; break;
!       case K_K3:              key = VTERM_KEY_KP_3; break;
!       case K_K4:              key = VTERM_KEY_KP_4; break;
!       case K_K5:              key = VTERM_KEY_KP_5; break;
!       case K_K6:              key = VTERM_KEY_KP_6; break;
!       case K_K7:              key = VTERM_KEY_KP_7; break;
!       case K_K8:              key = VTERM_KEY_KP_8; break;
!       case K_K9:              key = VTERM_KEY_KP_9; break;
!       case K_KDEL:            key = VTERM_KEY_DEL; break; /* TODO */
!       case K_KDIVIDE:         key = VTERM_KEY_KP_DIVIDE; break;
!       case K_KEND:            key = VTERM_KEY_KP_1; break; /* TODO */
!       case K_KENTER:          key = VTERM_KEY_KP_ENTER; break;
!       case K_KHOME:           key = VTERM_KEY_KP_7; break; /* TODO */
!       case K_KINS:            key = VTERM_KEY_KP_0; break; /* TODO */
!       case K_KMINUS:          key = VTERM_KEY_KP_MINUS; break;
!       case K_KMULTIPLY:       key = VTERM_KEY_KP_MULT; break;
!       case K_KPAGEDOWN:       key = VTERM_KEY_KP_3; break; /* TODO */
!       case K_KPAGEUP:         key = VTERM_KEY_KP_9; break; /* TODO */
!       case K_KPLUS:           key = VTERM_KEY_KP_PLUS; break;
!       case K_KPOINT:          key = VTERM_KEY_KP_PERIOD; break;
!       case K_LEFT:            key = VTERM_KEY_LEFT; break;
!       case K_PAGEDOWN:        key = VTERM_KEY_PAGEDOWN; break;
!       case K_PAGEUP:          key = VTERM_KEY_PAGEUP; break;
!       case K_RIGHT:           key = VTERM_KEY_RIGHT; break;
!       case K_UP:              key = VTERM_KEY_UP; break;
!       case TAB:               key = VTERM_KEY_TAB; break;
!     }
! 
!     /*
!      * Convert special keys to vterm keys:
!      * - Write keys to vterm: vterm_keyboard_key()
!      * - Write output to channel.
!      */
!     if (key != VTERM_KEY_NONE)
!       /* Special key, let vterm convert it. */
!       vterm_keyboard_key(vterm, key, mod);
!     else
!       /* Normal character, let vterm convert it. */
!       vterm_keyboard_unichar(vterm, c, mod);
  
!     /* Read back the converted escape sequence. */
!     return vterm_output_read(vterm, buf, KEY_BUF_LEN);
! }
  
! /*
!  * Called to update the window that contains the terminal.
!  */
!     static void
! term_update_lines(win_T *wp)
! {
!     int               vterm_rows;
!     int               vterm_cols;
!     VTerm     *vterm = wp->w_buffer->b_term->tl_vterm;
!     VTermScreen *screen = vterm_obtain_screen(vterm);
!     VTermPos  pos;
  
!     vterm_get_size(vterm, &vterm_rows, &vterm_cols);
! 
!     /* TODO: Only redraw what changed. */
!     for (pos.row = 0; pos.row < wp->w_height; ++pos.row)
!     {
!       int off = screen_get_current_line_off();
! 
!       if (pos.row < vterm_rows)
!           for (pos.col = 0; pos.col < wp->w_width && pos.col < vterm_cols;
!                                                                    ++pos.col)
!           {
!               VTermScreenCell cell;
!               int c;
! 
!               vterm_screen_get_cell(screen, pos, &cell);
!               /* TODO: use cell.attrs and colors */
!               /* TODO: use cell.width */
!               /* TODO: multi-byte chars */
!               c = cell.chars[0];
!               ScreenLines[off] = c == NUL ? ' ' : c;
!               ScreenAttrs[off] = 0;
!               ++off;
!           }
! 
!       screen_line(wp->w_winrow + pos.row, wp->w_wincol, pos.col, wp->w_width,
!                                                                       FALSE);
      }
  }
  
+ #endif
+ 
  #endif /* FEAT_TERMINAL */
*** ../vim-8.0.0729/src/version.c       2017-07-18 21:33:16.354319501 +0200
--- src/version.c       2017-07-18 22:42:39.423860618 +0200
***************
*** 771,772 ****
--- 771,774 ----
  {   /* Add new patch number below this line */
+ /**/
+     730,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
179. You wonder why your household garbage can doesn't have an
     "empty recycle bin" button.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui