Patch 8.0.0813
Problem:    Cannot use Vim commands in a terminal window while the job is
            running.
Solution:   Implement Terminal Normal mode.
Files:      src/terminal.c, src/proto/terminal.pro, src/main.c, src/screen.c,
            src/normal.c, src/option.c, runtime/doc/terminal.txt


*** ../vim-8.0.0812/src/terminal.c      2017-07-29 22:23:35.170665661 +0200
--- src/terminal.c      2017-07-30 16:49:16.171156264 +0200
***************
*** 36,48 ****
   * that buffer, attributes come from the scrollback buffer tl_scrollback.
   *
   * TODO:
   * - For the scrollback buffer store lines in the buffer, only attributes in
   *   tl_scrollback.
   * - When the job ends:
   *   - Need an option or argument to drop the window+buffer right away, to be
!  *     used for a shell or Vim.
   * - To set BS correctly, check get_stty(); Pass the fd of the pty.
!  * - do not store terminal buffer in viminfo.  Or prefix term:// ?
   * - add a character in :ls output
   * - when closing window and job has not ended, make terminal hidden?
   * - when closing window and job has ended, make buffer hidden?
--- 36,58 ----
   * that buffer, attributes come from the scrollback buffer tl_scrollback.
   *
   * TODO:
+  * - Problem with statusline (Zyx, Christian)
+  * - Make CTRL-W "" paste register content to the job?
+  * - in bash mouse clicks are inserting characters.
+  * - mouse scroll: when over other window, scroll that window.
   * - For the scrollback buffer store lines in the buffer, only attributes in
   *   tl_scrollback.
+  * - Add term_status(): "" if not a terminal, "running" if job running,
+  *   "finished" if finished, "running,vim" when job is running and in
+  *   Terminal mode, "running,vim,pending" when job output is pending.
   * - When the job ends:
   *   - Need an option or argument to drop the window+buffer right away, to be
!  *     used for a shell or Vim. 'termfinish'; "close", "open" (open window 
when
!  *     job finishes).
!  * - add option values to the command:
!  *      :term <24x80> <close> vim notes.txt
   * - To set BS correctly, check get_stty(); Pass the fd of the pty.
!  * - do not store terminal window in viminfo.  Or prefix term:// ?
   * - add a character in :ls output
   * - when closing window and job has not ended, make terminal hidden?
   * - when closing window and job has ended, make buffer hidden?
***************
*** 53,58 ****
--- 63,70 ----
   * - support minimal size when 'termsize' is empty?
   * - implement "term" for job_start(): more job options when starting a
   *   terminal.
+  * - if the job in the terminal does not support the mouse, we can use the
+  *   mouse in the Terminal window for copy/paste.
   * - when 'encoding' is not utf-8, or the job is using another encoding, setup
   *   conversions.
   * - In the GUI use a terminal emulator for :!cmd.
