diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 44e1963a93..65098533b4 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2316,6 +2316,9 @@ searchpos({pattern} [, {flags} [, {stopline} [, {timeout}]]]) server2client({clientid}, {string}) Number send reply string serverlist() String get a list of available servers +setbufline( {expr}, {lnum}, {line}) + Number set line {lnum} to {line} in buffer + {expr} setbufvar({expr}, {varname}, {val}) none set {varname} in buffer {expr} to {val} setcharsearch({dict}) Dict set character search from {dict} @@ -2407,6 +2410,7 @@ term_wait({buf} [, {time}]) Number wait for screen to be updated test_alloc_fail({id}, {countdown}, {repeat}) none make memory allocation fail test_autochdir() none enable 'autochdir' during startup +test_feedinput() none add key sequence to input buffer test_garbagecollect_now() none free memory right now for testing test_ignore_error({expr}) none ignore a specific error test_null_channel() Channel null value for testing @@ -4632,18 +4636,20 @@ getqflist([{what}]) *getqflist()* returns only the items listed in {what} as a dictionary. The following string items are supported in {what}: context get the context stored with |setqflist()| + efm errorformat to use when parsing "lines". If + not present, then the 'erroformat' option + value is used. id get information for the quickfix list with |quickfix-ID|; zero means the id for the - current list or the list specifed by 'nr' + current list or the list specifed by "nr" items quickfix list entries + lines use 'errorformat' to extract items from a list + of lines and return the resulting entries. + Only a |List| type is accepted. The current + quickfix list is not modified. nr get information for this quickfix list; zero - means the current quickfix list and '$' means + means the current quickfix list and "$" means the last quickfix list - text use 'errorformat' to extract items from the - text and return the resulting entries. The - value can be a string with one line or a list - with multiple lines. The current quickfix list - is not modified. title get the list title winid get the |window-ID| (if opened) all all of the above quickfix properties @@ -4671,6 +4677,7 @@ getqflist([{what}]) *getqflist()* Examples: > :echo getqflist({'all': 1}) :echo getqflist({'nr': 2, 'title': 1}) + :echo getqflist({'lines' : ["F1:10:L10"]}) < getreg([{regname} [, 1 [, {list}]]]) *getreg()* @@ -6858,6 +6865,19 @@ serverlist() *serverlist()* Example: > :echo serverlist() < +setbufline({expr}, {lnum}, {text}) *setbufline()* + Set line {lnum} to {text} in buffer {expr}. To insert + lines use |append()|. + + For the use of {expr}, see |bufname()| above. + + {lnum} is used like with |setline()|. + This works like |setline()| for the specified buffer. + On success 0 is returned, on failure 1 is returned. + + If {expr} is not a valid buffer or {lnum} is not valid, an + error message is given. + setbufvar({expr}, {varname}, {val}) *setbufvar()* Set option or local variable {varname} in buffer {expr} to {val}. @@ -6926,13 +6946,19 @@ setfperm({fname}, {mode}) *setfperm()* *chmod* setline({lnum}, {text}) *setline()* Set line {lnum} of the current buffer to {text}. To insert - lines use |append()|. + lines use |append()|. To set lines in another buffer use + |setbufline()|. + {lnum} is used like with |getline()|. When {lnum} is just below the last line the {text} will be added as a new line. + If this succeeds, 0 is returned. If this fails (most likely - because {lnum} is invalid) 1 is returned. Example: > + because {lnum} is invalid) 1 is returned. + + Example: > :call setline(5, strftime("%c")) + < When {text} is a |List| then line {lnum} and following lines will be set to the items in the list. Example: > :call setline(5, ['aaa', 'bbb', 'ccc']) @@ -7064,22 +7090,24 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()* is created. The new quickfix list is added after the current quickfix list in the stack and all the following lists are freed. To add a new quickfix list at the end of the stack, - set "nr" in {what} to '$'. + set "nr" in {what} to "$". If the optional {what} dictionary argument is supplied, then only the items listed in {what} are set. The first {list} argument is ignored. The following items can be specified in {what}: context any Vim type can be stored as a context - text use 'errorformat' to extract items from the - text and add the resulting entries to the - quickfix list {nr}. The value can be a string - with one line or a list with multiple lines. + efm errorformat to use when parsing text from + "lines". If this is not present, then the + 'errorformat' option value is used. id quickfix list identifier |quickfix-ID| items list of quickfix entries. Same as the {list} argument. + lines use 'errorformat' to parse a list of lines and + add the resulting entries to the quickfix list + {nr} or {id}. Only a |List| value is supported. nr list number in the quickfix stack; zero - means the current quickfix list and '$' means + means the current quickfix list and "$" means the last quickfix list title quickfix list title text Unsupported keys in {what} are ignored. @@ -7087,12 +7115,13 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()* is modified. When creating a new quickfix list, "nr" can be set to a value one greater than the quickfix stack size. When modifying a quickfix list, to guarantee that the correct - list is modified, 'id' should be used instead of 'nr' to + list is modified, "id" should be used instead of "nr" to specify the list. Examples: > - :call setqflist([], 'r', {'title': 'My search'}) - :call setqflist([], 'r', {'nr': 2, 'title': 'Errors'}) + :call setqflist([], 'r', {'title': 'My search'}) + :call setqflist([], 'r', {'nr': 2, 'title': 'Errors'}) + :call setqflist([], 'a', {'id':myid, 'lines':["F1:10:L10"]}) < Returns zero for success, -1 for failure. @@ -7723,6 +7752,7 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()* "standout" "1" if standout "underline" "1" if underlined "undercurl" "1" if undercurled + "strike" "1" if strikethrough Example (echoes the color of the syntax item under the cursor): > @@ -8141,6 +8171,12 @@ term_start({cmd}, {options}) *term_start()* have "%d" where the buffer number goes, e.g. "10split|buffer %d"; when not specified "botright sbuf %d" is used + "eof_chars" Text to send after all buffer lines were + written to the terminal. When not set + CTRL-D is used. For Python use CTRL-Z or + "exit()". For a shell use "exit". A CR + is always added. + {only on MS-Windows} {only available when compiled with the |+terminal| feature} @@ -8161,6 +8197,11 @@ test_autochdir() *test_autochdir()* Set a flag to enable the effect of 'autochdir' before Vim startup has finished. +test_feedinput({string}) *test_feedinput()* + Characters in {string} are queued for processing as if they + were typed by the user. This uses a low level input buffer. + This function works only when with |+unix| or GUI is running. + test_garbagecollect_now() *test_garbagecollect_now()* Like garbagecollect(), but executed right away. This must only be called directly to avoid any structure to exist diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 5140fb905c..d6dbe654ec 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4228,6 +4228,7 @@ A jump table for the options with a short description can be found at |Q_op|. s standout (termcap entry "so" and "se") u underline (termcap entry "us" and "ue") c undercurl (termcap entry "Cs" and "Ce") + t strikethrough (termcap entry "Ts" and "Te") n no highlighting - no highlighting : use a highlight group diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 8bed7fbd61..1f3b17dc9f 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -4699,13 +4699,14 @@ the same syntax file on all terminals, and use the optimal highlighting. *bold* *underline* *undercurl* *inverse* *italic* *standout* - *nocombine* + *nocombine* *strikethrough* term={attr-list} *attr-list* *highlight-term* *E418* attr-list is a comma separated list (without spaces) of the following items (in any order): bold underline undercurl not always available + strikethrough not always available reverse inverse same as reverse italic @@ -4716,8 +4717,8 @@ term={attr-list} *attr-list* *highlight-term* *E418* Note that "bold" can be used here and by using a bold font. They have the same effect. "undercurl" is a curly underline. When "undercurl" is not possible - then "underline" is used. In general "undercurl" is only available in - the GUI. The color is set with |highlight-guisp|. + then "underline" is used. In general "undercurl" and "strikethrough" + is only available in the GUI. The color is set with |highlight-guisp|. start={term-list} *highlight-start* *E422* stop={term-list} *term-list* *highlight-stop* @@ -4882,7 +4883,8 @@ guifg={color-name} *highlight-guifg* guibg={color-name} *highlight-guibg* guisp={color-name} *highlight-guisp* These give the foreground (guifg), background (guibg) and special - (guisp) color to use in the GUI. "guisp" is used for undercurl. + (guisp) color to use in the GUI. "guisp" is used for undercurl and + strikethrough. There are a few special names: NONE no color (transparent) bg use normal background color diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 9e903d26a4..7be6927a0b 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -133,6 +133,14 @@ Syntax ~ height. ++cols={width} Use {width} for the terminal window width. + ++eof={text} when using [range], text to send after + the last line was written. The default + is to send CTRL-D. A CR is appended. + E.g. for a shell use "++eof=exit" and + for Python "++eof=exit()". Special + codes can be used like with `:map`, + e.g. "" for CTRL-Z. + {only on MS-Windows} If you want to use more options use the |term_start()| function. @@ -141,11 +149,13 @@ When the buffer associated with the terminal is unloaded or wiped out the job is killed, similar to calling `job_stop(job, "kill")` So long as the job is running the window behaves like it contains a modified -buffer. Trying to close the window with `CTRL-W :close` or `CTRL-W :hide` -fails, unless "!" is added, in which case the job is ended. The text in the -window is lost. The buffer still exists, but getting it in a window with -`:buffer` will show an -empty buffer. +buffer. Trying to close the window with `CTRL-W :quit` fails. When using +`CTRL-W :quit!` the job is ended. The text in the window is lost. The buffer +still exists, but getting it in a window with `:buffer` will show an empty +buffer. + +Trying to close the window with `CTRL-W :close` also fails. Using +`CTRL-W :close!` will close the window and make the buffer hidden. You can use `CTRL-W :hide` to close the terminal window and make the buffer hidden, the job keeps running. The `:buffer` command can be used to turn the diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index 0a91b9f48e..59315019d3 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -314,8 +314,8 @@ Visual-block Insert *v_b_I* With a blockwise selection, I{string} will insert {string} at the start of block on every line of the block, provided that the line extends into the block. Thus lines that are short will remain unmodified. TABs are split to -retain visual columns. -See |v_b_I_example|. +retain visual columns. Works only for adding text to a line, not for +deletions. See |v_b_I_example|. Visual-block Append *v_b_A* With a blockwise selection, A{string} will append {string} to the end of @@ -331,6 +331,7 @@ See |v_b_A_example|. Note: "I" and "A" behave differently for lines that don't extend into the selected block. This was done intentionally, so that you can do it the way you want. +Works only for adding text to a line, not for deletions. Visual-block change *v_b_c* All selected text in the block will be replaced by the same text string. When diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 52db561380..de2c5df524 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -76,6 +76,10 @@ endif # Set to yes to enable terminal support. TERMINAL=no +ifndef CTAGS +# this assumes ctags is Exuberant ctags +CTAGS = ctags -I INIT+ --fields=+S +endif # Link against the shared version of libstdc++ by default. Set # STATIC_STDCPLUS to "yes" to link against static version instead. @@ -885,6 +889,12 @@ xxd/xxd.exe: xxd/xxd.c GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h $(MAKE) -C GvimExt -f Make_ming.mak CROSS=$(CROSS) CROSS_COMPILE=$(CROSS_COMPILE) CXX='$(CXX)' STATIC_STDCPLUS=$(STATIC_STDCPLUS) +tags: notags + $(CTAGS) *.c *.cpp *.h if_perl.xs + +notags: + -$(DEL) tags + clean: -$(DEL) $(OUTDIR)$(DIRSLASH)*.o -$(DEL) $(OUTDIR)$(DIRSLASH)*.res diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index c8c1d11736..33d6dcbf2f 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -344,7 +344,8 @@ FEATURES = HUGE !endif !ifndef CTAGS -CTAGS = ctags +# this assumes ctags is Exuberant ctags +CTAGS = ctags -I INIT+ --fields=+S !endif !ifndef CSCOPE @@ -1220,7 +1221,7 @@ GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h tags: notags - $(CTAGS) *.c *.cpp *.h if_perl.xs proto\*.pro + $(CTAGS) *.c *.cpp *.h if_perl.xs notags: - if exist tags del tags diff --git a/src/Makefile b/src/Makefile index 97f3a7c743..b1ef20e835 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2139,6 +2139,7 @@ test_arglist \ test_autocmd \ test_backspace_opt \ test_breakindent \ + test_bufline \ test_bufwintabinfo \ test_cd \ test_cdo \ diff --git a/src/auto/configure b/src/auto/configure index 245b123ece..99ee32ba09 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -7557,20 +7557,34 @@ $as_echo_n "checking --enable-terminal argument... " >&6; } # Check whether --enable-terminal was given. if test "${enable_terminal+set}" = set; then : enableval=$enable_terminal; enable_terminal="yes" +else + enable_terminal="auto" fi -if test "$enable_terminal" = "yes"; then +if test "$enable_terminal" = "yes" || test "$enable_terminal" = "auto" -a "x$features" = "xhuge" ; then if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use terminal emulator with tiny or small features" >&5 $as_echo "cannot use terminal emulator with tiny or small features" >&6; } enable_terminal="no" else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + if test "$enable_terminal" = "auto"; then + enable_terminal="yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: defaulting to yes" >&5 +$as_echo "defaulting to yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } + fi fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + if test "$enable_terminal" = "auto"; then + enable_terminal="no" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: defaulting to no" >&5 +$as_echo "defaulting to no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } + fi fi if test "$enable_terminal" = "yes"; then $as_echo "#define FEAT_TERMINAL 1" >>confdefs.h diff --git a/src/channel.c b/src/channel.c index 99a9e2824a..5e441673dd 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1321,11 +1321,16 @@ write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel) return; memcpy((char *)p, (char *)line, len); - for (i = 0; i < len; ++i) - if (p[i] == NL) - p[i] = NUL; + if (channel->ch_write_text_mode) + p[len] = CAR; + else + { + for (i = 0; i < len; ++i) + if (p[i] == NL) + p[i] = NUL; - p[len] = NL; + p[len] = NL; + } p[len + 1] = NUL; channel_send(channel, PART_IN, p, len + 1, "write_buf_line"); vim_free(p); @@ -1438,6 +1443,12 @@ channel_write_in(channel_T *channel) in_part->ch_buf_top = lnum; if (lnum > buf->b_ml.ml_line_count || lnum > in_part->ch_buf_bot) { +#if defined(FEAT_TERMINAL) + /* Send CTRL-D or "eof_chars" to close stdin on MS-Windows. */ + if (channel->ch_job != NULL) + term_send_eof(channel); +#endif + /* Writing is done, no longer need the buffer. */ in_part->ch_bufref.br_buf = NULL; ch_log(channel, "Finished writing all lines to channel"); @@ -4651,6 +4662,20 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2) return FAIL; } } + else if (STRCMP(hi->hi_key, "eof_chars") == 0) + { + char_u *p; + + if (!(supported2 & JO2_EOF_CHARS)) + break; + opt->jo_set2 |= JO2_EOF_CHARS; + p = opt->jo_eof_chars = get_tv_string_chk(item); + if (p == NULL) + { + EMSG2(_(e_invarg2), "term_opencmd"); + return FAIL; + } + } else if (STRCMP(hi->hi_key, "term_rows") == 0) { if (!(supported2 & JO2_TERM_ROWS)) diff --git a/src/charset.c b/src/charset.c index d649179dd7..8b83f68068 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1535,6 +1535,22 @@ skipwhite(char_u *q) return p; } +/* + * getwhitecols: return the number of whitespace + * columns (bytes) at the start of a given line + */ + int +getwhitecols_curline() +{ + return getwhitecols(ml_get_curline()); +} + + int +getwhitecols(char_u *p) +{ + return skipwhite(p) - p; +} + /* * skip over digits */ diff --git a/src/configure.ac b/src/configure.ac index 435bc1c981..e607bd0825 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -2095,16 +2095,26 @@ fi AC_MSG_CHECKING(--enable-terminal argument) AC_ARG_ENABLE(terminal, [ --enable-terminal Enable terminal emulation support.], - [enable_terminal="yes"], ) -if test "$enable_terminal" = "yes"; then + [enable_terminal="yes"], [enable_terminal="auto"]) +if test "$enable_terminal" = "yes" || test "$enable_terminal" = "auto" -a "x$features" = "xhuge" ; then if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then AC_MSG_RESULT([cannot use terminal emulator with tiny or small features]) enable_terminal="no" else - AC_MSG_RESULT(yes) + if test "$enable_terminal" = "auto"; then + enable_terminal="yes" + AC_MSG_RESULT(defaulting to yes) + else + AC_MSG_RESULT(yes) + fi fi else - AC_MSG_RESULT(no) + if test "$enable_terminal" = "auto"; then + enable_terminal="no" + AC_MSG_RESULT(defaulting to no) + else + AC_MSG_RESULT(no) + fi fi if test "$enable_terminal" = "yes"; then AC_DEFINE(FEAT_TERMINAL) diff --git a/src/diff.c b/src/diff.c index dac39c21e8..0e352d8938 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1660,6 +1660,40 @@ diff_equal_entry(diff_T *dp, int idx1, int idx2) return TRUE; } +/* + * Compare the characters at "p1" and "p2". If they are equal (possibly + * ignoring case) return TRUE and set "len" to the number of bytes. + */ + static int +diff_equal_char(char_u *p1, char_u *p2, int *len) +{ +#ifdef FEAT_MBYTE + int l = (*mb_ptr2len)(p1); + + if (l != (*mb_ptr2len)(p2)) + return FALSE; + if (l > 1) + { + if (STRNCMP(p1, p2, l) != 0 + && (!enc_utf8 + || !(diff_flags & DIFF_ICASE) + || utf_fold(utf_ptr2char(p1)) + != utf_fold(utf_ptr2char(p2)))) + return FALSE; + *len = l; + } + else +#endif + { + if ((*p1 != *p2) + && (!(diff_flags & DIFF_ICASE) + || TOLOWER_LOC(*p1) != TOLOWER_LOC(*p2))) + return FALSE; + *len = 1; + } + return TRUE; +} + /* * Compare strings "s1" and "s2" according to 'diffopt'. * Return non-zero when they are different. @@ -1689,30 +1723,10 @@ diff_cmp(char_u *s1, char_u *s2) } else { -#ifdef FEAT_MBYTE - l = (*mb_ptr2len)(p1); - if (l != (*mb_ptr2len)(p2)) + if (!diff_equal_char(p1, p2, &l)) break; - if (l > 1) - { - if (STRNCMP(p1, p2, l) != 0 - && (!enc_utf8 - || !(diff_flags & DIFF_ICASE) - || utf_fold(utf_ptr2char(p1)) - != utf_fold(utf_ptr2char(p2)))) - break; - p1 += l; - p2 += l; - } - else -#endif - { - if (*p1 != *p2 && (!(diff_flags & DIFF_ICASE) - || TOLOWER_LOC(*p1) != TOLOWER_LOC(*p2))) - break; - ++p1; - ++p2; - } + p1 += l; + p2 += l; } } @@ -1969,6 +1983,10 @@ diff_find_change( int idx; int off; int added = TRUE; +#ifdef FEAT_MBYTE + char_u *p1, *p2; + int l; +#endif /* Make a copy of the line, the next ml_get() will invalidate it. */ line_org = vim_strsave(ml_get_buf(wp->w_buffer, lnum, FALSE)); @@ -2017,10 +2035,11 @@ diff_find_change( } else { - if (line_org[si_org] != line_new[si_new]) + if (!diff_equal_char(line_org + si_org, line_new + si_new, + &l)) break; - ++si_org; - ++si_new; + si_org += l; + si_new += l; } } #ifdef FEAT_MBYTE @@ -2056,10 +2075,16 @@ diff_find_change( } else { - if (line_org[ei_org] != line_new[ei_new]) + p1 = line_org + ei_org; + p2 = line_new + ei_new; +#ifdef FEAT_MBYTE + p1 -= (*mb_head_off)(line_org, p1); + p2 -= (*mb_head_off)(line_new, p2); +#endif + if (!diff_equal_char(p1, p2, &l)) break; - --ei_org; - --ei_new; + ei_org -= l; + ei_new -= l; } } if (*endp < ei_org) diff --git a/src/edit.c b/src/edit.c index 2e4866d282..f2b57ca848 100644 --- a/src/edit.c +++ b/src/edit.c @@ -5196,7 +5196,7 @@ ins_complete(int c, int enable_pum) * first non_blank in the line, if it is not a wordchar * include it to get a better pattern, but then we don't * want the "\\<" prefix, check it bellow */ - compl_col = (colnr_T)(skipwhite(line) - line); + compl_col = (colnr_T)getwhitecols(line); compl_startpos.col = compl_col; compl_startpos.lnum = curwin->w_cursor.lnum; compl_cont_status &= ~CONT_SOL; /* clear SOL if present */ @@ -5362,7 +5362,7 @@ ins_complete(int c, int enable_pum) } else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) { - compl_col = (colnr_T)(skipwhite(line) - line); + compl_col = (colnr_T)getwhitecols(line); compl_length = (int)curs_col - (int)compl_col; if (compl_length < 0) /* cursor in indent: empty pattern */ compl_length = 0; @@ -8222,8 +8222,7 @@ in_cinkeys( { /* "0=word": Check if there are only blanks before the * word. */ - line = ml_get_curline(); - if ((int)(skipwhite(line) - line) != + if (getwhitecols(line) != (int)(curwin->w_cursor.col - (p - look))) match = FALSE; } diff --git a/src/evalfunc.c b/src/evalfunc.c index 4c3eff4085..54f75e4d02 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -328,6 +328,7 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv); static void f_searchpos(typval_T *argvars, typval_T *rettv); static void f_server2client(typval_T *argvars, typval_T *rettv); static void f_serverlist(typval_T *argvars, typval_T *rettv); +static void f_setbufline(typval_T *argvars, typval_T *rettv); static void f_setbufvar(typval_T *argvars, typval_T *rettv); static void f_setcharsearch(typval_T *argvars, typval_T *rettv); static void f_setcmdpos(typval_T *argvars, typval_T *rettv); @@ -392,6 +393,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv); static void f_tempname(typval_T *argvars, typval_T *rettv); static void f_test_alloc_fail(typval_T *argvars, typval_T *rettv); static void f_test_autochdir(typval_T *argvars, typval_T *rettv); +static void f_test_feedinput(typval_T *argvars, typval_T *rettv); static void f_test_override(typval_T *argvars, typval_T *rettv); static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv); static void f_test_ignore_error(typval_T *argvars, typval_T *rettv); @@ -764,6 +766,7 @@ static struct fst {"searchpos", 1, 4, f_searchpos}, {"server2client", 2, 2, f_server2client}, {"serverlist", 0, 0, f_serverlist}, + {"setbufline", 3, 3, f_setbufline}, {"setbufvar", 3, 3, f_setbufvar}, {"setcharsearch", 1, 1, f_setcharsearch}, {"setcmdpos", 1, 1, f_setcmdpos}, @@ -849,6 +852,7 @@ static struct fst #endif {"test_alloc_fail", 3, 3, f_test_alloc_fail}, {"test_autochdir", 0, 0, f_test_autochdir}, + {"test_feedinput", 1, 1, f_test_feedinput}, {"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now}, {"test_ignore_error", 1, 1, f_test_ignore_error}, #ifdef FEAT_JOB_CHANNEL @@ -9894,6 +9898,115 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv) rettv->vval.v_string = r; } +/* + * Set line or list of lines in buffer "buf". + */ + static void +set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines, typval_T *rettv) +{ + char_u *line = NULL; + list_T *l = NULL; + listitem_T *li = NULL; + long added = 0; + linenr_T lcount; + buf_T *curbuf_save; + int is_curbuf = buf == curbuf; + + if (buf == NULL || buf->b_ml.ml_mfp == NULL || lnum < 1) + { + rettv->vval.v_number = 1; /* FAIL */ + return; + } + + curbuf_save = curbuf; + curbuf = buf; + + lcount = curbuf->b_ml.ml_line_count; + + if (lines->v_type == VAR_LIST) + { + l = lines->vval.v_list; + li = l->lv_first; + } + else + line = get_tv_string_chk(lines); + + /* default result is zero == OK */ + for (;;) + { + if (l != NULL) + { + /* list argument, get next string */ + if (li == NULL) + break; + line = get_tv_string_chk(&li->li_tv); + li = li->li_next; + } + + rettv->vval.v_number = 1; /* FAIL */ + if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) + break; + + /* When coming here from Insert mode, sync undo, so that this can be + * undone separately from what was previously inserted. */ + if (u_sync_once == 2) + { + u_sync_once = 1; /* notify that u_sync() was called */ + u_sync(TRUE); + } + + if (lnum <= curbuf->b_ml.ml_line_count) + { + /* existing line, replace it */ + if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) + { + changed_bytes(lnum, 0); + if (is_curbuf && lnum == curwin->w_cursor.lnum) + check_cursor_col(); + rettv->vval.v_number = 0; /* OK */ + } + } + else if (added > 0 || u_save(lnum - 1, lnum) == OK) + { + /* lnum is one past the last line, append the line */ + ++added; + if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) + rettv->vval.v_number = 0; /* OK */ + } + + if (l == NULL) /* only one string argument */ + break; + ++lnum; + } + + if (added > 0) + appended_lines_mark(lcount, added); + + curbuf = curbuf_save; +} + +/* + * "setbufline()" function + */ + static void +f_setbufline(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + linenr_T lnum; + buf_T *buf; + + buf = get_buf_tv(&argvars[0], FALSE); + if (buf == NULL) + rettv->vval.v_number = 1; /* FAIL */ + else + { + lnum = get_tv_lnum_buf(&argvars[1], buf); + + set_buffer_lines(buf, lnum, &argvars[2], rettv); + } +} + /* * "setbufvar()" function */ @@ -10048,72 +10161,9 @@ f_setfperm(typval_T *argvars, typval_T *rettv) static void f_setline(typval_T *argvars, typval_T *rettv) { - linenr_T lnum; - char_u *line = NULL; - list_T *l = NULL; - listitem_T *li = NULL; - long added = 0; - linenr_T lcount = curbuf->b_ml.ml_line_count; + linenr_T lnum = get_tv_lnum(&argvars[0]); - lnum = get_tv_lnum(&argvars[0]); - if (argvars[1].v_type == VAR_LIST) - { - l = argvars[1].vval.v_list; - li = l->lv_first; - } - else - line = get_tv_string_chk(&argvars[1]); - - /* default result is zero == OK */ - for (;;) - { - if (l != NULL) - { - /* list argument, get next string */ - if (li == NULL) - break; - line = get_tv_string_chk(&li->li_tv); - li = li->li_next; - } - - rettv->vval.v_number = 1; /* FAIL */ - if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) - break; - - /* When coming here from Insert mode, sync undo, so that this can be - * undone separately from what was previously inserted. */ - if (u_sync_once == 2) - { - u_sync_once = 1; /* notify that u_sync() was called */ - u_sync(TRUE); - } - - if (lnum <= curbuf->b_ml.ml_line_count) - { - /* existing line, replace it */ - if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) - { - changed_bytes(lnum, 0); - if (lnum == curwin->w_cursor.lnum) - check_cursor_col(); - rettv->vval.v_number = 0; /* OK */ - } - } - else if (added > 0 || u_save(lnum - 1, lnum) == OK) - { - /* lnum is one past the last line, append the line */ - ++added; - if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) - rettv->vval.v_number = 0; /* OK */ - } - - if (l == NULL) /* only one string argument */ - break; - ++lnum; - } - - if (added > 0) - appended_lines_mark(lcount, added); + set_buffer_lines(curbuf, lnum, &argvars[1], rettv); } static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *what_arg, typval_T *rettv); @@ -11870,6 +11920,10 @@ f_synIDattr(typval_T *argvars UNUSED, typval_T *rettv) case 's': if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */ p = highlight_color(id, what, modec); + /* strikeout */ + else if (TOLOWER_ASC(what[1]) == 't' && + TOLOWER_ASC(what[2]) == 'r') + p = highlight_has_attr(id, HL_STRIKETHROUGH, modec); else /* standout */ p = highlight_has_attr(id, HL_STANDOUT, modec); break; @@ -12492,6 +12546,23 @@ f_test_autochdir(typval_T *argvars UNUSED, typval_T *rettv UNUSED) #endif } +/* + * "test_feedinput()" + */ + static void +f_test_feedinput(typval_T *argvars, typval_T *rettv UNUSED) +{ +#ifdef USE_INPUT_BUF + char_u *val = get_tv_string_chk(&argvars[0]); + + if (val != NULL) + { + trash_input_buf(); + add_to_input_buf_csi(val, (int)STRLEN(val)); + } +#endif +} + /* * "test_disable({name}, {val})" function */ diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 8b21b81f2a..1cb15f2047 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -2098,11 +2098,16 @@ viminfo_filename(char_u *file) else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL) { #ifdef VIMINFO_FILE2 - /* don't use $HOME when not defined (turned into "c:/"!). */ # ifdef VMS if (mch_getenv((char_u *)"SYS$LOGIN") == NULL) # else +# ifdef MSWIN + /* Use $VIM only if $HOME is the default "C:/". */ + if (STRCMP(vim_getenv((char_u *)"HOME", NULL), "C:/") == 0 + && mch_getenv((char_u *)"HOME") == NULL) +# else if (mch_getenv((char_u *)"HOME") == NULL) +# endif # endif { /* don't use $VIM when not available. */ diff --git a/src/gui.c b/src/gui.c index e773cde069..b9b0608cfe 100644 --- a/src/gui.c +++ b/src/gui.c @@ -2413,6 +2413,7 @@ gui_outstr_nowrap( /* Do we underline the text? */ if (hl_mask_todo & HL_UNDERLINE) draw_flags |= DRAW_UNDERL; + #else /* Do we underline the text? */ if ((hl_mask_todo & HL_UNDERLINE) || (hl_mask_todo & HL_ITALIC)) @@ -2422,6 +2423,10 @@ gui_outstr_nowrap( if (hl_mask_todo & HL_UNDERCURL) draw_flags |= DRAW_UNDERC; + /* Do we strikethrough the text? */ + if (hl_mask_todo & HL_STRIKETHROUGH) + draw_flags |= DRAW_STRIKE; + /* Do we draw transparently? */ if (flags & GUI_MON_TRS_CURSOR) draw_flags |= DRAW_TRANSP; diff --git a/src/gui.h b/src/gui.h index c903b6242f..89773c7aad 100644 --- a/src/gui.h +++ b/src/gui.h @@ -143,8 +143,9 @@ # define DRAW_ITALIC 0x10 /* draw italic text */ #endif #define DRAW_CURSOR 0x20 /* drawing block cursor (win32) */ -#define DRAW_WIDE 0x40 /* drawing wide char (MacVim) */ -#define DRAW_COMP 0x80 /* drawing composing char (MacVim) */ +#define DRAW_STRIKE 0x40 /* strikethrough */ +#define DRAW_WIDE 0x80 /* drawing wide char (MacVim) */ +#define DRAW_COMP 0x100 /* drawing composing char (MacVim) */ /* For our own tearoff menu item */ #define TEAR_STRING "-->Detach" diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 3d4ac93ae4..361f16c659 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -5908,6 +5908,27 @@ draw_under(int flags, int row, int col, int cells) #endif } + /* Draw a strikethrough line */ + if (flags & DRAW_STRIKE) + { +#if GTK_CHECK_VERSION(3,0,0) + cairo_set_line_width(cr, 1.0); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); + cairo_set_source_rgba(cr, + gui.spcolor->red, gui.spcolor->green, gui.spcolor->blue, + gui.spcolor->alpha); + cairo_move_to(cr, FILL_X(col), y + 1 - gui.char_height/2 + 0.5); + cairo_line_to(cr, FILL_X(col + cells), y + 1 - gui.char_height/2 + 0.5); + cairo_stroke(cr); +#else + gdk_gc_set_foreground(gui.text_gc, gui.spcolor); + gdk_draw_line(gui.drawarea->window, gui.text_gc, + FILL_X(col), y + 1 - gui.char_height/2, + FILL_X(col + cells), y + 1 - gui.char_height/2); + gdk_gc_set_foreground(gui.text_gc, gui.fgcolor); +#endif + } + /* Underline: draw a line at the bottom of the character cell. */ if (flags & DRAW_UNDERL) { @@ -5916,16 +5937,14 @@ draw_under(int flags, int row, int col, int cells) if (p_linespace > 1) y -= p_linespace - 1; #if GTK_CHECK_VERSION(3,0,0) - { - cairo_set_line_width(cr, 1.0); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); - cairo_set_source_rgba(cr, - gui.fgcolor->red, gui.fgcolor->green, gui.fgcolor->blue, - gui.fgcolor->alpha); - cairo_move_to(cr, FILL_X(col), y + 0.5); - cairo_line_to(cr, FILL_X(col + cells), y + 0.5); - cairo_stroke(cr); - } + cairo_set_line_width(cr, 1.0); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); + cairo_set_source_rgba(cr, + gui.fgcolor->red, gui.fgcolor->green, gui.fgcolor->blue, + gui.fgcolor->alpha); + cairo_move_to(cr, FILL_X(col), y + 0.5); + cairo_line_to(cr, FILL_X(col + cells), y + 0.5); + cairo_stroke(cr); #else gdk_draw_line(gui.drawarea->window, gui.text_gc, FILL_X(col), y, diff --git a/src/gui_mac.c b/src/gui_mac.c index 3628ddb2fa..2f4d304827 100644 --- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -3909,6 +3909,11 @@ draw_string_QD(int row, int col, char_u *s, int len, int flags) MoveTo(FILL_X(col), FILL_Y(row + 1) - 1); LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1); } + if (flags & DRAW_STRIKE) + { + MoveTo(FILL_X(col), FILL_Y(row + 1) - gui.char_height/2); + LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - gui.char_height/2); + } } if (flags & DRAW_UNDERC) diff --git a/src/gui_w32.c b/src/gui_w32.c index e94379ba7c..c4a57e675a 100644 --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -6427,6 +6427,18 @@ gui_mch_draw_string( DeleteObject(SelectObject(s_hdc, old_pen)); } + /* Strikethrough */ + if (flags & DRAW_STRIKE) + { + hpen = CreatePen(PS_SOLID, 1, gui.currSpColor); + old_pen = SelectObject(s_hdc, hpen); + y = FILL_Y(row + 1) - gui.char_height/2; + MoveToEx(s_hdc, FILL_X(col), y, NULL); + /* Note: LineTo() excludes the last pixel in the line. */ + LineTo(s_hdc, FILL_X(col + len), y); + DeleteObject(SelectObject(s_hdc, old_pen)); + } + /* Undercurl */ if (flags & DRAW_UNDERC) { diff --git a/src/gui_x11.c b/src/gui_x11.c index a638222251..1e790a81c4 100644 --- a/src/gui_x11.c +++ b/src/gui_x11.c @@ -2542,6 +2542,16 @@ gui_mch_draw_string( y, FILL_X(col + cells) - 1, y); } + if (flags & DRAW_STRIKE) + { + int y = FILL_Y(row + 1) - gui.char_height/2; + + XSetForeground(gui.dpy, gui.text_gc, prev_sp_color); + XDrawLine(gui.dpy, gui.wid, gui.text_gc, FILL_X(col), + y, FILL_X(col + cells) - 1, y); + XSetForeground(gui.dpy, gui.text_gc, prev_fg_color); + } + #ifdef FEAT_XFONTSET if (current_fontset != NULL) XSetClipMask(gui.dpy, gui.text_gc, None); diff --git a/src/if_ruby.c b/src/if_ruby.c index 79857aeace..5e1729b1cd 100644 --- a/src/if_ruby.c +++ b/src/if_ruby.c @@ -993,7 +993,7 @@ static VALUE vim_message(VALUE self UNUSED, VALUE str) if (RSTRING_LEN(str) > 0) { /* Only do this when the string isn't empty, alloc(0) causes trouble. */ - buff = ALLOCA_N(char, RSTRING_LEN(str)); + buff = ALLOCA_N(char, RSTRING_LEN(str) + 1); strcpy(buff, RSTRING_PTR(str)); p = strchr(buff, '\n'); if (p) *p = '\0'; diff --git a/src/iscygpty.c b/src/iscygpty.c index d7037c56fc..722f88f2f4 100644 --- a/src/iscygpty.c +++ b/src/iscygpty.c @@ -2,7 +2,7 @@ * iscygpty.c -- part of ptycheck * https://github.com/k-takata/ptycheck * - * Copyright (c) 2015-2016 K.Takata + * Copyright (c) 2015-2017 K.Takata * * You can redistribute it and/or modify it under the terms of either * the MIT license (as described below) or the Vim license. @@ -27,6 +27,8 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef _WIN32 + #include #include #include @@ -60,19 +62,19 @@ //#define USE_DYNFILEID #ifdef USE_DYNFILEID typedef BOOL (WINAPI *pfnGetFileInformationByHandleEx)( - HANDLE hFile, + HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - LPVOID lpFileInformation, - DWORD dwBufferSize + LPVOID lpFileInformation, + DWORD dwBufferSize ); static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL; # ifndef USE_FILEEXTD static BOOL WINAPI stub_GetFileInformationByHandleEx( - HANDLE hFile, + HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - LPVOID lpFileInformation, - DWORD dwBufferSize + LPVOID lpFileInformation, + DWORD dwBufferSize ) { return FALSE; @@ -111,7 +113,7 @@ int is_cygpty(int fd) return 0; #else HANDLE h; - int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; + int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * (MAX_PATH - 1); FILE_NAME_INFO *nameinfo; WCHAR *p = NULL; @@ -125,7 +127,7 @@ int is_cygpty(int fd) if (GetFileType(h) != FILE_TYPE_PIPE) { return 0; } - nameinfo = malloc(size); + nameinfo = malloc(size + sizeof(WCHAR)); if (nameinfo == NULL) { return 0; } @@ -178,4 +180,6 @@ int is_cygpty_used(void) return ret; } -/* vi:set ts=8 sts=4 sw=4 noet: */ +#endif /* _WIN32 */ + +/* vim: set ts=4 sw=4: */ diff --git a/src/iscygpty.h b/src/iscygpty.h index fbca4b4095..82fd0affbd 100644 --- a/src/iscygpty.h +++ b/src/iscygpty.h @@ -2,7 +2,7 @@ * iscygpty.h -- part of ptycheck * https://github.com/k-takata/ptycheck * - * Copyright (c) 2015-2016 K.Takata + * Copyright (c) 2015-2017 K.Takata * * You can redistribute it and/or modify it under the terms of either * the MIT license (as described below) or the Vim license. @@ -30,7 +30,12 @@ #ifndef _ISCYGPTY_H #define _ISCYGPTY_H +#ifdef _WIN32 int is_cygpty(int fd); int is_cygpty_used(void); +#else +#define is_cygpty(fd) 0 +#define is_cygpty_used() 0 +#endif #endif /* _ISCYGPTY_H */ diff --git a/src/misc1.c b/src/misc1.c index 9c88ec20ab..682a66591b 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -1589,8 +1589,7 @@ open_line( && curbuf->b_p_ai) { fixthisline(get_lisp_indent); - p = ml_get_curline(); - ai_col = (colnr_T)(skipwhite(p) - p); + ai_col = (colnr_T)getwhitecols_curline(); } #endif #ifdef FEAT_CINDENT @@ -1608,8 +1607,7 @@ open_line( : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum))) { do_c_expr_indent(); - p = ml_get_curline(); - ai_col = (colnr_T)(skipwhite(p) - p); + ai_col = (colnr_T)getwhitecols_curline(); } #endif #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT)) diff --git a/src/ops.c b/src/ops.c index 5c58e523f3..6fb6947ee2 100644 --- a/src/ops.c +++ b/src/ops.c @@ -2507,6 +2507,7 @@ op_insert(oparg_T *oap, long count1) { long ins_len, pre_textlen = 0; char_u *firstline, *ins_text; + colnr_T ind_pre = 0, ind_post; struct block_def bd; int i; pos_T t1; @@ -2541,7 +2542,10 @@ op_insert(oparg_T *oap, long count1) #endif /* Get the info about the block before entering the text */ block_prep(oap, &bd, oap->start.lnum, TRUE); + /* Get indent information */ + ind_pre = (colnr_T)getwhitecols_curline(); firstline = ml_get(oap->start.lnum) + bd.textcol; + if (oap->op_type == OP_APPEND) firstline += bd.textlen; pre_textlen = (long)STRLEN(firstline); @@ -2603,6 +2607,15 @@ op_insert(oparg_T *oap, long count1) { struct block_def bd2; + /* If indent kicked in, the firstline might have changed + * but only do that, if the indent actually increased. */ + ind_post = (colnr_T)getwhitecols_curline(); + if (curbuf->b_op_start.col > ind_pre && ind_post > ind_pre) + { + bd.textcol += ind_post - ind_pre; + bd.start_vcol += ind_post - ind_pre; + } + /* The user may have moved the cursor before inserting something, try * to adjust the block for that. */ if (oap->start.lnum == curbuf->b_op_start_orig.lnum && !bd.is_MAX) @@ -2754,7 +2767,7 @@ op_change(oparg_T *oap) # endif firstline = ml_get(oap->start.lnum); pre_textlen = (long)STRLEN(firstline); - pre_indent = (long)(skipwhite(firstline) - firstline); + pre_indent = (long)getwhitecols(firstline); bd.textcol = curwin->w_cursor.col; } #endif @@ -2779,7 +2792,7 @@ op_change(oparg_T *oap) firstline = ml_get(oap->start.lnum); if (bd.textcol > (colnr_T)pre_indent) { - long new_indent = (long)(skipwhite(firstline) - firstline); + long new_indent = (long)getwhitecols(firstline); pre_textlen += new_indent - pre_indent; bd.textcol += new_indent - pre_indent; @@ -5065,8 +5078,7 @@ format_lines( #endif if (second_indent > 0) /* the "leader" for FO_Q_SECOND */ { - char_u *p = ml_get_curline(); - int indent = (int)(skipwhite(p) - p); + int indent = getwhitecols_curline(); if (indent > 0) { diff --git a/src/option.c b/src/option.c index b1d8ce93f8..8d8262adf3 100644 --- a/src/option.c +++ b/src/option.c @@ -3317,8 +3317,10 @@ static struct vimoption options[] = p_term("t_so", T_SO) p_term("t_SR", T_CSR) p_term("t_sr", T_SR) + p_term("t_Te", T_STE) p_term("t_te", T_TE) p_term("t_ti", T_TI) + p_term("t_Ts", T_STS) p_term("t_ts", T_TS) p_term("t_u7", T_U7) p_term("t_ue", T_UE) diff --git a/src/os_unix.c b/src/os_unix.c index 8f258c492f..8e3e82ca68 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -2282,6 +2282,7 @@ vim_is_xterm(char_u *name) || STRNICMP(name, "kterm", 5) == 0 || STRNICMP(name, "mlterm", 6) == 0 || STRNICMP(name, "rxvt", 4) == 0 + || STRNICMP(name, "screen.xterm", 12) == 0 || STRCMP(name, "builtin_xterm") == 0); } @@ -4099,8 +4100,17 @@ mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc) ++*argc; while (*p != NUL && (inquote || (*p != ' ' && *p != TAB))) { - if (*p == '"') + if (p[0] == '"') inquote = !inquote; + else if (p[0] == '\\' && p[1] != NUL) + { + /* First pass: skip over "\ " and "\"". + * Second pass: Remove the backslash. */ + if (i == 1) + mch_memmove(p, p + 1, STRLEN(p)); + else + ++p; + } ++p; } if (*p == NUL) diff --git a/src/proto/charset.pro b/src/proto/charset.pro index 52b741a740..bb4132fe79 100644 --- a/src/proto/charset.pro +++ b/src/proto/charset.pro @@ -35,6 +35,8 @@ colnr_T getvcol_nolist(pos_T *posp); void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end); void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right); char_u *skipwhite(char_u *q); +int getwhitecols_curline(void); +int getwhitecols(char_u *p); char_u *skipdigits(char_u *q); char_u *skipbin(char_u *q); char_u *skiphex(char_u *q); diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro index cac644969b..4e299e5f9a 100644 --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -1,4 +1,5 @@ /* misc1.c */ +int get_whitespace_line_start(linenr_T lnum); int get_indent(void); int get_indent_lnum(linenr_T lnum); int get_indent_buf(buf_T *buf, linenr_T lnum); diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro index 2b05d341e2..3811ba7a51 100644 --- a/src/proto/terminal.pro +++ b/src/proto/terminal.pro @@ -16,6 +16,7 @@ int term_update_window(win_T *wp); int term_is_finished(buf_T *buf); int term_show_buffer(buf_T *buf); void term_change_in_curbuf(void); +void term_send_eof(channel_T *ch); int term_get_attr(buf_T *buf, linenr_T lnum, int col); char_u *term_get_status_text(term_T *term); int set_ref_in_term(int copyID); diff --git a/src/quickfix.c b/src/quickfix.c index 8277b937e9..ee871fc463 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4643,36 +4643,48 @@ enum { * Parse text from 'di' and return the quickfix list items */ static int -qf_get_list_from_text(dictitem_T *di, dict_T *retdict) +qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict) { int status = FAIL; qf_info_T *qi; + char_u *errorformat = p_efm; + dictitem_T *efm_di; + list_T *l; - /* Only string and list values are supported */ - if ((di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL) - || (di->di_tv.v_type == VAR_LIST - && di->di_tv.vval.v_list != NULL)) + /* Only a List value is supported */ + if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) { + /* If errorformat is supplied then use it, otherwise use the 'efm' + * option setting + */ + if ((efm_di = dict_find(what, (char_u *)"efm", -1)) != NULL) + { + if (efm_di->di_tv.v_type != VAR_STRING || + efm_di->di_tv.vval.v_string == NULL) + return FAIL; + errorformat = efm_di->di_tv.vval.v_string; + } + + l = list_alloc(); + if (l == NULL) + return FAIL; + qi = (qf_info_T *)alloc((unsigned)sizeof(qf_info_T)); if (qi != NULL) { vim_memset(qi, 0, (size_t)(sizeof(qf_info_T))); qi->qf_refcount++; - if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, p_efm, + if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat, TRUE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) { - list_T *l = list_alloc(); - if (l != NULL) - { - (void)get_errorlist(qi, NULL, 0, l); - dict_add_list(retdict, "items", l); - status = OK; - } + (void)get_errorlist(qi, NULL, 0, l); qf_free(qi, 0); } free(qi); } + dict_add_list(retdict, "items", l); + status = OK; } return status; @@ -4692,8 +4704,8 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) dictitem_T *di; int flags = QF_GETLIST_NONE; - if ((di = dict_find(what, (char_u *)"text", -1)) != NULL) - return qf_get_list_from_text(di, retdict); + if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL) + return qf_get_list_from_lines(what, di, retdict); if (wp != NULL) qi = GET_LOC_LIST(wp); @@ -4963,6 +4975,7 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title) int retval = FAIL; int qf_idx; int newlist = FALSE; + char_u *errorformat = p_efm; if (action == ' ' || qi->qf_curlist == qi->qf_listcount) newlist = TRUE; @@ -5040,6 +5053,7 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title) retval = OK; } } + if ((di = dict_find(what, (char_u *)"items", -1)) != NULL) { if (di->di_tv.v_type == VAR_LIST) @@ -5052,16 +5066,21 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title) } } - if ((di = dict_find(what, (char_u *)"text", -1)) != NULL) + if ((di = dict_find(what, (char_u *)"efm", -1)) != NULL) { - /* Only string and list values are supported */ - if ((di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL) - || (di->di_tv.v_type == VAR_LIST - && di->di_tv.vval.v_list != NULL)) + if (di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string == NULL) + return FAIL; + errorformat = di->di_tv.vval.v_string; + } + + if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL) + { + /* Only a List value is supported */ + if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) { if (action == 'r') qf_free_items(qi, qf_idx); - if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, p_efm, + if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, errorformat, FALSE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) retval = OK; } diff --git a/src/screen.c b/src/screen.c index bbd211f819..0d477d2877 100644 --- a/src/screen.c +++ b/src/screen.c @@ -235,7 +235,7 @@ redraw_later_clear(void) else #endif /* Use attributes that is very unlikely to appear in text. */ - screen_attr = HL_BOLD | HL_UNDERLINE | HL_INVERSE; + screen_attr = HL_BOLD | HL_UNDERLINE | HL_INVERSE | HL_STRIKETHROUGH; } /* @@ -3463,7 +3463,7 @@ win_line( { /* For checking first word with a capital skip white space. */ if (cap_col == 0) - cap_col = (int)(skipwhite(line) - line); + cap_col = getwhitecols(line); /* To be able to spell-check over line boundaries copy the end of the * current line into nextline[]. Above the start of the next line was @@ -8098,6 +8098,8 @@ screen_start_highlight(int attr) out_str(T_CZH); if ((attr & HL_INVERSE) && T_MR != NULL) /* inverse (reverse) */ out_str(T_MR); + if ((attr & HL_STRIKETHROUGH) && T_STS != NULL) /* strike */ + out_str(T_STS); /* * Output the color or start string after bold etc., in case the @@ -8222,6 +8224,13 @@ screen_stop_highlight(void) else out_str(T_CZR); } + if (screen_attr & HL_STRIKETHROUGH) + { + if (STRCMP(T_STE, T_ME) == 0) + do_ME = TRUE; + else + out_str(T_STE); + } if (do_ME || (screen_attr & (HL_BOLD | HL_INVERSE))) out_str(T_ME); diff --git a/src/spell.c b/src/spell.c index 0eb87638eb..2742997c2c 100644 --- a/src/spell.c +++ b/src/spell.c @@ -1625,11 +1625,11 @@ spell_move_to( /* For checking first word with a capital skip white space. */ if (capcol == 0) - capcol = (int)(skipwhite(line) - line); + capcol = getwhitecols(line); else if (curline && wp == curwin) { /* For spellbadword(): check if first word needs a capital. */ - col = (int)(skipwhite(line) - line); + col = getwhitecols(line); if (check_need_cap(lnum, col)) capcol = col; @@ -3593,7 +3593,7 @@ check_need_cap(linenr_T lnum, colnr_T col) line = ml_get_curline(); endcol = 0; - if ((int)(skipwhite(line) - line) >= (int)col) + if (getwhitecols(line) >= (int)col) { /* At start of line, check if previous line is empty or sentence * ends there. */ diff --git a/src/structs.h b/src/structs.h index 2832c663b7..ca86063d63 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1635,6 +1635,7 @@ struct channel_S { int ch_last_msg_id; /* ID of the last message */ chanpart_T ch_part[PART_COUNT]; /* info for socket, out, err and in */ + int ch_write_text_mode; /* write buffer lines with CR, not NL */ char *ch_hostname; /* only for socket, allocated */ int ch_port; /* only for socket */ @@ -1716,7 +1717,8 @@ struct channel_S { #define JO2_CURWIN 0x0200 /* "curwin" */ #define JO2_HIDDEN 0x0400 /* "hidden" */ #define JO2_TERM_OPENCMD 0x0800 /* "term_opencmd" */ -#define JO2_ALL 0x0FFF +#define JO2_EOF_CHARS 0x1000 /* "eof_chars" */ +#define JO2_ALL 0x1FFF #define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE) #define JO_CB_ALL \ @@ -1782,6 +1784,7 @@ typedef struct char_u *jo_term_name; char_u *jo_term_opencmd; int jo_term_finish; + char_u *jo_eof_chars; #endif } jobopt_T; diff --git a/src/syntax.c b/src/syntax.c index f6741b7b95..0c9be41c3a 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -86,9 +86,9 @@ static int include_link = 0; /* when 2 include "link" and "clear" */ */ static char *(hl_name_table[]) = {"bold", "standout", "underline", "undercurl", - "italic", "reverse", "inverse", "nocombine", "NONE"}; + "italic", "reverse", "inverse", "nocombine", "strikethrough", "NONE"}; static int hl_attr_table[] = - {HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_NOCOMBINE, 0}; + {HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_NOCOMBINE, HL_STRIKETHROUGH, 0}; #define ATTR_COMBINE(attr_a, attr_b) ((((attr_b) & HL_NOCOMBINE) ? attr_b : (attr_a)) | (attr_b)) static int get_attr_entry(garray_T *table, attrentry_T *aep); @@ -9952,6 +9952,8 @@ highlight_changed(void) break; case 'c': attr |= HL_UNDERCURL; break; + case 't': attr |= HL_STRIKETHROUGH; + break; case ':': ++p; /* highlight group name */ if (attr || *p == NUL) /* no combinations */ return FAIL; diff --git a/src/term.c b/src/term.c index bc28880464..30a0aec93f 100644 --- a/src/term.c +++ b/src/term.c @@ -217,6 +217,8 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_US, IF_EB("\033|8h", ESC_STR "|8h")}, /* HL_UNDERLINE */ {(int)KS_UCE, IF_EB("\033|8C", ESC_STR "|8C")}, /* HL_UNDERCURL */ {(int)KS_UCS, IF_EB("\033|8c", ESC_STR "|8c")}, /* HL_UNDERCURL */ + {(int)KS_STE, IF_EB("\033|4C", ESC_STR "|4C")}, /* HL_STRIKETHROUGH */ + {(int)KS_STS, IF_EB("\033|4c", ESC_STR "|4c")}, /* HL_STRIKETHROUGH */ {(int)KS_CZR, IF_EB("\033|4H", ESC_STR "|4H")}, /* HL_ITALIC */ {(int)KS_CZH, IF_EB("\033|4h", ESC_STR "|4h")}, /* HL_ITALIC */ {(int)KS_VB, IF_EB("\033|f", ESC_STR "|f")}, @@ -831,6 +833,8 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_MD, IF_EB("\033[1m", ESC_STR "[1m")}, {(int)KS_UE, IF_EB("\033[m", ESC_STR "[m")}, {(int)KS_US, IF_EB("\033[4m", ESC_STR "[4m")}, + {(int)KS_STE, IF_EB("\033[29m", ESC_STR "[29m")}, + {(int)KS_STS, IF_EB("\033[9m", ESC_STR "[9m")}, {(int)KS_MS, "y"}, {(int)KS_UT, "y"}, {(int)KS_LE, "\b"}, @@ -1151,6 +1155,8 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_US, "[US]"}, {(int)KS_UCE, "[UCE]"}, {(int)KS_UCS, "[UCS]"}, + {(int)KS_STE, "[STE]"}, + {(int)KS_STS, "[STS]"}, {(int)KS_MS, "[MS]"}, {(int)KS_UT, "[UT]"}, {(int)KS_XN, "[XN]"}, @@ -1601,6 +1607,7 @@ set_termname(char_u *term) {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"}, + {KS_STE,"Te"}, {KS_STS,"Ts"}, {KS_CM, "cm"}, {KS_SR, "sr"}, {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, @@ -4502,6 +4509,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') { + int version = col; + LOG_TR("Received CRV response"); crv_status = STATUS_GOT; # ifdef FEAT_AUTOCMD @@ -4514,10 +4523,11 @@ check_termcode( switch_to_8bit(); /* rxvt sends its version number: "20703" is 2.7.3. + * Screen sends 40500. * Ignore it for when the user has set 'term' to xterm, * even though it's an rxvt. */ - if (col > 20000) - col = 0; + if (version > 20000) + version = 0; if (tp[1 + (tp[0] != CSI)] == '>' && semicols == 2) { @@ -4528,19 +4538,19 @@ check_termcode( if (!option_was_set((char_u *)"ttym")) { # ifdef TTYM_SGR - if (col >= 277) + if (version >= 277) set_option_value((char_u *)"ttym", 0L, (char_u *)"sgr", 0); else # endif /* if xterm version >= 95 use mouse dragging */ - if (col >= 95) + if (version >= 95) set_option_value((char_u *)"ttym", 0L, (char_u *)"xterm2", 0); } /* if xterm version >= 141 try to get termcap codes */ - if (col >= 141) + if (version >= 141) { LOG_TR("Enable checking for XT codes"); check_for_codes = TRUE; @@ -4549,7 +4559,7 @@ check_termcode( } /* libvterm sends 0;100;0 */ - if (col == 100 + if (version == 100 && STRNCMP(tp + extra - 2, "0;100;0c", 8) == 0) { /* If run from Vim $COLORS is set to the number of @@ -4564,14 +4574,26 @@ check_termcode( * compatible. */ # ifdef MACOS /* Mac Terminal.app sends 1;95;0 */ - if (col == 95 + if (version == 95 && STRNCMP(tp + extra - 2, "1;95;0c", 7) == 0) is_not_xterm = TRUE; # endif - /* Gnome Terminal.app sends 1;3801;0 or 1;4402;0, - * assuming any version number over 3000 is not an - * xterm. */ - if (col >= 3000) + /* Gnome terminal sends 1;3801;0 or 1;4402;0. + * xfce4-terminal sends 1;2802;0. + * screen sends 83;40500;0 + * Assuming any version number over 2800 is not an + * xterm (without the limit for rxvt and screen). */ + if (col >= 2800) + is_not_xterm = TRUE; + + /* PuTTY sends 0;136;0 */ + if (version == 136 + && STRNCMP(tp + extra - 2, "0;136;0c", 8) == 0) + is_not_xterm = TRUE; + + /* Konsole sends 0;115;0 */ + if (version == 115 + && STRNCMP(tp + extra - 2, "0;115;0c", 8) == 0) is_not_xterm = TRUE; /* Only request the cursor style if t_SH and t_RS are diff --git a/src/term.h b/src/term.h index 0fedfeaa85..b95b4f6de8 100644 --- a/src/term.h +++ b/src/term.h @@ -55,6 +55,8 @@ enum SpecialKey KS_US, /* underscore (underline) mode */ KS_UCE, /* exit undercurl mode */ KS_UCS, /* undercurl mode */ + KS_STE, /* exit strikethrough mode */ + KS_STS, /* strikethrough mode */ KS_MS, /* save to move cur in reverse mode */ KS_CM, /* cursor motion */ KS_SR, /* scroll reverse (backward) */ @@ -149,6 +151,8 @@ extern char_u *(term_strings[]); /* current terminal strings */ #define T_US (TERM_STR(KS_US)) /* underscore (underline) mode */ #define T_UCE (TERM_STR(KS_UCE)) /* exit undercurl mode */ #define T_UCS (TERM_STR(KS_UCS)) /* undercurl mode */ +#define T_STE (TERM_STR(KS_STE)) /* exit strikethrough mode */ +#define T_STS (TERM_STR(KS_STS)) /* strikethrough mode */ #define T_MS (TERM_STR(KS_MS)) /* save to move cur in reverse mode */ #define T_CM (TERM_STR(KS_CM)) /* cursor motion */ #define T_SR (TERM_STR(KS_SR)) /* scroll reverse (backward) */ diff --git a/src/terminal.c b/src/terminal.c index 92bf314834..4166883b82 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -39,7 +39,6 @@ * * TODO: * - ":term NONE" does not work in MS-Windows. - * - 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". @@ -48,16 +47,6 @@ * - 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" - "err_io", "err_name", "err_buf", "err_modifiable", "err_msg" - * Check that something is connected to the terminal. - * Test: "cat" reading from a file or buffer - * "ls" writing stdout to a file or buffer - * shell writing stderr to a file or buffer * - For the GUI fill termios with default values, perhaps like pangoterm: * http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134 * - if the job in the terminal does not support the mouse, we can use the @@ -110,6 +99,7 @@ struct terminal_S { int tl_channel_closed; int tl_finish; /* 'c' for ++close, 'o' for ++open */ char_u *tl_opencmd; + char_u *tl_eof_chars; #ifdef WIN3264 void *tl_winpty_config; @@ -218,16 +208,6 @@ init_job_options(jobopt_T *opt) opt->jo_out_mode = MODE_RAW; opt->jo_err_mode = MODE_RAW; opt->jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE; - - opt->jo_io[PART_OUT] = JIO_BUFFER; - opt->jo_io[PART_ERR] = JIO_BUFFER; - opt->jo_set |= JO_OUT_IO + JO_ERR_IO; - - opt->jo_modifiable[PART_OUT] = 0; - opt->jo_modifiable[PART_ERR] = 0; - opt->jo_set |= JO_OUT_MODIFIABLE + JO_ERR_MODIFIABLE; - - opt->jo_set |= JO_OUT_BUF + JO_ERR_BUF; } /* @@ -236,8 +216,24 @@ init_job_options(jobopt_T *opt) static void setup_job_options(jobopt_T *opt, int rows, int cols) { - opt->jo_io_buf[PART_OUT] = curbuf->b_fnum; - opt->jo_io_buf[PART_ERR] = curbuf->b_fnum; + if (!(opt->jo_set & JO_OUT_IO)) + { + /* Connect stdout to the terminal. */ + opt->jo_io[PART_OUT] = JIO_BUFFER; + opt->jo_io_buf[PART_OUT] = curbuf->b_fnum; + opt->jo_modifiable[PART_OUT] = 0; + opt->jo_set |= JO_OUT_IO + JO_OUT_BUF + JO_OUT_MODIFIABLE; + } + + if (!(opt->jo_set & JO_ERR_IO)) + { + /* Connect stderr to the terminal. */ + opt->jo_io[PART_ERR] = JIO_BUFFER; + opt->jo_io_buf[PART_ERR] = curbuf->b_fnum; + opt->jo_modifiable[PART_ERR] = 0; + opt->jo_set |= JO_ERR_IO + JO_ERR_BUF + JO_ERR_MODIFIABLE; + } + opt->jo_pty = TRUE; if ((opt->jo_set2 & JO2_TERM_ROWS) == 0) opt->jo_term_rows = rows; @@ -257,6 +253,15 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit) if (check_restricted() || check_secure()) return; + if ((opt->jo_set & (JO_IN_IO + JO_OUT_IO + JO_ERR_IO)) + == (JO_IN_IO + JO_OUT_IO + JO_ERR_IO) + || (!(opt->jo_set & JO_OUT_IO) && (opt->jo_set & JO_OUT_BUF)) + || (!(opt->jo_set & JO_ERR_IO) && (opt->jo_set & JO_ERR_BUF))) + { + EMSG(_(e_invarg)); + return; + } + term = (term_T *)alloc_clear(sizeof(term_T)); if (term == NULL) return; @@ -389,6 +394,9 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit) if (opt->jo_term_opencmd != NULL) term->tl_opencmd = vim_strsave(opt->jo_term_opencmd); + if (opt->jo_eof_chars != NULL) + term->tl_eof_chars = vim_strsave(opt->jo_eof_chars); + set_string_option_direct((char_u *)"buftype", -1, (char_u *)"terminal", OPT_FREE|OPT_LOCAL, 0); @@ -490,6 +498,20 @@ ex_terminal(exarg_T *eap) opt.jo_term_cols = atoi((char *)ep + 1); p = skiptowhite(cmd); } + else if ((int)(p - cmd) == 3 && STRNICMP(cmd, "eof", 3) == 0 + && ep != NULL) + { + char_u *buf = NULL; + char_u *keys; + + p = skiptowhite(cmd); + *p = NUL; + keys = replace_termcodes(ep + 1, &buf, TRUE, TRUE, TRUE); + opt.jo_set2 |= JO2_EOF_CHARS; + opt.jo_eof_chars = vim_strsave(keys); + vim_free(buf); + *p = ' '; + } else { if (*p) @@ -570,6 +592,7 @@ free_terminal(buf_T *buf) vim_free(term->tl_title); vim_free(term->tl_status_text); vim_free(term->tl_opencmd); + vim_free(term->tl_eof_chars); vim_free(term->tl_cursor_color); vim_free(term); buf->b_term = NULL; @@ -1721,7 +1744,7 @@ cell2attr(VTermScreenCellAttrs cellattrs, VTermColor cellfg, VTermColor cellbg) if (cellattrs.italic) attr |= HL_ITALIC; if (cellattrs.strike) - attr |= HL_STANDOUT; + attr |= HL_STRIKETHROUGH; if (cellattrs.reverse) attr |= HL_INVERSE; @@ -2437,7 +2460,7 @@ f_term_getattr(typval_T *argvars, typval_T *rettv) {"bold", HL_BOLD}, {"italic", HL_ITALIC}, {"underline", HL_UNDERLINE}, - {"strike", HL_STANDOUT}, + {"strike", HL_STRIKETHROUGH}, {"reverse", HL_INVERSE}, }; @@ -2819,14 +2842,13 @@ f_term_start(typval_T *argvars, typval_T *rettv) jobopt_T opt; init_job_options(&opt); - /* TODO: allow more job options */ if (argvars[1].v_type != VAR_UNKNOWN && get_job_options(&argvars[1], &opt, JO_TIMEOUT_ALL + JO_STOPONEXIT - + JO_EXIT_CB + JO_CLOSE_CALLBACK, + + JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO, JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN - + JO2_CWD + JO2_ENV) == FAIL) + + JO2_CWD + JO2_ENV + JO2_EOF_CHARS) == FAIL) return; if (opt.jo_vertical) @@ -2895,6 +2917,32 @@ f_term_wait(typval_T *argvars, typval_T *rettv UNUSED) } } +/* + * Called when a channel has sent all the lines to a terminal. + * Send a CTRL-D to mark the end of the text. + */ + void +term_send_eof(channel_T *ch) +{ + term_T *term; + + for (term = first_term; term != NULL; term = term->tl_next) + if (term->tl_job == ch->ch_job) + { + if (term->tl_eof_chars != NULL) + { + channel_send(ch, PART_IN, term->tl_eof_chars, + (int)STRLEN(term->tl_eof_chars), NULL); + channel_send(ch, PART_IN, (char_u *)"\r", 1, NULL); + } +# ifdef WIN3264 + else + /* Default: CTRL-D */ + channel_send(ch, PART_IN, (char_u *)"\004\r", 2, NULL); +# endif + } +} + # if defined(WIN3264) || defined(PROTO) /************************************** @@ -3065,8 +3113,6 @@ term_and_job_init( 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]); @@ -3088,6 +3134,9 @@ term_and_job_init( GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)); + /* Write lines with CR instead of NL. */ + channel->ch_write_text_mode = TRUE; + jo = CreateJobObject(NULL, NULL); if (jo == NULL) goto failed; @@ -3193,7 +3242,6 @@ terminal_enabled(void) return dyn_winpty_init(FALSE) == OK; } - # else /************************************** @@ -3214,7 +3262,6 @@ term_and_job_init( { create_vterm(term, term->tl_rows, term->tl_cols); - /* TODO: if the command is "NONE" only create a pty. */ term->tl_job = job_start(argvar, opt); if (term->tl_job != NULL) ++term->tl_job->jv_refcount; diff --git a/src/testdir/setup.vim b/src/testdir/setup.vim index cb8bebb47a..fca5194abf 100644 --- a/src/testdir/setup.vim +++ b/src/testdir/setup.vim @@ -21,6 +21,9 @@ if 1 let $XAUTHORITY = $HOME . '/.Xauthority' endif + " Avoid storing shell history. + let $HISTFILE = "" + " Make sure $HOME does not get read or written. " It must exist, gnome tries to create $HOME/.gnome2 let $HOME = getcwd() . '/XfakeHOME' diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim index e83256a4d3..189cd82d12 100644 --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -3,6 +3,7 @@ set belloff=all source test_assign.vim +source test_bufline.vim source test_cd.vim source test_changedtick.vim source test_cursor_func.vim diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim new file mode 100644 index 0000000000..7df36aa6a2 --- /dev/null +++ b/src/testdir/test_bufline.vim @@ -0,0 +1,26 @@ +" Tests for setbufline() and getbufline() + +func Test_setbufline_getbufline() + new + let b = bufnr('%') + hide + call assert_equal(0, setbufline(b, 1, ['foo', 'bar'])) + call assert_equal(['foo'], getbufline(b, 1)) + call assert_equal(['bar'], getbufline(b, 2)) + call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) + exe "bd!" b + call assert_equal([], getbufline(b, 1, 2)) + + split Xtest + call setline(1, ['a', 'b', 'c']) + let b = bufnr('%') + wincmd w + call assert_equal(1, setbufline(b, 5, ['x'])) + call assert_equal(1, setbufline(1234, 1, ['x'])) + call assert_equal(0, setbufline(b, 4, ['d', 'e'])) + call assert_equal(['c'], getbufline(b, 3)) + call assert_equal(['d'], getbufline(b, 4)) + call assert_equal(['e'], getbufline(b, 5)) + call assert_equal([], getbufline(b, 6)) + exe "bwipe! " . b +endfunc diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim index d352e8feff..7c2c5e341c 100644 --- a/src/testdir/test_cindent.vim +++ b/src/testdir/test_cindent.vim @@ -71,7 +71,7 @@ func Test_cino_extern_c() bwipe! endfunc -func! Test_cindent_rawstring() +func Test_cindent_rawstring() new setl cindent call feedkeys("i" . @@ -81,5 +81,25 @@ func! Test_cindent_rawstring() \ "statement;\", "x") call assert_equal("\tstatement;", getline(line('.'))) bw! -endfunction +endfunc + +func Test_cindent_expr() + new + func! MyIndentFunction() + return v:lnum == 1 ? shiftwidth() : 0 + endfunc + setl expandtab sw=8 indentkeys+=; indentexpr=MyIndentFunction() + call setline(1, ['var_a = something()', 'b = something()']) + call cursor(1, 1) + call feedkeys("^\j$A;\", 'tnix') + call assert_equal([' var_a = something();', 'b = something();'], getline(1, '$')) + + %d + call setline(1, [' var_a = something()', ' b = something()']) + call cursor(1, 1) + call feedkeys("^\j$A;\", 'tnix') + call assert_equal([' var_a = something();', ' b = something()'], getline(1, '$')) + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index 088ec5ccf6..3625a68e5a 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -280,13 +280,13 @@ func Test_diffopt_icase() set diffopt=icase,foldcolumn:0 e one - call setline(1, ['One', 'Two', 'Three', 'Four']) + call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#ve']) redraw let normattr = screenattr(1, 1) diffthis botright vert new two - call setline(1, ['one', 'TWO', 'Three ', 'Four']) + call setline(1, ['one', 'TWO', 'Three ', 'Four', 'fI=VE']) diffthis redraw @@ -295,6 +295,10 @@ func Test_diffopt_icase() call assert_notequal(normattr, screenattr(3, 1)) call assert_equal(normattr, screenattr(4, 1)) + let dtextattr = screenattr(5, 3) + call assert_notequal(dtextattr, screenattr(5, 1)) + call assert_notequal(dtextattr, screenattr(5, 5)) + diffoff! %bwipe! set diffopt& diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 076d583fd0..6a8d0e7bf2 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -2299,27 +2299,39 @@ func Xsetexpr_tests(cchar) call s:setup_commands(a:cchar) let t = ["File1:10:Line10", "File1:20:Line20"] - call g:Xsetlist([], ' ', {'text' : t}) - call g:Xsetlist([], 'a', {'text' : "File1:30:Line30"}) + call g:Xsetlist([], ' ', {'lines' : t}) + call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]}) let l = g:Xgetlist() call assert_equal(3, len(l)) call assert_equal(20, l[1].lnum) call assert_equal('Line30', l[2].text) - call g:Xsetlist([], 'r', {'text' : "File2:5:Line5"}) + call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]}) let l = g:Xgetlist() call assert_equal(1, len(l)) call assert_equal('Line5', l[0].text) - call assert_equal(-1, g:Xsetlist([], 'a', {'text' : 10})) + call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10})) + call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"})) call g:Xsetlist([], 'f') " Add entries to multiple lists - call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:10:Line10"]}) - call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:20:Line20"]}) - call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:15:Line15"]}) - call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:25:Line25"]}) + call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]}) + call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]}) call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text) call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text) + + " Adding entries using a custom efm + set efm& + call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m', + \ 'lines' : ["F1#10#L10", "F2#20#L20"]}) + call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum) + call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]}) + call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text) + call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum) + call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [], + \ 'lines' : ['F1:10:L10']})) endfunc func Test_setexpr() @@ -2334,10 +2346,10 @@ func Xmultidirstack_tests(cchar) call g:Xsetlist([], 'f') Xexpr "" | Xexpr "" - call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "Entering dir 'Xone/a'"}) - call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "Entering dir 'Xtwo/a'"}) - call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "one.txt:3:one one one"}) - call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "two.txt:5:two two two"}) + call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]}) + call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]}) let l1 = g:Xgetlist({'nr':1, 'items':1}) let l2 = g:Xgetlist({'nr':2, 'items':1}) @@ -2371,10 +2383,10 @@ func Xmultifilestack_tests(cchar) call g:Xsetlist([], 'f') Xexpr "" | Xexpr "" - call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "[one.txt]"}) - call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "[two.txt]"}) - call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "(3,5) one one one"}) - call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "(5,9) two two two"}) + call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]}) + call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]}) + call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]}) let l1 = g:Xgetlist({'nr':1, 'items':1}) let l2 = g:Xgetlist({'nr':2, 'items':1}) @@ -2523,28 +2535,37 @@ endfunc " Test for getting the quickfix list items from some text without modifying " the quickfix stack -func XgetListFromText(cchar) +func XgetListFromLines(cchar) call s:setup_commands(a:cchar) call g:Xsetlist([], 'f') - let l = g:Xgetlist({'text' : "File1:10:Line10"}).items - call assert_equal(1, len(l)) - call assert_equal('Line10', l[0].text) - - let l = g:Xgetlist({'text' : ["File2:20:Line20", "File2:30:Line30"]}).items + let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items call assert_equal(2, len(l)) call assert_equal(30, l[1].lnum) - call assert_equal({}, g:Xgetlist({'text' : 10})) - call assert_equal({}, g:Xgetlist({'text' : []})) + call assert_equal({}, g:Xgetlist({'lines' : 10})) + call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'})) + call assert_equal([], g:Xgetlist({'lines' : []}).items) + call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items) + + " Parse text using a custom efm + set efm& + let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items + call assert_equal('Line30', l[0].text) + let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items + call assert_equal('File3:30:Line30', l[0].text) + let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]}) + call assert_equal({}, l) + call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:') + call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:') " Make sure that the quickfix stack is not modified call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr) endfunc -func Test_get_list_from_text() - call XgetListFromText('c') - call XgetListFromText('l') +func Test_get_list_from_lines() + call XgetListFromLines('c') + call XgetListFromLines('l') endfunc " Tests for the quickfix list id @@ -2567,7 +2588,7 @@ func Xqfid_tests(cchar) call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]}) call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context) - call g:Xsetlist([], 'a', {'id':start_id+1, 'text':'F1:10:L10'}) + call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']}) call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text) call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'})) call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'})) diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index b6c926f401..dce5f05cd1 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -164,10 +164,8 @@ func Test_terminal_scrape_123() call term_wait(1234) call term_wait(buf) - if has('win32') - " TODO: this should not be needed - sleep 100m - endif + let g:buf = buf + call WaitFor('len(term_scrape(g:buf, 1)) > 0') call Check_123(buf) " Must still work after the job ended. @@ -293,6 +291,8 @@ func Test_terminal_size() let size = term_getsize('') bwipe! call assert_equal([7, 27], size) + + call delete('Xtext') endfunc func Test_terminal_curwin() @@ -325,7 +325,7 @@ func Test_terminal_curwin() split dummy bwipe! - + call delete('Xtext') endfunc func Test_finish_open_close() @@ -458,14 +458,16 @@ endfunction func Test_terminal_noblock() let g:buf = term_start(&shell) + if has('mac') + " The shell or something else has a problem dealing with more than 1000 + " characters at the same time. + let len = 1000 + else + let len = 5000 + endif for c in ['a','b','c','d','e','f','g','h','i','j','k'] - call term_sendkeys(g:buf, 'echo ' . repeat(c, 5000) . "\") - if has('mac') - " TODO: this should not be needed, but without it sending keys blocks - " after 8000 chars or so. - sleep 100m - endif + call term_sendkeys(g:buf, 'echo ' . repeat(c, len) . "\") endfor call term_sendkeys(g:buf, "echo done\") @@ -489,25 +491,48 @@ func Test_terminal_noblock() endfunc func Test_terminal_write_stdin() - " Todo: make this work on all systems. - if !has('unix') - return + if !executable('wc') + throw 'skipped: wc command not available' endif new call setline(1, ['one', 'two', 'three']) %term wc - call WaitFor('getline(1) != ""') - let nrs = split(getline(1)) + call WaitFor('getline("$") =~ "3"') + let nrs = split(getline('$')) call assert_equal(['3', '3', '14'], nrs) bwipe + new call setline(1, ['one', 'two', 'three', 'four']) 2,3term wc - call WaitFor('getline(1) != ""') - let nrs = split(getline(1)) + call WaitFor('getline("$") =~ "2"') + let nrs = split(getline('$')) call assert_equal(['2', '2', '10'], nrs) bwipe + if executable('python') + new + call setline(1, ['print("hello")']) + 1term ++eof=exit() python + " MS-Windows echoes the input, Unix doesn't. + call WaitFor('getline("$") =~ "exit" || getline(1) =~ "hello"') + if getline(1) =~ 'hello' + call assert_equal('hello', getline(1)) + else + call assert_equal('hello', getline(line('$') - 1)) + endif + bwipe + + if has('win32') + new + call setline(1, ['print("hello")']) + 1term ++eof= python + call WaitFor('getline("$") =~ "Z"') + call assert_equal('hello', getline(line('$') - 1)) + bwipe + endif + endif + bwipe! endfunc @@ -530,3 +555,61 @@ func Test_terminal_no_cmd() call assert_equal('look here', term_getline(buf, 1)) bwipe! endfunc + +func Test_terminal_special_chars() + " this file name only works on Unix + if !has('unix') + return + endif + call mkdir('Xdir with spaces') + call writefile(['x'], 'Xdir with spaces/quoted"file') + term ls Xdir\ with\ spaces/quoted\"file + call WaitFor('term_getline("", 1) =~ "quoted"') + call assert_match('quoted"file', term_getline('', 1)) + call term_wait('') + + call delete('Xdir with spaces', 'rf') + bwipe +endfunc + +func Test_terminal_wrong_options() + call assert_fails('call term_start(&shell, { + \ "in_io": "file", + \ "in_name": "xxx", + \ "out_io": "file", + \ "out_name": "xxx", + \ "err_io": "file", + \ "err_name": "xxx" + \ })', 'E474:') + call assert_fails('call term_start(&shell, { + \ "out_buf": bufnr("%") + \ })', 'E474:') + call assert_fails('call term_start(&shell, { + \ "err_buf": bufnr("%") + \ })', 'E474:') +endfunc + +func Test_terminal_redir_file() + let cmd = Get_cat_123_cmd() + let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) + call term_wait(buf) + call WaitFor('len(readfile("Xfile")) > 0') + call assert_match('123', readfile('Xfile')[0]) + call delete('Xfile') + + if has('unix') + let buf = term_start('xyzabc', {'err_io': 'file', 'err_name': 'Xfile'}) + call term_wait(buf) + call WaitFor('len(readfile("Xfile")) > 0') + call assert_match('executing job failed', readfile('Xfile')[0]) + call delete('Xfile') + + call writefile(['one line'], 'Xfile') + let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'}) + call term_wait(buf) + call WaitFor('term_getline(' . buf . ', 1) == "one line"') + call assert_equal('one line', term_getline(buf, 1)) + bwipe + call delete('Xfile') + endif +endfunc diff --git a/src/testdir/test_timers.vim b/src/testdir/test_timers.vim index c7495a4821..c9b1071f82 100644 --- a/src/testdir/test_timers.vim +++ b/src/testdir/test_timers.vim @@ -206,5 +206,24 @@ func Test_timer_errors() call assert_equal(3, g:call_count) endfunc +func FeedAndPeek(timer) + call test_feedinput('a') + call getchar(1) +endfunc + +func Interrupt(timer) + call test_feedinput("\") +endfunc + +func Test_peek_and_get_char() + if !has('unix') && !has('gui_running') + return + endif + call timer_start(0, 'FeedAndPeek') + let intr = timer_start(100, 'Interrupt') + let c = getchar() + call assert_equal(char2nr('a'), c) + call timer_stop(intr) +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/ui.c b/src/ui.c index cea3e78ff9..aafcb81d07 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1671,11 +1671,6 @@ set_input_buf(char_u *p) } } -#if defined(FEAT_GUI) \ - || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE) \ - || defined(FEAT_XCLIPBOARD) || defined(VMS) \ - || defined(FEAT_CLIENTSERVER) \ - || defined(PROTO) /* * Add the given bytes to the input buffer * Special keys start with CSI. A real CSI must have been translated to @@ -1696,15 +1691,7 @@ add_to_input_buf(char_u *s, int len) while (len--) inbuf[inbufcount++] = *s++; } -#endif -#if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \ - || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) \ - || (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \ - || (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \ - || defined(FEAT_MENU))) \ - || defined(PROTO) /* * Add "str[len]" to the input buffer while escaping CSI bytes. */ @@ -1726,7 +1713,6 @@ add_to_input_buf_csi(char_u *str, int len) } } } -#endif #if defined(FEAT_HANGULIN) || defined(PROTO) void @@ -1764,7 +1750,6 @@ trash_input_buf(void) /* * Read as much data from the input buffer as possible up to maxlen, and store * it in buf. - * Note: this function used to be Read() in unix.c */ int read_from_input_buf(char_u *buf, long maxlen) diff --git a/src/version.c b/src/version.c index 63f1c5b879..0b57b004ab 100644 --- a/src/version.c +++ b/src/version.c @@ -784,6 +784,58 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1052, +/**/ + 1051, +/**/ + 1050, +/**/ + 1049, +/**/ + 1048, +/**/ + 1047, +/**/ + 1046, +/**/ + 1045, +/**/ + 1044, +/**/ + 1043, +/**/ + 1042, +/**/ + 1041, +/**/ + 1040, +/**/ + 1039, +/**/ + 1038, +/**/ + 1037, +/**/ + 1036, +/**/ + 1035, +/**/ + 1034, +/**/ + 1033, +/**/ + 1032, +/**/ + 1031, +/**/ + 1030, +/**/ + 1029, +/**/ + 1028, +/**/ + 1027, /**/ 1026, /**/ diff --git a/src/vim.h b/src/vim.h index 112804aa36..1aabb7c2de 100644 --- a/src/vim.h +++ b/src/vim.h @@ -436,13 +436,8 @@ typedef off_t off_T; * The characters and attributes cached for the screen. */ typedef char_u schar_T; -#ifdef FEAT_SYN_HL typedef unsigned short sattr_T; -# define MAX_TYPENR 65535 -#else -typedef unsigned char sattr_T; -# define MAX_TYPENR 255 -#endif +#define MAX_TYPENR 65535 /* * The u8char_T can hold one decoded UTF-8 character. @@ -683,7 +678,8 @@ extern int (*dyn_libintl_putenv)(const char *envstring); #define HL_UNDERCURL 0x10 #define HL_STANDOUT 0x20 #define HL_NOCOMBINE 0x40 -#define HL_ALL 0x7f +#define HL_STRIKETHROUGH 0x80 +#define HL_ALL 0xff /* special attribute addition: Put message in history */ #define MSG_HIST 0x1000