forked from aniani/vim
patch 8.0.1609: shell commands in the GUI use a dumb terminal
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.
This commit is contained in:
@@ -3845,7 +3845,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
To avoid problems with flags that are added in the future, use the
|
To avoid problems with flags that are added in the future, use the
|
||||||
"+=" and "-=" feature of ":set" |add-option-flags|.
|
"+=" and "-=" feature of ":set" |add-option-flags|.
|
||||||
|
|
||||||
Valid letters are as follows:
|
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'*
|
*guioptions_a* *'go-a'*
|
||||||
'a' Autoselect: If present, then whenever VISUAL mode is started,
|
'a' Autoselect: If present, then whenever VISUAL mode is started,
|
||||||
or the Visual area extended, Vim tries to become the owner of
|
or the Visual area extended, Vim tries to become the owner of
|
||||||
|
@@ -5383,11 +5383,13 @@ job_check_ended(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a job and return it. Implements job_start().
|
* 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.
|
* The returned job has a refcount of one.
|
||||||
* Returns NULL when out of memory.
|
* Returns NULL when out of memory.
|
||||||
*/
|
*/
|
||||||
job_T *
|
job_T *
|
||||||
job_start(typval_T *argvars, jobopt_T *opt_arg)
|
job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg)
|
||||||
{
|
{
|
||||||
job_T *job;
|
job_T *job;
|
||||||
char_u *cmd = NULL;
|
char_u *cmd = NULL;
|
||||||
@@ -5474,6 +5476,13 @@ job_start(typval_T *argvars, jobopt_T *opt_arg)
|
|||||||
|
|
||||||
job_set_options(job, &opt);
|
job_set_options(job, &opt);
|
||||||
|
|
||||||
|
#ifdef USE_ARGV
|
||||||
|
if (argv_arg != NULL)
|
||||||
|
{
|
||||||
|
argv = argv_arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (argvars[0].v_type == VAR_STRING)
|
if (argvars[0].v_type == VAR_STRING)
|
||||||
{
|
{
|
||||||
/* Command is a string. */
|
/* Command is a string. */
|
||||||
@@ -5551,7 +5560,8 @@ job_start(typval_T *argvars, jobopt_T *opt_arg)
|
|||||||
|
|
||||||
theend:
|
theend:
|
||||||
#ifdef USE_ARGV
|
#ifdef USE_ARGV
|
||||||
vim_free(argv);
|
if (argv != argv_arg)
|
||||||
|
vim_free(argv);
|
||||||
#else
|
#else
|
||||||
vim_free(ga.ga_data);
|
vim_free(ga.ga_data);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -7032,7 +7032,7 @@ f_job_start(typval_T *argvars, typval_T *rettv)
|
|||||||
rettv->v_type = VAR_JOB;
|
rettv->v_type = VAR_JOB;
|
||||||
if (check_restricted() || check_secure())
|
if (check_restricted() || check_secure())
|
||||||
return;
|
return;
|
||||||
rettv->vval.v_job = job_start(argvars, NULL);
|
rettv->vval.v_job = job_start(argvars, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -214,6 +214,7 @@
|
|||||||
#define SHM_ALL "rmfixlnwaWtToOsAIcqF" /* all possible flags for 'shm' */
|
#define SHM_ALL "rmfixlnwaWtToOsAIcqF" /* all possible flags for 'shm' */
|
||||||
|
|
||||||
/* characters for p_go: */
|
/* characters for p_go: */
|
||||||
|
#define GO_TERMINAL '!' /* use terminal for system commands */
|
||||||
#define GO_ASEL 'a' /* autoselect */
|
#define GO_ASEL 'a' /* autoselect */
|
||||||
#define GO_ASELML 'A' /* autoselect modeless selection */
|
#define GO_ASELML 'A' /* autoselect modeless selection */
|
||||||
#define GO_BOT 'b' /* use bottom scrollbar */
|
#define GO_BOT 'b' /* use bottom scrollbar */
|
||||||
@@ -236,7 +237,7 @@
|
|||||||
#define GO_FOOTER 'F' /* add footer */
|
#define GO_FOOTER 'F' /* add footer */
|
||||||
#define GO_VERTICAL 'v' /* arrange dialog buttons vertically */
|
#define GO_VERTICAL 'v' /* arrange dialog buttons vertically */
|
||||||
#define GO_KEEPWINSIZE 'k' /* keep GUI window size */
|
#define GO_KEEPWINSIZE 'k' /* keep GUI window size */
|
||||||
#define GO_ALL "aAbcefFghilmMprtTvk" /* all possible flags for 'go' */
|
#define GO_ALL "!aAbcefFghilmMprtTvk" /* all possible flags for 'go' */
|
||||||
|
|
||||||
/* flags for 'comments' option */
|
/* flags for 'comments' option */
|
||||||
#define COM_NEST 'n' /* comments strings nest */
|
#define COM_NEST 'n' /* comments strings nest */
|
||||||
|
198
src/os_unix.c
198
src/os_unix.c
@@ -4154,10 +4154,13 @@ wait4pid(pid_t child, waitstatus *status)
|
|||||||
return wait_pid;
|
return wait_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEAT_JOB_CHANNEL) || !defined(USE_SYSTEM) || defined(PROTO)
|
#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".
|
* Parse "cmd" and put the white-separated parts in "argv".
|
||||||
* "argv" is an allocated array with "argc" entries.
|
* "argv" is an allocated array with "argc" entries and room for 4 more.
|
||||||
* Returns FAIL when out of memory.
|
* Returns FAIL when out of memory.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@@ -4359,8 +4362,121 @@ may_send_sigint(int c UNUSED, pid_t pid UNUSED, pid_t wpid UNUSED)
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
#if !defined(USE_SYSTEM) || (defined(FEAT_GUI) && defined(FEAT_TERMINAL))
|
||||||
mch_call_shell(
|
|
||||||
|
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,
|
char_u *cmd,
|
||||||
int options) /* SHELL_*, see vim.h */
|
int options) /* SHELL_*, see vim.h */
|
||||||
{
|
{
|
||||||
@@ -4369,7 +4485,6 @@ mch_call_shell(
|
|||||||
char *ofn = NULL;
|
char *ofn = NULL;
|
||||||
#endif
|
#endif
|
||||||
int tmode = cur_tmode;
|
int tmode = cur_tmode;
|
||||||
#ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
|
|
||||||
char_u *newcmd; /* only needed for unix */
|
char_u *newcmd; /* only needed for unix */
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
@@ -4443,14 +4558,23 @@ mch_call_shell(
|
|||||||
restore_clipboard();
|
restore_clipboard();
|
||||||
# endif
|
# endif
|
||||||
return x;
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
|
#else /* USE_SYSTEM */
|
||||||
|
|
||||||
# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
|
# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
|
||||||
127, some shells use that already */
|
127, some shells use that already */
|
||||||
# define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
|
# define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
|
||||||
|
|
||||||
char_u *newcmd;
|
/*
|
||||||
|
* 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 pid;
|
||||||
pid_t wpid = 0;
|
pid_t wpid = 0;
|
||||||
pid_t wait_pid = 0;
|
pid_t wait_pid = 0;
|
||||||
@@ -4461,8 +4585,8 @@ mch_call_shell(
|
|||||||
# endif
|
# endif
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
int argc;
|
char_u *tofree1 = NULL;
|
||||||
char_u *p_shcf_copy = NULL;
|
char_u *tofree2 = NULL;
|
||||||
int i;
|
int i;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int pty_master_fd = -1; /* for pty's */
|
int pty_master_fd = -1; /* for pty's */
|
||||||
@@ -4474,44 +4598,13 @@ mch_call_shell(
|
|||||||
int pipe_error = FALSE;
|
int pipe_error = FALSE;
|
||||||
int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
|
int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
|
||||||
|
|
||||||
newcmd = vim_strsave(p_sh);
|
|
||||||
if (newcmd == NULL) /* out of memory */
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
out_flush();
|
out_flush();
|
||||||
if (options & SHELL_COOKED)
|
if (options & SHELL_COOKED)
|
||||||
settmode(TMODE_COOK); /* set to normal mode */
|
settmode(TMODE_COOK); /* set to normal mode */
|
||||||
|
|
||||||
if (mch_parse_cmd(newcmd, TRUE, &argv, &argc) == FAIL)
|
if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
|
||||||
goto error;
|
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
|
* 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
|
* input from the buffer: Try using a pseudo-tty to get the stdin/stdout
|
||||||
@@ -5319,8 +5412,6 @@ finished:
|
|||||||
MSG_PUTS(_("\nCommand terminated\n"));
|
MSG_PUTS(_("\nCommand terminated\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vim_free(argv);
|
|
||||||
vim_free(p_shcf_copy);
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (!did_settmode)
|
if (!did_settmode)
|
||||||
@@ -5329,11 +5420,28 @@ error:
|
|||||||
# ifdef FEAT_TITLE
|
# ifdef FEAT_TITLE
|
||||||
resettitle();
|
resettitle();
|
||||||
# endif
|
# endif
|
||||||
vim_free(newcmd);
|
vim_free(argv);
|
||||||
|
vim_free(tofree1);
|
||||||
|
vim_free(tofree2);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
}
|
||||||
#endif /* USE_SYSTEM */
|
#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)
|
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
|
||||||
|
@@ -66,7 +66,7 @@ void job_set_options(job_T *job, jobopt_T *opt);
|
|||||||
void job_stop_on_exit(void);
|
void job_stop_on_exit(void);
|
||||||
int has_pending_job(void);
|
int has_pending_job(void);
|
||||||
void job_check_ended(void);
|
void job_check_ended(void);
|
||||||
job_T *job_start(typval_T *argvars, jobopt_T *opt_arg);
|
job_T *job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg);
|
||||||
char *job_status(job_T *job);
|
char *job_status(job_T *job);
|
||||||
void job_info(job_T *job, dict_T *dict);
|
void job_info(job_T *job, dict_T *dict);
|
||||||
int job_stop(job_T *job, typval_T *argvars, char *type);
|
int job_stop(job_T *job, typval_T *argvars, char *type);
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
/* terminal.c */
|
/* 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);
|
void ex_terminal(exarg_T *eap);
|
||||||
int term_write_session(FILE *fd, win_T *wp);
|
int term_write_session(FILE *fd, win_T *wp);
|
||||||
int term_should_restore(buf_T *buf);
|
int term_should_restore(buf_T *buf);
|
||||||
|
343
src/terminal.c
343
src/terminal.c
@@ -38,10 +38,14 @@
|
|||||||
* in tl_scrollback are no longer used.
|
* in tl_scrollback are no longer used.
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
* - When using 'termguicolors' still use the 16 ANSI colors as-is. Helps for
|
* - Make terminal close by default when started without a command. Add
|
||||||
* - In the GUI use a terminal emulator for :!cmd. Make the height the same as
|
* ++noclose argument.
|
||||||
* the window and position it higher up when it gets filled, so it looks like
|
* - Win32: In the GUI use a terminal emulator for :!cmd.
|
||||||
* the text scrolls up.
|
* - 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()
|
* - implement term_setsize()
|
||||||
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
||||||
* completion works.
|
* completion works.
|
||||||
@@ -104,6 +108,10 @@ struct terminal_S {
|
|||||||
VTerm *tl_vterm;
|
VTerm *tl_vterm;
|
||||||
job_T *tl_job;
|
job_T *tl_job;
|
||||||
buf_T *tl_buffer;
|
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. */
|
/* Set when setting the size of a vterm, reset after redrawing. */
|
||||||
int tl_vterm_size_changed;
|
int tl_vterm_size_changed;
|
||||||
@@ -175,10 +183,13 @@ static term_T *in_terminal_loop = NULL;
|
|||||||
/*
|
/*
|
||||||
* Functions with separate implementation for MS-Windows and Unix-like systems.
|
* 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 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 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_report_winsize(term_T *term, int rows, int cols);
|
||||||
static void term_free_vterm(term_T *term);
|
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
|
/* The character that we know (or assume) that the terminal expects for the
|
||||||
* backspace key. */
|
* backspace key. */
|
||||||
@@ -209,6 +220,16 @@ static int desired_cursor_blink = -1;
|
|||||||
static void
|
static void
|
||||||
set_term_and_win_size(term_T *term)
|
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)
|
if (*curwin->w_p_tms != NUL)
|
||||||
{
|
{
|
||||||
char_u *p = vim_strchr(curwin->w_p_tms, 'x') + 1;
|
char_u *p = vim_strchr(curwin->w_p_tms, 'x') + 1;
|
||||||
@@ -236,7 +257,7 @@ set_term_and_win_size(term_T *term)
|
|||||||
* Initialize job options for a terminal job.
|
* Initialize job options for a terminal job.
|
||||||
* Caller may overrule some of them.
|
* Caller may overrule some of them.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
init_job_options(jobopt_T *opt)
|
init_job_options(jobopt_T *opt)
|
||||||
{
|
{
|
||||||
clear_job_options(opt);
|
clear_job_options(opt);
|
||||||
@@ -301,12 +322,17 @@ term_close_buffer(buf_T *buf, buf_T *old_curbuf)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Start a terminal window and return its buffer.
|
* Start a terminal window and return its buffer.
|
||||||
* When "without_job" is TRUE only create the buffer, b_term and open the
|
* Use either "argvar" or "argv", the other must be NULL.
|
||||||
* window.
|
* When "flags" has TERM_START_NOJOB only create the buffer, b_term and open
|
||||||
|
* the window.
|
||||||
* Returns NULL when failed.
|
* Returns NULL when failed.
|
||||||
*/
|
*/
|
||||||
static buf_T *
|
buf_T *
|
||||||
term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
term_start(
|
||||||
|
typval_T *argvar,
|
||||||
|
char **argv,
|
||||||
|
jobopt_T *opt,
|
||||||
|
int flags)
|
||||||
{
|
{
|
||||||
exarg_T split_ea;
|
exarg_T split_ea;
|
||||||
win_T *old_curwin = curwin;
|
win_T *old_curwin = curwin;
|
||||||
@@ -334,26 +360,31 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
|||||||
term->tl_cursor_visible = TRUE;
|
term->tl_cursor_visible = TRUE;
|
||||||
term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
|
term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
|
||||||
term->tl_finish = opt->jo_term_finish;
|
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);
|
ga_init2(&term->tl_scrollback, sizeof(sb_line_T), 300);
|
||||||
|
|
||||||
vim_memset(&split_ea, 0, sizeof(split_ea));
|
vim_memset(&split_ea, 0, sizeof(split_ea));
|
||||||
if (opt->jo_curwin)
|
if (opt->jo_curwin)
|
||||||
{
|
{
|
||||||
/* Create a new buffer in the current window. */
|
/* Create a new buffer in the current window. */
|
||||||
if (!can_abandon(curbuf, forceit))
|
if (!can_abandon(curbuf, flags & TERM_START_FORCEIT))
|
||||||
{
|
{
|
||||||
no_write_message();
|
no_write_message();
|
||||||
vim_free(term);
|
vim_free(term);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
|
if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
|
||||||
ECMD_HIDE + (forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
|
ECMD_HIDE
|
||||||
|
+ ((flags & TERM_START_FORCEIT) ? ECMD_FORCEIT : 0),
|
||||||
|
curwin) == FAIL)
|
||||||
{
|
{
|
||||||
vim_free(term);
|
vim_free(term);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (opt->jo_hidden)
|
else if (opt->jo_hidden || (flags & TERM_START_SYSTEM))
|
||||||
{
|
{
|
||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
|
|
||||||
@@ -418,6 +449,8 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
|||||||
|
|
||||||
if (opt->jo_term_name != NULL)
|
if (opt->jo_term_name != NULL)
|
||||||
curbuf->b_ffname = vim_strsave(opt->jo_term_name);
|
curbuf->b_ffname = vim_strsave(opt->jo_term_name);
|
||||||
|
else if (argv != NULL)
|
||||||
|
curbuf->b_ffname = vim_strsave((char_u *)"!system");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -476,12 +509,12 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
|||||||
set_term_and_win_size(term);
|
set_term_and_win_size(term);
|
||||||
setup_job_options(opt, term->tl_rows, term->tl_cols);
|
setup_job_options(opt, term->tl_rows, term->tl_cols);
|
||||||
|
|
||||||
if (without_job)
|
if (flags & TERM_START_NOJOB)
|
||||||
return curbuf;
|
return curbuf;
|
||||||
|
|
||||||
#if defined(FEAT_SESSION)
|
#if defined(FEAT_SESSION)
|
||||||
/* Remember the command for the session file. */
|
/* Remember the command for the session file. */
|
||||||
if (opt->jo_term_norestore)
|
if (opt->jo_term_norestore || argv != NULL)
|
||||||
{
|
{
|
||||||
term->tl_command = vim_strsave((char_u *)"NONE");
|
term->tl_command = vim_strsave((char_u *)"NONE");
|
||||||
}
|
}
|
||||||
@@ -533,12 +566,13 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* System dependent: setup the vterm and maybe start the job in it. */
|
/* System dependent: setup the vterm and maybe start the job in it. */
|
||||||
if (argvar->v_type == VAR_STRING
|
if (argv == NULL
|
||||||
|
&& argvar->v_type == VAR_STRING
|
||||||
&& argvar->vval.v_string != NULL
|
&& argvar->vval.v_string != NULL
|
||||||
&& STRCMP(argvar->vval.v_string, "NONE") == 0)
|
&& STRCMP(argvar->vval.v_string, "NONE") == 0)
|
||||||
res = create_pty_only(term, opt);
|
res = create_pty_only(term, opt);
|
||||||
else
|
else
|
||||||
res = term_and_job_init(term, argvar, opt);
|
res = term_and_job_init(term, argvar, argv, opt);
|
||||||
|
|
||||||
newbuf = curbuf;
|
newbuf = curbuf;
|
||||||
if (res == OK)
|
if (res == OK)
|
||||||
@@ -546,19 +580,26 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
|||||||
/* Get and remember the size we ended up with. Update the pty. */
|
/* Get and remember the size we ended up with. Update the pty. */
|
||||||
vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
|
vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
|
||||||
term_report_winsize(term, 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
|
/* 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. */
|
* a deadlock if the job is waiting for Vim to read. */
|
||||||
channel_set_nonblock(term->tl_job->jv_channel, PART_IN);
|
channel_set_nonblock(term->tl_job->jv_channel, PART_IN);
|
||||||
|
|
||||||
if (!opt->jo_hidden)
|
if (old_curbuf == NULL)
|
||||||
{
|
{
|
||||||
++curbuf->b_locked;
|
++curbuf->b_locked;
|
||||||
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
|
||||||
--curbuf->b_locked;
|
--curbuf->b_locked;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (old_curbuf != NULL)
|
|
||||||
{
|
{
|
||||||
--curbuf->b_nwindows;
|
--curbuf->b_nwindows;
|
||||||
curbuf = old_curbuf;
|
curbuf = old_curbuf;
|
||||||
@@ -572,7 +613,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_autocmds(EVENT_TERMINALOPEN, NULL, NULL, FALSE, curbuf);
|
apply_autocmds(EVENT_TERMINALOPEN, NULL, NULL, FALSE, newbuf);
|
||||||
return newbuf;
|
return newbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,7 +712,7 @@ ex_terminal(exarg_T *eap)
|
|||||||
argvar[0].v_type = VAR_STRING;
|
argvar[0].v_type = VAR_STRING;
|
||||||
argvar[0].vval.v_string = cmd;
|
argvar[0].vval.v_string = cmd;
|
||||||
argvar[1].v_type = VAR_UNKNOWN;
|
argvar[1].v_type = VAR_UNKNOWN;
|
||||||
term_start(argvar, &opt, FALSE, eap->forceit);
|
term_start(argvar, NULL, &opt, eap->forceit ? TERM_START_FORCEIT : 0);
|
||||||
vim_free(tofree);
|
vim_free(tofree);
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
@@ -833,7 +874,13 @@ update_cursor(term_T *term, int redraw)
|
|||||||
{
|
{
|
||||||
if (term->tl_normal_mode)
|
if (term->tl_normal_mode)
|
||||||
return;
|
return;
|
||||||
setcursor();
|
#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 (redraw)
|
||||||
{
|
{
|
||||||
if (term->tl_buffer == curbuf && term->tl_cursor_visible)
|
if (term->tl_buffer == curbuf && term->tl_cursor_visible)
|
||||||
@@ -867,6 +914,15 @@ write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
|
|||||||
ch_log(channel, "writing %d bytes to terminal", (int)len);
|
ch_log(channel, "writing %d bytes to terminal", (int)len);
|
||||||
term_write_job_output(term, msg, 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
|
/* In Terminal-Normal mode we are displaying the buffer, not the terminal
|
||||||
* contents, thus no screen update is needed. */
|
* contents, thus no screen update is needed. */
|
||||||
if (!term->tl_normal_mode)
|
if (!term->tl_normal_mode)
|
||||||
@@ -1905,11 +1961,15 @@ terminal_loop(int blocking)
|
|||||||
|
|
||||||
while (blocking || vpeekc_nomap() != NUL)
|
while (blocking || vpeekc_nomap() != NUL)
|
||||||
{
|
{
|
||||||
/* TODO: skip screen update when handling a sequence of keys. */
|
#ifdef FEAT_GUI
|
||||||
/* Repeat redrawing in case a message is received while redrawing. */
|
if (!curbuf->b_term->tl_system)
|
||||||
while (must_redraw != 0)
|
#endif
|
||||||
if (update_screen(0) == FAIL)
|
/* TODO: skip screen update when handling a sequence of keys. */
|
||||||
break;
|
/* 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);
|
update_cursor(curbuf->b_term, FALSE);
|
||||||
restore_cursor = TRUE;
|
restore_cursor = TRUE;
|
||||||
|
|
||||||
@@ -2585,6 +2645,139 @@ term_channel_closed(channel_T *ch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
* Called to update a window that contains an active terminal.
|
||||||
* Returns FAIL when there is no terminal running in this window or in
|
* Returns FAIL when there is no terminal running in this window or in
|
||||||
@@ -2650,90 +2843,11 @@ term_update_window(win_T *wp)
|
|||||||
for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
|
for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
|
||||||
&& pos.row < wp->w_height; ++pos.row)
|
&& 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)
|
if (pos.row < term->tl_rows)
|
||||||
{
|
{
|
||||||
for (pos.col = 0; pos.col < max_col; )
|
int max_col = MIN(wp->w_width, term->tl_cols);
|
||||||
{
|
|
||||||
VTermScreenCell cell;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if (vterm_screen_get_cell(screen, pos, &cell) == 0)
|
term_line2screenline(screen, &pos, max_col);
|
||||||
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
|
else
|
||||||
pos.col = 0;
|
pos.col = 0;
|
||||||
@@ -3623,7 +3737,7 @@ term_load_dump(typval_T *argvars, typval_T *rettv, int do_diff)
|
|||||||
/* TODO: use the file name arguments for the buffer name */
|
/* TODO: use the file name arguments for the buffer name */
|
||||||
opt.jo_term_name = (char_u *)"dump diff";
|
opt.jo_term_name = (char_u *)"dump diff";
|
||||||
|
|
||||||
buf = term_start(&argvars[0], &opt, TRUE, FALSE);
|
buf = term_start(&argvars[0], NULL, &opt, TERM_START_NOJOB);
|
||||||
if (buf != NULL && buf->b_term != NULL)
|
if (buf != NULL && buf->b_term != NULL)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -4396,7 +4510,7 @@ f_term_start(typval_T *argvars, typval_T *rettv)
|
|||||||
|
|
||||||
if (opt.jo_vertical)
|
if (opt.jo_vertical)
|
||||||
cmdmod.split = WSP_VERT;
|
cmdmod.split = WSP_VERT;
|
||||||
buf = term_start(&argvars[0], &opt, FALSE, FALSE);
|
buf = term_start(&argvars[0], NULL, &opt, 0);
|
||||||
|
|
||||||
if (buf != NULL && buf->b_term != NULL)
|
if (buf != NULL && buf->b_term != NULL)
|
||||||
rettv->vval.v_number = buf->b_fnum;
|
rettv->vval.v_number = buf->b_fnum;
|
||||||
@@ -4592,6 +4706,7 @@ dyn_winpty_init(int verbose)
|
|||||||
term_and_job_init(
|
term_and_job_init(
|
||||||
term_T *term,
|
term_T *term,
|
||||||
typval_T *argvar,
|
typval_T *argvar,
|
||||||
|
char **argv UNUSED,
|
||||||
jobopt_T *opt)
|
jobopt_T *opt)
|
||||||
{
|
{
|
||||||
WCHAR *cmd_wchar = NULL;
|
WCHAR *cmd_wchar = NULL;
|
||||||
@@ -4880,18 +4995,20 @@ terminal_enabled(void)
|
|||||||
* Create a new terminal of "rows" by "cols" cells.
|
* Create a new terminal of "rows" by "cols" cells.
|
||||||
* Start job for "cmd".
|
* Start job for "cmd".
|
||||||
* Store the pointers in "term".
|
* Store the pointers in "term".
|
||||||
|
* When "argv" is not NULL then "argvar" is not used.
|
||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
term_and_job_init(
|
term_and_job_init(
|
||||||
term_T *term,
|
term_T *term,
|
||||||
typval_T *argvar,
|
typval_T *argvar,
|
||||||
|
char **argv,
|
||||||
jobopt_T *opt)
|
jobopt_T *opt)
|
||||||
{
|
{
|
||||||
create_vterm(term, term->tl_rows, term->tl_cols);
|
create_vterm(term, term->tl_rows, term->tl_cols);
|
||||||
|
|
||||||
/* This will change a string in "argvar". */
|
/* This may change a string in "argvar". */
|
||||||
term->tl_job = job_start(argvar, opt);
|
term->tl_job = job_start(argvar, argv, opt);
|
||||||
if (term->tl_job != NULL)
|
if (term->tl_job != NULL)
|
||||||
++term->tl_job->jv_refcount;
|
++term->tl_job->jv_refcount;
|
||||||
|
|
||||||
|
@@ -766,6 +766,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1609,
|
||||||
/**/
|
/**/
|
||||||
1608,
|
1608,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2543,4 +2543,9 @@ typedef enum {
|
|||||||
#define REPLACE_CR_NCHAR -1
|
#define REPLACE_CR_NCHAR -1
|
||||||
#define REPLACE_NL_NCHAR -2
|
#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 */
|
#endif /* VIM__H */
|
||||||
|
Reference in New Issue
Block a user