***************
*** 78,90 ****
  struct terminal_S {
      term_T    *tl_next;
  
  #ifdef WIN3264
      void      *tl_winpty_config;
      void      *tl_winpty;
  #endif
-     VTerm     *tl_vterm;
-     job_T     *tl_job;
-     buf_T     *tl_buffer;
  
      /* last known vterm size */
      int               tl_rows;
--- 90,106 ----
  struct terminal_S {
      term_T    *tl_next;
  
+     VTerm     *tl_vterm;
+     job_T     *tl_job;
+     buf_T     *tl_buffer;
+ 
+     int               tl_terminal_mode;
+     int               tl_channel_closed;
+ 
  #ifdef WIN3264
      void      *tl_winpty_config;
      void      *tl_winpty;
  #endif
  
      /* last known vterm size */
      int               tl_rows;
***************
*** 553,558 ****
--- 569,773 ----
  }
  
  /*
+  * Add the last line of the scrollback buffer to the buffer in the window.
+  */
+     static void
+ add_scrollback_line_to_buffer(term_T *term)
+ {
+     linenr_T      lnum = term->tl_scrollback.ga_len - 1;
+     sb_line_T     *line = (sb_line_T *)term->tl_scrollback.ga_data + lnum;
+     garray_T      ga;
+     int                   c;
+     int                   col;
+     int                   i;
+ 
+     ga_init2(&ga, 1, 100);
+     for (col = 0; col < line->sb_cols; col += line->sb_cells[col].width)
+     {
+       if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
+           goto failed;
+       for (i = 0; (c = line->sb_cells[col].chars[i]) > 0 || i == 0; ++i)
+           ga.ga_len += mb_char2bytes(c == NUL ? ' ' : c,
+                                        (char_u *)ga.ga_data + ga.ga_len);
+     }
+     if (ga_grow(&ga, 1) == FAIL)
+       goto failed;
+     *((char_u *)ga.ga_data + ga.ga_len) = NUL;
+     ml_append_buf(term->tl_buffer, lnum, ga.ga_data, ga.ga_len + 1, FALSE);
+ 
+     if (lnum == 0)
+     {
+       /* Delete the empty line that was in the empty buffer. */
+       curbuf = term->tl_buffer;
+       ml_delete(2, FALSE);
+       curbuf = curwin->w_buffer;
+     }
+ 
+ failed:
+     ga_clear(&ga);
+ }
+ 
+ /*
+  * Add the current lines of the terminal to scrollback and to the buffer.
+  * Called after the job has ended and when switching to Terminal mode.
+  */
+     static void
+ move_terminal_to_buffer(term_T *term)
+ {
+     win_T         *wp;
+     int                   len;
+     int                   lines_skipped = 0;
+     VTermPos      pos;
+     VTermScreenCell cell;
+     VTermScreenCell *p;
+     VTermScreen           *screen = vterm_obtain_screen(term->tl_vterm);
+ 
+     for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
+     {
+       len = 0;
+       for (pos.col = 0; pos.col < term->tl_cols; ++pos.col)
+           if (vterm_screen_get_cell(screen, pos, &cell) != 0
+                                                      && cell.chars[0] != NUL)
+               len = pos.col + 1;
+ 
+       if (len == 0)
+           ++lines_skipped;
+       else
+       {
+           while (lines_skipped > 0)
+           {
+               /* Line was skipped, add an empty line. */
+               --lines_skipped;
+               if (ga_grow(&term->tl_scrollback, 1) == OK)
+               {
+                   sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
+                                                 + term->tl_scrollback.ga_len;
+ 
+                   line->sb_cols = 0;
+                   line->sb_cells = NULL;
+                   ++term->tl_scrollback.ga_len;
+ 
+                   add_scrollback_line_to_buffer(term);
+               }
+           }
+ 
+           p = (VTermScreenCell *)alloc((int)sizeof(VTermScreenCell) * len);
+           if (p != NULL && ga_grow(&term->tl_scrollback, 1) == OK)
+           {
+               sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
+                                                 + term->tl_scrollback.ga_len;
+ 
+               for (pos.col = 0; pos.col < len; ++pos.col)
+               {
+                   if (vterm_screen_get_cell(screen, pos, &cell) == 0)
+                       vim_memset(p + pos.col, 0, sizeof(cell));
+                   else
+                       p[pos.col] = cell;
+               }
+               line->sb_cols = len;
+               line->sb_cells = p;
+               ++term->tl_scrollback.ga_len;
+ 
+               add_scrollback_line_to_buffer(term);
+           }
+           else
+               vim_free(p);
+       }
+     }
+ 
+     FOR_ALL_WINDOWS(wp)
+     {
+       if (wp->w_buffer == term->tl_buffer)
+       {
+           wp->w_cursor.lnum = term->tl_buffer->b_ml.ml_line_count;
+           wp->w_cursor.col = 0;
+           wp->w_valid = 0;
+           redraw_win_later(wp, NOT_VALID);
+       }
+     }
+ }
+ 
+     static void
+ set_terminal_mode(term_T *term, int on)
+ {
+     term->tl_terminal_mode = on;
+     vim_free(term->tl_status_text);
+     term->tl_status_text = NULL;
+     if (term->tl_buffer == curbuf)
+       maketitle();
+ }
+ 
+ /*
+  * Called after the job if finished and Terminal mode is not active:
+  * Move the vterm contents into the scrollback buffer and free the vterm.
+  */
+     static void
+ cleanup_vterm(term_T *term)
+ {
+     move_terminal_to_buffer(term);
+     term_free_vterm(term);
+     set_terminal_mode(term, FALSE);
+ }
+ 
+ /*
+  * Switch from sending keys to the job to Terminal-Normal mode.
+  * Suspends updating the terminal window.
+  */
+     static void
+ term_enter_terminal_mode()
+ {
+     term_T *term = curbuf->b_term;
+ 
+     /* Append the current terminal contents to the buffer. */
+     move_terminal_to_buffer(term);
+ 
+     set_terminal_mode(term, TRUE);
+ }
+ 
+ /*
+  * Returns TRUE if the current window contains a terminal and we are in
+  * Terminal-Normal mode.
+  */
+     int
+ term_in_terminal_mode()
+ {
+     term_T *term = curbuf->b_term;
+ 
+     return term != NULL && term->tl_terminal_mode;
+ }
+ 
+ /*
+  * Switch from Terminal-Normal mode to sending keys to the job.
+  * Restores updating the terminal window.
+  */
+     void
+ term_leave_terminal_mode()
+ {
+     term_T    *term = curbuf->b_term;
+     sb_line_T *line;
+     garray_T  *gap;
+ 
+     /* Remove the terminal contents from the scrollback and the buffer. */
+     gap = &term->tl_scrollback;
+     while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled)
+     {
+       ml_delete(curbuf->b_ml.ml_line_count, FALSE);
+       line = (sb_line_T *)gap->ga_data + gap->ga_len - 1;
+       vim_free(line->sb_cells);
+       --gap->ga_len;
+       if (gap->ga_len == 0)
+           break;
+     }
+     check_cursor();
+ 
+     set_terminal_mode(term, FALSE);
+ 
+     if (term->tl_channel_closed)
+       cleanup_vterm(term);
+     redraw_buf_and_status_later(curbuf, NOT_VALID);
+ }
+ 
+ /*
   * Get a key from the user without mapping.
   * TODO: use terminal mode mappings.
   */
