Note: this isn't completely finished, but wanted to send it out now.
Add the "!" flag to 'guioptions' to try it out. Try:
        :!cat testdir/color_ramp.txt
Report problems if you see them (or send a patch! :-).


Patch 8.0.1609
Problem:    Shell commands in the GUI use a dumb terminal.
Solution:   Add the "!" flag to 'guioptions' to execute system commands in a
            special terminal window.  Only for Unix now.
Files:      src/os_unix.c, src/option.h, src/evalfunc.c, src/terminal.c,
            src/proto/terminal.pro, src/channel.c, src/proto/channel.pro,
            src/vim.h, runtime/doc/options.txt


*** ../vim-8.0.1608/src/os_unix.c       2018-03-05 21:59:33.214889934 +0100
--- src/os_unix.c       2018-03-16 20:42:01.367637679 +0100
***************
*** 4154,4163 ****
      return wait_pid;
  }
  
! #if defined(FEAT_JOB_CHANNEL) || !defined(USE_SYSTEM) || defined(PROTO)
  /*
   * Parse "cmd" and put the white-separated parts in "argv".
!  * "argv" is an allocated array with "argc" entries.
   * Returns FAIL when out of memory.
   */
      int
--- 4154,4166 ----
      return wait_pid;
  }
  
! #if defined(FEAT_JOB_CHANNEL) \
!       || !defined(USE_SYSTEM) \
!       || (defined(FEAT_GUI) && defined(FEAT_TERMINAL)) \
!       || defined(PROTO)
  /*
   * Parse "cmd" and put the white-separated parts in "argv".
!  * "argv" is an allocated array with "argc" entries and room for 4 more.
   * Returns FAIL when out of memory.
   */
      int
***************
*** 4359,4366 ****
  # endif
  }
  
!     int
! mch_call_shell(
      char_u    *cmd,
      int               options)        /* SHELL_*, see vim.h */
  {
--- 4362,4482 ----
  # endif
  }
  
! #if !defined(USE_SYSTEM) || (defined(FEAT_GUI) && defined(FEAT_TERMINAL))
! 
!     static int
! build_argv(
!       char_u *cmd,
!       char ***argvp,
!       char_u **sh_tofree,
!       char_u **shcf_tofree)
! {
!     char      **argv = NULL;
!     int               argc;
! 
!     *sh_tofree = vim_strsave(p_sh);
!     if (*sh_tofree == NULL)           /* out of memory */
!       return FAIL;
! 
!     if (mch_parse_cmd(*sh_tofree, TRUE, &argv, &argc) == FAIL)
!       return FAIL;
!     *argvp = argv;
! 
!     if (cmd != NULL)
!     {
!       char_u  *s;
!       char_u  *p;
! 
!       if (extra_shell_arg != NULL)
!           argv[argc++] = (char *)extra_shell_arg;
! 
!       /* Break 'shellcmdflag' into white separated parts.  This doesn't
!        * handle quoted strings, they are very unlikely to appear. */
!       *shcf_tofree = alloc((unsigned)STRLEN(p_shcf) + 1);
!       if (*shcf_tofree == NULL)    /* out of memory */
!           return FAIL;
!       s = *shcf_tofree;
!       p = p_shcf;
!       while (*p != NUL)
!       {
!           argv[argc++] = (char *)s;
!           while (*p && *p != ' ' && *p != TAB)
!               *s++ = *p++;
!           *s++ = NUL;
!           p = skipwhite(p);
!       }
! 
!       argv[argc++] = (char *)cmd;
!     }
!     argv[argc] = NULL;
!     return OK;
! }
! #endif
! 
! #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
! /*
!  * Use a terminal window to run a shell command in.
!  */
!     static int
! mch_call_shell_terminal(
!     char_u    *cmd,
!     int               options UNUSED) /* SHELL_*, see vim.h */
! {
!     jobopt_T  opt;
!     char      **argv = NULL;
!     char_u    *tofree1 = NULL;
!     char_u    *tofree2 = NULL;
!     int               retval = -1;
!     buf_T     *buf;
!     aco_save_T        aco;
!     oparg_T   oa;             /* operator arguments */
! 
!     if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
!       goto theend;
! 
!     init_job_options(&opt);
!     ch_log(NULL, "starting terminal for system command '%s'", cmd);
!     buf = term_start(NULL, argv, &opt, TERM_START_SYSTEM);
! 
!     /* Find a window to make "buf" curbuf. */
!     aucmd_prepbuf(&aco, buf);
! 
!     clear_oparg(&oa);
!     while (term_use_loop())
!     {
!       if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
!       {
!           /* If terminal_loop() returns OK we got a key that is handled
!            * in Normal model. We don't do redrawing anyway. */
!           if (terminal_loop(TRUE) == OK)
!               normal_cmd(&oa, TRUE);
!       }
!       else
!           normal_cmd(&oa, TRUE);
!     }
!     retval = 0;
!     ch_log(NULL, "system command finished");
! 
!     /* restore curwin/curbuf and a few other things */
!     aucmd_restbuf(&aco);
! 
!     wait_return(TRUE);
!     do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
! 
! theend:
!     vim_free(argv);
!     vim_free(tofree1);
!     vim_free(tofree2);
!     return retval;
! }
! #endif
! 
! #ifdef USE_SYSTEM
! /*
!  * Use system() to start the shell: simple but slow.
!  */
!     static int
! mch_call_shell_system(
      char_u    *cmd,
      int               options)        /* SHELL_*, see vim.h */
  {
***************
*** 4369,4375 ****
      char      *ofn = NULL;
  #endif
      int               tmode = cur_tmode;
- #ifdef USE_SYSTEM     /* use system() to start the shell: simple but slow */
      char_u    *newcmd;        /* only needed for unix */
      int               x;
  
--- 4485,4490 ----
***************
*** 4443,4456 ****
      restore_clipboard();
  # endif
      return x;
  
! #else /* USE_SYSTEM */            /* don't use system(), use fork()/exec() */
  
  # define EXEC_FAILED 122    /* Exit code when shell didn't execute.  Don't use
                               127, some shells use that already */
  # define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
  
!     char_u    *newcmd;
      pid_t     pid;
      pid_t     wpid = 0;
      pid_t     wait_pid = 0;
--- 4558,4580 ----
      restore_clipboard();
  # endif
      return x;
+ }
  
