Compare commits

...

31 Commits

Author SHA1 Message Date
Bram Moolenaar
753289f9bf patch 8.0.0995: terminal tests fail on Mac
Problem:    Terminal tests fail on Mac.
Solution:   Add workaround: sleep a moment in between sending keys.
2017-08-25 23:22:05 +02:00
Bram Moolenaar
be0b72977f patch 8.0.0994: MS-Windows: cursor in terminal blinks undesirably
Problem:    MS-Windows: cursor in terminal blinks even though the blinking
            cursor was disabled on the system.
Solution:   Use GetCaretBlinkTime(). (Ken Takata)
2017-08-24 21:48:26 +02:00
Bram Moolenaar
f6d9f96b2d patch 8.0.0993: sometimes an xterm sends an extra CTRL-X
Problem:    Sometimes an xterm sends an extra CTRL-X after the response for
            the background color.  Related to t_RS.
Solution:   Check for the CTRL-X after the terminating 0x7.
2017-08-24 20:21:16 +02:00
Bram Moolenaar
33d66bd9fa patch 8.0.0992: terminal title is wrong when 'encoding' is DBCS
Problem:    Terminal title is wrong when 'encoding' is DBCS.
Solution:   Convert the title from DBCS to utf-8. (Yasuhiro Matsumoto, closes
            #2009)
2017-08-23 23:51:58 +02:00
Bram Moolenaar
6c4d12c527 patch 8.0.0991: using wrong character conversion for DBCS
Problem:    Using wrong character conversion for DBCS.
Solution:   Use utf_char2bytes instead of mb_char2bytes. (Yasuhiro Matsumoto,
            closes #2012)
2017-08-23 23:36:25 +02:00
Bram Moolenaar
285f243e50 patch 8.0.0990: with DBCS 'encoding' wrong pasting register into terminal
Problem:    When 'encoding' is a double-byte encoding, pasting a register into
            a terminal ends up with the wrong characters.
Solution:   Convert from 'encoding' to utf-8. (Yasuhiro Matsumoto, closes
            #2007)
2017-08-23 23:10:21 +02:00
Bram Moolenaar
77f7474d08 patch 8.0.0989: ActiveTcl dll name has changed in 8.6.6
Problem:    ActiveTcl dll name has changed in 8.6.6.
Solution:   Adjust the makefile. (Ken Takata)
2017-08-23 22:40:41 +02:00
Bram Moolenaar
829aa64cf5 patch 8.0.0988: warning from Covscan about using NULL pointer
Problem:    Warning from Covscan about using NULL pointer.
Solution:   Add extra check for NULL. (zdohnal)
2017-08-23 22:32:35 +02:00
Bram Moolenaar
d2c45a1964 patch 8.0.0987: terminal: second byte of double-byte char wrong
Problem:    terminal: second byte of double-byte char wrong
Solution:   Set the second byte to NUL only for utf-8 and non-multibyte.
2017-08-22 22:29:00 +02:00
Bram Moolenaar
ec0e07a324 patch 8.0.0986: terminal feature always requires multi-byte feature
Problem:    Terminal feature always requires multi-byte feature.
Solution:   Remove #ifdef FEAT_MBYTE, disable terminal without multi-byte.
2017-08-22 22:21:37 +02:00
Bram Moolenaar
6d0826dfbb patch 8.0.0985: libvterm has its own idea of character width
Problem:    Libvterm has its own idea of character width.
Solution:   Use the Vim functions for character width and composing to avoid a
            mismatch. (idea by Yasuhiro Matsumoto)
2017-08-22 22:12:17 +02:00
Bram Moolenaar
5830232c02 patch 8.0.0984: terminal blinking cursor not correct in the GUI
Problem:    Terminal blinking cursor not correct in the GUI.
Solution:   Set blinkoff correctly.  Also make the cursor blink on MS-Windows
            by default. (Ken Takata)
2017-08-22 20:33:53 +02:00
Bram Moolenaar
3f9a1ff141 patch 8.0.0983: unnecessary check for NULL pointer
Problem:    Unnecessary check for NULL pointer.
Solution:   Remove the NULL check in dialog_changed(), it already happens in
            dialog_msg(). (Ken Takata)
2017-08-21 22:06:02 +02:00
Bram Moolenaar
740c433c59 patch 8.0.0982: cannot use a terminal when 'encoding' is non-utf8 multi-byte
Problem:    When 'encoding' is set to a multi-byte encoding other than utf-8
            the characters from ther terminal are messed up.
Solution:   Convert displayed text from utf-8 to 'encoding' for MS-Windows.
            (Yasuhiro Matsumoto, close #2000)
2017-08-21 22:01:27 +02:00
Bram Moolenaar
0cbba82359 patch 8.0.0981: cursor in terminal window blinks by default
Problem:    Cursor in terminal window blinks by default, while in a real xterm
            it does not blink, unless the -bc argument is used.
Solution:   Do not use a blinking cursor by default.
2017-08-21 21:39:28 +02:00
Bram Moolenaar
b109bb4e12 patch 8.0.0980: Coverity warning for failing to open /dev/null
Problem:    Coverity warning for failing to open /dev/null.
Solution:   When /dev/null can't be opened exit the child.
2017-08-21 21:07:29 +02:00
Bram Moolenaar
eef0531621 patch 8.0.0979: terminal noblock test fails on MS-Windows
Problem:    Terminal noblock test fails on MS-Windows. (Christian Brabandt)
Solution:   Ignore empty line below "done".
2017-08-20 20:21:23 +02:00
Bram Moolenaar
37819ed540 patch 8.0.0978: writing to terminal job is not tested
Problem:    Writing to terminal job is not tested.
Solution:   Add a test.
2017-08-20 19:33:47 +02:00
Bram Moolenaar
5983d50247 patch 8.0.0977: cannot send lines to a terminal job on MS-Windows
Problem:    Cannot send lines to a terminal job on MS-Windows.
Solution:   Set jv_in_buf.  Command doesn't get EOF yet though.
2017-08-20 19:22:56 +02:00
Bram Moolenaar
b241208a13 patch 8.0.0976: cannot send lines to a terminal job
Problem:    Cannot send lines to a terminal job.
Solution:   Make [range]terminal send selected lines to the job.
            Use ++rows and ++cols for the terminal size.
2017-08-20 18:09:14 +02:00
Bram Moolenaar
edbc0d46cf patch 8.0.0975: using freed memory when setting 'backspace'
Problem:    Using freed memory when setting 'backspace'.
Solution:   When changing oldval also change origval.
2017-08-20 16:11:51 +02:00
Bram Moolenaar
8efa026a25 patch 8.0.0974: resetting a string option does not trigger OptionSet
Problem:    Resetting a string option does not trigger OptionSet. (Rick Howe)
Solution:   Set the origval.
2017-08-20 15:47:20 +02:00
Bram Moolenaar
ce1c32780a patch 8.0.0973: initial info about blinking cursor is wrong
Problem:    initial info about blinking cursor is wrong
Solution:   Invert the blink flag.  Add t_VS to stop a blinking cursor.
2017-08-20 15:05:15 +02:00
Bram Moolenaar
37b9b81997 patch 8.0.0972: compiler warnings for unused variables
Problem:    Compiler warnings for unused variables. (Tony Mechelynck)
Solution:   Add #ifdefs.
2017-08-19 23:23:43 +02:00
Bram Moolenaar
0aed9a2e2e patch 8.0.0971: 'winptydll' missing from :options
Problem:    'winptydll' missing from :options.
Solution:   Add the entry.
2017-08-19 23:18:02 +02:00
Bram Moolenaar
d6a7b3e6bb patch 8.0.0970: passing invalid highlight id
Problem:    if there is no StatusLine highlighting and there is StatusLineNC
            or StatusLineTermNC highlighting then an invalid highlight id is
            passed to combine_stl_hlt(). (Coverity)
Solution:   Check id_S to be -1 instead of zero.
2017-08-19 21:35:35 +02:00
Bram Moolenaar
dc926dd0dd patch 8.0.0969: Coverity warning for unused return value
Problem:    Coverity warning for unused return value.
Solution:   Add (void) to avoid the warning.
2017-08-19 21:26:44 +02:00
Bram Moolenaar
77ac9b5c62 patch 8.0.0968: crash when switching terminal modes
Problem:    Crash when switching terminal modes. (Nikolai Pavlov)
Solution:   Check that there are scrollback lines.
2017-08-19 21:23:05 +02:00
Bram Moolenaar
93c92eff26 patch 8.0.0967: using a terminal may cause the cursor to blink
Problem:    Using a terminal may cause the cursor to blink.
Solution:   Do not set t_vs, since we cannot restore the old blink state.
2017-08-19 21:11:57 +02:00
Bram Moolenaar
fc8bec0be4 patch 8.0.0966: build failure without terminal feature
Problem:    Build failure without terminal feature.
Solution:   Move #endif.
2017-08-19 19:57:34 +02:00
Bram Moolenaar
3eee06e7d4 patch 8.0.0965: not restoring cursor shape after it was set in a terminal
Problem:    The cursor shape is not reset after it was changed in a terminal.
Solution:   Request the original cursor shape and restore it.  Add t_RS.
            Do not add t_SH for now, it does not work properly.
2017-08-19 19:40:50 +02:00
24 changed files with 658 additions and 202 deletions

View File

@@ -1,4 +1,4 @@
*terminal.txt* For Vim version 8.0. Last change: 2017 Aug 12
*terminal.txt* For Vim version 8.0. Last change: 2017 Aug 20
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -102,10 +102,9 @@ Syntax ~
parentheses. E.g. if "gdb" exists the second terminal
buffer will use "!gdb (1)".
If [range] is given it is used for the terminal size.
One number specifies the number of rows. Unless the
"vertical" modifier is used, then it is the number of
columns.
If [range] is given the specified lines are used as
input for the job. It will not be possible to type
keys in the terminal window.
Two comma separated numbers are used as "rows,cols".
E.g. `:24,80gdb` opens a terminal with 24 rows and 80
@@ -125,6 +124,10 @@ Syntax ~
cannot be |abandon|ed.
++hidden Open the terminal in a hidden buffer,
no window will be used.
++rows={height} Use {height} for the terminal window
height.
++cols={width} Use {width} for the terminal window
width.
If you want to use more options use the |term_start()|
function.

View File

@@ -1,7 +1,7 @@
" These commands create the option window.
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2017 Aug 11
" Last Change: 2017 Aug 19
" If there already is an option window, jump to that one.
let buf = bufnr('option-window')
@@ -510,6 +510,10 @@ if has("terminal")
call append("$", "termkey\tkey that precedes Vim commands in a terminal window")
call append("$", "\t(local to window)")
call <SID>OptionL("tk")
if exists("&winptydll")
call append("$", "winptydll\tname of the winpty dynamic library")
call <SID>OptionG("winptydll", &winptydll)
endif
endif

View File

@@ -340,6 +340,7 @@ endif
# TCL_VER=[TCL version, eg 83, 84] (default is 86)
# TCL_VER_LONG=[Tcl version, eg 8.3] (default is 8.6)
# You must set TCL_VER_LONG when you set TCL_VER.
# TCL_DLL=[TCL dll name, eg tcl86.dll] (default is tcl86.dll)
ifdef TCL
ifndef DYNAMIC_TCL
DYNAMIC_TCL=yes
@@ -350,6 +351,9 @@ endif
ifndef TCL_VER_LONG
TCL_VER_LONG = 8.6
endif
ifndef TCL_DLL
TCL_DLL = tcl$(TCL_VER).dll
endif
TCLINC += -I$(TCL)/include
endif
@@ -526,7 +530,7 @@ endif
ifdef TCL
CFLAGS += -DFEAT_TCL $(TCLINC)
ifeq (yes, $(DYNAMIC_TCL))
CFLAGS += -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"tcl$(TCL_VER).dll\" -DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
CFLAGS += -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"$(TCL_DLL)\" -DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
endif
endif
@@ -971,7 +975,11 @@ $(OUTDIR)/terminal.o: terminal.c $(INCL) $(TERM_DEPS)
$(CC) -c $(CFLAGS) terminal.c -o $(OUTDIR)/terminal.o
CCCTERM = $(CC) -c $(CFLAGS) -Ilibvterm/include -DINLINE="" -DVSNPRINTF=vim_vsnprintf
CCCTERM = $(CC) -c $(CFLAGS) -Ilibvterm/include -DINLINE="" \
-DVSNPRINTF=vim_vsnprintf \
-DIS_COMBINING_FUNCTION=utf_iscomposing_uint \
-DWCWIDTH_FUNCTION=utf_uint2cells
$(OUTDIR)/term_encoding.o: libvterm/src/encoding.c $(TERM_DEPS)
$(CCCTERM) libvterm/src/encoding.c -o $@

View File

@@ -84,6 +84,7 @@
# TCL_VER=[Tcl version, e.g. 80, 83] (default is 86)
# TCL_VER_LONG=[Tcl version, eg 8.3] (default is 8.6)
# You must set TCL_VER_LONG when you set TCL_VER.
# TCL_DLL=[Tcl dll name, e.g. tcl86.dll] (default is tcl86.dll)
#
# Cscope support: CSCOPE=yes
#
@@ -832,7 +833,9 @@ TCL_VER_LONG = 8.6
!message Tcl requested (version $(TCL_VER)) - root dir is "$(TCL)"
!if "$(DYNAMIC_TCL)" == "yes"
!message Tcl DLL will be loaded dynamically
!ifndef TCL_DLL
TCL_DLL = tcl$(TCL_VER).dll
!endif
CFLAGS = $(CFLAGS) -DFEAT_TCL -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"$(TCL_DLL)\" \
-DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
TCL_OBJ = $(OUTDIR)\if_tcl.obj
@@ -1474,7 +1477,12 @@ $(OUTDIR)/dimm_i.obj: $(OUTDIR) dimm_i.c $(INCL)
$(OUTDIR)/glbl_ime.obj: $(OUTDIR) glbl_ime.cpp dimm.h $(INCL)
CCCTERM = $(CC) $(CFLAGS) -Ilibvterm/include -DINLINE="" -DVSNPRINTF=vim_vsnprintf -D_CRT_SECURE_NO_WARNINGS
CCCTERM = $(CC) $(CFLAGS) -Ilibvterm/include -DINLINE="" \
-DVSNPRINTF=vim_vsnprintf \
-DIS_COMBINING_FUNCTION=utf_iscomposing_uint \
-DWCWIDTH_FUNCTION=utf_uint2cells \
-D_CRT_SECURE_NO_WARNINGS
$(OUTDIR)/term_encoding.obj: $(OUTDIR) libvterm/src/encoding.c $(TERM_DEPS)
$(CCCTERM) -Fo$@ libvterm/src/encoding.c

View File

@@ -3296,7 +3296,11 @@ objects/channel.o: channel.c
Makefile:
@echo The name of the makefile MUST be "Makefile" (with capital M)!!!!
CCCTERM = $(CCC) -Ilibvterm/include -DINLINE="" -DVSNPRINTF=vim_vsnprintf
CCCTERM = $(CCC) -Ilibvterm/include -DINLINE="" \
-DVSNPRINTF=vim_vsnprintf \
-DIS_COMBINING_FUNCTION=utf_iscomposing_uint \
-DWCWIDTH_FUNCTION=utf_uint2cells
objects/term_encoding.o: libvterm/src/encoding.c $(TERM_DEPS)
$(CCCTERM) -o $@ libvterm/src/encoding.c

View File

@@ -3559,7 +3559,7 @@ channel_set_nonblock(channel_T *channel, ch_part_T part)
ioctlsocket(fd, FIONBIO, &val);
#else
fcntl(fd, F_SETFL, O_NONBLOCK);
(void)fcntl(fd, F_SETFL, O_NONBLOCK);
#endif
ch_part->ch_nonblocking = TRUE;
}

View File

@@ -1484,8 +1484,8 @@ EX(CMD_tearoff, "tearoff", ex_tearoff,
NEEDARG|EXTRA|TRLBAR|NOTRLCOM|CMDWIN,
ADDR_LINES),
EX(CMD_terminal, "terminal", ex_terminal,
RANGE|NOTADR|BANG|FILES|TRLBAR|CMDWIN,
ADDR_OTHER),
RANGE|BANG|FILES|TRLBAR|CMDWIN,
ADDR_LINES),
EX(CMD_tfirst, "tfirst", ex_tag,
RANGE|NOTADR|BANG|TRLBAR|ZEROR,
ADDR_LINES),

View File

@@ -1981,9 +1981,7 @@ dialog_changed(
buf_T *buf2;
exarg_T ea;
dialog_msg(buff, _("Save changes to \"%s\"?"),
(buf->b_fname != NULL) ?
buf->b_fname : (char_u *)_("Untitled"));
dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname);
if (checkall)
ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
else

View File

@@ -1269,8 +1269,10 @@
/*
* +terminal ":terminal" command. Runs a terminal in a window.
* requires +channel and +multibyte
*/
#if !defined(FEAT_JOB_CHANNEL) && defined(FEAT_TERMINAL)
#if defined(FEAT_TERMINAL) && \
!(defined(FEAT_JOB_CHANNEL) && defined(FEAT_MBYTE))
# undef FEAT_TERMINAL
#endif
#if defined(FEAT_TERMINAL) && !defined(CURSOR_SHAPE)

View File

@@ -1370,7 +1370,8 @@ retry:
* Decrypt the read bytes. This is done before checking for
* EOF because the crypt layer may be buffering.
*/
if (cryptkey != NULL && size > 0)
if (cryptkey != NULL && curbuf->b_cryptstate != NULL
&& size > 0)
{
if (crypt_works_inplace(curbuf->b_cryptstate))
{

View File

@@ -68,6 +68,7 @@
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
#if !defined(IS_COMBINING_FUNCTION) || !defined(WCWIDTH_FUNCTION)
struct interval {
int first;
int last;
@@ -126,7 +127,6 @@ static const struct interval combining[] = {
{ 0xE0100, 0xE01EF }
};
/* auxiliary function for binary search in interval table */
static int bisearch(uint32_t ucs, const struct interval *table, int max) {
int min = 0;
@@ -146,6 +146,7 @@ static int bisearch(uint32_t ucs, const struct interval *table, int max) {
return 0;
}
#endif
/* The following two functions define the column width of an ISO 10646
@@ -180,6 +181,11 @@ static int bisearch(uint32_t ucs, const struct interval *table, int max) {
* in ISO 10646.
*/
#ifdef WCWIDTH_FUNCTION
/* use a provided wcwidth() function */
int WCWIDTH_FUNCTION(uint32_t ucs);
#else
# define WCWIDTH_FUNCTION mk_wcwidth
static int mk_wcwidth(uint32_t ucs)
{
@@ -211,6 +217,7 @@ static int mk_wcwidth(uint32_t ucs)
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
(ucs >= 0x30000 && ucs <= 0x3fffd)));
}
#endif
#if 0 /* unused */
static int mk_wcswidth(const uint32_t *pwcs, size_t n)
@@ -317,15 +324,28 @@ static int mk_wcswidth_cjk(const uint32_t *pwcs, size_t n)
}
#endif
#ifdef IS_COMBINING_FUNCTION
/* Use a provided is_combining() function. */
int IS_COMBINING_FUNCTION(uint32_t codepoint);
#else
# define IS_COMBINING_FUNCTION vterm_is_combining
static int
vterm_is_combining(uint32_t codepoint)
{
return bisearch(codepoint, combining, sizeof(combining) / sizeof(struct interval) - 1);
}
#endif
/* ################################
* ### The rest added by Paul Evans */
INTERNAL int vterm_unicode_width(uint32_t codepoint)
{
return mk_wcwidth(codepoint);
return WCWIDTH_FUNCTION(codepoint);
}
INTERNAL int vterm_unicode_is_combining(uint32_t codepoint)
{
return bisearch(codepoint, combining, sizeof(combining) / sizeof(struct interval) - 1);
return IS_COMBINING_FUNCTION(codepoint);
}

View File

@@ -1395,6 +1395,17 @@ static struct interval ambiguous[] =
{0x100000, 0x10fffd}
};
#if defined(FEAT_TERMINAL) || defined(PROTO)
/*
* utf_char2cells() with different argument type for libvterm.
*/
int
utf_uint2cells(uint32_t c)
{
return utf_char2cells((int)c);
}
#endif
/*
* For UTF-8 character "c" return 2 for a double-width character, 1 for others.
* Returns 4 or 6 for an unprintable character.
@@ -2296,6 +2307,17 @@ utf_char2bytes(int c, char_u *buf)
return 6;
}
#if defined(FEAT_TERMINAL) || defined(PROTO)
/*
* utf_iscomposing() with different argument type for libvterm.
*/
int
utf_iscomposing_uint(uint32_t c)
{
return utf_iscomposing((int)c);
}
#endif
/*
* Return TRUE if "c" is a composing UTF-8 character. This means it will be
* drawn on top of the preceding character.

View File

@@ -3157,6 +3157,8 @@ static struct vimoption options[] =
p_term("t_AL", T_CAL)
p_term("t_al", T_AL)
p_term("t_bc", T_BC)
p_term("t_BE", T_BE)
p_term("t_BD", T_BD)
p_term("t_cd", T_CD)
p_term("t_ce", T_CE)
p_term("t_cl", T_CL)
@@ -3173,12 +3175,11 @@ static struct vimoption options[] =
p_term("t_db", T_DB)
p_term("t_DL", T_CDL)
p_term("t_dl", T_DL)
p_term("t_EC", T_CEC)
p_term("t_EI", T_CEI)
p_term("t_fs", T_FS)
p_term("t_GP", T_CGP)
p_term("t_IE", T_CIE)
p_term("t_SC", T_CSC)
p_term("t_EC", T_CEC)
p_term("t_SH", T_CSH)
p_term("t_IS", T_CIS)
p_term("t_ke", T_KE)
p_term("t_ks", T_KS)
@@ -3192,10 +3193,13 @@ static struct vimoption options[] =
p_term("t_op", T_OP)
p_term("t_RB", T_RBG)
p_term("t_RI", T_CRI)
p_term("t_RS", T_CRS)
p_term("t_RV", T_CRV)
p_term("t_Sb", T_CSB)
p_term("t_SC", T_CSC)
p_term("t_se", T_SE)
p_term("t_Sf", T_CSF)
p_term("t_SH", T_CSH)
p_term("t_SI", T_CSI)
p_term("t_so", T_SO)
p_term("t_SR", T_CSR)
@@ -3210,9 +3214,9 @@ static struct vimoption options[] =
p_term("t_vb", T_VB)
p_term("t_ve", T_VE)
p_term("t_vi", T_VI)
p_term("t_VS", T_CVS)
p_term("t_vs", T_VS)
p_term("t_WP", T_CWP)
p_term("t_GP", T_CGP)
p_term("t_WS", T_CWS)
p_term("t_xn", T_XN)
p_term("t_xs", T_XS)
@@ -3220,8 +3224,6 @@ static struct vimoption options[] =
p_term("t_ZR", T_CZR)
p_term("t_8f", T_8F)
p_term("t_8b", T_8B)
p_term("t_BE", T_BE)
p_term("t_BD", T_BD)
/* terminal key codes are not in here */
@@ -4349,8 +4351,6 @@ trigger_optionsset_string(
(char_u *)options[opt_idx].fullname, NULL, FALSE, NULL);
reset_v_option_vars();
}
vim_free(oldval);
vim_free(newval);
}
#endif
@@ -4841,6 +4841,16 @@ do_set(
/* The old value is kept until we are sure that the
* new value is valid. */
oldval = *(char_u **)varp;
/* When setting the local value of a global
* option, the old value may be the global value. */
if (((int)options[opt_idx].indir & PV_BOTH)
&& (opt_flags & OPT_LOCAL))
origval = *(char_u **)get_varp(
&options[opt_idx]);
else
origval = oldval;
if (nextchar == '&') /* set to default val */
{
newval = options[opt_idx].def_val[
@@ -4917,6 +4927,8 @@ do_set(
break;
}
vim_free(oldval);
if (origval == oldval)
origval = *(char_u **)varp;
oldval = *(char_u **)varp;
}
/*
@@ -4955,15 +4967,6 @@ do_set(
++arg;
}
/* When setting the local value of a global
* option, the old value may be the global value. */
if (((int)options[opt_idx].indir & PV_BOTH)
&& (opt_flags & OPT_LOCAL))
origval = *(char_u **)get_varp(
&options[opt_idx]);
else
origval = oldval;
/*
* Copy the new string into allocated memory.
* Can't use set_string_option_direct(), because
@@ -5167,7 +5170,9 @@ do_set(
new_value_alloced = TRUE;
}
/* Set the new value. */
/*
* Set the new value.
*/
*(char_u **)(varp) = newval;
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
@@ -5193,20 +5198,17 @@ do_set(
errmsg = did_set_string_option(opt_idx, (char_u **)varp,
new_value_alloced, oldval, errbuf, opt_flags);
/* If error detected, print the error message. */
if (errmsg != NULL)
{
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
if (errmsg == NULL)
trigger_optionsset_string(opt_idx, opt_flags,
saved_origval, saved_newval);
vim_free(saved_origval);
vim_free(saved_newval);
#endif
/* If error detected, print the error message. */
if (errmsg != NULL)
goto skip;
}
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
trigger_optionsset_string(opt_idx, opt_flags,
saved_origval, saved_newval);
#endif
}
else /* key code option */
{
char_u *p;
@@ -6012,8 +6014,11 @@ set_string_option(
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
/* call autocommand after handling side effects */
if (r == NULL)
trigger_optionsset_string(opt_idx, opt_flags,
saved_oldval, saved_newval);
vim_free(saved_oldval);
vim_free(saved_newval);
#endif
}
return r;

View File

@@ -4340,6 +4340,7 @@ mch_call_shell(
# 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;
@@ -5238,6 +5239,7 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
int use_buffer_for_in = options->jo_io[PART_IN] == JIO_BUFFER;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
SIGSET_DECL(curset)
@@ -5247,7 +5249,10 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
/* default is to fail */
job->jv_status = JOB_FAILED;
if (options->jo_pty)
if (options->jo_pty
&& (!(use_file_for_in || use_null_for_in)
|| !(use_file_for_in || use_null_for_out)
|| !(use_out_for_err || use_file_for_err || use_null_for_err)))
open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_name);
/* TODO: without the channel feature connect the child to /dev/null? */
@@ -5263,7 +5268,11 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
goto failed;
}
}
else if (!use_null_for_in && pty_master_fd < 0 && pipe(fd_in) < 0)
else
/* When writing buffer lines to the input don't use the pty, so that
* the pipe can be closed when all lines were written. */
if (!use_null_for_in && (pty_master_fd < 0 || use_buffer_for_in)
&& pipe(fd_in) < 0)
goto failed;
if (use_file_for_out)
@@ -5361,7 +5370,14 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
}
if (use_null_for_in || use_null_for_out || use_null_for_err)
{
null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
if (null_fd < 0)
{
perror("opening /dev/null failed");
_exit(OPEN_NULL_FAILED);
}
}
if (pty_slave_fd >= 0)
{

View File

@@ -10,6 +10,7 @@ int latin_char2len(int c);
int latin_char2bytes(int c, char_u *buf);
int latin_ptr2len(char_u *p);
int latin_ptr2len_len(char_u *p, int size);
int utf_uint2cells(uint32_t c);
int utf_char2cells(int c);
int latin_ptr2cells(char_u *p);
int utf_ptr2cells(char_u *p);
@@ -37,6 +38,7 @@ int utfc_ptr2len(char_u *p);
int utfc_ptr2len_len(char_u *p, int size);
int utf_char2len(int c);
int utf_char2bytes(int c, char_u *buf);
int utf_iscomposing_uint(uint32_t c);
int utf_iscomposing(int c);
int utf_printable(int c);
int utf_class(int c);

View File

@@ -53,7 +53,6 @@ void cursor_on(void);
void cursor_off(void);
void term_cursor_mode(int forced);
void term_cursor_color(char_u *color);
void term_cursor_blink(int blink);
void term_cursor_shape(int shape, int blink);
void scroll_region_set(win_T *wp, int off);
void scroll_region_reset(void);

View File

@@ -9999,7 +9999,7 @@ highlight_changed(void)
if (ga_grow(&highlight_ga, 28) == FAIL)
return FAIL;
hlcnt = highlight_ga.ga_len;
if (id_S == 0)
if (id_S == -1)
{
/* Make sure id_S is always valid to simplify code below. Use the last
* entry. */

View File

@@ -114,21 +114,22 @@ char *tgetstr(char *, char **);
# else
# define LOG_TR(msg)
# endif
# define STATUS_GET 1 /* send request when switching to RAW mode */
# define STATUS_SENT 2 /* did send request, waiting for response */
# define STATUS_GOT 3 /* received response */
/* Request Terminal Version status: */
# define CRV_GET 1 /* send T_CRV when switched to RAW mode */
# define CRV_SENT 2 /* did send T_CRV, waiting for answer */
# define CRV_GOT 3 /* received T_CRV response */
static int crv_status = CRV_GET;
static int crv_status = STATUS_GET;
/* Request Cursor position report: */
# define U7_GET 1 /* send T_U7 when switched to RAW mode */
# define U7_SENT 2 /* did send T_U7, waiting for answer */
# define U7_GOT 3 /* received T_U7 response */
static int u7_status = U7_GET;
static int u7_status = STATUS_GET;
/* Request background color report: */
# define RBG_GET 1 /* send T_RBG when switched to RAW mode */
# define RBG_SENT 2 /* did send T_RBG, waiting for answer */
# define RBG_GOT 3 /* received T_RBG response */
static int rbg_status = RBG_GET;
static int rbg_status = STATUS_GET;
/* Request cursor mode report: */
static int rcm_status = STATUS_GET;
# endif
/*
@@ -160,6 +161,14 @@ static char_u *vim_tgetstr(char *s, char_u **pp);
static int detected_8bit = FALSE; /* detected 8-bit terminal */
#ifdef FEAT_TERMRESPONSE
/* When the cursor shape was detected these values are used:
* 1: block, 2: underline, 3: vertical bar
* initial_cursor_blink is only valid when initial_cursor_shape is not zero. */
static int initial_cursor_shape = 0;
static int initial_cursor_blink = FALSE;
#endif
static struct builtin_term builtin_termcaps[] =
{
@@ -820,11 +829,13 @@ static struct builtin_term builtin_termcaps[] =
{(int)KS_VI, IF_EB("\033[?25l", ESC_STR "[?25l")},
{(int)KS_VE, IF_EB("\033[?25h", ESC_STR "[?25h")},
{(int)KS_VS, IF_EB("\033[?12h", ESC_STR "[?12h")},
{(int)KS_CVS, IF_EB("\033[?12l", ESC_STR "[?12l")},
# ifdef TERMINFO
{(int)KS_CSH, IF_EB("\033[%p1%d q", ESC_STR "[%p1%d q")},
# else
{(int)KS_CSH, IF_EB("\033[%d q", ESC_STR "[%d q")},
# endif
{(int)KS_CRS, IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")},
# ifdef TERMINFO
{(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
ESC_STR "[%i%p1%d;%p2%dH")},
@@ -1570,7 +1581,7 @@ set_termname(char_u *term)
{KS_DL, "dl"}, {KS_CDL,"DL"}, {KS_CS, "cs"},
{KS_CL, "cl"}, {KS_CD, "cd"},
{KS_VI, "vi"}, {KS_VE, "ve"}, {KS_MB, "mb"},
{KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"},
{KS_ME, "me"}, {KS_MR, "mr"},
{KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
{KS_CZH,"ZH"}, {KS_CZR,"ZR"}, {KS_UE, "ue"},
{KS_US, "us"}, {KS_UCE, "Ce"}, {KS_UCS, "Cs"},
@@ -1580,6 +1591,7 @@ set_termname(char_u *term)
{KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
{KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"},
{KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"},
{KS_VS, "vs"}, {KS_CVS, "VS"},
{KS_CIS, "IS"}, {KS_CIE, "IE"},
{KS_CSC, "SC"}, {KS_CEC, "EC"},
{KS_TS, "ts"}, {KS_FS, "fs"},
@@ -1803,9 +1815,9 @@ set_termname(char_u *term)
* is being used.
* Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
*/
#ifdef FEAT_GUI
# ifdef FEAT_GUI
if (!gui.in_use)
#endif
# endif
get_stty();
#endif
@@ -1906,8 +1918,8 @@ set_termname(char_u *term)
full_screen = TRUE; /* we can use termcap codes from now on */
set_term_defaults(); /* use current values as defaults */
#ifdef FEAT_TERMRESPONSE
LOG_TR("setting crv_status to CRV_GET");
crv_status = CRV_GET; /* Get terminal version later */
LOG_TR("setting crv_status to STATUS_GET");
crv_status = STATUS_GET; /* Get terminal version later */
#endif
/*
@@ -3298,9 +3310,10 @@ settmode(int tmode)
/* May need to check for T_CRV response and termcodes, it
* doesn't work in Cooked mode, an external program may get
* them. */
if (tmode != TMODE_RAW && (crv_status == CRV_SENT
|| u7_status == U7_SENT
|| rbg_status == RBG_SENT))
if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
|| u7_status == STATUS_SENT
|| rbg_status == STATUS_SENT
|| rcm_status == STATUS_SENT))
(void)vpeekc_nomap();
check_for_codes_from_term();
}
@@ -3347,7 +3360,7 @@ starttermcap(void)
may_req_termresponse();
/* Immediately check for a response. If t_Co changes, we don't
* want to redraw with wrong colors first. */
if (crv_status == CRV_SENT)
if (crv_status == STATUS_SENT)
check_for_codes_from_term();
}
#endif
@@ -3367,8 +3380,10 @@ stoptermcap(void)
# endif
{
/* May need to discard T_CRV, T_U7 or T_RBG response. */
if (crv_status == CRV_SENT || u7_status == U7_SENT
|| rbg_status == RBG_SENT)
if (crv_status == STATUS_SENT
|| u7_status == STATUS_SENT
|| rbg_status == STATUS_SENT
|| rcm_status == STATUS_SENT)
{
# ifdef UNIX
/* Give the terminal a chance to respond. */
@@ -3414,14 +3429,14 @@ stoptermcap(void)
void
may_req_termresponse(void)
{
if (crv_status == CRV_GET
if (crv_status == STATUS_GET
&& can_get_termresponse()
&& starting == 0
&& *T_CRV != NUL)
{
LOG_TR("Sending CRV");
LOG_TR("Sending CRV request");
out_str(T_CRV);
crv_status = CRV_SENT;
crv_status = STATUS_SENT;
/* check for the characters now, otherwise they might be eaten by
* get_keystroke() */
out_flush();
@@ -3442,7 +3457,7 @@ may_req_termresponse(void)
void
may_req_ambiguous_char_width(void)
{
if (u7_status == U7_GET
if (u7_status == STATUS_GET
&& can_get_termresponse()
&& starting == 0
&& *T_U7 != NUL
@@ -3457,7 +3472,7 @@ may_req_ambiguous_char_width(void)
buf[mb_char2bytes(0x25bd, buf)] = 0;
out_str(buf);
out_str(T_U7);
u7_status = U7_SENT;
u7_status = STATUS_SENT;
out_flush();
/* This overwrites a few characters on the screen, a redraw is needed
@@ -3477,19 +3492,40 @@ may_req_ambiguous_char_width(void)
/*
* Similar to requesting the version string: Request the terminal background
* color when it is the right moment.
* Also request the cursor shape, if possible.
*/
void
may_req_bg_color(void)
{
if (rbg_status == RBG_GET
&& can_get_termresponse()
&& starting == 0
int done = FALSE;
if (can_get_termresponse() && starting == 0)
{
/* Only request background if t_RB is set and 'background' wasn't
* changed. */
if (rbg_status == STATUS_GET
&& *T_RBG != NUL
&& !option_was_set((char_u *)"bg"))
{
LOG_TR("Sending BG request");
out_str(T_RBG);
rbg_status = RBG_SENT;
rbg_status = STATUS_SENT;
done = TRUE;
}
/* Only request the cursor shape if t_SH and t_RS are set. */
if (rcm_status == STATUS_GET
&& *T_CSH != NUL
&& *T_CRS != NUL)
{
LOG_TR("Sending cursor shape request");
out_str(T_CRS);
rcm_status = STATUS_SENT;
done = TRUE;
}
}
if (done)
{
/* check for the characters now, otherwise they might be eaten by
* get_keystroke() */
out_flush();
@@ -3626,10 +3662,10 @@ mouse_model_popup(void)
void
scroll_start(void)
{
if (*T_VS != NUL)
if (*T_VS != NUL && *T_CVS != NUL)
{
out_str(T_VS);
out_str(T_VE);
out_str(T_CVS);
screen_start(); /* don't know where cursor is now */
}
}
@@ -3655,9 +3691,8 @@ cursor_on(void)
void
cursor_off(void)
{
if (full_screen)
if (full_screen && !cursor_is_off)
{
if (!cursor_is_off)
out_str(T_VI); /* disable cursor */
cursor_is_off = TRUE;
}
@@ -3676,7 +3711,14 @@ term_cursor_mode(int forced)
/* Only do something when redrawing the screen and we can restore the
* mode. */
if (!full_screen || *T_CEI == NUL)
{
# ifdef FEAT_TERMRESPONSE
if (forced && initial_cursor_shape > 0)
/* Restore to initial values. */
term_cursor_shape(initial_cursor_shape, initial_cursor_blink);
# endif
return;
}
if ((State & REPLACE) == REPLACE)
{
@@ -3720,19 +3762,10 @@ term_cursor_color(char_u *color)
out_flush();
}
}
void
term_cursor_blink(int blink)
{
if (blink)
out_str(T_VS);
else
out_str(T_VE);
out_flush();
}
# endif
/*
* "shape" == 1: block, "shape" == 2: underline, "shape" == 3: vertical bar
* "shape": 1 = block, 2 = underline, 3 = vertical bar
*/
void
term_cursor_shape(int shape, int blink)
@@ -3742,8 +3775,18 @@ term_cursor_shape(int shape, int blink)
OUT_STR(tgoto((char *)T_CSH, 0, shape * 2 - blink));
out_flush();
}
/* When t_SH is not set try setting just the blink state. */
else if (blink && *T_VS != NUL)
{
out_str(T_VS);
out_flush();
}
else if (!blink && *T_CVS != NUL)
{
out_str(T_CVS);
out_flush();
}
}
# endif
#endif
/*
@@ -4290,7 +4333,8 @@ check_termcode(
{
/* Skip over the digits, the final char must
* follow. */
for (j = slen - 2; j < len && (isdigit(tp[j]) || tp[j] == ';'); ++j)
for (j = slen - 2; j < len && (isdigit(tp[j])
|| tp[j] == ';'); ++j)
;
++j;
if (len < j) /* got a partial sequence */
@@ -4394,7 +4438,7 @@ check_termcode(
char *aw = NULL;
LOG_TR("Received U7 status");
u7_status = U7_GOT;
u7_status = STATUS_GOT;
# ifdef FEAT_AUTOCMD
did_cursorhold = TRUE;
# endif
@@ -4433,8 +4477,8 @@ check_termcode(
/* eat it when at least one digit and ending in 'c' */
if (*T_CRV != NUL && i > 2 + (tp[0] != CSI) && tp[i] == 'c')
{
LOG_TR("Received CRV");
crv_status = CRV_GOT;
LOG_TR("Received CRV response");
crv_status = STATUS_GOT;
# ifdef FEAT_AUTOCMD
did_cursorhold = TRUE;
# endif
@@ -4566,8 +4610,8 @@ check_termcode(
char *newval = (3 * '6' < tp[j+7] + tp[j+12]
+ tp[j+17]) ? "light" : "dark";
LOG_TR("Received RBG");
rbg_status = RBG_GOT;
LOG_TR("Received RBG response");
rbg_status = STATUS_GOT;
if (STRCMP(p_bg, newval) != 0)
{
/* value differs, apply it */
@@ -4582,6 +4626,10 @@ check_termcode(
key_name[0] = (int)KS_EXTRA;
key_name[1] = (int)KE_IGNORE;
slen = i + 1 + (tp[i] == ESC);
if (tp[i] == 0x07 && i + 1 < len && tp[i + 1] == 0x18)
/* Sometimes the 0x07 is followed by 0x18, unclear
* when this happens. */
++slen;
break;
}
if (i == len)
@@ -4592,24 +4640,33 @@ check_termcode(
}
/* Check for key code response from xterm:
*
* {lead}{flag}+r<hex bytes><{tail}
*
* {lead} can be <Esc>P or DCS
* {flag} can be '0' or '1'
* {tail} can be Esc>\ or STERM
*
* Consume any code that starts with "{lead}.+r".
* Check for cursor shape response from xterm:
* {lead}1$r<number> q{tail}
*
* {lead} can be <Esc>P or DCS
* {tail} can be Esc>\ or STERM
*
* Consume any code that starts with "{lead}.+r" or "{lead}.$r".
*/
else if (check_for_codes
else if ((check_for_codes || rcm_status == STATUS_SENT)
&& ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
|| tp[0] == DCS))
{
j = 1 + (tp[0] == ESC);
if (len >= j + 3 && (argp[1] != '+' || argp[2] != 'r'))
if (len < j + 3)
i = len; /* need more chars */
else if ((argp[1] != '+' && argp[1] != '$') || argp[2] != 'r')
i = 0; /* no match */
else
else if (argp[1] == '+')
/* key code response */
for (i = j; i < len; ++i)
{
if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')
|| tp[i] == STERM)
{
@@ -4620,6 +4677,34 @@ check_termcode(
slen = i + 1 + (tp[i] == ESC);
break;
}
}
else if ((len >= j + 6 && isdigit(argp[3]))
&& argp[4] == ' '
&& argp[5] == 'q')
{
/* cursor shape response */
i = j + 6;
if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')
|| tp[i] == STERM)
{
int number = argp[3] - '0';
/* 0, 1 = block blink, 2 = block
* 3 = underline blink, 4 = underline
* 5 = vertical bar blink, 6 = vertical bar */
number = number == 0 ? 1 : number;
initial_cursor_shape = (number + 1) / 2;
/* The blink flag is actually inverted, compared to
* the value set with T_SH. */
initial_cursor_blink = (number & 1) ? FALSE : TRUE;
rcm_status = STATUS_GOT;
LOG_TR("Received cursor shape response");
key_name[0] = (int)KS_EXTRA;
key_name[1] = (int)KE_IGNORE;
slen = i + 1 + (tp[i] == ESC);
}
}
if (i == len)
{
@@ -5837,7 +5922,7 @@ gather_termleader(void)
termleader[len++] = CSI; /* the GUI codes are not in termcodes[] */
#endif
#ifdef FEAT_TERMRESPONSE
if (check_for_codes)
if (check_for_codes || *T_CRS != NUL)
termleader[len++] = DCS; /* the termcode response starts with DCS
in 8-bit mode */
#endif

View File

@@ -39,8 +39,10 @@ enum SpecialKey
KS_DB, /* text may be scrolled up from down */
KS_VI, /* cursor invisible */
KS_VE, /* cursor visible */
KS_VS, /* cursor very visible */
KS_VS, /* cursor very visible (blink) */
KS_CVS, /* cursor normally visible (no blink) */
KS_CSH, /* cursor shape */
KS_CRS, /* request cursor shape */
KS_ME, /* normal mode */
KS_MR, /* reverse mode */
KS_MD, /* bold mode */
@@ -130,8 +132,10 @@ extern char_u *(term_strings[]); /* current terminal strings */
#define T_DB (TERM_STR(KS_DB)) /* text may be scrolled up from down */
#define T_VI (TERM_STR(KS_VI)) /* cursor invisible */
#define T_VE (TERM_STR(KS_VE)) /* cursor visible */
#define T_VS (TERM_STR(KS_VS)) /* cursor very visible */
#define T_VS (TERM_STR(KS_VS)) /* cursor very visible (blink) */
#define T_CVS (TERM_STR(KS_CVS)) /* cursor normally visible (no blink) */
#define T_CSH (TERM_STR(KS_CSH)) /* cursor shape */
#define T_CRS (TERM_STR(KS_CRS)) /* request cursor shape */
#define T_ME (TERM_STR(KS_ME)) /* normal mode */
#define T_MR (TERM_STR(KS_MR)) /* reverse mode */
#define T_MD (TERM_STR(KS_MD)) /* bold mode */

View File

@@ -38,11 +38,20 @@
* in tl_scrollback are no longer used.
*
* TODO:
* - make [range]terminal pipe [range] lines to the terminal
* - better check for blinking - reply from Thomas Dickey Aug 22
* - test for writing lines to terminal job does not work on MS-Windows
* - implement term_setsize()
* - add test for giving error for invalid 'termsize' value.
* - support minimal size when 'termsize' is "rows*cols".
* - support minimal size when 'termsize' is empty?
* - do not set bufhidden to "hide"? works like a buffer with changes.
* document that CTRL-W :hide can be used.
* - GUI: when using tabs, focus in terminal, click on tab does not work.
* - GUI: when 'confirm' is set and trying to exit Vim, dialog offers to save
* changes to "!shell".
* (justrajdeep, 2017 Aug 22)
* - command argument with spaces doesn't work #1999
* :terminal ls dir\ with\ spaces
* - implement job options when starting a terminal. Allow:
* "in_io", "in_top", "in_bot", "in_name", "in_buf"
"out_io", "out_name", "out_buf", "out_modifiable", "out_msg"
@@ -59,7 +68,6 @@
* mouse in the Terminal window for copy/paste.
* - when 'encoding' is not utf-8, or the job is using another encoding, setup
* conversions.
* - update ":help function-list" for terminal functions.
* - In the GUI use a terminal emulator for :!cmd.
* - Copy text in the vterm to the Vim buffer once in a while, so that
* completion works.
@@ -447,10 +455,14 @@ ex_terminal(exarg_T *eap)
cmd = eap->arg;
while (*cmd && *cmd == '+' && *(cmd + 1) == '+')
{
char_u *p;
char_u *p, *ep;
cmd += 2;
p = skiptowhite(cmd);
ep = vim_strchr(cmd, '=');
if (ep != NULL && ep < p)
p = ep;
if ((int)(p - cmd) == 5 && STRNICMP(cmd, "close", 5) == 0)
opt.jo_term_finish = 'c';
else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "open", 4) == 0)
@@ -459,6 +471,20 @@ ex_terminal(exarg_T *eap)
opt.jo_curwin = 1;
else if ((int)(p - cmd) == 6 && STRNICMP(cmd, "hidden", 6) == 0)
opt.jo_hidden = 1;
else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "rows", 4) == 0
&& ep != NULL && isdigit(ep[1]))
{
opt.jo_set2 |= JO2_TERM_ROWS;
opt.jo_term_rows = atoi((char *)ep + 1);
p = skiptowhite(cmd);
}
else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "cols", 4) == 0
&& ep != NULL && isdigit(ep[1]))
{
opt.jo_set2 |= JO2_TERM_COLS;
opt.jo_term_cols = atoi((char *)ep + 1);
p = skiptowhite(cmd);
}
else
{
if (*p)
@@ -472,17 +498,14 @@ ex_terminal(exarg_T *eap)
/* Make a copy, an autocommand may set 'shell'. */
tofree = cmd = vim_strsave(p_sh);
if (eap->addr_count == 2)
if (eap->addr_count > 0)
{
opt.jo_term_rows = eap->line1;
opt.jo_term_cols = eap->line2;
}
else if (eap->addr_count == 1)
{
if (cmdmod.split & WSP_VERT)
opt.jo_term_cols = eap->line2;
else
opt.jo_term_rows = eap->line2;
/* Write lines from current buffer to the job. */
opt.jo_set |= JO_IN_IO | JO_IN_BUF | JO_IN_TOP | JO_IN_BOT;
opt.jo_io[PART_IN] = JIO_BUFFER;
opt.jo_io_buf[PART_IN] = curbuf->b_fnum;
opt.jo_in_top = eap->line1;
opt.jo_in_bot = eap->line2;
}
argvar.v_type = VAR_STRING;
@@ -830,6 +853,25 @@ add_scrollback_line_to_buffer(term_T *term, char_u *text, int len)
int empty = (buf->b_ml.ml_flags & ML_EMPTY);
linenr_T lnum = buf->b_ml.ml_line_count;
#ifdef WIN3264
if (!enc_utf8 && enc_codepage > 0)
{
WCHAR *ret = NULL;
int length = 0;
MultiByteToWideChar_alloc(CP_UTF8, 0, (char*)text, len + 1,
&ret, &length);
if (ret != NULL)
{
WideCharToMultiByte_alloc(enc_codepage, 0,
ret, length, (char **)&text, &len, 0, 0);
vim_free(ret);
ml_append_buf(term->tl_buffer, lnum, text, len, FALSE);
vim_free(text);
}
}
else
#endif
ml_append_buf(term->tl_buffer, lnum, text, len + 1, FALSE);
if (empty)
{
@@ -903,7 +945,7 @@ move_terminal_to_buffer(term_T *term)
width = 1;
vim_memset(p + pos.col, 0, sizeof(cellattr_T));
if (ga_grow(&ga, 1) == OK)
ga.ga_len += mb_char2bytes(' ',
ga.ga_len += utf_char2bytes(' ',
(char_u *)ga.ga_data + ga.ga_len);
}
else
@@ -921,7 +963,7 @@ move_terminal_to_buffer(term_T *term)
int c;
for (i = 0; (c = cell.chars[i]) > 0 || i == 0; ++i)
ga.ga_len += mb_char2bytes(c == NUL ? ' ' : c,
ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
(char_u *)ga.ga_data + ga.ga_len);
}
}
@@ -1036,14 +1078,13 @@ term_enter_job_mode()
/* 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)
while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled
&& gap->ga_len > 0)
{
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();
@@ -1078,6 +1119,29 @@ term_vgetc()
return c;
}
/*
* Get the part that is connected to the tty. Normally this is PART_IN, but
* when writing buffer lines to the job it can be another. This makes it
* possible to do "1,5term vim -".
*/
static ch_part_T
get_tty_part(term_T *term)
{
#ifdef UNIX
ch_part_T parts[3] = {PART_IN, PART_OUT, PART_ERR};
int i;
for (i = 0; i < 3; ++i)
{
int fd = term->tl_job->jv_channel->ch_part[parts[i]].ch_fd;
if (isatty(fd))
return parts[i];
}
#endif
return PART_IN;
}
/*
* Send keys to terminal.
* Return FAIL when the key needs to be handled in Normal mode.
@@ -1149,7 +1213,7 @@ send_keys_to_term(term_T *term, int c, int typed)
len = term_convert_key(term, c, msg);
if (len > 0)
/* TODO: if FAIL is returned, stop? */
channel_send(term->tl_job->jv_channel, PART_IN,
channel_send(term->tl_job->jv_channel, get_tty_part(term),
(char_u *)msg, (int)len, NULL);
return OK;
@@ -1202,9 +1266,31 @@ term_paste_register(int prev_c UNUSED)
for (item = l->lv_first; item != NULL; item = item->li_next)
{
char_u *s = get_tv_string(&item->li_tv);
#ifdef WIN3264
char_u *tmp = s;
if (!enc_utf8 && enc_codepage > 0)
{
WCHAR *ret = NULL;
int length = 0;
MultiByteToWideChar_alloc(enc_codepage, 0, (char*)s, STRLEN(s),
&ret, &length);
if (ret != NULL)
{
WideCharToMultiByte_alloc(CP_UTF8, 0,
ret, length, (char **)&s, &length, 0, 0);
vim_free(ret);
}
}
#endif
channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
s, STRLEN(s), NULL);
#ifdef WIN3264
if (tmp != s)
vim_free(s);
#endif
if (item->li_next != NULL || type == MLINE)
channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
(char_u *)"\r", 1, NULL);
@@ -1239,7 +1325,7 @@ term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg)
{
entry.blinkwait = 700;
entry.blinkon = 400;
entry.blinkon = 250;
entry.blinkoff = 250;
}
*fg = gui.back_pixel;
if (term->tl_cursor_color == NULL)
@@ -1271,8 +1357,6 @@ may_set_cursor_props(term_T *term)
term_cursor_color(term->tl_cursor_color);
else
term_cursor_color((char_u *)"");
/* do both blink and shape+blink, in case setting shape does not work */
term_cursor_blink(term->tl_cursor_blink);
term_cursor_shape(term->tl_cursor_shape, term->tl_cursor_blink);
}
}
@@ -1287,9 +1371,9 @@ may_restore_cursor_props(void)
if (did_change_cursor)
{
did_change_cursor = FALSE;
ui_cursor_shape_forced(TRUE);
term_cursor_color((char_u *)"");
term_cursor_blink(FALSE);
/* this will restore the initial cursor style, if possible */
ui_cursor_shape_forced(TRUE);
}
}
@@ -1335,7 +1419,8 @@ terminal_loop(void)
#ifdef UNIX
{
int fd = curbuf->b_term->tl_job->jv_channel->ch_part[PART_IN].ch_fd;
int part = get_tty_part(curbuf->b_term);
int fd = curbuf->b_term->tl_job->jv_channel->ch_part[part].ch_fd;
if (isatty(fd))
{
@@ -1432,6 +1517,18 @@ terminal_loop(void)
goto theend;
}
}
# ifdef WIN3264
if (!enc_utf8 && has_mbyte && c >= 0x80)
{
WCHAR wc;
char_u mb[3];
mb[0] = (unsigned)c >> 8;
mb[1] = c;
if (MultiByteToWideChar(GetACP(), 0, (char*)mb, 2, &wc, 1) > 0)
c = wc;
}
# endif
if (send_keys_to_term(curbuf->b_term, c, TRUE) != OK)
{
ret = OK;
@@ -1740,6 +1837,24 @@ handle_settermprop(
* displayed */
if (*skipwhite((char_u *)value->string) == NUL)
term->tl_title = NULL;
#ifdef WIN3264
else if (!enc_utf8 && enc_codepage > 0)
{
WCHAR *ret = NULL;
int length = 0;
MultiByteToWideChar_alloc(CP_UTF8, 0,
(char*)value->string, STRLEN(value->string),
&ret, &length);
if (ret != NULL)
{
WideCharToMultiByte_alloc(enc_codepage, 0,
ret, length, (char**)&term->tl_title,
&length, 0, 0);
vim_free(ret);
}
}
#endif
else
term->tl_title = vim_strsave((char_u *)value->string);
vim_free(term->tl_status_text);
@@ -1846,7 +1961,7 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
break;
}
for (i = 0; (c = cells[col].chars[i]) > 0 || i == 0; ++i)
ga.ga_len += mb_char2bytes(c == NUL ? ' ' : c,
ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
(char_u *)ga.ga_data + ga.ga_len);
p[col].width = cells[col].width;
p[col].attrs = cells[col].attrs;
@@ -2032,15 +2147,14 @@ term_update_window(win_T *wp)
if (c == NUL)
{
ScreenLines[off] = ' ';
#if defined(FEAT_MBYTE)
if (enc_utf8)
ScreenLinesUC[off] = NUL;
#endif
}
else
{
#if defined(FEAT_MBYTE)
if (enc_utf8 && c >= 0x80)
if (enc_utf8)
{
if (c >= 0x80)
{
ScreenLines[off] = ' ';
ScreenLinesUC[off] = c;
@@ -2048,12 +2162,28 @@ term_update_window(win_T *wp)
else
{
ScreenLines[off] = c;
if (enc_utf8)
ScreenLinesUC[off] = NUL;
}
#else
}
#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);
@@ -2061,11 +2191,14 @@ term_update_window(win_T *wp)
++off;
if (cell.width == 2)
{
ScreenLines[off] = NUL;
#if defined(FEAT_MBYTE)
if (enc_utf8)
ScreenLinesUC[off] = NUL;
#endif
/* 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;
}
@@ -2150,6 +2283,7 @@ create_vterm(term_T *term, int rows, int cols)
{
VTerm *vterm;
VTermScreen *screen;
VTermValue value;
vterm = vterm_new(rows, cols);
term->tl_vterm = vterm;
@@ -2174,6 +2308,20 @@ create_vterm(term_T *term, int rows, int cols)
/* Allow using alternate screen. */
vterm_screen_enable_altscreen(screen, 1);
/* For unix do not use a blinking cursor. In an xterm this causes the
* cursor to blink if it's blinking in the xterm.
* For Windows we respect the system wide setting. */
#ifdef WIN3264
if (GetCaretBlinkTime() == INFINITE)
value.boolean = 0;
else
value.boolean = 1;
#else
value.boolean = 0;
#endif
vterm_state_set_termprop(vterm_obtain_state(vterm),
VTERM_PROP_CURSORBLINK, &value);
}
/*
@@ -2826,13 +2974,20 @@ dyn_winpty_init(int verbose)
* Return OK or FAIL.
*/
static int
term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *opt)
term_and_job_init(
term_T *term,
int rows,
int cols,
typval_T *argvar,
jobopt_T *opt)
{
WCHAR *p = NULL;
WCHAR *cmd_wchar = NULL;
channel_T *channel = NULL;
job_T *job = NULL;
DWORD error;
HANDLE jo = NULL, child_process_handle, child_thread_handle;
HANDLE jo = NULL;
HANDLE child_process_handle;
HANDLE child_thread_handle;
void *winpty_err;
void *spawn_config = NULL;
char buf[MAX_PATH];
@@ -2852,8 +3007,8 @@ term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *
cmd = ga.ga_data;
}
p = enc_to_utf16(cmd, NULL);
if (p == NULL)
cmd_wchar = enc_to_utf16(cmd, NULL);
if (cmd_wchar == NULL)
return FAIL;
job = job_alloc();
@@ -2878,7 +3033,7 @@ term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *
WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN |
WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN,
NULL,
p,
cmd_wchar,
NULL,
NULL,
&winpty_err);
@@ -2893,20 +3048,25 @@ term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *
if (job == NULL)
goto failed;
/* TODO: when all lines are written and the fd is closed, the command
* doesn't get EOF and hangs. */
if (opt->jo_set & JO_IN_BUF)
job->jv_in_buf = buflist_findnr(opt->jo_io_buf[PART_IN]);
if (!winpty_spawn(term->tl_winpty, spawn_config, &child_process_handle,
&child_thread_handle, &error, &winpty_err))
goto failed;
channel_set_pipes(channel,
(sock_T) CreateFileW(
(sock_T)CreateFileW(
winpty_conin_name(term->tl_winpty),
GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL),
(sock_T) CreateFileW(
(sock_T)CreateFileW(
winpty_conout_name(term->tl_winpty),
GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL),
(sock_T) CreateFileW(
(sock_T)CreateFileW(
winpty_conerr_name(term->tl_winpty),
GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL));
@@ -2923,7 +3083,7 @@ term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *
}
winpty_spawn_config_free(spawn_config);
vim_free(p);
vim_free(cmd_wchar);
create_vterm(term, rows, cols);
@@ -2946,8 +3106,8 @@ term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *
failed:
if (argvar->v_type == VAR_LIST)
vim_free(ga.ga_data);
if (p != NULL)
vim_free(p);
if (cmd_wchar != NULL)
vim_free(cmd_wchar);
if (spawn_config != NULL)
winpty_spawn_config_free(spawn_config);
if (channel != NULL)
@@ -3023,7 +3183,12 @@ terminal_enabled(void)
* Return OK or FAIL.
*/
static int
term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *opt)
term_and_job_init(
term_T *term,
int rows,
int cols,
typval_T *argvar,
jobopt_T *opt)
{
create_vterm(term, rows, cols);

View File

@@ -548,6 +548,19 @@ func Test_OptionSet()
call assert_equal([['key', 'invalid', 'invalid1', 'invalid']], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 18: Setting string option"
let oldval = &tags
let g:options=[['tags', oldval, 'tagpath', 'global']]
set tags=tagpath
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 1l: Resetting string option"
let g:options=[['tags', 'tagpath', oldval, 'global']]
set tags&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" Cleanup
au! OptionSet
for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp']

View File

@@ -251,7 +251,7 @@ endfunc
func Test_terminal_size()
let cmd = Get_cat_123_cmd()
exe '5terminal ' . cmd
exe 'terminal ++rows=5 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal(5, size[0])
@@ -262,7 +262,7 @@ func Test_terminal_size()
call assert_equal(6, size[0])
vsplit
exe '5,33terminal ' . cmd
exe 'terminal ++rows=5 ++cols=33 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal([5, 33], size)
@@ -272,7 +272,7 @@ func Test_terminal_size()
bwipe!
call assert_equal([6, 36], size)
exe 'vertical 20terminal ' . cmd
exe 'vertical terminal ++cols=20 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal(20, size[1])
@@ -283,7 +283,7 @@ func Test_terminal_size()
call assert_equal(26, size[1])
split
exe 'vertical 6,20terminal ' . cmd
exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal([6, 20], size)
@@ -456,11 +456,23 @@ func Test_terminal_noblock()
for c in ['a','b','c','d','e','f','g','h','i','j','k']
call term_sendkeys(g:buf, 'echo ' . repeat(c, 5000) . "\<cr>")
if has('mac')
" TODO: this should not be needed, but without it sending keys blocks
" after 8000 chars or so.
sleep 100m
endif
endfor
call term_sendkeys(g:buf, "echo done\<cr>")
" On MS-Windows there is an extra empty line below "done". Find "done" in
" the last-but-one or the last-but-two line.
let g:lnum = term_getsize(g:buf)[0] - 1
call WaitFor('term_getline(g:buf, g:lnum) =~ "done"', 3000)
call assert_match('done', term_getline(g:buf, g:lnum))
call WaitFor('term_getline(g:buf, g:lnum) =~ "done" || term_getline(g:buf, g:lnum - 1) =~ "done"', 3000)
let line = term_getline(g:buf, g:lnum)
if line !~ 'done'
let line = term_getline(g:buf, g:lnum - 1)
endif
call assert_match('done', line)
let g:job = term_getjob(g:buf)
call Stop_shell_in_terminal(g:buf)
@@ -470,3 +482,26 @@ func Test_terminal_noblock()
unlet g:lnum
bwipe
endfunc
func Test_terminal_write_stdin()
" Todo: make this work on all systems.
if !has('unix')
return
endif
new
call setline(1, ['one', 'two', 'three'])
%term wc
call WaitFor('getline(1) != ""')
let nrs = split(getline(1))
call assert_equal(['3', '3', '14'], nrs)
bwipe
call setline(1, ['one', 'two', 'three', 'four'])
2,3term wc
call WaitFor('getline(1) != ""')
let nrs = split(getline(1))
call assert_equal(['2', '2', '10'], nrs)
bwipe
bwipe!
endfunc

View File

@@ -921,7 +921,7 @@ undo_write(bufinfo_T *bi, char_u *ptr, size_t len)
static int
undo_flush(bufinfo_T *bi)
{
if (bi->bi_buffer != NULL && bi->bi_used > 0)
if (bi->bi_buffer != NULL && bi->bi_state != NULL && bi->bi_used > 0)
{
crypt_encode_inplace(bi->bi_state, bi->bi_buffer, bi->bi_used);
if (fwrite(bi->bi_buffer, bi->bi_used, (size_t)1, bi->bi_fp) != 1)

View File

@@ -769,6 +769,68 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
995,
/**/
994,
/**/
993,
/**/
992,
/**/
991,
/**/
990,
/**/
989,
/**/
988,
/**/
987,
/**/
986,
/**/
985,
/**/
984,
/**/
983,
/**/
982,
/**/
981,
/**/
980,
/**/
979,
/**/
978,
/**/
977,
/**/
976,
/**/
975,
/**/
974,
/**/
973,
/**/
972,
/**/
971,
/**/
970,
/**/
969,
/**/
968,
/**/
967,
/**/
966,
/**/
965,
/**/
964,
/**/