***************
*** 641,646 ****
--- 856,876 ----
  }
  
  /*
+  * Returns TRUE if the current window contains a terminal and we are sending
+  * keys to the job.
+  */
+     int
+ term_use_loop()
+ {
+     term_T *term = curbuf->b_term;
+ 
+     return term != NULL
+       && !term->tl_terminal_mode
+       && term->tl_vterm != NULL
+       && term_job_running(term);
+ }
+ 
+ /*
   * Wait for input and send it to the job.
   * Return when the start of a CTRL-W command is typed or anything else that
   * should be handled as a Normal mode command.
***************
*** 653,662 ****
      int               c;
      int               termkey = 0;
  
-     if (curbuf->b_term->tl_vterm == NULL || !term_job_running(curbuf->b_term))
-       /* job finished */
-       return OK;
- 
      if (*curwin->w_p_tk != NUL)
        termkey = string_to_key(curwin->w_p_tk, TRUE);
  
--- 883,888 ----
***************
*** 665,670 ****
--- 891,897 ----
        /* TODO: skip screen update when handling a sequence of keys. */
        update_screen(0);
        update_cursor(curbuf->b_term, FALSE);
+ 
        c = term_vgetc();
        if (curbuf->b_term->tl_vterm == NULL
                                          || !term_job_running(curbuf->b_term))
***************
*** 687,694 ****
--- 914,928 ----
                break;
  
            if (termkey == 0 && c == '.')