! #else /* USE_SYSTEM */
  
  # define EXEC_FAILED 122    /* Exit code when shell didn't execute.  Don't use
                               127, some shells use that already */
  # define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
  
! /*
!  * Don't use system(), use fork()/exec().
!  */
!     static int
! mch_call_shell_fork(
!     char_u    *cmd,
!     int               options)        /* SHELL_*, see vim.h */
! {
!     int               tmode = cur_tmode;
      pid_t     pid;
      pid_t     wpid = 0;
      pid_t     wait_pid = 0;
***************
*** 4461,4468 ****
  # endif
      int               retval = -1;
      char      **argv = NULL;
!     int               argc;
!     char_u    *p_shcf_copy = NULL;
      int               i;
      char_u    *p;
      int               pty_master_fd = -1;         /* for pty's */
--- 4585,4592 ----
  # endif
      int               retval = -1;
      char      **argv = NULL;
!     char_u    *tofree1 = NULL;
!     char_u    *tofree2 = NULL;
      int               i;
      char_u    *p;
      int               pty_master_fd = -1;         /* for pty's */
***************
*** 4474,4517 ****
      int               pipe_error = FALSE;
      int               did_settmode = FALSE;   /* settmode(TMODE_RAW) called */
  
-     newcmd = vim_strsave(p_sh);
-     if (newcmd == NULL)               /* out of memory */
-       goto error;
- 
      out_flush();
      if (options & SHELL_COOKED)
        settmode(TMODE_COOK);           /* set to normal mode */
  
!     if (mch_parse_cmd(newcmd, TRUE, &argv, &argc) == FAIL)
        goto error;
  
-     if (cmd != NULL)
-     {
-       char_u  *s;
- 
-       if (extra_shell_arg != NULL)
-           argv[argc++] = (char *)extra_shell_arg;
- 
-       /* Break 'shellcmdflag' into white separated parts.  This doesn't
-        * handle quoted strings, they are very unlikely to appear. */
-       p_shcf_copy = alloc((unsigned)STRLEN(p_shcf) + 1);
-       if (p_shcf_copy == NULL)    /* out of memory */
-           goto error;
-       s = p_shcf_copy;
-       p = p_shcf;
-       while (*p != NUL)
-       {
-           argv[argc++] = (char *)s;
-           while (*p && *p != ' ' && *p != TAB)
-               *s++ = *p++;
-           *s++ = NUL;
-           p = skipwhite(p);
-       }
- 
-       argv[argc++] = (char *)cmd;
-     }
-     argv[argc] = NULL;
- 
      /*
       * For the GUI, when writing the output into the buffer and when reading
       * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
--- 4598,4610 ----
      int               pipe_error = FALSE;
      int               did_settmode = FALSE;   /* settmode(TMODE_RAW) called */
  
      out_flush();
      if (options & SHELL_COOKED)
        settmode(TMODE_COOK);           /* set to normal mode */
  
!     if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
        goto error;
  
      /*
       * For the GUI, when writing the output into the buffer and when reading
       * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
***************
*** 5319,5326 ****
                MSG_PUTS(_("\nCommand terminated\n"));
        }
      }
-     vim_free(argv);
-     vim_free(p_shcf_copy);
  
  error:
      if (!did_settmode)
--- 5412,5417 ----
***************
*** 5329,5339 ****
  # ifdef FEAT_TITLE
      resettitle();
  # endif
!     vim_free(newcmd);
  
      return retval;
! 
  #endif /* USE_SYSTEM */
  }
  
  #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
--- 5420,5447 ----
  # ifdef FEAT_TITLE
      resettitle();
  # endif
!     vim_free(argv);
!     vim_free(tofree1);
!     vim_free(tofree2);
  
      return retval;
! }
  #endif /* USE_SYSTEM */
+ 
+     int
+ mch_call_shell(
+     char_u    *cmd,
+     int               options)        /* SHELL_*, see vim.h */
+ {
+ #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
+     if (gui.in_use && vim_strchr(p_go, GO_TERMINAL) != NULL)
+       return mch_call_shell_terminal(cmd, options);
+ #endif
+ #ifdef USE_SYSTEM
+     return mch_call_shell_system(cmd, options);
+ #else
+     return mch_call_shell_fork(cmd, options);
+ #endif
  }
  
  #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