+           {
                /* "CTRL-W .": send CTRL-W to the job */
                c = Ctrl_W;
+           }
+           else if (termkey == 0 && c == 'N')
+           {
+               term_enter_terminal_mode();
+               return FAIL;
+           }
            else if (termkey == 0 || c != termkey)
            {
                stuffcharReadbuff(Ctrl_W);
***************
*** 704,709 ****
--- 938,945 ----
  
  /*
   * Called when a job has finished.
+  * This updates the title and status, but does not close the vter, because
+  * there might still be pending output in the channel.
   */
      void
  term_job_ended(job_T *job)
***************
*** 891,1008 ****
        line->sb_cells = p;
        ++term->tl_scrollback.ga_len;
        ++term->tl_scrollback_scrolled;
-     }
-     return 0; /* ignored */
- }
- 
- /*
-  * Fill the buffer with the scrollback lines and current lines of the 
terminal.
-  * Called after the job has ended.
-  */
-     static void
- move_scrollback_to_buffer(term_T *term)
- {
-     linenr_T      lnum;
-     garray_T      ga;
-     int                   c;
-     int                   col;
-     int                   i;
-     win_T         *wp;
-     int                   len;
-     int                   lines_skipped = 0;
-     VTermPos      pos;
-     VTermScreenCell cell;
-     VTermScreenCell *p;
-     VTermScreen           *screen = vterm_obtain_screen(term->tl_vterm);
- 
-     /* Append the the visible lines to the scrollback. */
-     for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
-     {
-       len = 0;
-       for (pos.col = 0; pos.col < term->tl_cols; ++pos.col)
-           if (vterm_screen_get_cell(screen, pos, &cell) != 0
-                                                      && cell.chars[0] != NUL)
-               len = pos.col + 1;
- 
-       if (len == 0)
-           ++lines_skipped;
-       else
-       {
-           while (lines_skipped > 0)
-           {
-               /* Line was skipped, add an empty line. */
-               --lines_skipped;
-               if (ga_grow(&term->tl_scrollback, 1) == OK)
-               {
-                   sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
-                                                 + term->tl_scrollback.ga_len;
- 
-                   line->sb_cols = 0;
-                   line->sb_cells = NULL;
-                   ++term->tl_scrollback.ga_len;
-               }
-           }
- 
-           p = (VTermScreenCell *)alloc((int)sizeof(VTermScreenCell) * len);
-           if (p != NULL && ga_grow(&term->tl_scrollback, 1) == OK)
-           {
-               sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
-                                                 + term->tl_scrollback.ga_len;
- 
-               for (pos.col = 0; pos.col < len; ++pos.col)
-               {
-                   if (vterm_screen_get_cell(screen, pos, &cell) == 0)
-                       vim_memset(p + pos.col, 0, sizeof(cell));
-                   else
-                       p[pos.col] = cell;
-               }
-               line->sb_cols = len;
-               line->sb_cells = p;
-               ++term->tl_scrollback.ga_len;
-           }
-           else
-               vim_free(p);
-       }
-     }
- 
-     /* Add the text to the buffer. */
-     ga_init2(&ga, 1, 100);
-     for (lnum = 0; lnum < term->tl_scrollback.ga_len; ++lnum)
-     {
-       sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data + lnum;
- 
-       ga.ga_len = 0;
-       for (col = 0; col < line->sb_cols; ++col)
-       {
-           if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
-               goto failed;
-           for (i = 0; (c = line->sb_cells[col].chars[i]) > 0 || i == 0; ++i)
-               ga.ga_len += mb_char2bytes(c == NUL ? ' ' : c,
-                                            (char_u *)ga.ga_data + ga.ga_len);
-       }
-       if (ga_grow(&ga, 1) == FAIL)
-           goto failed;
-       *((char_u *)ga.ga_data + ga.ga_len) = NUL;
-       ml_append_buf(term->tl_buffer, lnum, ga.ga_data, ga.ga_len + 1, FALSE);
-     }
- 
-     /* Delete the empty line that was in the empty buffer. */
-     curbuf = term->tl_buffer;
-     ml_delete(lnum + 1, FALSE);
-     curbuf = curwin->w_buffer;
- 
- failed:
-     ga_clear(&ga);
  
!     FOR_ALL_WINDOWS(wp)
!     {
!       if (wp->w_buffer == term->tl_buffer)
!       {
!           wp->w_cursor.lnum = term->tl_buffer->b_ml.ml_line_count;
!           wp->w_cursor.col = 0;
!           wp->w_valid = 0;
!       }
      }
  }
  
  static VTermScreenCallbacks screen_callbacks = {
--- 1127,1136 ----
        line->sb_cells = p;
        ++term->tl_scrollback.ga_len;
        ++term->tl_scrollback_scrolled;
  
!       add_scrollback_line_to_buffer(term);
      }