*** ../vim-8.0.1608/src/option.h        2018-03-09 21:33:29.244607400 +0100
--- src/option.h        2018-03-13 21:25:36.660819811 +0100
***************
*** 214,219 ****
--- 214,220 ----
  #define SHM_ALL               "rmfixlnwaWtToOsAIcqF" /* all possible flags 
for 'shm' */
  
  /* characters for p_go: */
+ #define GO_TERMINAL   '!'             /* use terminal for system commands */
  #define GO_ASEL               'a'             /* autoselect */
  #define GO_ASELML     'A'             /* autoselect modeless selection */
  #define GO_BOT                'b'             /* use bottom scrollbar */
***************
*** 236,242 ****
  #define GO_FOOTER     'F'             /* add footer */
  #define GO_VERTICAL   'v'             /* arrange dialog buttons vertically */
  #define GO_KEEPWINSIZE        'k'             /* keep GUI window size */
! #define GO_ALL                "aAbcefFghilmMprtTvk" /* all possible flags for 
'go' */
  
  /* flags for 'comments' option */
  #define COM_NEST      'n'             /* comments strings nest */
--- 237,243 ----
  #define GO_FOOTER     'F'             /* add footer */
  #define GO_VERTICAL   'v'             /* arrange dialog buttons vertically */
  #define GO_KEEPWINSIZE        'k'             /* keep GUI window size */
! #define GO_ALL                "!aAbcefFghilmMprtTvk" /* all possible flags 
for 'go' */
  
  /* flags for 'comments' option */
  #define COM_NEST      'n'             /* comments strings nest */
*** ../vim-8.0.1608/src/evalfunc.c      2018-03-12 22:16:33.261746681 +0100
--- src/evalfunc.c      2018-03-13 21:44:12.065740473 +0100
***************
*** 7032,7038 ****
      rettv->v_type = VAR_JOB;
      if (check_restricted() || check_secure())
        return;
!     rettv->vval.v_job = job_start(argvars, NULL);
  }
  
  /*
--- 7032,7038 ----
      rettv->v_type = VAR_JOB;
      if (check_restricted() || check_secure())
        return;
!     rettv->vval.v_job = job_start(argvars, NULL, NULL);
  }
  
  /*
*** ../vim-8.0.1608/src/terminal.c      2018-03-13 13:13:56.715070346 +0100
--- src/terminal.c      2018-03-16 20:40:09.108192020 +0100
***************
*** 38,47 ****
   * in tl_scrollback are no longer used.
   *
   * TODO:
!  * - When using 'termguicolors' still use the 16 ANSI colors as-is.  Helps for
!  * - In the GUI use a terminal emulator for :!cmd.  Make the height the same 
as
!  *   the window and position it higher up when it gets filled, so it looks 
like
!  *   the text scrolls up.
   * - implement term_setsize()
   * - Copy text in the vterm to the Vim buffer once in a while, so that
   *   completion works.
--- 38,51 ----
   * in tl_scrollback are no longer used.
   *
   * TODO:
!  * - Make terminal close by default when started without a command.  Add
!  *   ++noclose argument.
!  * - Win32: In the GUI use a terminal emulator for :!cmd.
!  * - Add a way to set the 16 ANSI colors, to be used for 'termguicolors' and 
in
!  *   the GUI.
!  * - Some way for the job running in the terminal to send a :drop command back
!  *   to the Vim running the terminal.  Should be usable by a simple shell or
!  *   python script.
   * - implement term_setsize()
   * - Copy text in the vterm to the Vim buffer once in a while, so that
   *   completion works.
***************
*** 104,109 ****
--- 108,117 ----
      VTerm     *tl_vterm;
      job_T     *tl_job;
      buf_T     *tl_buffer;
+ #if defined(FEAT_GUI)
+     int               tl_system;      /* when non-zero used for :!cmd output 
*/
+     int               tl_toprow;      /* row with first line of system 
terminal */
+ #endif
  
      /* Set when setting the size of a vterm, reset after redrawing. */
      int               tl_vterm_size_changed;
***************
*** 175,184 ****
  /*
   * Functions with separate implementation for MS-Windows and Unix-like 
systems.
   */
! static int term_and_job_init(term_T *term, typval_T *argvar, jobopt_T *opt);
  static int create_pty_only(term_T *term, jobopt_T *opt);
  static void term_report_winsize(term_T *term, int rows, int cols);
  static void term_free_vterm(term_T *term);
  
  /* The character that we know (or assume) that the terminal expects for the
   * backspace key. */
--- 183,195 ----
  /*
   * Functions with separate implementation for MS-Windows and Unix-like 
systems.
   */
! static int term_and_job_init(term_T *term, typval_T *argvar, char **argv, 
jobopt_T *opt);
  static int create_pty_only(term_T *term, jobopt_T *opt);
  static void term_report_winsize(term_T *term, int rows, int cols);
  static void term_free_vterm(term_T *term);