+     return 0; /* ignored */
  }
  
  static VTermScreenCallbacks screen_callbacks = {
***************
*** 1029,1042 ****
      for (term = first_term; term != NULL; term = term->tl_next)
        if (term->tl_job == ch->ch_job)
        {
            vim_free(term->tl_title);
            term->tl_title = NULL;
            vim_free(term->tl_status_text);
            term->tl_status_text = NULL;
  
!           /* move the lines into the buffer and free the vterm */
!           move_scrollback_to_buffer(term);
!           term_free_vterm(term);
  
            redraw_buf_and_status_later(term->tl_buffer, NOT_VALID);
            did_one = TRUE;
--- 1157,1172 ----
      for (term = first_term; term != NULL; term = term->tl_next)
        if (term->tl_job == ch->ch_job)
        {
+           term->tl_channel_closed = TRUE;
+ 
            vim_free(term->tl_title);
            term->tl_title = NULL;
            vim_free(term->tl_status_text);
            term->tl_status_text = NULL;
  
!           /* Unless in Terminal-Normal mode: clear the vterm. */
!           if (!term->tl_terminal_mode)
!               cleanup_vterm(term);
  
            redraw_buf_and_status_later(term->tl_buffer, NOT_VALID);
            did_one = TRUE;
***************
*** 1227,1234 ****
      VTermState        *state;
      VTermPos  pos;
  
!     if (term == NULL || term->tl_vterm == NULL)
        return FAIL;
      vterm = term->tl_vterm;
      screen = vterm_obtain_screen(vterm);
      state = vterm_obtain_state(vterm);
--- 1357,1365 ----
      VTermState        *state;
      VTermPos  pos;
  
!     if (term == NULL || term->tl_vterm == NULL || term->tl_terminal_mode)
        return FAIL;
+ 
      vterm = term->tl_vterm;
      screen = vterm_obtain_screen(vterm);
      state = vterm_obtain_state(vterm);
***************
*** 1347,1352 ****
--- 1478,1495 ----
  }
  
  /*
+  * Return TRUE if "wp" is a terminal window where the job has finished or we
+  * are in Terminal-Normal mode.
+  */
+     int
+ term_show_buffer(buf_T *buf)
+ {
+     term_T *term = buf->b_term;
+ 
+     return term != NULL && (term->tl_vterm == NULL || term->tl_terminal_mode);
+ }
+ 
+ /*
   * The current buffer is going to be changed.  If there is terminal
   * highlighting remove it now.
   */
***************
*** 1450,1456 ****
        char_u *txt;
        size_t len;
  
!       if (term->tl_title != NULL)
            txt = term->tl_title;
        else if (term_job_running(term))
            txt = (char_u *)_("running");
--- 1593,1606 ----
        char_u *txt;
        size_t len;
  
!       if (term->tl_terminal_mode)
!       {
!           if (term_job_running(term))
!               txt = (char_u *)_("Terminal");
!           else
!               txt = (char_u *)_("Terminal-finished");
!       }
!       else if (term->tl_title != NULL)
            txt = term->tl_title;
        else if (term_job_running(term))
            txt = (char_u *)_("running");
*** ../vim-8.0.0812/src/proto/terminal.pro      2017-07-29 20:07:00.764940487 
+0200
--- src/proto/terminal.pro      2017-07-30 15:59:29.864818283 +0200
***************
*** 2,12 ****
--- 2,16 ----
  void ex_terminal(exarg_T *eap);
  void free_terminal(buf_T *buf);
  void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
+ int term_in_terminal_mode(void);
+ void term_leave_terminal_mode(void);
+ int term_use_loop(void);
  int terminal_loop(void);
  void term_job_ended(job_T *job);
  void term_channel_closed(channel_T *ch);
  int term_update_window(win_T *wp);
  int term_is_finished(buf_T *buf);
+ int term_show_buffer(buf_T *buf);
  void term_change_in_curbuf(void);
  int term_get_attr(buf_T *buf, linenr_T lnum, int col);
  char_u *term_get_status_text(term_T *term);
***************
*** 16,23 ****
  void f_term_getline(typval_T *argvars, typval_T *rettv);
  void f_term_getsize(typval_T *argvars, typval_T *rettv);
  void f_term_list(typval_T *argvars, typval_T *rettv);
- void f_term_start(typval_T *argvars, typval_T *rettv);
  void f_term_scrape(typval_T *argvars, typval_T *rettv);
  void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
  void f_term_wait(typval_T *argvars, typval_T *rettv);
  /* vim: set ft=c : */
--- 20,27 ----
  void f_term_getline(typval_T *argvars, typval_T *rettv);
  void f_term_getsize(typval_T *argvars, typval_T *rettv);
  void f_term_list(typval_T *argvars, typval_T *rettv);
  void f_term_scrape(typval_T *argvars, typval_T *rettv);
  void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
+ void f_term_start(typval_T *argvars, typval_T *rettv);
  void f_term_wait(typval_T *argvars, typval_T *rettv);
  /* vim: set ft=c : */
*** ../vim-8.0.0812/src/main.c  2017-07-16 20:13:22.265843572 +0200
--- src/main.c  2017-07-30 15:47:01.714210944 +0200
***************
*** 1356,1366 ****
        else
        {
  #ifdef FEAT_TERMINAL
!           if (curbuf->b_term != NULL && oa.op_type == OP_NOP
!                                                         && oa.regname == NUL)
!               terminal_loop();
  #endif
!           normal_cmd(&oa, TRUE);
        }
      }
  }
--- 1356,1372 ----
        else
        {
  #ifdef FEAT_TERMINAL
!           if (term_use_loop() && oa.op_type == OP_NOP && oa.regname == NUL)
!           {
!               /* If terminal_loop() returns OK we got a key that is handled
!                * in Normal model.  With FAIL the terminal was closed and the
!                * screen needs to be redrawn. */
!               if (terminal_loop() == OK)
!                   normal_cmd(&oa, TRUE);
!           }
!           else
  #endif
!               normal_cmd(&oa, TRUE);
        }
      }
  }
*** ../vim-8.0.0812/src/screen.c        2017-07-30 13:57:37.616783276 +0200
--- src/screen.c        2017-07-30 15:43:01.783920068 +0200
***************
*** 3245,3251 ****
  #endif
  
  #ifdef FEAT_TERMINAL
!     if (term_is_finished(wp->w_buffer))
      {
        extra_check = TRUE;
        get_term_attr = TRUE;
--- 3245,3251 ----
  #endif
  
  #ifdef FEAT_TERMINAL
!     if (term_show_buffer(wp->w_buffer))
      {
        extra_check = TRUE;
        get_term_attr = TRUE;
*** ../vim-8.0.0812/src/normal.c        2017-07-16 20:13:22.269843541 +0200
--- src/normal.c        2017-07-30 15:59:33.516791950 +0200
***************
*** 9037,9042 ****
--- 9037,9050 ----
      static void
  nv_edit(cmdarg_T *cap)
  {
+ #ifdef FEAT_TERMINAL
+     if (term_in_terminal_mode())
+     {
+       term_leave_terminal_mode();
+       return;
+     }
+ #endif
+ 
      /* <Insert> is equal to "i" */
      if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS)
        cap->cmdchar = 'i';
*** ../vim-8.0.0812/src/option.c        2017-07-28 13:48:15.398855045 +0200
--- src/option.c        2017-07-30 15:57:41.817597536 +0200
***************
*** 8222,8233 ****
      }
  #endif
  
- #ifdef FEAT_TITLE
      /* when 'modifiable' is changed, redraw the window title */
      else if ((int *)varp == &curbuf->b_p_ma)
      {
        redraw_titles();
      }
      /* when 'endofline' is changed, redraw the window title */
      else if ((int *)varp == &curbuf->b_p_eol)
      {
--- 8222,8243 ----
      }
  #endif
  
      /* when 'modifiable' is changed, redraw the window title */
      else if ((int *)varp == &curbuf->b_p_ma)
      {
+ # ifdef FEAT_TERMINAL
+       /* Cannot set 'modifiable' when in Terminal mode. */
+       if (term_in_terminal_mode())
+       {
+           curbuf->b_p_ma = FALSE;
+           return (char_u *)N_("E946: Cannot make a terminal with running job 
modifiable");
+       }
+ # endif
+ # ifdef FEAT_TITLE
        redraw_titles();
+ # endif
      }
+ #ifdef FEAT_TITLE
      /* when 'endofline' is changed, redraw the window title */
      else if ((int *)varp == &curbuf->b_p_eol)
      {
*** ../vim-8.0.0812/runtime/doc/terminal.txt    2017-07-28 13:48:15.398855045 
+0200
--- runtime/doc/terminal.txt    2017-07-30 16:45:34.584766890 +0200
***************
*** 1,4 ****
! *terminal.txt*        For Vim version 8.0.  Last change: 2017 Jul 28
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
--- 1,4 ----
! *terminal.txt*        For Vim version 8.0.  Last change: 2017 Jul 30
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
***************
*** 33,56 ****
  The job runs asynchronously from Vim, the window will be updated to show
  output from the job, also  while editing in any other window.
  
  Typing ~
  
  When the keyboard focus is in the terminal window, typed keys will be send to
  the job.  This uses a pty when possible.  You can click outside of the
  terminal window to move keyboard focus elsewhere.
  
! Navigate between windows with CTRL-W commands.  E.g. CTRL-W CTRL-W moves focus
! to the next window.  Use "CTRL-W :" to edit an Ex command.  Use "CTRL-W ." to
! send a CTRL-W to the job in the terminal.
  
- See option 'termkey' for specifying another key that precedes a Vim command.
- Typing 'termkey' twice sends 'termkey' to the job.
  
  Size ~
  
  See option 'termsize' for controlling the size of the terminal window.
  (TODO: scrolling when the terminal is larger than the window)
  
  Syntax ~
  
  :ter[minal] [command]                         *:ter* *:terminal*
--- 33,71 ----
  The job runs asynchronously from Vim, the window will be updated to show
  output from the job, also  while editing in any other window.
  
+ 
  Typing ~
  
  When the keyboard focus is in the terminal window, typed keys will be send to
  the job.  This uses a pty when possible.  You can click outside of the
  terminal window to move keyboard focus elsewhere.
  
! CTRL-W can be used to navigate between windows and other CTRL-W commands, 
e.g.:
!       CTRL-W CTRL-W   move focus to the next window
!       CTRL-W :        enter an Ex command
! See |CTRL-W| for more commands.
! 
! Special in the terminal window:                       *CTRL-W_.*  *CTRL-W_N* 
!       CTRL-W .        send a CTRL-W to the job in the terminal
!       CTRL-W N        go to Terminal Normal mode, see |Terminal-mode|
! 
! See option 'termkey' for specifying another key instead of CTRL-W that
! will work like CTRL-W.  However, typing 'termkey' twice sends 'termkey' to
! the job.  For example:
!       'termkey' CTRL-W    move focus to the next window
!       'termkey' :         enter an Ex command
!       'termkey' 'termkey' send 'termkey' to the job in the terminal
!       'termkey' .         send a CTRL-W to the job in the terminal
!       'termkey' N         go to terminal Normal mode, see below
!       'termkey' CTRL-N    same as CTRL-W N
  
  
  Size ~
  
  See option 'termsize' for controlling the size of the terminal window.
  (TODO: scrolling when the terminal is larger than the window)
  
+ 
  Syntax ~
  
  :ter[minal] [command]                         *:ter* *:terminal*
***************
*** 99,104 ****
--- 114,138 ----
  not when 'termsize' is "rowsXcols".
  
  
+ Terminal Normal mode ~
+                                                       *Terminal-mode*
+ When the job is running the contents of the terminal is under control of the
+ job.  That includes the cursor position.  The terminal contents can change at
+ any time.
+ 
+ Use CTRL-W N (or 'termkey' N) to go to Terminal Normal mode.  Now the contents
+ of the terminal window is under control of Vim, the job output is suspended.
+                                                       *E946*
+ In this mode you can move the cursor around with the usual Vim commands,
+ Visually mark text, yank text, etc.  But you cannot change the contents of the
+ buffer.  The commands that would start insert mode, such as 'i' and 'a',
+ return control of the window to the job.  Any pending output will now be
+ displayed.
+ 
+ In Terminal mode the statusline and window title show "(Terminal)".  If the
+ job ends while in Terminal mode this changes to "(Terminal-finished)".
+ 
+ 
  Unix ~
  
  On Unix a pty is used to make it possible to run all kinds of commands.  You
*** ../vim-8.0.0812/src/version.c       2017-07-30 13:57:37.616783276 +0200
--- src/version.c       2017-07-30 16:43:17.709763223 +0200
***************
*** 771,772 ****
--- 771,774 ----
  {   /* Add new patch number below this line */
+ /**/
+     813,
  /**/

-- 
TALL KNIGHT: We shall say Ni! again to you if you do not appease us.
ARTHUR:      All right!  What do you want?
TALL KNIGHT: We want ... a shrubbery!
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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