+ #ifdef FEAT_GUI
+ static void update_system_term(term_T *term);
+ #endif
  
  /* The character that we know (or assume) that the terminal expects for the
   * backspace key. */
***************
*** 209,214 ****
--- 220,235 ----
      static void
  set_term_and_win_size(term_T *term)
  {
+ #ifdef FEAT_GUI
+     if (term->tl_system)
+     {
+       /* Use the whole screen for the system command.  However, it will start
+        * at the command line and scroll up as needed, using tl_toprow. */
+       term->tl_rows = Rows;
+       term->tl_cols = Columns;
+     }
+     else
+ #endif
      if (*curwin->w_p_tms != NUL)
      {
        char_u *p = vim_strchr(curwin->w_p_tms, 'x') + 1;
***************
*** 236,242 ****
   * Initialize job options for a terminal job.
   * Caller may overrule some of them.
   */
!     static void
  init_job_options(jobopt_T *opt)
  {
      clear_job_options(opt);
--- 257,263 ----
   * Initialize job options for a terminal job.
   * Caller may overrule some of them.
   */
!     void
  init_job_options(jobopt_T *opt)
  {
      clear_job_options(opt);
***************
*** 301,312 ****
  
  /*
   * Start a terminal window and return its buffer.
!  * When "without_job" is TRUE only create the buffer, b_term and open the
!  * window.
   * Returns NULL when failed.
   */
!     static buf_T *
! term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
  {
      exarg_T   split_ea;
      win_T     *old_curwin = curwin;
--- 322,338 ----
  
  /*
   * Start a terminal window and return its buffer.
!  * Use either "argvar" or "argv", the other must be NULL.
!  * When "flags" has TERM_START_NOJOB only create the buffer, b_term and open
!  * the window.
   * Returns NULL when failed.
   */
!     buf_T *
! term_start(
!       typval_T    *argvar,
!       char        **argv,
!       jobopt_T    *opt,
!       int         flags)
  {
      exarg_T   split_ea;
      win_T     *old_curwin = curwin;
***************
*** 334,359 ****
      term->tl_cursor_visible = TRUE;
      term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
      term->tl_finish = opt->jo_term_finish;
      ga_init2(&term->tl_scrollback, sizeof(sb_line_T), 300);
  
      vim_memset(&split_ea, 0, sizeof(split_ea));
      if (opt->jo_curwin)
      {
        /* Create a new buffer in the current window. */
!       if (!can_abandon(curbuf, forceit))
        {
            no_write_message();
            vim_free(term);
            return NULL;
        }
        if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
!                    ECMD_HIDE + (forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
        {
            vim_free(term);
            return NULL;
        }
      }
!     else if (opt->jo_hidden)
      {
        buf_T *buf;
  
--- 360,390 ----
      term->tl_cursor_visible = TRUE;
      term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
      term->tl_finish = opt->jo_term_finish;
+ #ifdef FEAT_GUI
+     term->tl_system = (flags & TERM_START_SYSTEM);
+ #endif
      ga_init2(&term->tl_scrollback, sizeof(sb_line_T), 300);
  
      vim_memset(&split_ea, 0, sizeof(split_ea));
      if (opt->jo_curwin)
      {
        /* Create a new buffer in the current window. */
!       if (!can_abandon(curbuf, flags & TERM_START_FORCEIT))
        {
            no_write_message();
            vim_free(term);
            return NULL;
        }
        if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
!                    ECMD_HIDE
!                          + ((flags & TERM_START_FORCEIT) ? ECMD_FORCEIT : 0),
!                    curwin) == FAIL)
        {
            vim_free(term);
            return NULL;
        }
      }
!     else if (opt->jo_hidden || (flags & TERM_START_SYSTEM))
      {
        buf_T *buf;
  
***************
*** 418,423 ****
--- 449,456 ----
  
      if (opt->jo_term_name != NULL)
        curbuf->b_ffname = vim_strsave(opt->jo_term_name);
+     else if (argv != NULL)
+       curbuf->b_ffname = vim_strsave((char_u *)"!system");
      else
      {
        int     i;
***************
*** 476,487 ****
      set_term_and_win_size(term);
      setup_job_options(opt, term->tl_rows, term->tl_cols);
  
!     if (without_job)
        return curbuf;
  
  #if defined(FEAT_SESSION)
      /* Remember the command for the session file. */
!     if (opt->jo_term_norestore)
      {
        term->tl_command = vim_strsave((char_u *)"NONE");
      }
--- 509,520 ----
      set_term_and_win_size(term);
      setup_job_options(opt, term->tl_rows, term->tl_cols);
  
!     if (flags & TERM_START_NOJOB)
        return curbuf;
  
  #if defined(FEAT_SESSION)
      /* Remember the command for the session file. */
!     if (opt->jo_term_norestore || argv != NULL)
      {
        term->tl_command = vim_strsave((char_u *)"NONE");
      }
***************
*** 533,544 ****
      }
  
      /* System dependent: setup the vterm and maybe start the job in it. */
!     if (argvar->v_type == VAR_STRING
            && argvar->vval.v_string != NULL
            && STRCMP(argvar->vval.v_string, "NONE") == 0)
        res = create_pty_only(term, opt);
      else
!       res = term_and_job_init(term, argvar, opt);
  
      newbuf = curbuf;
      if (res == OK)
--- 566,578 ----
      }
  
      /* System dependent: setup the vterm and maybe start the job in it. */
!     if (argv == NULL
!           && argvar->v_type == VAR_STRING
            && argvar->vval.v_string != NULL
            && STRCMP(argvar->vval.v_string, "NONE") == 0)
        res = create_pty_only(term, opt);
      else
!       res = term_and_job_init(term, argvar, argv, opt);
  
      newbuf = curbuf;
      if (res == OK)
***************
*** 546,564 ****
        /* Get and remember the size we ended up with.  Update the pty. */
        vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
        term_report_winsize(term, term->tl_rows, term->tl_cols);
  
        /* Make sure we don't get stuck on sending keys to the job, it leads to
         * a deadlock if the job is waiting for Vim to read. */
        channel_set_nonblock(term->tl_job->jv_channel, PART_IN);
  
!       if (!opt->jo_hidden)
        {
            ++curbuf->b_locked;
            apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
            --curbuf->b_locked;
        }
! 
!       if (old_curbuf != NULL)
        {
            --curbuf->b_nwindows;
            curbuf = old_curbuf;
--- 580,605 ----
        /* Get and remember the size we ended up with.  Update the pty. */
        vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
        term_report_winsize(term, term->tl_rows, term->tl_cols);
+ #ifdef FEAT_GUI
+       if (term->tl_system)
+       {
+           /* display first line below typed command */
+           term->tl_toprow = msg_row + 1;
+           term->tl_dirty_row_end = 0;
+       }
+ #endif
  
        /* Make sure we don't get stuck on sending keys to the job, it leads to
         * a deadlock if the job is waiting for Vim to read. */
        channel_set_nonblock(term->tl_job->jv_channel, PART_IN);
  
!       if (old_curbuf == NULL)
        {
            ++curbuf->b_locked;
            apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
            --curbuf->b_locked;
        }
!       else
        {
            --curbuf->b_nwindows;
            curbuf = old_curbuf;
***************
*** 572,578 ****
        return NULL;
      }
  
!     apply_autocmds(EVENT_TERMINALOPEN, NULL, NULL, FALSE, curbuf);
      return newbuf;
  }
  
--- 613,619 ----
        return NULL;
      }
  
!     apply_autocmds(EVENT_TERMINALOPEN, NULL, NULL, FALSE, newbuf);
      return newbuf;
  }
  
***************
*** 671,677 ****
      argvar[0].v_type = VAR_STRING;
      argvar[0].vval.v_string = cmd;
      argvar[1].v_type = VAR_UNKNOWN;
!     term_start(argvar, &opt, FALSE, eap->forceit);
      vim_free(tofree);
  
  theend:
--- 712,718 ----
      argvar[0].v_type = VAR_STRING;
      argvar[0].vval.v_string = cmd;
      argvar[1].v_type = VAR_UNKNOWN;
!     term_start(argvar, NULL, &opt, eap->forceit ? TERM_START_FORCEIT : 0);
      vim_free(tofree);
  
  theend:
***************
*** 833,839 ****
  {
      if (term->tl_normal_mode)
        return;
!     setcursor();
      if (redraw)
      {
        if (term->tl_buffer == curbuf && term->tl_cursor_visible)
--- 874,886 ----
  {
      if (term->tl_normal_mode)
        return;
! #ifdef FEAT_GUI
!     if (term->tl_system)
!       windgoto(term->tl_cursor_pos.row + term->tl_toprow,
!                                                     term->tl_cursor_pos.col);
!     else
! #endif
!       setcursor();
      if (redraw)
      {
        if (term->tl_buffer == curbuf && term->tl_cursor_visible)
***************
*** 867,872 ****
--- 914,928 ----
      ch_log(channel, "writing %d bytes to terminal", (int)len);
      term_write_job_output(term, msg, len);
  
+ #ifdef FEAT_GUI
+     if (term->tl_system)
+     {
+       /* show system output, scrolling up the screen as needed */
+       update_system_term(term);
+       update_cursor(term, TRUE);
+     }
+     else
+ #endif
      /* In Terminal-Normal mode we are displaying the buffer, not the terminal
       * contents, thus no screen update is needed. */
      if (!term->tl_normal_mode)
***************
*** 1905,1915 ****
  
      while (blocking || vpeekc_nomap() != NUL)
      {
!       /* TODO: skip screen update when handling a sequence of keys. */
!       /* Repeat redrawing in case a message is received while redrawing. */
!       while (must_redraw != 0)
!           if (update_screen(0) == FAIL)
!               break;
        update_cursor(curbuf->b_term, FALSE);
        restore_cursor = TRUE;
  
--- 1961,1975 ----
  
      while (blocking || vpeekc_nomap() != NUL)
      {
! #ifdef FEAT_GUI
!       if (!curbuf->b_term->tl_system)
! #endif
!           /* TODO: skip screen update when handling a sequence of keys. */
!           /* Repeat redrawing in case a message is received while redrawing.
!            */
!           while (must_redraw != 0)
!               if (update_screen(0) == FAIL)
!                   break;
        update_cursor(curbuf->b_term, FALSE);
        restore_cursor = TRUE;
  
***************
*** 2586,2591 ****
--- 2646,2784 ----
  }
  
  /*
+  * Fill one screen line from a line of the terminal.
+  * Advances "pos" to past the last column.
+  */
+     static void
+ term_line2screenline(VTermScreen *screen, VTermPos *pos, int max_col)
+ {
+     int off = screen_get_current_line_off();
+ 
+     for (pos->col = 0; pos->col < max_col; )
+     {
+       VTermScreenCell cell;
+       int             c;
+ 
+       if (vterm_screen_get_cell(screen, *pos, &cell) == 0)
+           vim_memset(&cell, 0, sizeof(cell));
+ 
+       c = cell.chars[0];
+       if (c == NUL)
+       {
+           ScreenLines[off] = ' ';
+           if (enc_utf8)
+               ScreenLinesUC[off] = NUL;
+       }
+       else
+       {
+           if (enc_utf8)
+           {
+               int i;
+ 
+               /* composing chars */
+               for (i = 0; i < Screen_mco
+                             && i + 1 < VTERM_MAX_CHARS_PER_CELL; ++i)
+               {
+                   ScreenLinesC[i][off] = cell.chars[i + 1];
+                   if (cell.chars[i + 1] == 0)
+                       break;
+               }
+               if (c >= 0x80 || (Screen_mco > 0
+                                        && ScreenLinesC[0][off] != 0))
+               {
+                   ScreenLines[off] = ' ';
+                   ScreenLinesUC[off] = c;
+               }
+               else
+               {
+                   ScreenLines[off] = c;
+                   ScreenLinesUC[off] = NUL;
+               }
+           }
+ #ifdef WIN3264
+           else if (has_mbyte && c >= 0x80)
+           {
+               char_u  mb[MB_MAXBYTES+1];
+               WCHAR   wc = c;
+ 
+               if (WideCharToMultiByte(GetACP(), 0, &wc, 1,
+                                              (char*)mb, 2, 0, 0) > 1)
+               {
+                   ScreenLines[off] = mb[0];
+                   ScreenLines[off + 1] = mb[1];
+                   cell.width = mb_ptr2cells(mb);
+               }
+               else
+                   ScreenLines[off] = c;
+           }
+ #endif
+           else
+               ScreenLines[off] = c;
+       }
+       ScreenAttrs[off] = cell2attr(cell.attrs, cell.fg, cell.bg);
+ 
+       ++pos->col;
+       ++off;
+       if (cell.width == 2)
+       {
+           if (enc_utf8)
+               ScreenLinesUC[off] = NUL;
+ 
+           /* don't set the second byte to NUL for a DBCS encoding, it
+            * has been set above */
+           if (enc_utf8 || !has_mbyte)
+               ScreenLines[off] = NUL;
+ 
+           ++pos->col;
+           ++off;
+       }
+     }
+ }
+ 
+     static void
+ update_system_term(term_T *term)
+ {
+     VTermPos      pos;
+     VTermScreen           *screen;
+ 
+     if (term->tl_vterm == NULL)
+       return;
+     screen = vterm_obtain_screen(term->tl_vterm);
+ 
+     /* Scroll up to make more room for terminal lines if needed. */
+     while (term->tl_toprow > 0
+                         && (Rows - term->tl_toprow) < term->tl_dirty_row_end)
+     {
+       int save_p_more = p_more;
+ 
+       p_more = FALSE;
+       msg_row = Rows - 1;
+       msg_puts((char_u *)"\n");
+       p_more = save_p_more;
+       --term->tl_toprow;
+     }
+ 
+     for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
+                                                 && pos.row < Rows; ++pos.row)
+     {
+       if (pos.row < term->tl_rows)
+       {
+           int max_col = MIN(Columns, term->tl_cols);
+ 
+           term_line2screenline(screen, &pos, max_col);
+       }
+       else
+           pos.col = 0;
+ 
+       screen_line(term->tl_toprow + pos.row, 0, pos.col, Columns, FALSE);
+     }
+ 
+     term->tl_dirty_row_start = MAX_ROW;
+     term->tl_dirty_row_end = 0;
+     update_cursor(term, TRUE);
+ }
+ 
+ /*
   * Called to update a window that contains an active terminal.
   * Returns FAIL when there is no terminal running in this window or in
   * Terminal-Normal mode.
***************
*** 2650,2739 ****
      for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
                                          && pos.row < wp->w_height; ++pos.row)
      {
-       int off = screen_get_current_line_off();
-       int max_col = MIN(wp->w_width, term->tl_cols);
- 
        if (pos.row < term->tl_rows)
        {
!           for (pos.col = 0; pos.col < max_col; )
!           {
!               VTermScreenCell cell;
!               int             c;
! 
!               if (vterm_screen_get_cell(screen, pos, &cell) == 0)
!                   vim_memset(&cell, 0, sizeof(cell));
! 
!               c = cell.chars[0];
!               if (c == NUL)
!               {
!                   ScreenLines[off] = ' ';
!                   if (enc_utf8)
!                       ScreenLinesUC[off] = NUL;
!               }
!               else
!               {
!                   if (enc_utf8)
!                   {
!                       int i;
! 
!                       /* composing chars */
!                       for (i = 0; i < Screen_mco
!                                     && i + 1 < VTERM_MAX_CHARS_PER_CELL; ++i)
!                       {
!                           ScreenLinesC[i][off] = cell.chars[i + 1];
!                           if (cell.chars[i + 1] == 0)
!                               break;
!                       }
!                       if (c >= 0x80 || (Screen_mco > 0
!                                                && ScreenLinesC[0][off] != 0))
!                       {
!                           ScreenLines[off] = ' ';
!                           ScreenLinesUC[off] = c;
!                       }
!                       else
!                       {
!                           ScreenLines[off] = c;
!                           ScreenLinesUC[off] = NUL;
!                       }
!                   }
! #ifdef WIN3264
!                   else if (has_mbyte && c >= 0x80)
!                   {
!                       char_u  mb[MB_MAXBYTES+1];
!                       WCHAR   wc = c;
  
!                       if (WideCharToMultiByte(GetACP(), 0, &wc, 1,
!                                                      (char*)mb, 2, 0, 0) > 1)
!                       {
!                           ScreenLines[off] = mb[0];
!                           ScreenLines[off + 1] = mb[1];
!                           cell.width = mb_ptr2cells(mb);
!                       }
!                       else
!                           ScreenLines[off] = c;
!                   }
! #endif
!                   else
!                       ScreenLines[off] = c;
!               }
!               ScreenAttrs[off] = cell2attr(cell.attrs, cell.fg, cell.bg);
! 
!               ++pos.col;
!               ++off;
!               if (cell.width == 2)
!               {
!                   if (enc_utf8)
!                       ScreenLinesUC[off] = NUL;
! 
!                   /* don't set the second byte to NUL for a DBCS encoding, it
!                    * has been set above */
!                   if (enc_utf8 || !has_mbyte)
!                       ScreenLines[off] = NUL;
! 
!                   ++pos.col;
!                   ++off;
!               }
!           }
        }
        else
            pos.col = 0;
--- 2843,2853 ----
      for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
                                          && pos.row < wp->w_height; ++pos.row)
      {
        if (pos.row < term->tl_rows)
        {
!           int max_col = MIN(wp->w_width, term->tl_cols);
  
!           term_line2screenline(screen, &pos, max_col);
        }
        else
            pos.col = 0;
***************
*** 3623,3629 ****
      /* TODO: use the file name arguments for the buffer name */
      opt.jo_term_name = (char_u *)"dump diff";
  
!     buf = term_start(&argvars[0], &opt, TRUE, FALSE);
      if (buf != NULL && buf->b_term != NULL)
      {
        int             i;
--- 3737,3743 ----
      /* TODO: use the file name arguments for the buffer name */
      opt.jo_term_name = (char_u *)"dump diff";
  
!     buf = term_start(&argvars[0], NULL, &opt, TERM_START_NOJOB);
      if (buf != NULL && buf->b_term != NULL)
      {
        int             i;
***************
*** 4396,4402 ****
  
      if (opt.jo_vertical)
        cmdmod.split = WSP_VERT;
!     buf = term_start(&argvars[0], &opt, FALSE, FALSE);
  
      if (buf != NULL && buf->b_term != NULL)
        rettv->vval.v_number = buf->b_fnum;
--- 4510,4516 ----
  
      if (opt.jo_vertical)
        cmdmod.split = WSP_VERT;
!     buf = term_start(&argvars[0], NULL, &opt, 0);
  
      if (buf != NULL && buf->b_term != NULL)
        rettv->vval.v_number = buf->b_fnum;
***************
*** 4592,4597 ****
--- 4706,4712 ----
  term_and_job_init(
        term_T      *term,
        typval_T    *argvar,
+       char        **argv UNUSED,
        jobopt_T    *opt)
  {
      WCHAR         *cmd_wchar = NULL;
***************
*** 4880,4897 ****
   * Create a new terminal of "rows" by "cols" cells.
   * Start job for "cmd".
   * Store the pointers in "term".
   * Return OK or FAIL.
   */
      static int
  term_and_job_init(
        term_T      *term,
        typval_T    *argvar,
        jobopt_T    *opt)
  {
      create_vterm(term, term->tl_rows, term->tl_cols);
  
!     /* This will change a string in "argvar". */
!     term->tl_job = job_start(argvar, opt);
      if (term->tl_job != NULL)
        ++term->tl_job->jv_refcount;
  
--- 4995,5014 ----
   * Create a new terminal of "rows" by "cols" cells.
   * Start job for "cmd".
   * Store the pointers in "term".
+  * When "argv" is not NULL then "argvar" is not used.
   * Return OK or FAIL.
   */
      static int
  term_and_job_init(
        term_T      *term,
        typval_T    *argvar,
+       char        **argv,
        jobopt_T    *opt)
  {
      create_vterm(term, term->tl_rows, term->tl_cols);
  
!     /* This may change a string in "argvar". */
!     term->tl_job = job_start(argvar, argv, opt);
      if (term->tl_job != NULL)
        ++term->tl_job->jv_refcount;
  
*** ../vim-8.0.1608/src/proto/terminal.pro      2018-03-11 19:30:40.128142740 
+0100
--- src/proto/terminal.pro      2018-03-14 22:48:26.777762521 +0100
***************
*** 1,4 ****
--- 1,6 ----
  /* terminal.c */
+ void init_job_options(jobopt_T *opt);
+ buf_T *term_start(typval_T *argvar, char **argv, jobopt_T *opt, int flags);
  void ex_terminal(exarg_T *eap);
  int term_write_session(FILE *fd, win_T *wp);
  int term_should_restore(buf_T *buf);
*** ../vim-8.0.1608/src/channel.c       2018-03-10 20:27:32.071757661 +0100
--- src/channel.c       2018-03-13 21:43:30.738004891 +0100
***************
*** 5383,5393 ****
  
  /*
   * Create a job and return it.  Implements job_start().
   * The returned job has a refcount of one.
   * Returns NULL when out of memory.
   */
      job_T *
! job_start(typval_T *argvars, jobopt_T *opt_arg)
  {
      job_T     *job;
      char_u    *cmd = NULL;
--- 5383,5395 ----
  
  /*
   * Create a job and return it.  Implements job_start().
+  * "argv_arg" is only for Unix.
+  * When "argv_arg" is NULL then "argvars" is used.
   * The returned job has a refcount of one.
   * Returns NULL when out of memory.
   */
      job_T *
! job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg)
  {
      job_T     *job;
      char_u    *cmd = NULL;
***************
*** 5474,5479 ****
--- 5476,5488 ----
  
      job_set_options(job, &opt);
  
+ #ifdef USE_ARGV
+     if (argv_arg != NULL)
+     {
+       argv = argv_arg;
+     }
+     else
+ #endif
      if (argvars[0].v_type == VAR_STRING)
      {
        /* Command is a string. */
***************
*** 5551,5557 ****
  
  theend:
  #ifdef USE_ARGV
!     vim_free(argv);
  #else
      vim_free(ga.ga_data);
  #endif
--- 5560,5567 ----
  
  theend:
  #ifdef USE_ARGV
!     if (argv != argv_arg)
!       vim_free(argv);
  #else
      vim_free(ga.ga_data);
  #endif
*** ../vim-8.0.1608/src/proto/channel.pro       2017-12-09 19:13:08.579678220 
+0100
--- src/proto/channel.pro       2018-03-13 22:27:20.877173011 +0100
***************
*** 66,72 ****
  void job_stop_on_exit(void);
  int has_pending_job(void);
  void job_check_ended(void);
! job_T *job_start(typval_T *argvars, jobopt_T *opt_arg);
  char *job_status(job_T *job);
  void job_info(job_T *job, dict_T *dict);
  int job_stop(job_T *job, typval_T *argvars, char *type);
--- 66,72 ----
  void job_stop_on_exit(void);
  int has_pending_job(void);
  void job_check_ended(void);
! job_T *job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg);
  char *job_status(job_T *job);
  void job_info(job_T *job, dict_T *dict);
  int job_stop(job_T *job, typval_T *argvars, char *type);
*** ../vim-8.0.1608/src/vim.h   2018-03-11 17:02:07.310194396 +0100
--- src/vim.h   2018-03-13 22:18:13.232722972 +0100
***************
*** 2543,2546 ****
--- 2543,2551 ----
  #define REPLACE_CR_NCHAR    -1
  #define REPLACE_NL_NCHAR    -2
  
+ /* flags for term_start() */
+ #define TERM_START_NOJOB      1
+ #define TERM_START_FORCEIT    2
+ #define TERM_START_SYSTEM     4
+ 
  #endif /* VIM__H */
*** ../vim-8.0.1608/runtime/doc/options.txt     2018-02-22 21:06:44.550819285 
+0100
--- runtime/doc/options.txt     2018-03-13 21:22:21.450057261 +0100
***************
*** 3760,3766 ****
        To avoid problems with flags that are added in the future, use the
        "+=" and "-=" feature of ":set" |add-option-flags|.
  
!       Valid letters are as follows:
                                                        *guioptions_a* *'go-a'*
          'a'   Autoselect:  If present, then whenever VISUAL mode is started,
                or the Visual area extended, Vim tries to become the owner of
--- 3845,3858 ----
        To avoid problems with flags that are added in the future, use the
        "+=" and "-=" feature of ":set" |add-option-flags|.
  
!       Valid characters are as follows:
!                                                               *'go-!'*
!         '!'   External commands are executed in a terminal window.  Without
!               this flag the MS-Windows GUI will open a console window to
!               execute the command.  The Unix GUI will simulate a dumb
!               terminal to list the command output.
!               The terminal window will be positioned at the bottom, and grow
!               upwards as needed.
                                                        *guioptions_a* *'go-a'*
          'a'   Autoselect:  If present, then whenever VISUAL mode is started,
                or the Visual area extended, Vim tries to become the owner of
*** ../vim-8.0.1608/src/version.c       2018-03-14 21:38:57.912996023 +0100
--- src/version.c       2018-03-16 20:44:10.622996708 +0100
***************
*** 768,769 ****
--- 768,771 ----
  {   /* Add new patch number below this line */
+ /**/
+     1609,
  /**/

-- 
Don't Panic!
                -- The Hitchhiker's Guide to the Galaxy

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