summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Make_mvc.mak4
-rw-r--r--src/Makefile2
-rw-r--r--src/arglist.c19
-rwxr-xr-xsrc/auto/configure19
-rw-r--r--src/autocmd.c68
-rw-r--r--src/blob.c37
-rw-r--r--src/buffer.c246
-rw-r--r--src/change.c45
-rw-r--r--src/channel.c2
-rw-r--r--src/charset.c71
-rw-r--r--src/cindent.c3
-rw-r--r--src/clientserver.c8
-rw-r--r--src/clipboard.c3
-rw-r--r--src/config.mk.in1
-rw-r--r--src/configure.ac13
-rw-r--r--src/dict.c5
-rw-r--r--src/diff.c283
-rw-r--r--src/drawline.c277
-rw-r--r--src/drawscreen.c44
-rw-r--r--src/edit.c55
-rw-r--r--src/errors.h25
-rw-r--r--src/eval.c50
-rw-r--r--src/evalbuffer.c1
-rw-r--r--src/evalfunc.c286
-rw-r--r--src/evalvars.c35
-rw-r--r--src/evalwindow.c102
-rw-r--r--src/ex_cmds.c39
-rw-r--r--src/ex_cmds.h2
-rw-r--r--src/ex_cmds2.c30
-rw-r--r--src/ex_docmd.c15
-rw-r--r--src/ex_getln.c58
-rw-r--r--src/fileio.c15
-rw-r--r--src/fold.c14
-rw-r--r--src/getchar.c12
-rw-r--r--src/globals.h4
-rw-r--r--src/gui.c19
-rw-r--r--src/gui.h7
-rw-r--r--src/gui_beval.c1
-rw-r--r--src/gui_gtk_x11.c336
-rw-r--r--src/gui_w32.c525
-rw-r--r--src/gui_xim.c7
-rw-r--r--src/help.c2
-rw-r--r--src/highlight.c97
-rw-r--r--src/if_lua.c5
-rw-r--r--src/if_perl.xs2
-rw-r--r--src/if_py_both.h3
-rw-r--r--src/if_ruby.c2
-rw-r--r--src/if_tcl.c3
-rw-r--r--src/indent.c72
-rw-r--r--src/insexpand.c153
-rw-r--r--src/keymap.h4
-rw-r--r--src/list.c81
-rw-r--r--src/mbyte.c35
-rw-r--r--src/memline.c78
-rw-r--r--src/misc1.c5
-rw-r--r--src/misc2.c24
-rw-r--r--src/mouse.c46
-rw-r--r--src/move.c5
-rw-r--r--src/netbeans.c17
-rw-r--r--src/normal.c53
-rw-r--r--src/ops.c196
-rw-r--r--src/option.c57
-rw-r--r--src/option.h11
-rw-r--r--src/optiondefs.h29
-rw-r--r--src/optionstr.c56
-rw-r--r--src/os_mswin.c62
-rw-r--r--src/os_unix.c13
-rw-r--r--src/os_win32.c19
-rw-r--r--src/po/Make_mvc.mak238
-rw-r--r--src/po/Makefile142
-rw-r--r--src/po/README.txt13
-rw-r--r--src/po/README_mingw.txt6
-rw-r--r--src/po/README_mvc.txt52
-rw-r--r--src/po/ca.po34
-rw-r--r--src/po/hu.po2
-rw-r--r--src/po/it.po62
-rw-r--r--src/po/ru.cp1251.po446
-rw-r--r--src/po/ru.po689
-rw-r--r--src/po/sr.po51
-rw-r--r--src/popupwin.c4
-rw-r--r--src/profiler.c8
-rw-r--r--src/proto/diff.pro1
-rw-r--r--src/proto/evalvars.pro2
-rw-r--r--src/proto/getchar.pro2
-rw-r--r--src/proto/gui_gtk_x11.pro2
-rw-r--r--src/proto/indent.pro4
-rw-r--r--src/proto/list.pro1
-rw-r--r--src/proto/memline.pro5
-rw-r--r--src/proto/move.pro1
-rw-r--r--src/proto/ops.pro1
-rw-r--r--src/proto/option.pro1
-rw-r--r--src/proto/optionstr.pro1
-rw-r--r--src/proto/os_mswin.pro1
-rw-r--r--src/proto/screen.pro6
-rw-r--r--src/proto/search.pro2
-rw-r--r--src/proto/term.pro1
-rw-r--r--src/proto/typval.pro1
-rw-r--r--src/proto/undo.pro3
-rw-r--r--src/proto/userfunc.pro1
-rw-r--r--src/proto/vim9class.pro9
-rw-r--r--src/proto/window.pro12
-rw-r--r--src/quickfix.c79
-rw-r--r--src/regexp.c3
-rw-r--r--src/register.c91
-rw-r--r--src/screen.c135
-rw-r--r--src/scriptfile.c2
-rw-r--r--src/search.c44
-rw-r--r--src/spell.c4
-rw-r--r--src/spellfile.c2
-rw-r--r--src/spellsuggest.c16
-rw-r--r--src/strings.c153
-rw-r--r--src/structs.h35
-rw-r--r--src/syntax.c12
-rw-r--r--src/tag.c8
-rw-r--r--src/term.c41
-rw-r--r--src/termdefs.h6
-rw-r--r--src/terminal.c5
-rw-r--r--src/testdir/Make_all.mak4
-rw-r--r--src/testdir/check.vim8
-rw-r--r--src/testdir/dumps/Test_balloon_eval_term_02.dump2
-rw-r--r--src/testdir/dumps/Test_conceal_cul_wcr_01.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_cul_wcr_02.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_cul_wcr_03.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_1.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_2.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_3.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_4.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_wrap_1.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_wrap_2.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_wrap_3.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_double_width_wrap_4.dump4
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_1.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_2.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_3.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_4.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_5.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump3
-rw-r--r--src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump3
-rw-r--r--src/testdir/dumps/Test_cursorline_with_visualmode_01.dump12
-rw-r--r--src/testdir/dumps/Test_difffunc_diffexpr_1.dump12
-rw-r--r--src/testdir/dumps/Test_display_scroll_update_visual.dump2
-rw-r--r--src/testdir/dumps/Test_drop_modified_1.dump10
-rw-r--r--src/testdir/dumps/Test_echowin_showmode.dump2
-rw-r--r--src/testdir/dumps/Test_hlsearch_visual_1.dump6
-rw-r--r--src/testdir/dumps/Test_matchparen_win_execute_1.dump5
-rw-r--r--src/testdir/dumps/Test_number_insert_delete_lines_1.dump8
-rw-r--r--src/testdir/dumps/Test_number_insert_delete_lines_2.dump8
-rw-r--r--src/testdir/dumps/Test_number_insert_delete_lines_3.dump8
-rw-r--r--src/testdir/dumps/Test_popup_command_03.dump2
-rw-r--r--src/testdir/dumps/Test_prop_above_below_empty_1.dump20
-rw-r--r--src/testdir/dumps/Test_prop_above_below_empty_2.dump20
-rw-r--r--src/testdir/dumps/Test_prop_above_below_empty_3.dump20
-rw-r--r--src/testdir/dumps/Test_prop_above_below_empty_4.dump20
-rw-r--r--src/testdir/dumps/Test_prop_above_below_empty_5.dump20
-rw-r--r--src/testdir/dumps/Test_prop_above_below_empty_6.dump16
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_1.dump2
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_2.dump2
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_3.dump2
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_4.dump2
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_5.dump2
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_6.dump2
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump8
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump8
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump8
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump8
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump8
-rw-r--r--src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_1.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_2.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_3.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_4.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_5.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_6.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_7.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_8.dump8
-rw-r--r--src/testdir/dumps/Test_prop_wincolor_9.dump8
-rw-r--r--src/testdir/dumps/Test_prop_with_text_above_6.dump2
-rw-r--r--src/testdir/dumps/Test_prop_with_text_above_7.dump2
-rw-r--r--src/testdir/dumps/Test_prop_with_text_empty_line_6.dump4
-rw-r--r--src/testdir/dumps/Test_prop_with_text_override_2.dump2
-rw-r--r--src/testdir/dumps/Test_relnr_colors_wrapped_1.dump20
-rw-r--r--src/testdir/dumps/Test_relnr_colors_wrapped_2.dump20
-rw-r--r--src/testdir/dumps/Test_relnr_colors_wrapped_3.dump20
-rw-r--r--src/testdir/dumps/Test_relnr_colors_wrapped_4.dump20
-rw-r--r--src/testdir/dumps/Test_relnr_colors_wrapped_5.dump20
-rw-r--r--src/testdir/dumps/Test_statusline_showcmd_3.dump6
-rw-r--r--src/testdir/dumps/Test_syntax_c_01.dump4
-rw-r--r--src/testdir/dumps/Test_tabline_showcmd_3.dump6
-rw-r--r--src/testdir/dumps/Test_terminal_popup_7.dump2
-rw-r--r--src/testdir/dumps/Test_textprop_hl_override_2.dump2
-rw-r--r--src/testdir/dumps/Test_vim9_no_redraw.dump2
-rw-r--r--src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump8
-rw-r--r--src/testdir/dumps/Test_visual_block_with_virtualedit.dump6
-rw-r--r--src/testdir/dumps/Test_visual_block_with_virtualedit2.dump6
-rw-r--r--src/testdir/dumps/Test_visual_ends_before_showbreak.dump6
-rw-r--r--src/testdir/dumps/Test_visual_hl_with_showbreak.dump2
-rw-r--r--src/testdir/dumps/Test_visual_sbr_1.dump2
-rw-r--r--src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump2
-rw-r--r--src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump2
-rw-r--r--src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump2
-rw-r--r--src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump2
-rw-r--r--src/testdir/dumps/Test_win_gotoid_2.dump2
-rw-r--r--src/testdir/dumps/Test_wincolor_01.dump4
-rw-r--r--src/testdir/shared.vim5
-rw-r--r--src/testdir/test_autocmd.vim165
-rw-r--r--src/testdir/test_breakindent.vim84
-rw-r--r--src/testdir/test_clientserver.vim2
-rw-r--r--src/testdir/test_cmdline.vim52
-rw-r--r--src/testdir/test_cmdwin.vim115
-rw-r--r--src/testdir/test_comments.vim6
-rw-r--r--src/testdir/test_conceal.vim398
-rw-r--r--src/testdir/test_diffmode.vim309
-rw-r--r--src/testdir/test_display.vim20
-rw-r--r--src/testdir/test_edit.vim35
-rw-r--r--src/testdir/test_excmd.vim27
-rw-r--r--src/testdir/test_execute_func.vim24
-rw-r--r--src/testdir/test_exists.vim49
-rw-r--r--src/testdir/test_expand.vim13
-rw-r--r--src/testdir/test_filetype.vim78
-rw-r--r--src/testdir/test_filter_map.vim142
-rw-r--r--src/testdir/test_format.vim168
-rw-r--r--src/testdir/test_functions.vim51
-rw-r--r--src/testdir/test_goto.vim13
-rw-r--r--src/testdir/test_gui.vim12
-rw-r--r--src/testdir/test_highlight.vim28
-rw-r--r--src/testdir/test_ins_complete.vim74
-rw-r--r--src/testdir/test_listchars.vim76
-rw-r--r--src/testdir/test_listlbr.vim8
-rw-r--r--src/testdir/test_listlbr_utf8.vim21
-rw-r--r--src/testdir/test_lua.vim22
-rw-r--r--src/testdir/test_mapping.vim20
-rw-r--r--src/testdir/test_matchparen.vim25
-rw-r--r--src/testdir/test_messages.vim12
-rw-r--r--src/testdir/test_mswin_event.vim54
-rw-r--r--src/testdir/test_normal.vim26
-rw-r--r--src/testdir/test_number.vim65
-rw-r--r--src/testdir/test_options.vim68
-rw-r--r--src/testdir/test_perl.vim17
-rw-r--r--src/testdir/test_popup.vim18
-rw-r--r--src/testdir/test_popupwin.vim18
-rw-r--r--src/testdir/test_prompt_buffer.vim45
-rw-r--r--src/testdir/test_put.vim38
-rw-r--r--src/testdir/test_python2.vim17
-rw-r--r--src/testdir/test_python3.vim17
-rw-r--r--src/testdir/test_quotestar.vim4
-rw-r--r--src/testdir/test_registers.vim18
-rw-r--r--src/testdir/test_remote.vim79
-rw-r--r--src/testdir/test_ruby.vim17
-rw-r--r--src/testdir/test_scroll_opt.vim38
-rw-r--r--src/testdir/test_startup.vim16
-rw-r--r--src/testdir/test_tabpage.vim96
-rw-r--r--src/testdir/test_tagjump.vim29
-rw-r--r--src/testdir/test_tcl.vim17
-rw-r--r--src/testdir/test_terminal2.vim8
-rw-r--r--src/testdir/test_textprop.vim134
-rw-r--r--src/testdir/test_undo.vim2
-rw-r--r--src/testdir/test_user_func.vim19
-rw-r--r--src/testdir/test_utf8_comparisons.vim35
-rw-r--r--src/testdir/test_vim9_assign.vim97
-rw-r--r--src/testdir/test_vim9_builtin.vim30
-rw-r--r--src/testdir/test_vim9_class.vim758
-rw-r--r--src/testdir/test_vim9_disassemble.vim195
-rw-r--r--src/testdir/test_vim9_expr.vim27
-rw-r--r--src/testdir/test_vim9_import.vim49
-rw-r--r--src/testdir/test_vim9_script.vim25
-rw-r--r--src/testdir/test_vim9_typealias.vim4
-rw-r--r--src/testdir/test_virtualedit.vim17
-rw-r--r--src/testdir/test_visual.vim341
-rw-r--r--src/testdir/test_window_cmd.vim339
-rw-r--r--src/testdir/test_winfixbuf.vim3286
-rw-r--r--src/testing.c2
-rw-r--r--src/textformat.c46
-rw-r--r--src/textobject.c2
-rw-r--r--src/textprop.c23
-rw-r--r--src/typval.c10
-rw-r--r--src/undo.c38
-rw-r--r--src/userfunc.c113
-rw-r--r--src/version.c366
-rw-r--r--src/vim.h7
-rw-r--r--src/vim9class.c417
-rw-r--r--src/vim9compile.c12
-rw-r--r--src/vim9expr.c42
-rw-r--r--src/window.c409
-rw-r--r--src/xxd/Makefile2
-rw-r--r--src/xxd/xxd.c44
291 files changed, 13633 insertions, 2974 deletions
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index bc2516c..4db2298 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -374,9 +374,9 @@ DYNAMIC_SODIUM = yes
!if "$(SODIUM)" != "no"
! if "$(CPU)" == "AMD64"
-SOD_LIB = $(SODIUM)\x64\Release\v140\dynamic
+SOD_LIB = $(SODIUM)\x64\Release\v143\dynamic
! elseif "$(CPU)" == "i386"
-SOD_LIB = $(SODIUM)\Win32\Release\v140\dynamic
+SOD_LIB = $(SODIUM)\Win32\Release\v143\dynamic
! else
SODIUM = no
! endif
diff --git a/src/Makefile b/src/Makefile
index 59511d2..33903d3 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2070,7 +2070,7 @@ xxd/xxd$(EXEEXT): xxd/xxd.c
languages:
@if test -n "$(MAKEMO)" -a -f $(PODIR)/Makefile; then \
cd $(PODIR); \
- CC="$(CC)" $(MAKE) prefix=$(DESTDIR)$(prefix); \
+ CC="$(CC)" $(MAKE) prefix=$(DESTDIR)$(prefix) originals; \
fi
-@if test -n "$(MAKEMO)" -a -f $(PODIR)/Makefile; then \
cd $(PODIR); \
diff --git a/src/arglist.c b/src/arglist.c
index d28b31d..187e16e 100644
--- a/src/arglist.c
+++ b/src/arglist.c
@@ -502,7 +502,7 @@ do_arglist(
void
set_arglist(char_u *str)
{
- do_arglist(str, AL_SET, 0, FALSE);
+ do_arglist(str, AL_SET, 0, TRUE);
}
/*
@@ -682,6 +682,7 @@ do_argfile(exarg_T *eap, int argn)
int other;
char_u *p;
int old_arg_idx = curwin->w_arg_idx;
+ int is_split_cmd = *eap->cmd == 's';
if (ERROR_IF_ANY_POPUP_WINDOW)
return;
@@ -697,13 +698,18 @@ do_argfile(exarg_T *eap, int argn)
return;
}
+ if (!is_split_cmd
+ && (&ARGLIST[argn])->ae_fnum != curbuf->b_fnum
+ && !check_can_set_curbuf_forceit(eap->forceit))
+ return;
+
setpcmark();
#ifdef FEAT_GUI
need_mouse_correct = TRUE;
#endif
// split window or create new tab page first
- if (*eap->cmd == 's' || cmdmod.cmod_tab != 0)
+ if (is_split_cmd || cmdmod.cmod_tab != 0)
{
if (win_split(0, 0) == FAIL)
return;
@@ -1253,10 +1259,6 @@ do_arg_all(
// When the ":tab" modifier was used do this for all tab pages.
arg_all_close_unused_windows(&aall);
- // Now set the last used tabpage to where we started.
- if (valid_tabpage(new_lu_tp))
- lastused_tabpage = new_lu_tp;
-
// Open a window for files in the argument list that don't have one.
// ARGCOUNT may change while doing this, because of autocommands.
if (count > aall.opened_len || count <= 0)
@@ -1291,6 +1293,11 @@ do_arg_all(
// to window with first arg
if (valid_tabpage(aall.new_curtab))
goto_tabpage_tp(aall.new_curtab, TRUE, TRUE);
+
+ // Now set the last used tabpage to where we started.
+ if (valid_tabpage(new_lu_tp))
+ lastused_tabpage = new_lu_tp;
+
if (win_valid(aall.new_curwin))
win_enter(aall.new_curwin, FALSE);
diff --git a/src/auto/configure b/src/auto/configure
index 70ebb33..9712104 100755
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -650,6 +650,7 @@ ac_subst_vars='LTLIBOBJS
LIBOBJS
LINK_AS_NEEDED
DEPEND_CFLAGS_FILTER
+MSGFMTCMD
MSGFMT_DESKTOP
MAKEMO
MSGFMT
@@ -6494,10 +6495,11 @@ printf "%s\n" "$vi_cv_perl_xsubpp" >&6; }
fi
- perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+ perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
-e 'ccflags;perl_inc;print"\n"' | sed -e 's/-fno[^ ]*//' \
-e 's/-fdebug-prefix-map[^ ]*//g' \
-e 's/-pipe //' \
+ -e 's/-flto\(=auto\)\? //' \
-e 's/-W[^ ]*//g' \
-e 's/-D_FORTIFY_SOURCE=.//g'`
perllibs=`cd $srcdir; $vi_cv_path_perl -MExtUtils::Embed -e 'ldopts' | \
@@ -10402,9 +10404,12 @@ system ("touch conf.gtktest");
tmp_version = g_strdup("$min_gtk_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_gtk_version");
+ g_free(tmp_version);
exit(1);
}
+g_free(tmp_version);
+
if ((gtk_major_version > major) ||
((gtk_major_version == major) && (gtk_minor_version > minor)) ||
((gtk_major_version == major) && (gtk_minor_version == minor) &&
@@ -15960,6 +15965,18 @@ printf "%s\n" "yes" >&6; }
printf "%s\n" "no" >&6; }
fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if msgfmt supports --no-convert" >&5
+printf %s "checking if msgfmt supports --no-convert... " >&6; }
+ if "$MSGFMT" --help | grep -q -- '--no-convert' >/dev/null; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt --no-convert -v"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt -v"
+ fi
+
fi
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no \"po/Makefile\" - disabled" >&5
diff --git a/src/autocmd.c b/src/autocmd.c
index a78e78b..8e43b34 100644
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -179,6 +179,7 @@ static struct event_name
{"TerminalOpen", EVENT_TERMINALOPEN},
{"TerminalWinOpen", EVENT_TERMINALWINOPEN},
{"TermResponse", EVENT_TERMRESPONSE},
+ {"TermResponseAll", EVENT_TERMRESPONSEALL},
{"TextChanged", EVENT_TEXTCHANGED},
{"TextChangedI", EVENT_TEXTCHANGEDI},
{"TextChangedP", EVENT_TEXTCHANGEDP},
@@ -187,6 +188,7 @@ static struct event_name
{"VimEnter", EVENT_VIMENTER},
{"VimLeave", EVENT_VIMLEAVE},
{"VimLeavePre", EVENT_VIMLEAVEPRE},
+ {"WinNewPre", EVENT_WINNEWPRE},
{"WinNew", EVENT_WINNEW},
{"WinClosed", EVENT_WINCLOSED},
{"WinEnter", EVENT_WINENTER},
@@ -1564,9 +1566,12 @@ aucmd_prepbuf(
}
aco->save_curwin_id = curwin->w_id;
- aco->save_curbuf = curbuf;
aco->save_prevwin_id = prevwin == NULL ? 0 : prevwin->w_id;
aco->save_State = State;
+#ifdef FEAT_JOB_CHANNEL
+ if (bt_prompt(curbuf))
+ aco->save_prompt_insert = curbuf->b_prompt_insert;
+#endif
if (win != NULL)
{
@@ -1602,7 +1607,7 @@ aucmd_prepbuf(
p_acd = FALSE;
#endif
- (void)win_split_ins(0, WSP_TOP, auc_win, 0);
+ (void)win_split_ins(0, WSP_TOP | WSP_FORCE_ROOM, auc_win, 0, NULL);
(void)win_comp_pos(); // recompute window positions
p_ea = save_ea;
#ifdef FEAT_AUTOCHDIR
@@ -1665,7 +1670,7 @@ win_found:
stop_insert_mode = save_stop_insert_mode;
#endif
// Remove the window and frame from the tree of frames.
- (void)winframe_remove(curwin, &dummy, NULL);
+ (void)winframe_remove(curwin, &dummy, NULL, NULL);
win_remove(curwin, NULL);
// The window is marked as not used, but it is not freed, it can be
@@ -1691,6 +1696,8 @@ win_found:
#ifdef FEAT_JOB_CHANNEL
// May need to restore insert mode for a prompt buffer.
entering_window(curwin);
+ if (bt_prompt(curbuf))
+ curbuf->b_prompt_insert = aco->save_prompt_insert;
#endif
prevwin = win_find_by_id(aco->save_prevwin_id);
#ifdef FEAT_EVAL
@@ -2100,7 +2107,8 @@ apply_autocmds_group(
{
if (event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE
|| event == EVENT_OPTIONSET
- || event == EVENT_MODECHANGED)
+ || event == EVENT_MODECHANGED
+ || event == EVENT_TERMRESPONSEALL)
autocmd_fname = NULL;
else if (fname != NULL && !ends_excmd(*fname))
autocmd_fname = fname;
@@ -2180,7 +2188,8 @@ apply_autocmds_group(
|| event == EVENT_USER
|| event == EVENT_WINCLOSED
|| event == EVENT_WINRESIZED
- || event == EVENT_WINSCROLLED)
+ || event == EVENT_WINSCROLLED
+ || event == EVENT_TERMRESPONSEALL)
{
fname = vim_strsave(fname);
autocmd_fname_full = TRUE; // don't expand it later
@@ -2418,6 +2427,11 @@ BYPASS_AU:
# ifdef FEAT_EVAL
static char_u *old_termresponse = NULL;
+static char_u *old_termu7resp = NULL;
+static char_u *old_termblinkresp = NULL;
+static char_u *old_termrbgresp = NULL;
+static char_u *old_termrfgresp = NULL;
+static char_u *old_termstyleresp = NULL;
# endif
/*
@@ -2430,7 +2444,14 @@ block_autocmds(void)
# ifdef FEAT_EVAL
// Remember the value of v:termresponse.
if (autocmd_blocked == 0)
+ {
old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
+ old_termu7resp = get_vim_var_str(VV_TERMU7RESP);
+ old_termblinkresp = get_vim_var_str(VV_TERMBLINKRESP);
+ old_termrbgresp = get_vim_var_str(VV_TERMRBGRESP);
+ old_termrfgresp = get_vim_var_str(VV_TERMRFGRESP);
+ old_termstyleresp = get_vim_var_str(VV_TERMSTYLERESP);
+ }
# endif
++autocmd_blocked;
}
@@ -2441,12 +2462,37 @@ unblock_autocmds(void)
--autocmd_blocked;
# ifdef FEAT_EVAL
- // When v:termresponse was set while autocommands were blocked, trigger
- // the autocommands now. Esp. useful when executing a shell command
- // during startup (vimdiff).
- if (autocmd_blocked == 0
- && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
- apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
+ // When v:termresponse, etc, were set while autocommands were blocked,
+ // trigger the autocommands now. Esp. useful when executing a shell
+ // command during startup (vimdiff).
+ if (autocmd_blocked == 0)
+ {
+ if (get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
+ {
+ apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
+ apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"version", NULL, FALSE, curbuf);
+ }
+ if (get_vim_var_str(VV_TERMU7RESP) != old_termu7resp)
+ {
+ apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"ambiguouswidth", NULL, FALSE, curbuf);
+ }
+ if (get_vim_var_str(VV_TERMBLINKRESP) != old_termblinkresp)
+ {
+ apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"cursorblink", NULL, FALSE, curbuf);
+ }
+ if (get_vim_var_str(VV_TERMRBGRESP) != old_termrbgresp)
+ {
+ apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"background", NULL, FALSE, curbuf);
+ }
+ if (get_vim_var_str(VV_TERMRFGRESP) != old_termrfgresp)
+ {
+ apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"foreground", NULL, FALSE, curbuf);
+ }
+ if (get_vim_var_str(VV_TERMSTYLERESP) != old_termstyleresp)
+ {
+ apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"cursorshape", NULL, FALSE, curbuf);
+ }
+ }
# endif
}
diff --git a/src/blob.c b/src/blob.c
index c5d7eae..9cdd504 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -641,25 +641,28 @@ blob_filter_map(
if (filter_map_one(&tv, expr, filtermap, fc, &newtv, &rem) == FAIL
|| did_emsg)
break;
- if (newtv.v_type != VAR_NUMBER && newtv.v_type != VAR_BOOL)
+ if (filtermap != FILTERMAP_FOREACH)
{
- clear_tv(&newtv);
- emsg(_(e_invalid_operation_for_blob));
- break;
- }
- if (filtermap != FILTERMAP_FILTER)
- {
- if (newtv.vval.v_number != val)
- blob_set(b_ret, i, newtv.vval.v_number);
- }
- else if (rem)
- {
- char_u *p = (char_u *)blob_arg->bv_ga.ga_data;
+ if (newtv.v_type != VAR_NUMBER && newtv.v_type != VAR_BOOL)
+ {
+ clear_tv(&newtv);
+ emsg(_(e_invalid_operation_for_blob));
+ break;
+ }
+ if (filtermap != FILTERMAP_FILTER)
+ {
+ if (newtv.vval.v_number != val)
+ blob_set(b_ret, i, newtv.vval.v_number);
+ }
+ else if (rem)
+ {
+ char_u *p = (char_u *)blob_arg->bv_ga.ga_data;
- mch_memmove(p + i, p + i + 1,
- (size_t)b->bv_ga.ga_len - i - 1);
- --b->bv_ga.ga_len;
- --i;
+ mch_memmove(p + i, p + i + 1,
+ (size_t)b->bv_ga.ga_len - i - 1);
+ --b->bv_ga.ga_len;
+ --i;
+ }
}
++idx;
}
diff --git a/src/buffer.c b/src/buffer.c
index 64e4926..243593a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -919,10 +919,9 @@ buf_freeall(buf_T *buf, int flags)
ml_close(buf, TRUE); // close and delete the memline/memfile
buf->b_ml.ml_line_count = 0; // no lines in buffer
if ((flags & BFA_KEEP_UNDO) == 0)
- {
- u_blockfree(buf); // free the memory allocated for undo
- u_clearall(buf); // reset all undo information
- }
+ // free the memory allocated for undo
+ // and reset all undo information
+ u_clearallandblockfree(buf);
#ifdef FEAT_SYN_HL
syntax_clear(&buf->b_s); // reset syntax info
#endif
@@ -1371,6 +1370,13 @@ do_buffer_ext(
if ((flags & DOBUF_NOPOPUP) && bt_popup(buf) && !bt_terminal(buf))
return OK;
#endif
+ if (
+ action == DOBUF_GOTO
+ && buf != curbuf
+ && !check_can_set_curbuf_forceit((flags & DOBUF_FORCEIT) ? TRUE : FALSE))
+ // disallow navigating to another buffer when 'winfixbuf' is applied
+ return FAIL;
+
if ((action == DOBUF_GOTO || action == DOBUF_SPLIT)
&& (buf->b_flags & BF_DUMMY))
{
@@ -1791,6 +1797,7 @@ set_curbuf(buf_T *buf, int action)
bufref_T newbufref;
bufref_T prevbufref;
int valid;
+ int last_winid = get_last_winid();
setpcmark();
if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0)
@@ -1819,7 +1826,11 @@ set_curbuf(buf_T *buf, int action)
if (prevbuf == curwin->w_buffer)
reset_synblock(curwin);
#endif
- if (unload)
+ // autocommands may have opened a new window
+ // with prevbuf, grr
+ if (unload ||
+ (last_winid != get_last_winid() &&
+ strchr((char *)"wdu", prevbuf->b_p_bh[0]) != NULL))
close_windows(prevbuf, FALSE);
#if defined(FEAT_EVAL)
if (bufref_valid(&prevbufref) && !aborting())
@@ -1855,6 +1866,10 @@ set_curbuf(buf_T *buf, int action)
#endif
) || curwin->w_buffer == NULL)
{
+ // autocommands changed curbuf and we will move to another
+ // buffer soon, so decrement curbuf->b_nwindows
+ if (curbuf != NULL && prevbuf != curbuf)
+ curbuf->b_nwindows--;
// If the buffer is not valid but curwin->w_buffer is NULL we must
// enter some buffer. Using the last one is hopefully OK.
if (!valid)
@@ -2773,17 +2788,19 @@ ExpandBufnames(
char_u ***file,
int options)
{
- int count = 0;
+ int count;
buf_T *buf;
int round;
char_u *p;
- int attempt;
char_u *patc = NULL;
#ifdef FEAT_VIMINFO
bufmatch_T *matches = NULL;
#endif
int fuzzy;
fuzmatch_str_T *fuzmatch = NULL;
+ regmatch_T regmatch;
+ int score = 0;
+ int to_free = FALSE;
*num_file = 0; // return values in case of FAIL
*file = NULL;
@@ -2799,151 +2816,138 @@ ExpandBufnames(
// expression matching)
if (!fuzzy)
{
- if (*pat == '^')
+ if (*pat == '^' && pat[1] != NUL)
{
- patc = alloc(STRLEN(pat) + 11);
+ int len = (int)STRLEN(pat);
+ patc = alloc(len);
if (patc == NULL)
return FAIL;
- STRCPY(patc, "\\(^\\|[\\/]\\)");
- STRCPY(patc + 11, pat + 1);
+ STRNCPY(patc, pat + 1, len - 1);
+ patc[len - 1] = NUL;
+ to_free = TRUE;
}
+ else if (*pat == '^')
+ patc = (char_u *)"";
else
patc = pat;
+ regmatch.regprog = vim_regcomp(patc, RE_MAGIC);
}
- // attempt == 0: try match with '\<', match at start of word
- // attempt == 1: try match without '\<', match anywhere
- for (attempt = 0; attempt <= (fuzzy ? 0 : 1); ++attempt)
+ // round == 1: Count the matches.
+ // round == 2: Build the array to keep the matches.
+ for (round = 1; round <= 2; ++round)
{
- regmatch_T regmatch;
- int score = 0;
-
- if (!fuzzy)
- {
- if (attempt > 0 && patc == pat)
- break; // there was no anchor, no need to try again
- regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
- }
-
- // round == 1: Count the matches.
- // round == 2: Build the array to keep the matches.
- for (round = 1; round <= 2; ++round)
+ count = 0;
+ FOR_ALL_BUFFERS(buf)
{
- count = 0;
- FOR_ALL_BUFFERS(buf)
- {
- if (!buf->b_p_bl) // skip unlisted buffers
- continue;
+ if (!buf->b_p_bl) // skip unlisted buffers
+ continue;
#ifdef FEAT_DIFF
- if (options & BUF_DIFF_FILTER)
- // Skip buffers not suitable for
- // :diffget or :diffput completion.
- if (buf == curbuf || !diff_mode_buf(buf))
- continue;
+ if (options & BUF_DIFF_FILTER)
+ // Skip buffers not suitable for
+ // :diffget or :diffput completion.
+ if (buf == curbuf || !diff_mode_buf(buf))
+ continue;
#endif
- if (!fuzzy)
+ if (!fuzzy)
+ {
+ if (regmatch.regprog == NULL)
{
- if (regmatch.regprog == NULL)
- {
- // invalid pattern, possibly after recompiling
- if (patc != pat)
- vim_free(patc);
- return FAIL;
- }
- p = buflist_match(&regmatch, buf, p_wic);
+ // invalid pattern, possibly after recompiling
+ if (to_free)
+ vim_free(patc);
+ return FAIL;
}
- else
+ p = buflist_match(&regmatch, buf, p_wic);
+ }
+ else
+ {
+ p = NULL;
+ // first try matching with the short file name
+ if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0)
+ p = buf->b_sfname;
+ if (p == NULL)
{
- p = NULL;
- // first try matching with the short file name
- if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0)
- p = buf->b_sfname;
- if (p == NULL)
- {
- // next try matching with the full path file name
- if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0)
- p = buf->b_ffname;
- }
+ // next try matching with the full path file name
+ if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0)
+ p = buf->b_ffname;
}
+ }
- if (p == NULL)
- continue;
+ if (p == NULL)
+ continue;
- if (round == 1)
- {
- ++count;
- continue;
- }
+ if (round == 1)
+ {
+ ++count;
+ continue;
+ }
- if (options & WILD_HOME_REPLACE)
- p = home_replace_save(buf, p);
- else
- p = vim_strsave(p);
+ if (options & WILD_HOME_REPLACE)
+ p = home_replace_save(buf, p);
+ else
+ p = vim_strsave(p);
- if (!fuzzy)
- {
+ if (!fuzzy)
+ {
#ifdef FEAT_VIMINFO
- if (matches != NULL)
- {
- matches[count].buf = buf;
- matches[count].match = p;
- count++;
- }
- else
-#endif
- (*file)[count++] = p;
- }
- else
+ if (matches != NULL)
{
- fuzmatch[count].idx = count;
- fuzmatch[count].str = p;
- fuzmatch[count].score = score;
+ matches[count].buf = buf;
+ matches[count].match = p;
count++;
}
+ else
+#endif
+ (*file)[count++] = p;
}
- if (count == 0) // no match found, break here
- break;
- if (round == 1)
+ else
+ {
+ fuzmatch[count].idx = count;
+ fuzmatch[count].str = p;
+ fuzmatch[count].score = score;
+ count++;
+ }
+ }
+ if (count == 0) // no match found, break here
+ break;
+ if (round == 1)
+ {
+ if (!fuzzy)
{
- if (!fuzzy)
+ *file = ALLOC_MULT(char_u *, count);
+ if (*file == NULL)
{
- *file = ALLOC_MULT(char_u *, count);
- if (*file == NULL)
- {
- vim_regfree(regmatch.regprog);
- if (patc != pat)
- vim_free(patc);
- return FAIL;
- }
+ vim_regfree(regmatch.regprog);
+ if (to_free)
+ vim_free(patc);
+ return FAIL;
+ }
#ifdef FEAT_VIMINFO
- if (options & WILD_BUFLASTUSED)
- matches = ALLOC_MULT(bufmatch_T, count);
+ if (options & WILD_BUFLASTUSED)
+ matches = ALLOC_MULT(bufmatch_T, count);
#endif
- }
- else
+ }
+ else
+ {
+ fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
+ if (fuzmatch == NULL)
{
- fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
- if (fuzmatch == NULL)
- {
- *num_file = 0;
- *file = NULL;
- return FAIL;
- }
+ *num_file = 0;
+ *file = NULL;
+ return FAIL;
}
}
}
-
- if (!fuzzy)
- {
- vim_regfree(regmatch.regprog);
- if (count) // match(es) found, break here
- break;
- }
}
- if (!fuzzy && patc != pat)
- vim_free(patc);
+ if (!fuzzy)
+ {
+ vim_regfree(regmatch.regprog);
+ if (to_free)
+ vim_free(patc);
+ }
#ifdef FEAT_VIMINFO
if (!fuzzy)
@@ -4217,7 +4221,7 @@ build_stl_str_hl(
stl_hlrec_T **tabtab) // return: tab page nrs (can be NULL)
{
linenr_T lnum;
- size_t len;
+ colnr_T len;
char_u *p;
char_u *s;
char_u *t;
@@ -4324,12 +4328,12 @@ build_stl_str_hl(
// Get the byte value now, in case we need it below. This is more efficient
// than making a copy of the line.
- len = STRLEN(p);
- if (wp->w_cursor.col > (colnr_T)len)
+ len = ml_get_buf_len(wp->w_buffer, lnum);
+ if (wp->w_cursor.col > len)
{
// Line may have changed since checking the cursor column, or the lnum
// was adjusted above.
- wp->w_cursor.col = (colnr_T)len;
+ wp->w_cursor.col = len;
wp->w_cursor.coladd = 0;
byteval = 0;
}
@@ -5936,6 +5940,8 @@ buf_spname(buf_T *buf)
#endif
if (buf->b_fname != NULL)
return buf->b_fname;
+ if (buf == cmdwin_buf)
+ return (char_u *)_("[Command Line]");
#ifdef FEAT_JOB_CHANNEL
if (bt_prompt(buf))
return (char_u *)_("[Prompt]");
diff --git a/src/change.c b/src/change.c
index c0b8785..daf4fae 100644
--- a/src/change.c
+++ b/src/change.c
@@ -559,6 +559,12 @@ changed_common(
if (!redraw_not_allowed && wp->w_redr_type < UPD_VALID)
wp->w_redr_type = UPD_VALID;
+ // When inserting/deleting lines and the window has specific lines
+ // to be redrawn, w_redraw_top and w_redraw_bot may now be invalid,
+ // so just redraw everything.
+ if (xtra != 0 && wp->w_redraw_top != 0)
+ redraw_win_later(wp, UPD_NOT_VALID);
+
// Reset "w_skipcol" if the topline length has become smaller to
// such a degree that nothing will be visible anymore, accounting
// for 'smoothscroll' <<< or 'listchars' "precedes" marker.
@@ -656,22 +662,20 @@ changed_common(
set_topline(wp, wp->w_topline);
#endif
// If lines have been added or removed, relative numbering always
- // requires a redraw.
+ // requires an update even if cursor didn't move.
if (wp->w_p_rnu && xtra != 0)
- {
wp->w_last_cursor_lnum_rnu = 0;
- redraw_win_later(wp, UPD_VALID);
- }
+
#ifdef FEAT_SYN_HL
- // Cursor line highlighting probably need to be updated with
- // "UPD_VALID" if it's below the change.
- // If the cursor line is inside the change we need to redraw more.
- if (wp->w_p_cul)
+ if (wp->w_p_cul && wp->w_last_cursorline >= lnum)
{
- if (xtra == 0)
- redraw_win_later(wp, UPD_VALID);
- else if (lnum <= wp->w_last_cursorline)
- redraw_win_later(wp, UPD_SOME_VALID);
+ if (wp->w_last_cursorline < lnume)
+ // If 'cursorline' was inside the change, it has already
+ // been invalidated in w_lines[] by the loop above.
+ wp->w_last_cursorline = 0;
+ else
+ // If 'cursorline' was below the change, adjust its lnum.
+ wp->w_last_cursorline += xtra;
}
#endif
}
@@ -1052,7 +1056,7 @@ ins_char_bytes(char_u *buf, int charlen)
col = curwin->w_cursor.col;
oldp = ml_get(lnum);
- linelen = (int)STRLEN(oldp) + 1;
+ linelen = (int)ml_get_len(lnum) + 1;
// The lengths default to the values for when not replacing.
oldlen = 0;
@@ -1189,7 +1193,7 @@ ins_str(char_u *s)
col = curwin->w_cursor.col;
oldp = ml_get(lnum);
- oldlen = (int)STRLEN(oldp);
+ oldlen = (int)ml_get_len(lnum);
newp = alloc(oldlen + newlen + 1);
if (newp == NULL)
@@ -1268,7 +1272,7 @@ del_bytes(
int fixpos = fixpos_arg;
oldp = ml_get(lnum);
- oldlen = (int)STRLEN(oldp);
+ oldlen = (int)ml_get_len(lnum);
// Can't do anything when the cursor is on the NUL after the line.
if (col >= oldlen)
@@ -1360,6 +1364,7 @@ del_bytes(
mch_memmove(newp + newlen + 1, oldp + oldlen + 1,
(size_t)curbuf->b_ml.ml_line_len - oldlen - 1);
curbuf->b_ml.ml_line_len -= count;
+ curbuf->b_ml.ml_line_textlen = 0;
}
#endif
@@ -1431,12 +1436,12 @@ open_line(
#endif
// make a copy of the current line so we can mess with it
- saved_line = vim_strsave(ml_get_curline());
+ saved_line = vim_strnsave(ml_get_curline(), ml_get_curline_len());
if (saved_line == NULL) // out of memory!
return FALSE;
#ifdef FEAT_PROP_POPUP
- at_eol = curwin->w_cursor.col >= (int)STRLEN(saved_line);
+ at_eol = curwin->w_cursor.col >= (int)ml_get_curline_len();
#endif
if (State & VREPLACE_FLAG)
@@ -1449,7 +1454,7 @@ open_line(
// the line, replacing what was there before and pushing the right
// stuff onto the replace stack. -- webb.
if (curwin->w_cursor.lnum < orig_line_count)
- next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1));
+ next_line = vim_strnsave(ml_get(curwin->w_cursor.lnum + 1), ml_get_len(curwin->w_cursor.lnum + 1));
else
next_line = vim_strsave((char_u *)"");
if (next_line == NULL) // out of memory!
@@ -2302,7 +2307,7 @@ open_line(
if (State & VREPLACE_FLAG)
{
// Put new line in p_extra
- p_extra = vim_strsave(ml_get_curline());
+ p_extra = vim_strnsave(ml_get_curline(), ml_get_curline_len());
if (p_extra == NULL)
goto theend;
@@ -2347,7 +2352,7 @@ truncate_line(int fixpos)
newp = vim_strsave((char_u *)"");
else
newp = vim_strnsave(old_line, col);
- deleted = (int)STRLEN(old_line) - col;
+ deleted = (int)ml_get_len(lnum) - col;
if (newp == NULL)
return FAIL;
diff --git a/src/channel.c b/src/channel.c
index 8d850c6..b99b3a9 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1493,7 +1493,7 @@ channel_set_req_callback(
write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel)
{
char_u *line = ml_get_buf(buf, lnum, FALSE);
- int len = (int)STRLEN(line);
+ int len = ml_get_buf_len(buf, lnum);
char_u *p;
int i;
diff --git a/src/charset.c b/src/charset.c
index 0e4dbbe..5ae90da 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -971,6 +971,9 @@ init_chartabsize_arg(
cts->cts_vcol = col;
cts->cts_line = line;
cts->cts_ptr = ptr;
+#ifdef FEAT_LINEBREAK
+ cts->cts_bri_size = -1;
+#endif
#ifdef FEAT_PROP_POPUP
if (lnum > 0 && !ignore_text_props)
{
@@ -1123,7 +1126,6 @@ win_lbr_chartabsize(
int n;
char_u *sbr;
int no_sbr = FALSE;
- colnr_T vcol_start = 0; // start from where to consider linebreak
#endif
#if defined(FEAT_PROP_POPUP)
@@ -1158,8 +1160,12 @@ win_lbr_chartabsize(
* First get the normal size, without 'linebreak' or text properties
*/
size = win_chartabsize(wp, s, vcol);
- if (*s == NUL && !has_lcs_eol)
- size = 0; // NUL is not displayed
+ if (*s == NUL)
+ {
+ // 1 cell for EOL list char (if present), as opposed to the two cell ^@
+ // for a NUL character in the text.
+ size = has_lcs_eol ? 1 : 0;
+ }
# ifdef FEAT_LINEBREAK
int is_doublewidth = has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1;
# endif
@@ -1282,7 +1288,11 @@ win_lbr_chartabsize(
if (*sbr != NUL)
head_prev += vim_strsize(sbr);
if (wp->w_p_bri)
- head_prev += get_breakindent_win(wp, line);
+ {
+ if (cts->cts_bri_size < 0)
+ cts->cts_bri_size = get_breakindent_win(wp, line);
+ head_prev += cts->cts_bri_size;
+ }
if (wcol < head_prev)
{
head_prev -= wcol;
@@ -1303,7 +1313,11 @@ win_lbr_chartabsize(
if (*sbr != NUL)
head_mid += vim_strsize(sbr);
if (wp->w_p_bri)
- head_mid += get_breakindent_win(wp, line);
+ {
+ if (cts->cts_bri_size < 0)
+ cts->cts_bri_size = get_breakindent_win(wp, line);
+ head_mid += cts->cts_bri_size;
+ }
if (head_mid > 0 && wcol + size > wp->w_width)
{
// Calculate effective window width.
@@ -1341,22 +1355,21 @@ win_lbr_chartabsize(
if (headp != NULL)
*headp = head;
+ int need_lbr = FALSE;
/*
* If 'linebreak' set check at a blank before a non-blank if the line
- * needs a break here
+ * needs a break here.
*/
- if (wp->w_p_lbr && wp->w_p_wrap && wp->w_width != 0)
+ if (wp->w_p_lbr && wp->w_p_wrap && wp->w_width != 0
+ && VIM_ISBREAK((int)s[0]) && !VIM_ISBREAK((int)s[1]))
{
char_u *t = cts->cts_line;
while (VIM_ISBREAK((int)t[0]))
t++;
- vcol_start = t - cts->cts_line;
+ // 'linebreak' is only needed when not in leading whitespace.
+ need_lbr = s >= t;
}
- if (wp->w_p_lbr && vcol_start <= vcol
- && VIM_ISBREAK((int)s[0])
- && !VIM_ISBREAK((int)s[1])
- && wp->w_p_wrap
- && wp->w_width != 0)
+ if (need_lbr)
{
/*
* Count all characters from first non-blank after a blank up to next
@@ -1482,7 +1495,6 @@ getvcol(
{
colnr_T vcol;
char_u *ptr; // points to current char
- char_u *posptr; // points to char at pos->col
char_u *line; // start of the line
int incr;
int head;
@@ -1498,24 +1510,6 @@ getvcol(
vcol = 0;
line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
- if (pos->col == MAXCOL)
- posptr = NULL; // continue until the NUL
- else
- {
- colnr_T i;
-
- // In a few cases the position can be beyond the end of the line.
- for (i = 0; i < pos->col; ++i)
- if (ptr[i] == NUL)
- {
- pos->col = i;
- break;
- }
- posptr = ptr + pos->col;
- if (has_mbyte)
- // always start on the first byte
- posptr -= (*mb_head_off)(line, posptr);
- }
init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
cts.cts_max_head_vcol = -1;
@@ -1577,11 +1571,12 @@ getvcol(
incr = g_chartab[c] & CT_CELL_MASK;
}
- if (posptr != NULL && ptr >= posptr) // character at pos->col
+ char_u *next_ptr = ptr + (*mb_ptr2len)(ptr);
+ if (next_ptr - line > pos->col) // character at pos->col
break;
vcol += incr;
- MB_PTR_ADV(ptr);
+ ptr = next_ptr;
}
}
else
@@ -1609,12 +1604,12 @@ getvcol(
wp->w_virtcol_first_char = cts.cts_first_char;
#endif
- if (posptr != NULL && cts.cts_ptr >= posptr)
- // character at pos->col
+ char_u *next_ptr = cts.cts_ptr + (*mb_ptr2len)(cts.cts_ptr);
+ if (next_ptr - line > pos->col) // character at pos->col
break;
cts.cts_vcol += incr;
- MB_PTR_ADV(cts.cts_ptr);
+ cts.cts_ptr = next_ptr;
}
vcol = cts.cts_vcol;
ptr = cts.cts_ptr;
@@ -1695,7 +1690,7 @@ getvvcol(
endadd = 0;
// Cannot put the cursor on part of a wide character.
ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
- if (pos->col < (colnr_T)STRLEN(ptr))
+ if (pos->col < ml_get_buf_len(wp->w_buffer, pos->lnum))
{
int c = (*mb_ptr2char)(ptr + pos->col);
diff --git a/src/cindent.c b/src/cindent.c
index 6289422..cf18441 100644
--- a/src/cindent.c
+++ b/src/cindent.c
@@ -4108,7 +4108,8 @@ in_cinkeys(
}
else
// TODO: multi-byte
- if (keytyped == (int)p[-1] || (icase && keytyped < 256
+ if (keytyped == (int)p[-1] || (icase
+ && keytyped < 256 && keytyped >= 0
&& TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1])))
{
line = ml_get_cursor();
diff --git a/src/clientserver.c b/src/clientserver.c
index cfc0ab6..340add3 100644
--- a/src/clientserver.c
+++ b/src/clientserver.c
@@ -566,6 +566,10 @@ build_drop_cmd(
char_u *p;
char_u *cdp;
char_u *cwd;
+ // reset wildignore temporarily
+ const char *wig[] =
+ { "<CR><C-\\><C-N>:let g:_wig=&wig|set wig=",
+ "<C-\\><C-N>:let &wig=g:_wig|unlet g:_wig<CR>"};
if (filec > 0 && filev[0][0] == '+')
{
@@ -599,6 +603,8 @@ build_drop_cmd(
ga_init2(&ga, 1, 100);
ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd ");
ga_concat(&ga, cdp);
+ // reset wildignorecase temporarily
+ ga_concat(&ga, (char_u *)wig[0]);
// Call inputsave() so that a prompt for an encryption key works.
ga_concat(&ga, (char_u *)
@@ -650,6 +656,8 @@ build_drop_cmd(
ga_concat(&ga, cdp);
ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>");
vim_free(cdp);
+ // reset wildignorecase
+ ga_concat(&ga, (char_u *)wig[1]);
if (sendReply)
ga_concat(&ga, (char_u *)":call SetupRemoteReplies()<CR>");
diff --git a/src/clipboard.c b/src/clipboard.c
index d80699b..8b9850e 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -1334,7 +1334,8 @@ did_set_clipboard(optset_T *args UNUSED)
#ifdef FEAT_GUI_GTK
if (gui.in_use)
{
- gui_gtk_set_selection_targets();
+ gui_gtk_set_selection_targets((GdkAtom)GDK_SELECTION_PRIMARY);
+ gui_gtk_set_selection_targets((GdkAtom)clip_plus.gtk_sel_atom);
gui_gtk_set_dnd_targets();
}
#endif
diff --git a/src/config.mk.in b/src/config.mk.in
index 4eb6928..2aaaf69 100644
--- a/src/config.mk.in
+++ b/src/config.mk.in
@@ -175,6 +175,7 @@ OS_EXTRA_OBJ = @OS_EXTRA_OBJ@
MAKEMO = @MAKEMO@
MSGFMT = @MSGFMT@
+MSGFMTCMD = @MSGFMTCMD@
MSGFMT_DESKTOP = @MSGFMT_DESKTOP@
### set if $SOURCE_DATE_EPOCH was set when running configure
diff --git a/src/configure.ac b/src/configure.ac
index ebe0d08..6311269 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1163,11 +1163,13 @@ if test "$enable_perlinterp" = "yes" -o "$enable_perlinterp" = "dynamic"; then
dnl Remove "-fno-something", it breaks using cproto.
dnl Remove "-fdebug-prefix-map", it isn't supported by clang.
dnl Remove "FORTIFY_SOURCE", it will be defined twice.
- dnl remove -pipe and -Wxxx, it confuses cproto
+ dnl Remove -pipe and -Wxxx, it confuses cproto
+ dnl Remove -flto[=auto], it causes link failures for clang
perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
-e 'ccflags;perl_inc;print"\n"' | sed -e 's/-fno[[^ ]]*//' \
-e 's/-fdebug-prefix-map[[^ ]]*//g' \
-e 's/-pipe //' \
+ -e 's/-flto\(=auto\)\? //' \
-e 's/-W[[^ ]]*//g' \
-e 's/-D_FORTIFY_SOURCE=.//g'`
dnl Remove "-lc", it breaks on FreeBSD when using "-pthread".
@@ -4521,6 +4523,15 @@ if test "$enable_nls" = "yes"; then
AC_MSG_RESULT([no])
fi
AC_SUBST(MSGFMT_DESKTOP)
+ AC_MSG_CHECKING([if msgfmt supports --no-convert])
+ if "$MSGFMT" --help | grep -q -- '--no-convert' >/dev/null; then
+ AC_MSG_RESULT([yes])
+ MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt --no-convert -v"
+ else
+ AC_MSG_RESULT([no])
+ MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt -v"
+ fi
+ AC_SUBST(MSGFMTCMD)
fi
else
AC_MSG_RESULT([no "po/Makefile" - disabled]);
diff --git a/src/dict.c b/src/dict.c
index cb22b42..508d00c 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -1329,8 +1329,8 @@ dict_extend_func(
}
/*
- * Implementation of map() and filter() for a Dict. Apply "expr" to every
- * item in Dict "d" and return the result in "rettv".
+ * Implementation of map(), filter(), foreach() for a Dict. Apply "expr" to
+ * every item in Dict "d" and return the result in "rettv".
*/
void
dict_filter_map(
@@ -1392,7 +1392,6 @@ dict_filter_map(
arg_errmsg, TRUE)))
break;
set_vim_var_string(VV_KEY, di->di_key, -1);
- newtv.v_type = VAR_UNKNOWN;
r = filter_map_one(&di->di_tv, expr, filtermap, fc, &newtv, &rem);
clear_tv(get_vim_var_tv(VV_KEY));
if (r == FAIL || did_emsg)
diff --git a/src/diff.c b/src/diff.c
index 9b8c816..c50670c 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -72,12 +72,19 @@ typedef struct {
long count_new;
} diffhunk_T;
+typedef enum {
+ DIO_OUTPUT_INDICES = 0, // default
+ DIO_OUTPUT_UNIFIED = 1 // unified diff format
+} dio_outfmt_T;
+
// two diff inputs and one result
typedef struct {
- diffin_T dio_orig; // original file input
- diffin_T dio_new; // new file input
- diffout_T dio_diff; // diff result
- int dio_internal; // using internal diff
+ diffin_T dio_orig; // original file input
+ diffin_T dio_new; // new file input
+ diffout_T dio_diff; // diff result
+ int dio_internal; // using internal diff
+ dio_outfmt_T dio_outfmt; // internal diff output format
+ int dio_ctxlen; // unified diff context length
} diffio_T;
static int diff_buf_idx(buf_T *buf);
@@ -97,7 +104,8 @@ static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new
static diff_T *diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp);
static int parse_diff_ed(char_u *line, diffhunk_T *hunk);
static int parse_diff_unified(char_u *line, diffhunk_T *hunk);
-static int xdiff_out(long start_a, long count_a, long start_b, long count_b, void *priv);
+static int xdiff_out_indices(long start_a, long count_a, long start_b, long count_b, void *priv);
+static int xdiff_out_unified(void *priv, mmbuffer_t *mb, int nbuf);
#define FOR_ALL_DIFFBLOCKS_IN_TAB(tp, dp) \
for ((dp) = (tp)->tp_first_diff; (dp) != NULL; (dp) = (dp)->df_next)
@@ -754,7 +762,7 @@ diff_write_buffer(buf_T *buf, diffin_T *din)
// xdiff requires one big block of memory with all the text.
for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
- len += (long)STRLEN(ml_get_buf(buf, lnum, FALSE)) + 1;
+ len += ml_get_buf_len(buf, lnum) + 1;
ptr = alloc(len);
if (ptr == NULL)
{
@@ -1140,9 +1148,12 @@ diff_file_internal(diffio_T *diffio)
if (diff_flags & DIFF_IBLANK)
param.flags |= XDF_IGNORE_BLANK_LINES;
- emit_cfg.ctxlen = 0; // don't need any diff_context here
+ emit_cfg.ctxlen = diffio->dio_ctxlen;
emit_cb.priv = &diffio->dio_diff;
- emit_cfg.hunk_func = xdiff_out;
+ if (diffio->dio_outfmt == DIO_OUTPUT_INDICES)
+ emit_cfg.hunk_func = xdiff_out_indices;
+ else
+ emit_cb.out_line = xdiff_out_unified;
if (xdl_diff(&diffio->dio_orig.din_mmfile,
&diffio->dio_new.din_mmfile,
&param, &emit_cfg, &emit_cb) < 0)
@@ -1509,6 +1520,7 @@ diff_win_options(
if (!wp->w_p_diff)
wp->w_p_wrap_save = wp->w_p_wrap;
wp->w_p_wrap = FALSE;
+ wp->w_skipcol = 0;
}
# ifdef FEAT_FOLDING
if (!wp->w_p_diff)
@@ -1572,8 +1584,11 @@ ex_diffoff(exarg_T *eap)
wp->w_p_crb = wp->w_p_crb_save;
if (!(diff_flags & DIFF_FOLLOWWRAP))
{
- if (!wp->w_p_wrap)
- wp->w_p_wrap = wp->w_p_wrap_save;
+ if (!wp->w_p_wrap && wp->w_p_wrap_save)
+ {
+ wp->w_p_wrap = TRUE;
+ wp->w_leftcol = 0;
+ }
}
#ifdef FEAT_FOLDING
free_string_option(wp->w_p_fdm);
@@ -3327,10 +3342,10 @@ parse_diff_unified(
/*
* Callback function for the xdl_diff() function.
- * Stores the diff output in a grow array.
+ * Stores the diff output (indices) in a grow array.
*/
static int
-xdiff_out(
+xdiff_out_indices(
long start_a,
long count_a,
long start_b,
@@ -3357,6 +3372,25 @@ xdiff_out(
return 0;
}
+/*
+ * Callback function for the xdl_diff() function.
+ * Stores the unified diff output in a grow array.
+ */
+ static int
+xdiff_out_unified(
+ void *priv,
+ mmbuffer_t *mb,
+ int nbuf)
+{
+ diffout_T *dout = (diffout_T *)priv;
+ int i;
+
+ for (i = 0; i < nbuf; i++)
+ ga_concat_len(&dout->dout_ga, (char_u *)mb[i].ptr, mb[i].size);
+
+ return 0;
+}
+
#endif // FEAT_DIFF
#if defined(FEAT_EVAL) || defined(PROTO)
@@ -3367,12 +3401,12 @@ xdiff_out(
void
f_diff_filler(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
-#ifdef FEAT_DIFF
+# ifdef FEAT_DIFF
if (in_vim9script() && check_for_lnum_arg(argvars, 0) == FAIL)
return;
rettv->vval.v_number = diff_check_fill(curwin, tv_get_lnum(argvars));
-#endif
+# endif
}
/*
@@ -3381,7 +3415,7 @@ f_diff_filler(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
void
f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
-#ifdef FEAT_DIFF
+# ifdef FEAT_DIFF
linenr_T lnum;
static linenr_T prev_lnum = 0;
static varnumber_T changedtick = 0;
@@ -3436,7 +3470,224 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
hlID = HLF_CHD; // changed line
}
rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
-#endif
+# endif
+}
+
+# ifdef FEAT_DIFF
+/*
+ * Parse the diff options passed in "optarg" to the diff() function and return
+ * the options in "diffopts" and the diff algorithm in "diffalgo".
+ */
+ static int
+parse_diff_optarg(
+ typval_T *opts,
+ int *diffopts,
+ long *diffalgo,
+ dio_outfmt_T *diff_output_fmt,
+ int *diff_ctxlen)
+{
+ dict_T *d = opts->vval.v_dict;
+
+ char_u *algo = dict_get_string(d, "algorithm", FALSE);
+ if (algo != NULL)
+ {
+ if (STRNCMP(algo, "myers", 5) == 0)
+ *diffalgo = 0;
+ else if (STRNCMP(algo, "minimal", 7) == 0)
+ *diffalgo = XDF_NEED_MINIMAL;
+ else if (STRNCMP(algo, "patience", 8) == 0)
+ *diffalgo = XDF_PATIENCE_DIFF;
+ else if (STRNCMP(algo, "histogram", 9) == 0)
+ *diffalgo = XDF_HISTOGRAM_DIFF;
+ }
+
+ char_u *output_fmt = dict_get_string(d, "output", FALSE);
+ if (output_fmt != NULL)
+ {
+ if (STRNCMP(output_fmt, "unified", 7) == 0)
+ *diff_output_fmt = DIO_OUTPUT_UNIFIED;
+ else if (STRNCMP(output_fmt, "indices", 7) == 0)
+ *diff_output_fmt = DIO_OUTPUT_INDICES;
+ else
+ {
+ semsg(_(e_unsupported_diff_output_format_str), output_fmt);
+ return FAIL;
+ }
+ }
+
+ *diff_ctxlen = dict_get_number_def(d, "context", 0);
+ if (*diff_ctxlen < 0)
+ *diff_ctxlen = 0;
+
+ if (dict_get_bool(d, "iblank", FALSE))
+ *diffopts |= DIFF_IBLANK;
+ if (dict_get_bool(d, "icase", FALSE))
+ *diffopts |= DIFF_ICASE;
+ if (dict_get_bool(d, "iwhite", FALSE))
+ *diffopts |= DIFF_IWHITE;
+ if (dict_get_bool(d, "iwhiteall", FALSE))
+ *diffopts |= DIFF_IWHITEALL;
+ if (dict_get_bool(d, "iwhiteeol", FALSE))
+ *diffopts |= DIFF_IWHITEEOL;
+ if (dict_get_bool(d, "indent-heuristic", FALSE))
+ *diffalgo |= XDF_INDENT_HEURISTIC;
+
+ return OK;
+}
+
+/*
+ * Concatenate the List of strings in "l" and store the result in
+ * "din->din_mmfile.ptr" and the length in "din->din_mmfile.size".
+ */
+ static void
+list_to_diffin(list_T *l, diffin_T *din, int icase)
+{
+ garray_T ga;
+ listitem_T *li;
+ char_u *str;
+
+ ga_init2(&ga, 512, 4);
+
+ FOR_ALL_LIST_ITEMS(l, li)
+ {
+ str = tv_get_string(&li->li_tv);
+ if (icase)
+ {
+ str = strlow_save(str);
+ if (str == NULL)
+ continue;
+ }
+ ga_concat(&ga, str);
+ ga_concat(&ga, (char_u *)NL_STR);
+ if (icase)
+ vim_free(str);
+ }
+ if (ga.ga_len > 0)
+ ((char *)ga.ga_data)[ga.ga_len] = NUL;
+
+ din->din_mmfile.ptr = (char *)ga.ga_data;
+ din->din_mmfile.size = ga.ga_len;
+}
+
+/*
+ * Get the start and end indices from the diff "hunk".
+ */
+ static dict_T *
+get_diff_hunk_indices(diffhunk_T *hunk)
+{
+ dict_T *hunk_dict;
+
+ hunk_dict = dict_alloc();
+ if (hunk_dict == NULL)
+ return NULL;
+
+ dict_add_number(hunk_dict, "from_idx", hunk->lnum_orig - 1);
+ dict_add_number(hunk_dict, "from_count", hunk->count_orig);
+ dict_add_number(hunk_dict, "to_idx", hunk->lnum_new - 1);
+ dict_add_number(hunk_dict, "to_count", hunk->count_new);
+
+ return hunk_dict;
+}
+# endif
+
+/*
+ * "diff()" function
+ */
+ void
+f_diff(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+{
+# ifdef FEAT_DIFF
+ diffio_T dio;
+
+ if (check_for_nonnull_list_arg(argvars, 0) == FAIL
+ || check_for_nonnull_list_arg(argvars, 1) == FAIL
+ || check_for_opt_nonnull_dict_arg(argvars, 2) == FAIL)
+ return;
+
+ CLEAR_FIELD(dio);
+ dio.dio_internal = TRUE;
+ ga_init2(&dio.dio_diff.dout_ga, sizeof(char *), 1000);
+
+ list_T *orig_list = argvars[0].vval.v_list;
+ list_T *new_list = argvars[1].vval.v_list;
+
+ // Save the 'diffopt' option value and restore it after getting the diff.
+ int save_diff_flags = diff_flags;
+ long save_diff_algorithm = diff_algorithm;
+ diff_flags = DIFF_INTERNAL;
+ diff_algorithm = 0;
+ dio.dio_outfmt = DIO_OUTPUT_UNIFIED;
+ if (argvars[2].v_type != VAR_UNKNOWN)
+ if (parse_diff_optarg(&argvars[2], &diff_flags, &diff_algorithm,
+ &dio.dio_outfmt, &dio.dio_ctxlen) == FAIL)
+ return;
+
+ // Concatenate the List of strings into a single string using newline
+ // separator. Internal diff library expects a single string.
+ list_to_diffin(orig_list, &dio.dio_orig, diff_flags & DIFF_ICASE);
+ list_to_diffin(new_list, &dio.dio_new, diff_flags & DIFF_ICASE);
+
+ // If 'diffexpr' is set, then the internal diff is not used. Set
+ // 'diffexpr' to an empty string temporarily.
+ int restore_diffexpr = FALSE;
+ char_u cc = *p_dex;
+ if (*p_dex != NUL)
+ {
+ restore_diffexpr = TRUE;
+ *p_dex = NUL;
+ }
+
+ // Compute the diff
+ int diff_status = diff_file(&dio);
+
+ // restore 'diffexpr'
+ if (restore_diffexpr)
+ *p_dex = cc;
+
+ if (diff_status == FAIL)
+ goto done;
+
+ int hunk_idx = 0;
+ dict_T *hunk_dict;
+
+ if (dio.dio_outfmt == DIO_OUTPUT_INDICES)
+ {
+ if (rettv_list_alloc(rettv) != OK)
+ goto done;
+ list_T *l = rettv->vval.v_list;
+
+ // Process each diff hunk
+ diffhunk_T *hunk = NULL;
+ while (hunk_idx < dio.dio_diff.dout_ga.ga_len)
+ {
+ hunk = ((diffhunk_T **)dio.dio_diff.dout_ga.ga_data)[hunk_idx++];
+
+ hunk_dict = get_diff_hunk_indices(hunk);
+ if (hunk_dict == NULL)
+ goto done;
+
+ list_append_dict(l, hunk_dict);
+ }
+ }
+ else
+ {
+ ga_append(&dio.dio_diff.dout_ga, NUL);
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string =
+ vim_strsave((char_u *)dio.dio_diff.dout_ga.ga_data);
+ }
+
+done:
+ clear_diffin(&dio.dio_new);
+ if (dio.dio_outfmt == DIO_OUTPUT_INDICES)
+ clear_diffout(&dio.dio_diff);
+ else
+ ga_clear(&dio.dio_diff.dout_ga);
+ clear_diffin(&dio.dio_orig);
+ // Restore the 'diffopt' option value.
+ diff_flags = save_diff_flags;
+ diff_algorithm = save_diff_algorithm;
+# endif
}
#endif
diff --git a/src/drawline.c b/src/drawline.c
index 7bbe86d..a8de449 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -589,7 +589,7 @@ handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv)
// Correct end of highlighted area for 'showbreak',
// required when 'linebreak' is also set.
if (wlv->tocol == wlv->vcol)
- wlv->tocol += wlv->n_extra;
+ wlv->tocol = wlv->vcol_sbr;
// combine 'showbreak' with 'wincolor'
wlv->char_attr = hl_combine_attr(wlv->win_attr, HL_ATTR(HLF_AT));
# ifdef FEAT_SYN_HL
@@ -812,12 +812,12 @@ text_prop_position(
*p_extra = l;
*n_extra = n_used + before + after + padding;
*n_attr = mb_charlen(*p_extra);
- if (above)
- *n_attr -= padding + after;
-
// n_attr_skip will not be decremented before draw_state is
// WL_LINE
*n_attr_skip = before + (padding > 0 ? padding : 0);
+ *n_attr -= *n_attr_skip;
+ if (above)
+ *n_attr -= after;
}
}
}
@@ -832,9 +832,10 @@ text_prop_position(
* Call screen_line() using values from "wlv".
* Also takes care of putting "<<<" on the first line for 'smoothscroll'
* when 'showbreak' is not set.
+ * When "clear_end" is TRUE clear until the end of the screen line.
*/
static void
-wlv_screen_line(win_T *wp, winlinevars_T *wlv, int negative_width)
+wlv_screen_line(win_T *wp, winlinevars_T *wlv, int clear_end)
{
if (wlv->row == 0 && wp->w_skipcol > 0
#if defined(FEAT_LINEBREAK)
@@ -872,8 +873,8 @@ wlv_screen_line(win_T *wp, winlinevars_T *wlv, int negative_width)
}
screen_line(wp, wlv->screen_row, wp->w_wincol, wlv->col,
- negative_width ? -wp->w_width : wp->w_width,
- wlv->screen_line_flags);
+ clear_end ? wp->w_width : -wp->w_width,
+ wlv->vcol - 1, wlv->screen_line_flags);
}
/*
@@ -885,6 +886,7 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
{
#ifdef FEAT_SYN_HL
long v;
+ int wcol;
// Highlight 'cursorcolumn' & 'colorcolumn' past end of the line.
if (wp->w_p_wrap)
@@ -892,9 +894,14 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
else
v = wp->w_leftcol;
+ wcol =
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? wp->w_width - wlv->col - 1 :
+# endif
+ wlv->col;
// check if line ends before left margin
- if (wlv->vcol < v + wlv->col - win_col_off(wp))
- wlv->vcol = v + wlv->col - win_col_off(wp);
+ if (wlv->vcol < v + wcol - win_col_off(wp))
+ wlv->vcol = v + wcol - win_col_off(wp);
# ifdef FEAT_CONCEAL
// Get rid of the boguscols now, we want to draw until the right
// edge for 'cursorcolumn'.
@@ -917,11 +924,7 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
# ifdef LINE_ATTR
|| wlv->line_attr != 0
# endif
- || wlv->win_attr != 0)
-# ifdef FEAT_RIGHTLEFT
- && !wp->w_p_rl
-# endif
- )
+ || wlv->win_attr != 0))
{
int rightmost_vcol = 0;
int i;
@@ -934,41 +937,61 @@ draw_screen_line(win_T *wp, winlinevars_T *wlv)
if (rightmost_vcol < wlv->color_cols[i])
rightmost_vcol = wlv->color_cols[i];
- while (wlv->col < wp->w_width)
+ while (
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? (wlv->col >= 0) :
+# endif
+ (wlv->col < wp->w_width))
{
ScreenLines[wlv->off] = ' ';
if (enc_utf8)
ScreenLinesUC[wlv->off] = 0;
- ScreenCols[wlv->off] = MAXCOL;
- ++wlv->col;
+
if (wlv->draw_color_col)
wlv->draw_color_col = advance_color_col(
VCOL_HLC, &wlv->color_cols);
int attr = wlv->win_attr;
- if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol)
- attr = HL_ATTR(HLF_CUC);
- else if (wlv->draw_color_col && VCOL_HLC == *wlv->color_cols)
- attr = HL_ATTR(HLF_MC);
# ifdef LINE_ATTR
- else if (wlv->line_attr != 0)
- attr = wlv->line_attr;
+ if (wlv->line_attr != 0)
+ attr = hl_combine_attr(attr, wlv->line_attr);
# endif
- ScreenAttrs[wlv->off++] = attr;
+ if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
+ && wlv->lnum != wp->w_cursor.lnum)
+ attr = hl_combine_attr(attr, HL_ATTR(HLF_CUC));
+ else if (wlv->draw_color_col && VCOL_HLC == *wlv->color_cols)
+ attr = hl_combine_attr(attr, HL_ATTR(HLF_MC));
+ ScreenAttrs[wlv->off] = attr;
+ ScreenCols[wlv->off] = wlv->vcol;
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ --wlv->off;
+ --wlv->col;
+ }
+ else
+# endif
+ {
+ ++wlv->off;
+ ++wlv->col;
+ }
+ ++wlv->vcol;
- if (VCOL_HLC >= rightmost_vcol
+ if (VCOL_HLC > rightmost_vcol
# ifdef LINE_ATTR
&& wlv->line_attr == 0
# endif
&& wlv->win_attr == 0)
break;
-
- ++wlv->vcol;
}
}
#endif
- wlv_screen_line(wp, wlv, FALSE);
+ // Set increasing virtual columns in ScreenCols[] to set correct curswant
+ // (or "coladd" for 'virtualedit') when clicking after end of line.
+ wlv->screen_line_flags |= SLF_INC_VCOL;
+ wlv_screen_line(wp, wlv, TRUE);
+ wlv->screen_line_flags &= ~SLF_INC_VCOL;
++wlv->row;
++wlv->screen_row;
}
@@ -1091,7 +1114,8 @@ apply_cursorline_highlight(
/*
* Display line "lnum" of window "wp" on the screen.
* Start at row "startrow", stop when "endrow" is reached.
- * When "number_only" is TRUE only update the number column.
+ * When only updating the number column, "number_only" is set to the height of
+ * the line, otherwise it is set to 0.
* "spv" is used to store information for spell checking, kept between
* sequential calls for the same window.
* wp->w_virtcol needs to be valid.
@@ -1120,8 +1144,6 @@ win_line(
#if defined(FEAT_LINEBREAK) && defined(FEAT_PROP_POPUP)
int in_linebreak = FALSE; // n_extra set for showing linebreak
#endif
- static char_u *at_end_str = (char_u *)""; // used for p_extra when
- // displaying eol at end-of-line
int lcs_eol_one = wp->w_lcs_chars.eol; // eol until it's been used
int lcs_prec_todo = wp->w_lcs_chars.prec;
// prec until it's been used
@@ -1273,7 +1295,7 @@ win_line(
wlv.vcol_sbr = -1;
#endif
- if (!number_only)
+ if (number_only == 0)
{
// To speed up the loop below, set extra_check when there is linebreak,
// trailing white space and/or syntax processing to be done.
@@ -1486,7 +1508,7 @@ win_line(
#endif
#ifdef FEAT_SPELL
- if (spv->spv_has_spell && !number_only)
+ if (spv->spv_has_spell && number_only == 0)
{
// Prepare for spell checking.
extra_check = TRUE;
@@ -1534,7 +1556,7 @@ win_line(
}
else
{
- v = (long)STRLEN(line);
+ v = ml_get_buf_len(wp->w_buffer, lnum);
if (v < SPWORDLEN)
{
// Short line, use it completely and append the start of the
@@ -1571,7 +1593,7 @@ win_line(
// find start of trailing whitespace
if (wp->w_lcs_chars.trail)
{
- trailcol = (colnr_T)STRLEN(ptr);
+ trailcol = ml_get_buf_len(wp->w_buffer, lnum);
while (trailcol > (colnr_T)0 && VIM_ISWHITE(ptr[trailcol - 1]))
--trailcol;
trailcol += (colnr_T)(ptr - line);
@@ -1632,16 +1654,6 @@ win_line(
if (text_props[i].tp_id < 0)
last_textprop_text_idx = i;
- // When skipping virtual text the props need to be sorted. The
- // order is reversed!
- if (lnum == wp->w_topline && wp->w_skipcol > 0)
- {
- for (int i = 0; i < text_prop_count; ++i)
- text_prop_idxs[i] = i;
- sort_text_props(wp->w_buffer, text_props,
- text_prop_idxs, text_prop_count);
- }
-
// Text props "above" move the line number down to where the text
// is. Only count the ones that are visible, not those that are
// skipped because of w_skipcol.
@@ -1667,19 +1679,23 @@ win_line(
}
}
- if (number_only)
+ if (number_only > 0)
{
// skip over rows only used for virtual text above
wlv.row += wlv.text_prop_above_count;
- if (wlv.row > endrow)
+ if (wlv.row >= endrow)
+ {
+ vim_free(text_props);
+ vim_free(text_prop_idxs);
return wlv.row;
+ }
wlv.screen_row += wlv.text_prop_above_count;
}
#endif
#if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
colnr_T vcol_first_char = 0;
- if (wp->w_p_lbr && !number_only)
+ if (wp->w_p_lbr && number_only == 0)
{
chartabsize_T cts;
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
@@ -1695,7 +1711,7 @@ win_line(
v = startrow == 0 ? wp->w_skipcol - skipcol_in_text_prop_above : 0;
else
v = wp->w_leftcol;
- if (v > 0 && !number_only)
+ if (v > 0 && number_only == 0)
{
char_u *prev_ptr = ptr;
chartabsize_T cts;
@@ -1840,7 +1856,7 @@ win_line(
}
#ifdef FEAT_SEARCH_EXTRA
- if (!number_only)
+ if (number_only == 0)
{
v = (long)(ptr - line);
area_highlighting |= prepare_search_hl_line(wp, lnum, (colnr_T)v,
@@ -1901,7 +1917,7 @@ win_line(
if (wlv.draw_state == WL_CMDLINE - 1 && wlv.n_extra == 0)
{
wlv.draw_state = WL_CMDLINE;
- if (cmdwin_type != 0 && wp == curwin)
+ if (wp == cmdwin_win)
{
// Draw the cmdline character.
wlv.n_extra = 1;
@@ -1933,6 +1949,38 @@ win_line(
wlv.draw_state = WL_NR;
handle_lnum_col(wp, &wlv, sign_present, num_attr);
}
+
+ // When only displaying the (relative) line number and that's done,
+ // stop here.
+ if (number_only > 0 && wlv.draw_state == WL_NR && wlv.n_extra == 0)
+ {
+ wlv_screen_line(wp, &wlv, FALSE);
+ // Need to update more screen lines if:
+ // - LineNrAbove or LineNrBelow is used, or
+ // - still drawing filler lines.
+ if ((wlv.row + 1 - wlv.startrow < number_only
+ && (HL_ATTR(HLF_LNA) != 0 || HL_ATTR(HLF_LNB) != 0))
+#ifdef FEAT_DIFF
+ || wlv.filler_todo > 0
+#endif
+ )
+ {
+ ++wlv.row;
+ ++wlv.screen_row;
+ if (wlv.row == endrow)
+ break;
+#ifdef FEAT_DIFF
+ --wlv.filler_todo;
+ if (wlv.filler_todo == 0 && wp->w_botfill)
+ break;
+#endif
+ win_line_start(wp, &wlv, TRUE);
+ continue;
+ }
+ else
+ break;
+ }
+
#ifdef FEAT_LINEBREAK
// Check if 'breakindent' applies and show it.
// May change wlv.draw_state to WL_BRI or WL_BRI - 1.
@@ -1957,24 +2005,15 @@ win_line(
if (wlv.cul_screenline && wlv.draw_state == WL_LINE
&& wlv.vcol >= left_curline_col
&& wlv.vcol < right_curline_col)
- {
apply_cursorline_highlight(&wlv, sign_present);
- }
#endif
// When still displaying '$' of change command, stop at cursor.
- // When only displaying the (relative) line number and that's done,
- // stop here.
- if (((dollar_vcol >= 0 && wp == curwin
- && lnum == wp->w_cursor.lnum
- && wlv.vcol >= (long)wp->w_virtcol)
- || (number_only && wlv.draw_state > WL_NR))
-#ifdef FEAT_DIFF
- && wlv.filler_todo <= 0
-#endif
- )
+ if (dollar_vcol >= 0 && wp == curwin
+ && lnum == wp->w_cursor.lnum
+ && wlv.vcol >= (long)wp->w_virtcol)
{
- wlv_screen_line(wp, &wlv, TRUE);
+ wlv_screen_line(wp, &wlv, FALSE);
// Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set.
#ifdef FEAT_SYN_HL
@@ -2274,7 +2313,7 @@ win_line(
// If another text prop follows the condition below at
// the last window column must know.
- // If this is an "above" text prop and 'nowrap' the we
+ // If this is an "above" text prop and 'nowrap' then we
// must wrap anyway.
text_prop_above = above;
text_prop_follows |= other_tpi != -1
@@ -3212,7 +3251,7 @@ win_line(
// Make sure, the highlighting for the tab char will be
// correctly set further below (effectively reverts the
- // FIX_FOR_BOGSUCOLS macro).
+ // FIX_FOR_BOGUSCOLS macro).
if (wlv.n_extra == tab_len + vc_saved && wp->w_p_list
&& wp->w_lcs_chars.tab1)
tab_len += vc_saved;
@@ -3290,7 +3329,7 @@ win_line(
if (!(area_highlighting && virtual_active()
&& wlv.tocol != MAXCOL
&& wlv.vcol < wlv.tocol))
- wlv.p_extra = at_end_str;
+ wlv.p_extra = (char_u *)"";
wlv.n_extra = 0;
}
if (wp->w_p_list && wp->w_lcs_chars.eol > 0)
@@ -3481,6 +3520,21 @@ win_line(
else
c = ' ';
+ if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
+ // When the first char to be concealed is double-width,
+ // need to advance one more virtual column.
+ wlv.n_extra++;
+
+ mb_c = c;
+ if (enc_utf8 && utf_char2len(c) > 1)
+ {
+ mb_utf8 = TRUE;
+ u8cc[0] = 0;
+ c = 0xc0;
+ }
+ else
+ mb_utf8 = FALSE; // don't draw as UTF-8
+
prev_syntax_id = syntax_seqnr;
if (wlv.n_extra > 0)
@@ -3509,15 +3563,6 @@ win_line(
is_concealing = TRUE;
skip_cells = 1;
}
- mb_c = c;
- if (enc_utf8 && utf_char2len(c) > 1)
- {
- mb_utf8 = TRUE;
- u8cc[0] = 0;
- c = 0xc0;
- }
- else
- mb_utf8 = FALSE; // don't draw as UTF-8
}
else
{
@@ -3535,10 +3580,12 @@ win_line(
#ifdef FEAT_CONCEAL
// In the cursor line and we may be concealing characters: correct
// the cursor column when we reach its position.
+ // With 'virtualedit' we may never reach cursor position, but we still
+ // need to correct the cursor column, so do that at end of line.
if (!did_wcol && wlv.draw_state == WL_LINE
&& wp == curwin && lnum == wp->w_cursor.lnum
&& conceal_cursor_line(wp)
- && (int)wp->w_virtcol <= wlv.vcol + skip_cells)
+ && (wlv.vcol + skip_cells >= wp->w_virtcol || c == NUL))
{
# ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
@@ -3546,6 +3593,9 @@ win_line(
else
# endif
wp->w_wcol = wlv.col - wlv.boguscols;
+ if (wlv.vcol + skip_cells < wp->w_virtcol)
+ // Cursor beyond end of the line with 'virtualedit'.
+ wp->w_wcol += wp->w_virtcol - wlv.vcol - skip_cells;
wp->w_wrow = wlv.row;
did_wcol = TRUE;
curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
@@ -3740,7 +3790,7 @@ win_line(
}
#endif
ScreenAttrs[wlv.off] = wlv.char_attr;
- ScreenCols[wlv.off] = MAXCOL;
+ ScreenCols[wlv.off] = wlv.vcol;
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
{
@@ -3972,10 +4022,21 @@ win_line(
#ifdef FEAT_CONCEAL
else if (wp->w_p_cole > 0 && is_concealing)
{
+ int concealed_wide = has_mbyte && (*mb_char2cells)(mb_c) > 1;
+
--skip_cells;
++wlv.vcol_off_co;
+ if (concealed_wide)
+ {
+ // When a double-width char is concealed,
+ // need to advance one more virtual column.
+ ++wlv.vcol;
+ ++wlv.vcol_off_co;
+ }
+
if (wlv.n_extra > 0)
wlv.vcol_off_co += wlv.n_extra;
+
if (wp->w_p_wrap)
{
// Special voodoo required if 'wrap' is on.
@@ -4008,8 +4069,7 @@ win_line(
n_attr = 0;
}
-
- if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
+ if (concealed_wide)
{
// Need to fill two screen columns.
# ifdef FEAT_RIGHTLEFT
@@ -4102,35 +4162,72 @@ win_line(
|| text_prop_next <= last_textprop_text_idx
#endif
|| (wp->w_p_list && wp->w_lcs_chars.eol != NUL
- && wlv.p_extra != at_end_str)
+ && lcs_eol_one != -1)
|| (wlv.n_extra != 0 && (wlv.c_extra != NUL
|| *wlv.p_extra != NUL)))
)
{
#ifdef FEAT_CONCEAL
wlv.col -= wlv.boguscols;
- wlv_screen_line(wp, &wlv, FALSE);
+ // Apply 'cursorline' and 'wincolor' highlight.
+ if (wlv.boguscols != 0 && (
+# ifdef LINE_ATTR
+ wlv.line_attr != 0 ||
+# endif
+ wlv.win_attr != 0
+ )
+ )
+ {
+ int attr = wlv.win_attr;
+# ifdef LINE_ATTR
+ if (wlv.line_attr != 0)
+ attr = hl_combine_attr(attr, wlv.line_attr);
+# endif
+ while ((
+# ifdef FEAT_RIGHTLEFT
+ wp->w_p_rl ? wlv.col >= 0 :
+# endif
+ wlv.col < wp->w_width))
+ {
+ ScreenLines[wlv.off] = ' ';
+ if (enc_utf8)
+ ScreenLinesUC[wlv.off] = 0;
+ ScreenAttrs[wlv.off] = attr;
+ ScreenCols[wlv.off] = wlv.vcol - 1;
+# ifdef FEAT_RIGHTLEFT
+ if (wp->w_p_rl)
+ {
+ wlv.off--;
+ wlv.col--;
+ wlv.boguscols++;
+ }
+ else
+# endif
+ {
+ wlv.off++;
+ wlv.col++;
+ wlv.boguscols--;
+ }
+ }
+ }
+ wlv_screen_line(wp, &wlv, TRUE);
wlv.col += wlv.boguscols;
wlv.boguscols = 0;
wlv.vcol_off_co = 0;
#else
- wlv_screen_line(wp, &wlv, FALSE);
+ wlv_screen_line(wp, &wlv, TRUE);
#endif
++wlv.row;
++wlv.screen_row;
- // When not wrapping and finished diff lines, or when displayed
- // '$' and highlighting until last column, break here.
- if (((!wp->w_p_wrap
+ // When not wrapping and finished diff lines, break here.
+ if (!wp->w_p_wrap
#ifdef FEAT_DIFF
&& wlv.filler_todo <= 0
#endif
#ifdef FEAT_PROP_POPUP
&& !text_prop_above
-#endif
- ) || lcs_eol_one == -1)
-#ifdef FEAT_PROP_POPUP
- && !text_prop_follows
+ && !text_prop_follows
#endif
)
break;
diff --git a/src/drawscreen.c b/src/drawscreen.c
index a2f60a6..f8818ff 100644
--- a/src/drawscreen.c
+++ b/src/drawscreen.c
@@ -1028,7 +1028,8 @@ redraw_win_toolbar(win_T *wp)
}
wp->w_winbar_items[item_idx].wb_menu = NULL; // end marker
- screen_line(wp, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_width, 0);
+ screen_line(wp, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_width, -1,
+ 0);
}
#endif
@@ -1087,7 +1088,7 @@ fold_line(
// 1. Add the cmdwin_type for the command-line window
// Ignores 'rightleft', this window is never right-left.
- if (cmdwin_type != 0 && wp == curwin)
+ if (wp == cmdwin_win)
{
ScreenLines[off] = cmdwin_type;
ScreenAttrs[off] = HL_ATTR(HLF_AT);
@@ -1300,7 +1301,7 @@ fold_line(
&& (lnume < bot->lnum
|| (lnume == bot->lnum
&& (bot->col - (*p_sel == 'e'))
- >= (colnr_T)STRLEN(ml_get_buf(wp->w_buffer, lnume, FALSE)))))))
+ >= ml_get_buf_len(wp->w_buffer, lnume))))))
{
if (VIsual_mode == Ctrl_V)
{
@@ -1363,7 +1364,7 @@ fold_line(
#endif
screen_line(wp, row + W_WINROW(wp), wp->w_wincol,
- wp->w_width, wp->w_width, 0);
+ wp->w_width, wp->w_width, -1, 0);
// Update w_cline_height and w_cline_folded if the cursor line was
// updated (saves a call to plines() later).
@@ -1408,7 +1409,7 @@ fold_line(
* - if wp->w_buffer->b_mod_set set, update lines between
* b_mod_top and b_mod_bot.
* - if wp->w_redraw_top non-zero, redraw lines between
- * wp->w_redraw_top and wp->w_redr_bot.
+ * wp->w_redraw_top and wp->w_redraw_bot.
* - continue redrawing when syntax status is invalid.
* 4. if scrolled up, update lines at the bottom.
* This results in three areas that may need updating:
@@ -1537,7 +1538,7 @@ win_update(win_T *wp)
// Make sure skipcol is valid, it depends on various options and the window
// width.
- if (wp->w_skipcol > 0)
+ if (wp->w_skipcol > 0 && wp->w_width > win_col_off(wp))
{
int w = 0;
int width1 = wp->w_width - win_col_off(wp);
@@ -1567,14 +1568,6 @@ win_update(win_T *wp)
else
#endif
- if (buf->b_mod_set && buf->b_mod_xlines != 0 && wp->w_redraw_top != 0)
- {
- // When there are both inserted/deleted lines and specific lines to be
- // redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
- // everything (only happens when redrawing is off for while).
- type = UPD_NOT_VALID;
- }
- else
{
// Set mod_top to the first line that needs displaying because of
// changes. Set mod_bot to the first line after the changes.
@@ -1699,11 +1692,6 @@ win_update(win_T *wp)
top_end = 1;
#endif
}
-
- // When line numbers are displayed need to redraw all lines below
- // inserted/deleted lines.
- if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu)
- mod_bot = MAXLNUM;
}
wp->w_redraw_top = 0; // reset for next time
wp->w_redraw_bot = 0;
@@ -2503,7 +2491,7 @@ win_update(win_T *wp)
#endif
// Display one line.
- row = win_line(wp, lnum, srow, wp->w_height, FALSE, &spv);
+ row = win_line(wp, lnum, srow, wp->w_height, 0, &spv);
#ifdef FEAT_FOLDING
wp->w_lines[idx].wl_folded = FALSE;
@@ -2540,17 +2528,23 @@ win_update(win_T *wp)
}
else
{
- if (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum)
+ // If:
+ // - 'number' is set and below inserted/deleted lines, or
+ // - 'relativenumber' is set and cursor moved vertically,
+ // the text doesn't need to be redrawn, but the number column does.
+ if ((wp->w_p_nu && mod_top != 0
+ && lnum >= mod_bot && buf->b_mod_xlines != 0)
+ || (wp->w_p_rnu
+ && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum))
{
#ifdef FEAT_FOLDING
- // 'relativenumber' set and the cursor moved vertically: The
- // text doesn't need to be drawn, but the number column does.
fold_count = foldedCount(wp, lnum, &win_foldinfo);
if (fold_count != 0)
fold_line(wp, fold_count, &win_foldinfo, lnum, row);
else
#endif
- (void)win_line(wp, lnum, srow, wp->w_height, TRUE, &spv);
+ (void)win_line(wp, lnum, srow, wp->w_height,
+ wp->w_lines[idx].wl_size, &spv);
}
// This line does not need to be drawn, advance to the next one.
@@ -3056,7 +3050,7 @@ redraw_asap(int type)
mch_memmove(ScreenLines2 + off,
screenline2 + r * cols,
(size_t)cols * sizeof(schar_T));
- screen_line(curwin, cmdline_row + r, 0, cols, cols, 0);
+ screen_line(curwin, cmdline_row + r, 0, cols, cols, -1, 0);
}
ret = 4;
}
diff --git a/src/edit.c b/src/edit.c
index cb6ae7e..69ec255 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -843,7 +843,12 @@ doESCkey:
if (cmdchar != 'r' && cmdchar != 'v' && c != Ctrl_C)
ins_apply_autocmds(EVENT_INSERTLEAVE);
did_cursorhold = FALSE;
- curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
+
+ // ins_redraw() triggers TextChangedI only when no characters
+ // are in the typeahead buffer, so only reset curbuf->b_last_changedtick
+ // if the TextChangedI was not blocked by char_avail() (e.g. using :norm!)
+ if (!char_avail())
+ curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
return (c == Ctrl_O);
}
continue;
@@ -2023,7 +2028,7 @@ insert_special(
* Only use mod_mask for special keys, to avoid things like <S-Space>,
* unless 'allow_modmask' is TRUE.
*/
-#ifdef MACOS_X
+#if defined(MACOS_X) || defined(FEAT_GUI_GTK)
// Command-key never produces a normal key
if (mod_mask & MOD_MASK_CMD)
allow_modmask = TRUE;
@@ -3217,7 +3222,7 @@ replace_do_bs(int limit_col)
{
// Do not adjust text properties for individual delete and insert
// operations, do it afterwards on the resulting text.
- len_before = STRLEN(ml_get_curline());
+ len_before = ml_get_curline_len();
++text_prop_frozen;
}
#endif
@@ -3232,14 +3237,14 @@ replace_do_bs(int limit_col)
{
(void)del_char_after_col(limit_col);
if (State & VREPLACE_FLAG)
- orig_len = (int)STRLEN(ml_get_cursor());
+ orig_len = ml_get_cursor_len();
replace_push(cc);
}
else
{
pchar_cursor(cc);
if (State & VREPLACE_FLAG)
- orig_len = (int)STRLEN(ml_get_cursor()) - 1;
+ orig_len = ml_get_cursor_len() - 1;
}
replace_pop_ins();
@@ -3247,7 +3252,7 @@ replace_do_bs(int limit_col)
{
// Get the number of screen cells used by the inserted characters
p = ml_get_cursor();
- ins_len = (int)STRLEN(p) - orig_len;
+ ins_len = ml_get_cursor_len() - orig_len;
vcol = start_vcol;
for (i = 0; i < ins_len; ++i)
{
@@ -3273,7 +3278,7 @@ replace_do_bs(int limit_col)
#ifdef FEAT_PROP_POPUP
if (curbuf->b_has_textprop)
{
- size_t len_now = STRLEN(ml_get_curline());
+ size_t len_now = ml_get_curline_len();
--text_prop_frozen;
adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col,
@@ -4063,7 +4068,7 @@ ins_bs(
(linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL)
return FALSE;
--Insstart.lnum;
- Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum));
+ Insstart.col = ml_get_len(Insstart.lnum);
}
/*
* In replace mode:
@@ -4096,12 +4101,30 @@ ins_bs(
&& has_format_option(FO_WHITE_PAR))
{
char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum,
- TRUE);
- int len;
+ FALSE);
+ int len = ml_get_curline_len();
- len = (int)STRLEN(ptr);
if (len > 0 && ptr[len - 1] == ' ')
- ptr[len - 1] = NUL;
+ {
+ char_u *newp = alloc(curbuf->b_ml.ml_line_len - 1);
+
+ if (newp != NULL)
+ {
+ mch_memmove(newp, ptr, len - 1);
+ newp[len - 1] = NUL;
+ if (curbuf->b_ml.ml_line_len > len + 1)
+ mch_memmove(newp + len, ptr + len + 1,
+ curbuf->b_ml.ml_line_len - len - 1);
+
+ if (curbuf->b_ml.ml_flags
+ & (ML_LINE_DIRTY | ML_ALLOCATED))
+ vim_free(curbuf->b_ml.ml_line_ptr);
+ curbuf->b_ml.ml_line_ptr = newp;
+ curbuf->b_ml.ml_line_len--;
+ curbuf->b_ml.ml_line_textlen--;
+ curbuf->b_ml.ml_flags |= ML_LINE_DIRTY;
+ }
+ }
}
(void)do_join(2, FALSE, FALSE, FALSE, FALSE);
@@ -4954,7 +4977,7 @@ ins_tab(void)
{
pos = curwin->w_cursor;
cursor = &pos;
- saved_line = vim_strsave(ml_get_curline());
+ saved_line = vim_strnsave(ml_get_curline(), ml_get_curline_len());
if (saved_line == NULL)
return FALSE;
ptr = saved_line + pos.col;
@@ -5065,6 +5088,7 @@ ins_tab(void)
vim_free(curbuf->b_ml.ml_line_ptr);
curbuf->b_ml.ml_line_ptr = newp;
curbuf->b_ml.ml_line_len -= i;
+ curbuf->b_ml.ml_line_textlen = 0;
curbuf->b_ml.ml_flags =
(curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
}
@@ -5150,7 +5174,7 @@ ins_eol(int c)
// NL in reverse insert will always start in the end of
// current line.
if (revins_on)
- curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
+ curwin->w_cursor.col += ml_get_cursor_len();
#endif
AppendToRedobuff(NL_STR);
@@ -5371,6 +5395,9 @@ do_insert_char_pre(int c)
if (!has_insertcharpre())
return NULL;
+ if (c == Ctrl_RSB)
+ return NULL;
+
if (has_mbyte)
buf[(*mb_char2bytes)(c, buf)] = NUL;
else
diff --git a/src/errors.h b/src/errors.h
index dfb6ce6..5dccc63 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -258,8 +258,9 @@ EXTERN char e_escape_not_allowed_in_digraph[]
EXTERN char e_using_loadkeymap_not_in_sourced_file[]
INIT(= N_("E105: Using :loadkeymap not in a sourced file"));
#endif
-// E106 unused
#ifdef FEAT_EVAL
+EXTERN char e_unsupported_diff_output_format_str[]
+ INIT(= N_("E106: Unsupported diff output format: %s"));
EXTERN char e_missing_parenthesis_str[]
INIT(= N_("E107: Missing parentheses: %s"));
EXTERN char e_no_such_variable_str[]
@@ -471,8 +472,8 @@ EXTERN char e_no_digraphs_version[]
EXTERN char e_cannot_set_language_to_str[]
INIT(= N_("E197: Cannot set language to \"%s\""));
// E198 unused
-EXTERN char e_active_window_or_buffer_deleted[]
- INIT(= N_("E199: Active window or buffer deleted"));
+EXTERN char e_active_window_or_buffer_changed_or_deleted[]
+ INIT(= N_("E199: Active window or buffer changed or deleted"));
EXTERN char e_readpre_autocommands_made_file_unreadable[]
INIT(= N_("E200: *ReadPre autocommands made the file unreadable"));
EXTERN char e_readpre_autocommands_must_not_change_current_buffer[]
@@ -2525,9 +2526,11 @@ EXTERN char e_invalid_action_str_2[]
EXTERN char e_setting_v_str_to_value_with_wrong_type[]
INIT(= N_("E963: Setting v:%s to value with wrong type"));
#endif
-#ifdef FEAT_PROP_POPUP
+#if defined(FEAT_PROP_POPUP) || defined(FEAT_EVAL)
EXTERN char_u e_invalid_column_number_nr[]
INIT(= N_("E964: Invalid column number: %ld"));
+#endif
+#ifdef FEAT_PROP_POPUP
EXTERN char e_missing_property_type_name[]
INIT(= N_("E965: Missing property type name"));
#endif
@@ -3184,7 +3187,7 @@ EXTERN char e_separator_not_supported_str[]
EXTERN char e_no_white_space_allowed_before_separator_str[]
INIT(= N_("E1242: No white space allowed before separator: %s"));
#endif
-#ifdef FEAT_GUI_GTK
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
EXTERN char e_ascii_code_not_in_range[]
INIT(= N_("E1243: ASCII code not in 32-127 range"));
#endif
@@ -3578,8 +3581,12 @@ EXTERN char e_const_variable_not_supported_in_interface[]
INIT(= N_("E1410: Const variable not supported in an interface"));
EXTERN char e_missing_dot_after_object_str[]
INIT(= N_("E1411: Missing dot after object \"%s\""));
+EXTERN char e_builtin_object_method_str_not_supported[]
+ INIT(= N_("E1412: Builtin object method \"%s\" not supported"));
+EXTERN char e_builtin_class_method_not_supported[]
+ INIT(= N_("E1413: Builtin class method not supported"));
#endif
-// E1412 - E1499 unused (reserved for Vim9 class support)
+// E1415 - E1499 unused (reserved for Vim9 class support)
EXTERN char e_cannot_mix_positional_and_non_positional_str[]
INIT(= N_("E1500: Cannot mix positional and non-positional arguments: %s"));
EXTERN char e_fmt_arg_nr_unused_str[]
@@ -3602,3 +3609,9 @@ EXTERN char e_xattr_other[]
INIT(= N_("E1509: Error occurred when reading or writing extended attribute"));
EXTERN char e_val_too_large[]
INIT(= N_("E1510: Value too large: %s"));
+EXTERN char e_wrong_number_of_characters_for_field_str[]
+ INIT(= N_("E1511: Wrong number of characters for field \"%s\""));
+EXTERN char e_wrong_character_width_for_field_str[]
+ INIT(= N_("E1512: Wrong character width for field \"%s\""));
+EXTERN char e_winfixbuf_cannot_go_to_buffer[]
+ INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled"));
diff --git a/src/eval.c b/src/eval.c
index 815d13d..69b8374 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1901,7 +1901,7 @@ set_var_lval(
&& !tv_check_lock(&di->di_tv, lp->ll_name, FALSE)))
&& tv_op(&tv, rettv, op) == OK)
set_var_const(lp->ll_name, lp->ll_sid, NULL, &tv, FALSE,
- ASSIGN_NO_DECL, 0);
+ ASSIGN_NO_DECL | ASSIGN_COMPOUND_OP, 0);
clear_tv(&tv);
}
}
@@ -2699,6 +2699,9 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
/*
* To be called after eval_next_non_blank() sets "getnext" to TRUE.
* Only called for Vim9 script.
+ *
+ * If "arg" is not NULL, then the caller should assign the return value to
+ * "arg".
*/
char_u *
eval_next_line(char_u *arg, evalarg_T *evalarg)
@@ -2747,8 +2750,12 @@ eval_next_line(char_u *arg, evalarg_T *evalarg)
}
// Advanced to the next line, "arg" no longer points into the previous
- // line.
- evalarg->eval_using_cmdline = FALSE;
+ // line. The caller assigns the return value to "arg".
+ // If "arg" is NULL, then the return value is discarded. In that case,
+ // "arg" still points to the previous line. So don't reset
+ // "eval_using_cmdline".
+ if (arg != NULL)
+ evalarg->eval_using_cmdline = FALSE;
return skipwhite(line);
}
@@ -6311,36 +6318,9 @@ echo_string_core(
break;
case VAR_OBJECT:
- {
- garray_T ga;
- ga_init2(&ga, 1, 50);
- ga_concat(&ga, (char_u *)"object of ");
- object_T *obj = tv->vval.v_object;
- class_T *cl = obj == NULL ? NULL : obj->obj_class;
- ga_concat(&ga, cl == NULL ? (char_u *)"[unknown]"
- : cl->class_name);
- if (cl != NULL)
- {
- ga_concat(&ga, (char_u *)" {");
- for (int i = 0; i < cl->class_obj_member_count; ++i)
- {
- if (i > 0)
- ga_concat(&ga, (char_u *)", ");
- ocmember_T *m = &cl->class_obj_members[i];
- ga_concat(&ga, m->ocm_name);
- ga_concat(&ga, (char_u *)": ");
- char_u *tf = NULL;
- ga_concat(&ga, echo_string_core(
- (typval_T *)(obj + 1) + i,
- &tf, numbuf, copyID, echo_style,
- restore_copyID, composite_val));
- vim_free(tf);
- }
- ga_concat(&ga, (char_u *)"}");
- }
-
- *tofree = r = ga.ga_data;
- }
+ *tofree = r = object_string(tv->vval.v_object, numbuf, copyID,
+ echo_style, restore_copyID,
+ composite_val);
break;
case VAR_FLOAT:
@@ -6488,7 +6468,7 @@ var2fpos(
if (charcol)
len = (long)mb_charlen(ml_get(pos.lnum));
else
- len = (long)STRLEN(ml_get(pos.lnum));
+ len = (long)ml_get_len(pos.lnum);
// Get the column number
// We accept "$" for the column number: last column.
@@ -6594,7 +6574,7 @@ var2fpos(
if (charcol)
pos.col = (colnr_T)mb_charlen(ml_get_curline());
else
- pos.col = (colnr_T)STRLEN(ml_get_curline());
+ pos.col = ml_get_curline_len();
}
return &pos;
}
diff --git a/src/evalbuffer.c b/src/evalbuffer.c
index e611c52..6ec734d 100644
--- a/src/evalbuffer.c
+++ b/src/evalbuffer.c
@@ -653,6 +653,7 @@ get_buffer_info(buf_T *buf)
dict_add_number(dict, "changedtick", CHANGEDTICK(buf));
dict_add_number(dict, "hidden",
buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0);
+ dict_add_number(dict, "command", buf == cmdwin_buf);
// Get a reference to buffer variables
dict_add_dict(dict, "variables", buf->b_vars);
diff --git a/src/evalfunc.c b/src/evalfunc.c
index e37b3a4..14650ca 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -63,15 +63,16 @@ static void f_get(typval_T *argvars, typval_T *rettv);
static void f_getchangelist(typval_T *argvars, typval_T *rettv);
static void f_getcharpos(typval_T *argvars, typval_T *rettv);
static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
+static void f_getcurpos(typval_T *argvars, typval_T *rettv);
+static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv);
static void f_getenv(typval_T *argvars, typval_T *rettv);
static void f_getfontname(typval_T *argvars, typval_T *rettv);
static void f_getjumplist(typval_T *argvars, typval_T *rettv);
static void f_getpid(typval_T *argvars, typval_T *rettv);
-static void f_getcurpos(typval_T *argvars, typval_T *rettv);
-static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv);
static void f_getpos(typval_T *argvars, typval_T *rettv);
static void f_getreg(typval_T *argvars, typval_T *rettv);
static void f_getreginfo(typval_T *argvars, typval_T *rettv);
+static void f_getregion(typval_T *argvars, typval_T *rettv);
static void f_getregtype(typval_T *argvars, typval_T *rettv);
static void f_gettagstack(typval_T *argvars, typval_T *rettv);
static void f_gettext(typval_T *argvars, typval_T *rettv);
@@ -607,10 +608,11 @@ arg_list_or_dict_or_blob_or_string_mod(
}
/*
- * Check second argument of map() or filter().
+ * Check second argument of map(), filter(), foreach().
*/
static int
-check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map)
+check_map_filter_arg2(type_T *type, argcontext_T *context,
+ filtermap_T filtermap)
{
type_T *expected_member = NULL;
type_T *(args[2]);
@@ -663,12 +665,14 @@ check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map)
{
where_T where = WHERE_INIT;
- if (is_map)
+ if (filtermap == FILTERMAP_MAP)
t_func_exp.tt_member = expected_member == NULL
|| type_any_or_unknown(type->tt_member)
? &t_any : expected_member;
- else
+ else if (filtermap == FILTERMAP_FILTER)
t_func_exp.tt_member = &t_bool;
+ else // filtermap == FILTERMAP_FOREACH
+ t_func_exp.tt_member = &t_unknown;
if (args[0] == NULL)
args[0] = &t_unknown;
if (type->tt_argcount == -1)
@@ -693,7 +697,7 @@ arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
return OK;
if (type->tt_type == VAR_FUNC)
- return check_map_filter_arg2(type, context, FALSE);
+ return check_map_filter_arg2(type, context, FILTERMAP_FILTER);
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
@@ -710,7 +714,24 @@ arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
return OK;
if (type->tt_type == VAR_FUNC)
- return check_map_filter_arg2(type, context, TRUE);
+ return check_map_filter_arg2(type, context, FILTERMAP_MAP);
+ semsg(_(e_string_or_function_required_for_argument_nr), 2);
+ return FAIL;
+}
+
+/*
+ * Check second argument of foreach(), the function.
+ */
+ static int
+arg_foreach_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
+{
+ if (type->tt_type == VAR_STRING
+ || type->tt_type == VAR_PARTIAL
+ || type_any_or_unknown(type))
+ return OK;
+
+ if (type->tt_type == VAR_FUNC)
+ return check_map_filter_arg2(type, context, FILTERMAP_FOREACH);
semsg(_(e_string_or_function_required_for_argument_nr), 2);
return FAIL;
}
@@ -965,6 +986,7 @@ arg_len1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
|| type->tt_type == VAR_BLOB
|| type->tt_type == VAR_LIST
|| type->tt_type == VAR_DICT
+ || type->tt_type == VAR_OBJECT
|| type_any_or_unknown(type))
return OK;
@@ -1128,7 +1150,9 @@ static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_num
static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, arg_any};
static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any};
static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number};
+static argcheck_T arg3_diff[] = {arg_list_string, arg_list_string, arg_dict_any};
static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any};
+static argcheck_T arg3_list_list_dict[] = {arg_list_any, arg_list_any, arg_dict_any};
static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool};
static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
static argcheck_T arg3_number_any_dict[] = {arg_number, arg_any, arg_dict_any};
@@ -1173,6 +1197,7 @@ static argcheck_T arg1_len[] = {arg_len1};
static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr};
static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool};
static argcheck_T arg2_filter[] = {arg_list_or_dict_or_blob_or_string_mod, arg_filter_func};
+static argcheck_T arg2_foreach[] = {arg_list_or_dict_or_blob_or_string, arg_foreach_func};
static argcheck_T arg2_instanceof[] = {arg_object, varargs_class, NULL };
static argcheck_T arg2_map[] = {arg_list_or_dict_or_blob_or_string_mod, arg_map_func};
static argcheck_T arg2_mapnew[] = {arg_list_or_dict_or_blob_or_string, arg_any};
@@ -1929,6 +1954,8 @@ static funcentry_T global_functions[] =
ret_number_bool, f_deletebufline},
{"did_filetype", 0, 0, 0, NULL,
ret_number_bool, f_did_filetype},
+ {"diff", 2, 3, FEARG_1, arg3_diff,
+ ret_any, f_diff},
{"diff_filler", 1, 1, FEARG_1, arg1_lnum,
ret_number, f_diff_filler},
{"diff_hlID", 2, 2, FEARG_1, arg2_lnum_number,
@@ -2013,6 +2040,8 @@ static funcentry_T global_functions[] =
ret_string, f_foldtext},
{"foldtextresult", 1, 1, FEARG_1, arg1_lnum,
ret_string, f_foldtextresult},
+ {"foreach", 2, 2, FEARG_1, arg2_foreach,
+ ret_first_arg, f_foreach},
{"foreground", 0, 0, 0, NULL,
ret_void, f_foreground},
{"fullcommand", 1, 2, FEARG_1, arg2_string_bool,
@@ -2105,6 +2134,8 @@ static funcentry_T global_functions[] =
ret_getreg, f_getreg},
{"getreginfo", 0, 1, FEARG_1, arg1_string,
ret_dict_any, f_getreginfo},
+ {"getregion", 2, 3, FEARG_1, arg3_list_list_dict,
+ ret_list_string, f_getregion},
{"getregtype", 0, 1, FEARG_1, arg1_string,
ret_string, f_getregtype},
{"getscriptinfo", 0, 1, 0, arg1_dict_any,
@@ -3606,7 +3637,7 @@ get_col(typval_T *argvars, typval_T *rettv, int charcol)
{
// '> can be MAXCOL, get the length of the line then
if (fp->lnum <= curbuf->b_ml.ml_line_count)
- col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
+ col = ml_get_len(fp->lnum) + 1;
else
col = MAXCOL;
}
@@ -3951,7 +3982,7 @@ f_empty(typval_T *argvars, typval_T *rettv)
n = argvars[0].vval.v_class != NULL;
break;
case VAR_OBJECT:
- n = argvars[0].vval.v_object != NULL;
+ n = object_empty(argvars[0].vval.v_object);
break;
case VAR_BLOB:
@@ -5427,6 +5458,229 @@ f_getpos(typval_T *argvars, typval_T *rettv)
}
/*
+ * Convert from block_def to string
+ */
+ static char_u *
+block_def2str(struct block_def *bd)
+{
+ char_u *p, *ret;
+ size_t size = bd->startspaces + bd->endspaces + bd->textlen;
+
+ ret = alloc(size + 1);
+ if (ret != NULL)
+ {
+ p = ret;
+ vim_memset(p, ' ', bd->startspaces);
+ p += bd->startspaces;
+ mch_memmove(p, bd->textstart, bd->textlen);
+ p += bd->textlen;
+ vim_memset(p, ' ', bd->endspaces);
+ *(p + bd->endspaces) = NUL;
+ }
+ return ret;
+}
+
+/*
+ * "getregion()" function
+ */
+ static void
+f_getregion(typval_T *argvars, typval_T *rettv)
+{
+ linenr_T lnum;
+ oparg_T oa;
+ struct block_def bd;
+ char_u *akt = NULL;
+ int inclusive = TRUE;
+ int fnum1 = -1, fnum2 = -1;
+ pos_T p1, p2;
+ char_u *type;
+ buf_T *save_curbuf;
+ buf_T *findbuf;
+ char_u default_type[] = "v";
+ int save_virtual;
+ int l;
+ int region_type = -1;
+ int is_select_exclusive;
+
+ if (rettv_list_alloc(rettv) == FAIL)
+ return;
+
+ if (check_for_list_arg(argvars, 0) == FAIL
+ || check_for_list_arg(argvars, 1) == FAIL
+ || check_for_opt_dict_arg(argvars, 2) == FAIL)
+ return;
+
+ if (list2fpos(&argvars[0], &p1, &fnum1, NULL, FALSE) != OK
+ || list2fpos(&argvars[1], &p2, &fnum2, NULL, FALSE) != OK
+ || fnum1 != fnum2)
+ return;
+
+ if (argvars[2].v_type == VAR_DICT)
+ {
+ is_select_exclusive = dict_get_bool(
+ argvars[2].vval.v_dict, "exclusive", *p_sel == 'e');
+ type = dict_get_string(
+ argvars[2].vval.v_dict, "type", FALSE);
+ if (type == NULL)
+ type = default_type;
+ }
+ else
+ {
+ is_select_exclusive = *p_sel == 'e';
+ type = default_type;
+ }
+
+ if (type[0] == 'v' && type[1] == NUL)
+ region_type = MCHAR;
+ else if (type[0] == 'V' && type[1] == NUL)
+ region_type = MLINE;
+ else if (type[0] == Ctrl_V && type[1] == NUL)
+ region_type = MBLOCK;
+ else
+ {
+ semsg(_(e_invalid_value_for_argument_str_str), "type", type);
+ return;
+ }
+
+ findbuf = fnum1 != 0 ? buflist_findnr(fnum1) : curbuf;
+ if (findbuf == NULL || findbuf->b_ml.ml_mfp == NULL)
+ {
+ emsg(_(e_buffer_is_not_loaded));
+ return;
+ }
+
+ if (p1.lnum < 1 || p1.lnum > findbuf->b_ml.ml_line_count)
+ {
+ semsg(_(e_invalid_line_number_nr), p1.lnum);
+ return;
+ }
+ if (p1.col < 1 || p1.col > ml_get_buf_len(findbuf, p1.lnum) + 1)
+ {
+ semsg(_(e_invalid_column_number_nr), p1.col);
+ return;
+ }
+ if (p2.lnum < 1 || p2.lnum > findbuf->b_ml.ml_line_count)
+ {
+ semsg(_(e_invalid_line_number_nr), p2.lnum);
+ return;
+ }
+ if (p2.col < 1 || p2.col > ml_get_buf_len(findbuf, p2.lnum) + 1)
+ {
+ semsg(_(e_invalid_column_number_nr), p2.col);
+ return;
+ }
+
+ save_curbuf = curbuf;
+ curbuf = findbuf;
+ curwin->w_buffer = curbuf;
+ save_virtual = virtual_op;
+ virtual_op = virtual_active();
+
+ // NOTE: Adjust is needed.
+ p1.col--;
+ p2.col--;
+
+ if (!LT_POS(p1, p2))
+ {
+ // swap position
+ pos_T p;
+
+ p = p1;
+ p1 = p2;
+ p2 = p;
+ }
+
+ if (region_type == MCHAR)
+ {
+ // handle 'selection' == "exclusive"
+ if (is_select_exclusive && !EQUAL_POS(p1, p2))
+ {
+ if (p2.coladd > 0)
+ p2.coladd--;
+ else if (p2.col > 0)
+ {
+ p2.col--;
+
+ mb_adjustpos(curbuf, &p2);
+ }
+ else if (p2.lnum > 1)
+ {
+ p2.lnum--;
+ p2.col = ml_get_len(p2.lnum);
+ if (p2.col > 0)
+ {
+ p2.col--;
+
+ mb_adjustpos(curbuf, &p2);
+ }
+ }
+ }
+ // if fp2 is on NUL (empty line) inclusive becomes false
+ if (*ml_get_pos(&p2) == NUL && !virtual_op)
+ inclusive = FALSE;
+ }
+ else if (region_type == MBLOCK)
+ {
+ colnr_T sc1, ec1, sc2, ec2;
+
+ getvvcol(curwin, &p1, &sc1, NULL, &ec1);
+ getvvcol(curwin, &p2, &sc2, NULL, &ec2);
+ oa.motion_type = MBLOCK;
+ oa.inclusive = TRUE;
+ oa.op_type = OP_NOP;
+ oa.start = p1;
+ oa.end = p2;
+ oa.start_vcol = MIN(sc1, sc2);
+ if (is_select_exclusive && ec1 < sc2 && 0 < sc2 && ec2 > ec1)
+ oa.end_vcol = sc2 - 1;
+ else
+ oa.end_vcol = MAX(ec1, ec2);
+ }
+
+ // Include the trailing byte of a multi-byte char.
+ l = utfc_ptr2len((char_u *)ml_get_pos(&p2));
+ if (l > 1)
+ p2.col += l - 1;
+
+ for (lnum = p1.lnum; lnum <= p2.lnum; lnum++)
+ {
+ int ret = 0;
+
+ if (region_type == MLINE)
+ akt = vim_strsave(ml_get(lnum));
+ else if (region_type == MBLOCK)
+ {
+ block_prep(&oa, &bd, lnum, FALSE);
+ akt = block_def2str(&bd);
+ }
+ else if (p1.lnum < lnum && lnum < p2.lnum)
+ akt = vim_strsave(ml_get(lnum));
+ else
+ {
+ charwise_block_prep(p1, p2, &bd, lnum, inclusive);
+ akt = block_def2str(&bd);
+ }
+
+ if (akt)
+ {
+ ret = list_append_string(rettv->vval.v_list, akt, -1);
+ vim_free(akt);
+ }
+
+ if (akt == NULL || ret == FAIL)
+ {
+ clear_tv(rettv);
+ (void)rettv_list_alloc(rettv);
+ break;
+ }
+ }
+
+ curbuf = save_curbuf;
+ curwin->w_buffer = curbuf;
+ virtual_op = save_virtual;
+}
+
+/*
* Common between getreg(), getreginfo() and getregtype(): get the register
* name from the first argument.
* Returns zero on error.
@@ -7613,6 +7867,9 @@ f_len(typval_T *argvars, typval_T *rettv)
case VAR_DICT:
rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
break;
+ case VAR_OBJECT:
+ rettv->vval.v_number = object_len(argvars[0].vval.v_object);
+ break;
case VAR_UNKNOWN:
case VAR_ANY:
case VAR_VOID:
@@ -7625,7 +7882,6 @@ f_len(typval_T *argvars, typval_T *rettv)
case VAR_CHANNEL:
case VAR_INSTR:
case VAR_CLASS:
- case VAR_OBJECT:
case VAR_TYPEALIAS:
emsg(_(e_invalid_type_for_len));
break;
@@ -10878,7 +11134,7 @@ f_synID(typval_T *argvars UNUSED, typval_T *rettv)
trans = (int)tv_get_bool_chk(&argvars[2], &transerr);
if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
- && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
+ && col >= 0 && col < (long)ml_get_len(lnum))
id = syn_get_id(curwin, lnum, col, trans, NULL, FALSE);
#endif
@@ -11055,7 +11311,7 @@ f_synconcealed(typval_T *argvars UNUSED, typval_T *rettv)
if (rettv_list_alloc(rettv) == OK)
{
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
- && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
+ && col >= 0 && col <= (long)ml_get_len(lnum)
&& curwin->w_p_cole > 0)
{
(void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE);
@@ -11112,7 +11368,7 @@ f_synstack(typval_T *argvars UNUSED, typval_T *rettv)
col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
- && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
+ && col >= 0 && col <= (long)ml_get_len(lnum)
&& rettv_list_alloc(rettv) == OK)
{
(void)syn_get_id(curwin, lnum, col, FALSE, NULL, TRUE);
@@ -11290,7 +11546,7 @@ f_virtcol(typval_T *argvars, typval_T *rettv)
fp->col = 0;
else
{
- len = (int)STRLEN(ml_get(fp->lnum));
+ len = (int)ml_get_len(fp->lnum);
if (fp->col > len)
fp->col = len;
}
diff --git a/src/evalvars.c b/src/evalvars.c
index 8e42c5a..de9d5b2 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -3830,7 +3830,7 @@ set_var(
* If the variable already exists and "is_const" is FALSE the value is updated.
* Otherwise the variable is created.
*/
- void
+ int
set_var_const(
char_u *name,
scid_T sid,
@@ -3854,6 +3854,7 @@ set_var_const(
int var_in_autoload = FALSE;
int flags = flags_arg;
int free_tv_arg = !copy; // free tv_arg if not used
+ int rc = FAIL;
if (sid != 0)
{
@@ -3977,7 +3978,14 @@ set_var_const(
if (check_typval_is_value(&di->di_tv) == FAIL)
goto failed;
- if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
+ // List and Blob types can be modified in-place using the "+="
+ // compound operator. For other types, this is not allowed.
+ int type_inplace_modifiable =
+ (di->di_tv.v_type == VAR_LIST || di->di_tv.v_type == VAR_BLOB);
+
+ if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0
+ && ((flags & ASSIGN_COMPOUND_OP) == 0
+ || !type_inplace_modifiable))
{
where_T where = WHERE_INIT;
svar_T *sv = find_typval_in_script(&di->di_tv, sid, TRUE);
@@ -3998,7 +4006,11 @@ set_var_const(
}
}
- if ((flags & ASSIGN_FOR_LOOP) == 0
+ // Modifying a final variable with a List value using the "+="
+ // operator is allowed. For other types, it is not allowed.
+ if (((flags & ASSIGN_FOR_LOOP) == 0
+ && ((flags & ASSIGN_COMPOUND_OP) == 0
+ || !type_inplace_modifiable))
? var_check_permission(di, name) == FAIL
: var_check_ro(di->di_flags, name, FALSE))
goto failed;
@@ -4116,10 +4128,14 @@ set_var_const(
// values.
item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);
+ rc = OK;
+
failed:
vim_free(name_tofree);
if (free_tv_arg)
clear_tv(tv_arg);
+
+ return rc;
}
/*
@@ -4832,6 +4848,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
{
tabpage_T *save_curtab;
tabpage_T *tp;
+ tabpage_T *save_lu_tp;
char_u *varname, *tabvarname;
typval_T *varp;
@@ -4851,6 +4868,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
return;
save_curtab = curtab;
+ save_lu_tp = lastused_tabpage;
goto_tabpage_tp(tp, FALSE, FALSE);
tabvarname = alloc(STRLEN(varname) + 3);
@@ -4862,9 +4880,13 @@ f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
vim_free(tabvarname);
}
- // Restore current tabpage
+ // Restore current tabpage and last accessed tabpage.
if (valid_tabpage(save_curtab))
+ {
goto_tabpage_tp(save_curtab, FALSE, FALSE);
+ if (valid_tabpage(save_lu_tp))
+ lastused_tabpage = save_lu_tp;
+ }
}
/*
@@ -4924,6 +4946,10 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
if (*varname == '&')
{
aco_save_T aco;
+ // safe the current window position, it could
+ // change because of 'scrollbind' window-local
+ // options
+ linenr_T old_topline = curwin->w_topline;
// Set curbuf to be our buf, temporarily.
aucmd_prepbuf(&aco, buf);
@@ -4935,6 +4961,7 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
// reset notion of buffer
aucmd_restbuf(&aco);
}
+ curwin->w_topline = old_topline;
}
else
{
diff --git a/src/evalwindow.c b/src/evalwindow.c
index fde90f2..ceca2c9 100644
--- a/src/evalwindow.c
+++ b/src/evalwindow.c
@@ -824,11 +824,15 @@ f_win_gotoid(typval_T *argvars, typval_T *rettv)
return;
id = tv_get_number(&argvars[0]);
- if (cmdwin_type != 0)
+ if (curwin->w_id == id)
{
- emsg(_(e_invalid_in_cmdline_window));
+ // Nothing to do.
+ rettv->vval.v_number = 1;
return;
}
+
+ if (text_or_buf_locked())
+ return;
#if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
if (popup_is_popup(curwin) && curbuf->b_term != NULL)
{
@@ -953,59 +957,17 @@ f_win_screenpos(typval_T *argvars, typval_T *rettv)
}
/*
- * Move the window wp into a new split of targetwin in a given direction
- */
- static void
-win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
-{
- int dir;
- int height = wp->w_height;
- win_T *oldwin = curwin;
-
- if (wp == targetwin)
- return;
-
- // Jump to the target window
- if (curwin != targetwin)
- win_goto(targetwin);
-
- // Remove the old window and frame from the tree of frames
- (void)winframe_remove(wp, &dir, NULL);
- win_remove(wp, NULL);
- last_status(FALSE); // may need to remove last status line
- (void)win_comp_pos(); // recompute window positions
-
- // Split a window on the desired side and put the old window there
- (void)win_split_ins(size, flags, wp, dir);
-
- // If splitting horizontally, try to preserve height
- if (size == 0 && !(flags & WSP_VERT))
- {
- win_setheight_win(height, wp);
- if (p_ea)
- win_equal(wp, TRUE, 'v');
- }
-
-#if defined(FEAT_GUI)
- // When 'guioptions' includes 'L' or 'R' may have to remove or add
- // scrollbars. Have to update them anyway.
- gui_may_update_scrollbars();
-#endif
-
- if (oldwin != curwin)
- win_goto(oldwin);
-}
-
-/*
* "win_splitmove()" function
*/
void
f_win_splitmove(typval_T *argvars, typval_T *rettv)
{
- win_T *wp;
- win_T *targetwin;
+ win_T *wp, *targetwin;
+ win_T *oldwin = curwin;
int flags = 0, size = 0;
+ rettv->vval.v_number = -1;
+
if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL
|| check_for_number_arg(argvars, 1) == FAIL
@@ -1020,7 +982,6 @@ f_win_splitmove(typval_T *argvars, typval_T *rettv)
|| win_valid_popup(wp) || win_valid_popup(targetwin))
{
emsg(_(e_invalid_window_number));
- rettv->vval.v_number = -1;
return;
}
@@ -1040,7 +1001,24 @@ f_win_splitmove(typval_T *argvars, typval_T *rettv)
size = (int)dict_get_number(d, "size");
}
- win_move_into_split(wp, targetwin, size, flags);
+ // Check if we're allowed to continue before we bother switching windows.
+ if (text_or_buf_locked() || check_split_disallowed(wp) == FAIL)
+ return;
+
+ if (curwin != targetwin)
+ win_goto(targetwin);
+
+ // Autocommands may have sent us elsewhere or closed "wp" or "oldwin".
+ if (curwin == targetwin && win_valid(wp))
+ {
+ if (win_splitmove(wp, size, flags) == OK)
+ rettv->vval.v_number = 0;
+ }
+ else
+ emsg(_(e_autocommands_caused_command_to_abort));
+
+ if (oldwin != curwin && win_valid(oldwin))
+ win_goto(oldwin);
}
/*
@@ -1076,7 +1054,7 @@ f_win_gettype(typval_T *argvars, typval_T *rettv)
else if (WIN_IS_POPUP(wp))
rettv->vval.v_string = vim_strsave((char_u *)"popup");
#endif
- else if (wp == curwin && cmdwin_type != 0)
+ else if (wp == cmdwin_win)
rettv->vval.v_string = vim_strsave((char_u *)"command");
#ifdef FEAT_QUICKFIX
else if (bt_quickfix(wp->w_buffer))
@@ -1373,13 +1351,8 @@ switch_win_noblock(
switchwin->sw_curtab = curtab;
if (no_display)
{
- curtab->tp_firstwin = firstwin;
- curtab->tp_lastwin = lastwin;
- curtab->tp_topframe = topframe;
- curtab = tp;
- firstwin = curtab->tp_firstwin;
- lastwin = curtab->tp_lastwin;
- topframe = curtab->tp_topframe;
+ unuse_tabpage(curtab);
+ use_tabpage(tp);
}
else
goto_tabpage_tp(tp, FALSE, FALSE);
@@ -1417,13 +1390,12 @@ restore_win_noblock(
{
if (no_display)
{
- curtab->tp_firstwin = firstwin;
- curtab->tp_lastwin = lastwin;
- curtab->tp_topframe = topframe;
- curtab = switchwin->sw_curtab;
- firstwin = curtab->tp_firstwin;
- lastwin = curtab->tp_lastwin;
- topframe = curtab->tp_topframe;
+ win_T *old_tp_curwin = curtab->tp_curwin;
+
+ unuse_tabpage(curtab);
+ // Don't change the curwin of the tabpage we temporarily visited.
+ curtab->tp_curwin = old_tp_curwin;
+ use_tabpage(switchwin->sw_curtab);
}
else
goto_tabpage_tp(switchwin->sw_curtab, FALSE, FALSE);
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index d8e891c..864f89d 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -323,7 +323,7 @@ sort_compare(const void *s1, const void *s2)
if (sort_nr)
{
if (l1.st_u.num.is_number != l2.st_u.num.is_number)
- result = l1.st_u.num.is_number - l2.st_u.num.is_number;
+ result = l1.st_u.num.is_number > l2.st_u.num.is_number ? 1 : -1;
else
result = l1.st_u.num.value == l2.st_u.num.value ? 0
: l1.st_u.num.value > l2.st_u.num.value ? 1 : -1;
@@ -489,7 +489,7 @@ ex_sort(exarg_T *eap)
for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
{
s = ml_get(lnum);
- len = (int)STRLEN(s);
+ len = ml_get_len(lnum);
if (maxlen < len)
maxlen = len;
@@ -691,7 +691,7 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
return FAIL;
for (extra = 0, l = line1; l <= line2; l++)
{
- str = vim_strsave(ml_get(l + extra));
+ str = vim_strnsave(ml_get(l + extra), ml_get_len(l + extra));
if (str != NULL)
{
ml_append(dest + l - line1, str, (colnr_T)0, FALSE);
@@ -824,9 +824,9 @@ ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
curwin->w_cursor.lnum = n;
while (line1 <= line2)
{
- // need to use vim_strsave() because the line will be unlocked within
+ // need to make a copy because the line will be unlocked within
// ml_append()
- p = vim_strsave(ml_get(line1));
+ p = vim_strnsave(ml_get(line1), ml_get_len(line1));
if (p != NULL)
{
ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
@@ -2428,6 +2428,9 @@ getfile(
int retval;
char_u *free_me = NULL;
+ if (!check_can_set_curbuf_forceit(forceit))
+ return GETFILE_ERROR;
+
if (text_locked())
return GETFILE_ERROR;
if (curbuf_locked())
@@ -2782,9 +2785,16 @@ do_ecmd(
{
bufref_T save_au_new_curbuf;
int save_cmdwin_type = cmdwin_type;
+ win_T *save_cmdwin_win = cmdwin_win;
+
+ // Should only be possible to get here if the cmdwin is closed, or
+ // if it's opening and its buffer hasn't been set yet (the new
+ // buffer is for it).
+ assert(cmdwin_buf == NULL);
// BufLeave applies to the old buffer.
cmdwin_type = 0;
+ cmdwin_win = NULL;
/*
* Be careful: The autocommands may delete any buffer and change
@@ -2801,7 +2811,10 @@ do_ecmd(
save_au_new_curbuf = au_new_curbuf;
set_bufref(&au_new_curbuf, buf);
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
+
cmdwin_type = save_cmdwin_type;
+ cmdwin_win = save_cmdwin_win;
+
if (!bufref_valid(&au_new_curbuf))
{
// new buffer has been deleted
@@ -4212,7 +4225,8 @@ ex_substitute(exarg_T *eap)
if (sub_firstline == NULL)
{
- sub_firstline = vim_strsave(ml_get(sub_firstlnum));
+ sub_firstline = vim_strnsave(ml_get(sub_firstlnum),
+ ml_get_len(sub_firstlnum));
if (sub_firstline == NULL)
{
vim_free(new_start);
@@ -4366,7 +4380,8 @@ ex_substitute(exarg_T *eap)
// really update the line, it would change
// what matches. Temporarily replace the line
// and change it back afterwards.
- orig_line = vim_strsave(ml_get(lnum));
+ orig_line = vim_strnsave(ml_get(lnum),
+ ml_get_len(lnum));
if (orig_line != NULL)
{
char_u *new_line = concat_str(new_start,
@@ -4712,7 +4727,8 @@ ex_substitute(exarg_T *eap)
{
sub_firstlnum += nmatch - 1;
vim_free(sub_firstline);
- sub_firstline = vim_strsave(ml_get(sub_firstlnum));
+ sub_firstline = vim_strnsave(ml_get(sub_firstlnum),
+ ml_get_len(sub_firstlnum));
// When going beyond the last line, stop substituting.
if (sub_firstlnum <= line2)
do_again = TRUE;
@@ -5425,8 +5441,7 @@ ex_smile(exarg_T *eap UNUSED)
/*
* ":drop"
- * Opens the first argument in a window. When there are two or more arguments
- * the argument list is redefined.
+ * Opens the first argument in a window, and the argument list is redefined.
*/
void
ex_drop(exarg_T *eap)
@@ -5463,6 +5478,8 @@ ex_drop(exarg_T *eap)
// edited in a window yet. It's like ":tab all" but without closing
// windows or tabs.
ex_all(eap);
+ cmdmod.cmod_tab = 0;
+ ex_rewind(eap);
return;
}
@@ -5486,6 +5503,8 @@ ex_drop(exarg_T *eap)
buf_check_timestamp(curbuf, FALSE);
curbuf->b_p_ar = save_ar;
}
+ if (curbuf->b_ml.ml_flags & ML_EMPTY)
+ ex_rewind(eap);
return;
}
}
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 4ae6cc2..bd26e81 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -521,7 +521,7 @@ EXCMD(CMD_doautoall, "doautoall", ex_doautoall,
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
EXCMD(CMD_drop, "drop", ex_drop,
- EX_FILES|EX_CMDARG|EX_NEEDARG|EX_ARGOPT|EX_TRLBAR,
+ EX_BANG|EX_FILES|EX_CMDARG|EX_NEEDARG|EX_ARGOPT|EX_TRLBAR,
ADDR_NONE),
EXCMD(CMD_dsearch, "dsearch", ex_findpat,
EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK,
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index 0bde730..4a6f519 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -457,6 +457,36 @@ ex_listdo(exarg_T *eap)
tabpage_T *tp;
buf_T *buf = curbuf;
int next_fnum = 0;
+
+ if (curwin->w_p_wfb)
+ {
+ if ((eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) &&
+ !eap->forceit)
+ {
+ // Disallow :ldo if 'winfixbuf' is applied
+ emsg(_(e_winfixbuf_cannot_go_to_buffer));
+ return;
+ }
+
+ if (win_valid(prevwin) && !prevwin->w_p_wfb)
+ // 'winfixbuf' is set; attempt to change to a window without it.
+ win_goto(prevwin);
+ if (curwin->w_p_wfb)
+ {
+ // Split the window, which will be 'nowinfixbuf', and set curwin to
+ // that
+ (void)win_split(0, 0);
+
+ if (curwin->w_p_wfb)
+ {
+ // Autocommands set 'winfixbuf' or sent us to another window
+ // with it set, or we failed to split the window. Give up.
+ emsg(_(e_winfixbuf_cannot_go_to_buffer));
+ return;
+ }
+ }
+ }
+
#if defined(FEAT_SYN_HL)
char_u *save_ei = NULL;
#endif
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index c18a910..19b1d85 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7164,6 +7164,9 @@ ex_resize(exarg_T *eap)
static void
ex_find(exarg_T *eap)
{
+ if (!check_can_set_curbuf_forceit(eap->forceit))
+ return;
+
char_u *fname;
int count;
char_u *file_to_find = NULL;
@@ -7245,6 +7248,14 @@ ex_open(exarg_T *eap)
static void
ex_edit(exarg_T *eap)
{
+ // Exclude commands which keep the window's current buffer
+ if (
+ eap->cmdidx != CMD_badd
+ && eap->cmdidx != CMD_balt
+ // All other commands must obey 'winfixbuf' / ! rules
+ && !check_can_set_curbuf_forceit(eap->forceit))
+ return;
+
do_exedit(eap, NULL);
}
@@ -9031,7 +9042,7 @@ ex_checkpath(exarg_T *eap)
{
find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
- (linenr_T)1, (linenr_T)MAXLNUM);
+ (linenr_T)1, (linenr_T)MAXLNUM, eap->forceit);
}
#if defined(FEAT_QUICKFIX)
@@ -9101,7 +9112,7 @@ ex_findpat(exarg_T *eap)
find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
whole, !eap->forceit,
*eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
- n, action, eap->line1, eap->line2);
+ n, action, eap->line1, eap->line2, eap->forceit);
}
#endif
diff --git a/src/ex_getln.c b/src/ex_getln.c
index f2a960e..1731d29 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -4458,6 +4458,8 @@ open_cmdwin(void)
#ifdef FEAT_FOLDING
int save_KeyTyped;
#endif
+ int newbuf_status;
+ int cmdwin_valid;
// Can't do this when text or buffer is locked.
// Can't do this recursively. Can't do it when typing a password.
@@ -4491,25 +4493,50 @@ open_cmdwin(void)
ga_clear(&winsizes);
return K_IGNORE;
}
+ // win_split() autocommands may have messed with the old window or buffer.
+ // Treat it as abandoning this command-line.
+ if (!win_valid(old_curwin) || curwin == old_curwin
+ || !bufref_valid(&old_curbuf)
+ || old_curwin->w_buffer != old_curbuf.br_buf)
+ {
+ beep_flush();
+ ga_clear(&winsizes);
+ return Ctrl_C;
+ }
// Don't let quitting the More prompt make this fail.
got_int = FALSE;
- // Set "cmdwin_type" before any autocommands may mess things up.
+ // Set "cmdwin_..." variables before any autocommands may mess things up.
cmdwin_type = get_cmdline_type();
-
- // Create the command-line buffer empty.
- if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL) == FAIL)
+ cmdwin_win = curwin;
+
+ // Create empty command-line buffer. Be especially cautious of BufLeave
+ // autocommands from do_ecmd(), as cmdwin restrictions do not apply to them!
+ newbuf_status = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE,
+ NULL);
+ cmdwin_valid = win_valid(cmdwin_win);
+ if (newbuf_status == FAIL || !cmdwin_valid || curwin != cmdwin_win ||
+ !win_valid(old_curwin) || !bufref_valid(&old_curbuf) ||
+ old_curwin->w_buffer != old_curbuf.br_buf)
{
- // Some autocommand messed it up?
- win_close(curwin, TRUE);
- ga_clear(&winsizes);
+ if (newbuf_status == OK)
+ set_bufref(&bufref, curbuf);
+ if (cmdwin_valid && !last_window())
+ win_close(cmdwin_win, TRUE);
+
+ // win_close() autocommands may have already deleted the buffer.
+ if (newbuf_status == OK && bufref_valid(&bufref) &&
+ bufref.br_buf != curbuf)
+ close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, FALSE, FALSE);
+
cmdwin_type = 0;
+ cmdwin_win = NULL;
+ beep_flush();
+ ga_clear(&winsizes);
return Ctrl_C;
}
+ cmdwin_buf = curbuf;
- apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
- (void)setfname(curbuf, (char_u *)_("[Command Line]"), NULL, TRUE);
- apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
set_option_value_give_err((char_u *)"bt",
0L, (char_u *)"nofile", OPT_LOCAL);
curbuf->b_p_ma = TRUE;
@@ -4615,14 +4642,17 @@ open_cmdwin(void)
# endif
cmdwin_type = 0;
+ cmdwin_buf = NULL;
+ cmdwin_win = NULL;
exmode_active = save_exmode;
- // Safety check: The old window or buffer was deleted: It's a bug when
- // this happens!
- if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf))
+ // Safety check: The old window or buffer was changed or deleted: It's a bug
+ // when this happens!
+ if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)
+ || old_curwin->w_buffer != old_curbuf.br_buf)
{
cmdwin_result = Ctrl_C;
- emsg(_(e_active_window_or_buffer_deleted));
+ emsg(_(e_active_window_or_buffer_changed_or_deleted));
}
else
{
diff --git a/src/fileio.c b/src/fileio.c
index 180fe39..53bfbea 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1246,7 +1246,7 @@ retry:
for (;;)
{
p = ml_get(read_buf_lnum) + read_buf_col;
- n = (int)STRLEN(p);
+ n = ml_get_len(read_buf_lnum) - read_buf_col;
if ((int)tlen + n + 1 > size)
{
// Filled up to "size", append partial line.
@@ -4489,8 +4489,14 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options)
if (saved == OK)
{
+ int old_msg_silent = msg_silent;
+
curbuf->b_flags |= BF_CHECK_RO; // check for RO again
keep_filetype = TRUE; // don't detect 'filetype'
+
+ if (shortmess(SHM_FILEINFO))
+ msg_silent = 1;
+
if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
(linenr_T)0,
(linenr_T)MAXLNUM, &ea, flags) != OK)
@@ -4514,16 +4520,15 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options)
// Mark the buffer as unmodified and free undo info.
unchanged(buf, TRUE, TRUE);
if ((flags & READ_KEEP_UNDO) == 0)
- {
- u_blockfree(buf);
- u_clearall(buf);
- }
+ u_clearallandblockfree(buf);
else
{
// Mark all undo states as changed.
u_unchanged(curbuf);
}
}
+
+ msg_silent = old_msg_silent;
}
vim_free(ea.cmd);
diff --git a/src/fold.c b/src/fold.c
index 5c41ed1..2cd4dcd 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -107,7 +107,7 @@ copyFoldingState(win_T *wp_from, win_T *wp_to)
// hasAnyFolding() {{{2
/*
- * Return TRUE if there may be folded lines in the current window.
+ * Return TRUE if there may be folded lines in window "win".
*/
int
hasAnyFolding(win_T *win)
@@ -551,7 +551,7 @@ checkCloseRec(garray_T *gap, linenr_T lnum, int level)
return retval;
}
-// foldCreateAllowed() {{{2
+// foldManualAllowed() {{{2
/*
* Return TRUE if it's allowed to manually create or delete a fold.
* Give an error message and return FALSE if not.
@@ -1061,7 +1061,6 @@ find_wl_entry(win_T *win, linenr_T lnum)
foldAdjustVisual(void)
{
pos_T *start, *end;
- char_u *ptr;
if (!VIsual_active || !hasAnyFolding(curwin))
return;
@@ -1082,8 +1081,7 @@ foldAdjustVisual(void)
if (!hasFolding(end->lnum, NULL, &end->lnum))
return;
- ptr = ml_get(end->lnum);
- end->col = (colnr_T)STRLEN(ptr);
+ end->col = ml_get_len(end->lnum);
if (end->col > 0 && *p_sel == 'o')
--end->col;
// prevent cursor from moving on the trail byte
@@ -1091,7 +1089,7 @@ foldAdjustVisual(void)
mb_adjust_cursor();
}
-// cursor_foldstart() {{{2
+// foldAdjustCursor() {{{2
/*
* Move the cursor to the first line of a closed fold.
*/
@@ -1799,7 +1797,7 @@ foldAddMarker(linenr_T lnum, char_u *marker, int markerlen)
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
line = ml_get(lnum);
- line_len = (int)STRLEN(line);
+ line_len = ml_get_len(lnum);
if (u_save(lnum - 1, lnum + 1) != OK)
return;
@@ -1887,7 +1885,7 @@ foldDelMarker(linenr_T lnum, char_u *marker, int markerlen)
if (u_save(lnum - 1, lnum + 1) == OK)
{
// Make new line: text-before-marker + text-after-marker
- newline = alloc(STRLEN(line) - len + 1);
+ newline = alloc(ml_get_len(lnum) - len + 1);
if (newline != NULL)
{
STRNCPY(newline, line, p - line);
diff --git a/src/getchar.c b/src/getchar.c
index 3427a9f..49a24f0 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1339,12 +1339,12 @@ gotchars(char_u *chars, int len)
}
/*
- * Record a <Nop> key.
+ * Record an <Ignore> key.
*/
void
-gotchars_nop(void)
+gotchars_ignore(void)
{
- char_u nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_NOP };
+ char_u nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_IGNORE };
gotchars(nop_buf, 3);
}
@@ -3666,9 +3666,9 @@ vgetorpeek(int advance)
#endif
if (timedout && c == ESC)
{
- // When recording there will be no timeout. Add a <Nop> after the ESC
- // to avoid that it forms a key code with following characters.
- gotchars_nop();
+ // When recording there will be no timeout. Add an <Ignore> after the
+ // ESC to avoid that it forms a key code with following characters.
+ gotchars_ignore();
}
--vgetc_busy;
diff --git a/src/globals.h b/src/globals.h
index b74ef35..f04f19d 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -976,7 +976,7 @@ EXTERN int clip_unnamed_saved INIT(= 0);
*/
EXTERN win_T *firstwin; // first window
EXTERN win_T *lastwin; // last window
-EXTERN win_T *prevwin INIT(= NULL); // previous window
+EXTERN win_T *prevwin INIT(= NULL); // previous window (may equal curwin)
#define ONE_WINDOW (firstwin == lastwin)
#define W_NEXT(wp) ((wp)->w_next)
@@ -1686,6 +1686,8 @@ EXTERN int km_startsel INIT(= FALSE);
EXTERN int cmdwin_type INIT(= 0); // type of cmdline window or 0
EXTERN int cmdwin_result INIT(= 0); // result of cmdline window or 0
+EXTERN buf_T *cmdwin_buf INIT(= NULL); // buffer of cmdline window or NULL
+EXTERN win_T *cmdwin_win INIT(= NULL); // window of cmdline window or NULL
EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--"));
diff --git a/src/gui.c b/src/gui.c
index 16c1b54..1953691 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -455,8 +455,12 @@ gui_init_check(void)
gui.scrollbar_width = gui.scrollbar_height = SB_DEFAULT_WIDTH;
gui.prev_wrap = -1;
-#ifdef FEAT_GUI_GTK
- CLEAR_FIELD(gui.ligatures_map);
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
+ // Note: gui_set_ligatures() might already have been called e.g. from .vimrc,
+ // and in that case we don't want to overwrite ligatures map that has already
+ // been correctly populated (as that would lead to a cleared ligatures maps).
+ if (*p_guiligatures == NUL)
+ CLEAR_FIELD(gui.ligatures_map);
#endif
#if defined(ALWAYS_USE_GUI) || defined(VIMDLL)
@@ -1064,7 +1068,7 @@ gui_get_wide_font(void)
return OK;
}
-#if defined(FEAT_GUI_GTK) || defined(PROTO)
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) || defined(PROTO)
/*
* Set list of ascii characters that combined can create ligature.
* Store them in char map for quick access from gui_gtk2_draw_string.
@@ -1589,8 +1593,11 @@ again:
// Only comparing Rows and Columns may be sufficient, but let's stay on
// the safe side.
if (gui.num_rows != screen_Rows || gui.num_cols != screen_Columns
- || gui.num_rows != Rows || gui.num_cols != Columns)
+ || gui.num_rows != Rows || gui.num_cols != Columns || gui.force_redraw)
+ {
shell_resized();
+ gui.force_redraw = 0;
+ }
#ifdef FEAT_GUI_HAIKU
vim_unlock_screen();
@@ -2688,7 +2695,7 @@ gui_undraw_cursor(void)
int startcol = gui.cursor_col > 0 ? gui.cursor_col - 1 : gui.cursor_col;
int endcol = gui.cursor_col;
-#ifdef FEAT_GUI_GTK
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
gui_adjust_undraw_cursor_for_ligatures(&startcol, &endcol);
#endif
gui_redraw_block(gui.cursor_row, startcol,
@@ -3980,7 +3987,7 @@ gui_drag_scrollbar(scrollbar_T *sb, long value, int still_dragging)
if (hold_gui_events)
return;
- if (cmdwin_type != 0 && sb->wp != curwin)
+ if (cmdwin_type != 0 && sb->wp != cmdwin_win)
return;
if (still_dragging)
diff --git a/src/gui.h b/src/gui.h
index 0a1d274..f9fdd2d 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -176,7 +176,7 @@ typedef struct GuiScrollbar
// to reduce the count.
#endif
-#if FEAT_GUI_HAIKU
+#ifdef FEAT_GUI_HAIKU
VimScrollBar *id; // Pointer to real scroll bar
#endif
#ifdef FEAT_GUI_PHOTON
@@ -259,6 +259,7 @@ typedef struct Gui
int scrollbar_height; // Height of horizontal scrollbar
int left_sbar_x; // Calculated x coord for left scrollbar
int right_sbar_x; // Calculated x coord for right scrollbar
+ int force_redraw; // Force a redraw even e.g. not resized
#ifdef FEAT_MENU
# ifndef FEAT_GUI_GTK
@@ -388,10 +389,12 @@ typedef struct Gui
char_u *browse_fname; // file name from filedlg
guint32 event_time;
+#endif // FEAT_GUI_GTK
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
char_u ligatures_map[256]; // ascii map for characters 0-255, value is
// 1 if in 'guiligatures'
-#endif // FEAT_GUI_GTK
+#endif
#if defined(FEAT_GUI_TABLINE) \
&& (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
diff --git a/src/gui_beval.c b/src/gui_beval.c
index ba8e32e..68b85ee 100644
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -1011,6 +1011,7 @@ cancelBalloon(BalloonEval *beval)
createBalloonEvalWindow(BalloonEval *beval)
{
beval->balloonShell = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_window_set_transient_for(GTK_WINDOW(beval->balloonShell), GTK_WINDOW(gui.mainwin));
gtk_widget_set_app_paintable(beval->balloonShell, TRUE);
gtk_window_set_resizable(GTK_WINDOW(beval->balloonShell), FALSE);
diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c
index 87838b9..d4a8b93 100644
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -116,6 +116,7 @@ enum
TARGET_TEXT,
TARGET_TEXT_URI_LIST,
TARGET_TEXT_PLAIN,
+ TARGET_TEXT_PLAIN_UTF8,
TARGET_VIM,
TARGET_VIMENC
};
@@ -132,7 +133,9 @@ static const GtkTargetEntry selection_targets[] =
{"UTF8_STRING", 0, TARGET_UTF8_STRING},
{"COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT},
{"TEXT", 0, TARGET_TEXT},
- {"STRING", 0, TARGET_STRING}
+ {"STRING", 0, TARGET_STRING},
+ {"text/plain;charset=utf-8", 0, TARGET_TEXT_PLAIN_UTF8},
+ {"text/plain", 0, TARGET_TEXT_PLAIN}
};
#define N_SELECTION_TARGETS ARRAY_LENGTH(selection_targets)
@@ -790,6 +793,36 @@ draw_event(GtkWidget *widget UNUSED,
return FALSE;
}
+
+# if GTK_CHECK_VERSION(3,10,0)
+ static gboolean
+scale_factor_event(GtkWidget *widget,
+ GParamSpec* pspec UNUSED,
+ gpointer user_data UNUSED)
+{
+ if (gui.surface != NULL)
+ cairo_surface_destroy(gui.surface);
+
+ int w, h;
+ gtk_window_get_size(GTK_WINDOW(gui.mainwin), &w, &h);
+ gui.surface = gdk_window_create_similar_surface(
+ gtk_widget_get_window(widget),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ w, h);
+
+ int usable_height = h;
+ if (gtk_socket_id != 0)
+ usable_height -= (gui.char_height - (gui.char_height/2)); // sic.
+
+ gui_gtk_form_freeze(GTK_FORM(gui.formwin));
+ gui.force_redraw = 1;
+ gui_resize_shell(w, usable_height);
+ gui_gtk_form_thaw(GTK_FORM(gui.formwin));
+
+ return TRUE;
+}
+# endif // GTK_CHECK_VERSION(3,10,0)
+
#else // !GTK_CHECK_VERSION(3,0,0)
static gint
expose_event(GtkWidget *widget UNUSED,
@@ -1119,11 +1152,14 @@ modifiers_gdk2vim(guint state)
if (state & GDK_MOD1_MASK)
modifiers |= MOD_MASK_ALT;
#if GTK_CHECK_VERSION(2,10,0)
- if (state & GDK_SUPER_MASK)
+ if (state & GDK_META_MASK)
modifiers |= MOD_MASK_META;
-#endif
+ if (state & GDK_SUPER_MASK)
+ modifiers |= MOD_MASK_CMD;
+#else
if (state & GDK_MOD4_MASK)
- modifiers |= MOD_MASK_META;
+ modifiers |= MOD_MASK_CMD;
+#endif
return modifiers;
}
@@ -1528,6 +1564,8 @@ selection_get_cb(GtkWidget *widget UNUSED,
&& info != (guint)TARGET_VIMENC
&& info != (guint)TARGET_VIM
&& info != (guint)TARGET_COMPOUND_TEXT
+ && info != (guint)TARGET_TEXT_PLAIN
+ && info != (guint)TARGET_TEXT_PLAIN_UTF8
&& info != (guint)TARGET_TEXT)
return;
@@ -1659,11 +1697,12 @@ selection_get_cb(GtkWidget *widget UNUSED,
int
gui_mch_early_init_check(int give_message)
{
- char_u *p;
+ char_u *p, *q;
// Guess that when $DISPLAY isn't set the GUI can't start.
p = mch_getenv((char_u *)"DISPLAY");
- if (p == NULL || *p == NUL)
+ q = mch_getenv((char_u *)"WAYLAND_DISPLAY");
+ if ((p == NULL || *p == NUL) && (q == NULL || *q == NUL))
{
gui.dying = TRUE;
if (give_message)
@@ -1696,7 +1735,10 @@ gui_mch_init_check(void)
#if GTK_CHECK_VERSION(3,10,0)
// Vim currently assumes that Gtk means X11, so it cannot use native Gtk
// support for other backends such as Wayland.
- gdk_set_allowed_backends ("x11");
+ //
+ // Use an environment variable to enable unfinished Wayland support.
+ if (getenv("GVIM_ENABLE_WAYLAND") == NULL)
+ gdk_set_allowed_backends ("x11");
#endif
#ifdef FEAT_GUI_GNOME
@@ -2007,15 +2049,26 @@ button_press_event(GtkWidget *widget,
}
/*
- * GTK+ 2 abstracts scrolling via the GdkEventScroll.
+ * GTK+ abstracts scrolling via the GdkEventScroll.
*/
static gboolean
scroll_event(GtkWidget *widget,
GdkEventScroll *event,
gpointer data UNUSED)
{
- int button;
+ int button = 0; // silence gcc
int_u vim_modifiers;
+#if GTK_CHECK_VERSION(3,4,0)
+ static double acc_x, acc_y;
+#if !GTK_CHECK_VERSION(3,22,0)
+ static guint32 last_smooth_event_time;
+#endif
+#define DT_X11 1
+#define DT_WAYLAND 2
+ static int display_type;
+ if (!display_type)
+ display_type = gui_mch_get_display() ? DT_X11 : DT_WAYLAND;
+#endif
if (gtk_socket_id != 0 && !gtk_widget_has_focus(widget))
gtk_widget_grab_focus(widget);
@@ -2034,6 +2087,29 @@ scroll_event(GtkWidget *widget,
case GDK_SCROLL_RIGHT:
button = MOUSE_6;
break;
+#if GTK_CHECK_VERSION(3,4,0)
+ case GDK_SCROLL_SMOOTH:
+ if (event->is_stop)
+ {
+ acc_x = acc_y = 0;
+ // this event tells us to stop, without an actual moving
+ return FALSE;
+ }
+#if GTK_CHECK_VERSION(3,22,0)
+ if (gdk_device_get_axes(event->device) & GDK_AXIS_FLAG_WHEEL)
+ // this is from a wheel (as oppose to a touchpad / trackpoint)
+#else
+ if (event->time - last_smooth_event_time > 50)
+ // reset our accumulations after 50ms of silence
+#endif
+ acc_x = acc_y = 0;
+ acc_x += event->delta_x;
+ acc_y += event->delta_y;
+#if !GTK_CHECK_VERSION(3,22,0)
+ last_smooth_event_time = event->time;
+#endif
+ break;
+#endif
default: // This shouldn't happen
return FALSE;
}
@@ -2046,8 +2122,42 @@ scroll_event(GtkWidget *widget,
vim_modifiers = modifiers_gdk2mouse(event->state);
- gui_send_mouse_event(button, (int)event->x, (int)event->y,
- FALSE, vim_modifiers);
+#if GTK_CHECK_VERSION(3,4,0)
+ // on x11, despite not requested, when we copy into primary clipboard,
+ // we'll get smooth events. Unsmooth ones will also come along.
+ if (event->direction == GDK_SCROLL_SMOOTH && display_type == DT_WAYLAND)
+ {
+ while (acc_x >= 1.0)
+ { // right
+ acc_x = MAX(0.0, acc_x - 1.0);
+ gui_send_mouse_event(MOUSE_6, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ while (acc_x <= -1.0)
+ { // left
+ acc_x = MIN(0.0, acc_x + 1.0);
+ gui_send_mouse_event(MOUSE_7, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ while (acc_y >= 1.0)
+ { // down
+ acc_y = MAX(0.0, acc_y - 1.0);
+ gui_send_mouse_event(MOUSE_5, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ while (acc_y <= -1.0)
+ { // up
+ acc_y = MIN(0.0, acc_y + 1.0);
+ gui_send_mouse_event(MOUSE_4, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ }
+ else
+#undef DT_X11
+#undef DT_WAYLAND
+#endif
+ gui_send_mouse_event(button, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
return TRUE;
}
@@ -2501,10 +2611,12 @@ setup_save_yourself(void)
// Fall back to old method
// first get the existing value
- GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
+ Display * dpy = gui_mch_get_display();
+ if (!dpy)
+ return;
- if (XGetWMProtocols(GDK_WINDOW_XDISPLAY(mainwin_win),
- GDK_WINDOW_XID(mainwin_win),
+ GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
+ if (XGetWMProtocols(dpy, GDK_WINDOW_XID(mainwin_win),
&existing_atoms, &count))
{
Atom *new_atoms;
@@ -2612,7 +2724,10 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
// When started with "--echo-wid" argument, write window ID on stdout.
if (echo_wid_arg)
{
- printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
+ if (gui_mch_get_display())
+ printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
+ else
+ printf("WID: 0\n");
fflush(stdout);
}
@@ -2647,27 +2762,30 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
setup_save_yourself();
#ifdef FEAT_CLIENTSERVER
- if (serverName == NULL && serverDelayedStartName != NULL)
+ if (gui_mch_get_display())
{
- // This is a :gui command in a plain vim with no previous server
- commWindow = GDK_WINDOW_XID(mainwin_win);
+ if (serverName == NULL && serverDelayedStartName != NULL)
+ {
+ // This is a :gui command in a plain vim with no previous server
+ commWindow = GDK_WINDOW_XID(mainwin_win);
- (void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
- serverDelayedStartName);
- }
- else
- {
- /*
- * Cannot handle "XLib-only" windows with gtk event routines, we'll
- * have to change the "server" registration to that of the main window
- * If we have not registered a name yet, remember the window.
- */
- serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
- GDK_WINDOW_XID(mainwin_win));
+ (void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
+ serverDelayedStartName);
+ }
+ else
+ {
+ /*
+ * Cannot handle "XLib-only" windows with gtk event routines, we'll
+ * have to change the "server" registration to that of the main window
+ * If we have not registered a name yet, remember the window.
+ */
+ serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
+ GDK_WINDOW_XID(mainwin_win));
+ }
+ gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
+ g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
+ G_CALLBACK(property_event), NULL);
}
- gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
- g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
- G_CALLBACK(property_event), NULL);
#endif
}
@@ -3533,30 +3651,28 @@ gui_mch_set_curtab(int nr)
* Add selection targets for PRIMARY and CLIPBOARD selections.
*/
void
-gui_gtk_set_selection_targets(void)
+gui_gtk_set_selection_targets(GdkAtom selection)
{
int i, j = 0;
- int n_targets = N_SELECTION_TARGETS;
- GtkTargetEntry targets[N_SELECTION_TARGETS];
+ static int n_targets = N_SELECTION_TARGETS;
+ static GtkTargetEntry targets[N_SELECTION_TARGETS];
- for (i = 0; i < (int)N_SELECTION_TARGETS; ++i)
+ if (targets[0].target == NULL)
{
- // OpenOffice tries to use TARGET_HTML and fails when we don't
- // return something, instead of trying another target. Therefore only
- // offer TARGET_HTML when it works.
- if (!clip_html && selection_targets[i].info == TARGET_HTML)
- n_targets--;
- else
- targets[j++] = selection_targets[i];
+ for (i = 0; i < (int)N_SELECTION_TARGETS; ++i)
+ {
+ // OpenOffice tries to use TARGET_HTML and fails when we don't
+ // return something, instead of trying another target. Therefore only
+ // offer TARGET_HTML when it works.
+ if (!clip_html && selection_targets[i].info == TARGET_HTML)
+ n_targets--;
+ else
+ targets[j++] = selection_targets[i];
+ }
}
- gtk_selection_clear_targets(gui.drawarea, (GdkAtom)GDK_SELECTION_PRIMARY);
- gtk_selection_clear_targets(gui.drawarea, (GdkAtom)clip_plus.gtk_sel_atom);
- gtk_selection_add_targets(gui.drawarea,
- (GdkAtom)GDK_SELECTION_PRIMARY,
- targets, n_targets);
- gtk_selection_add_targets(gui.drawarea,
- (GdkAtom)clip_plus.gtk_sel_atom,
+ gtk_selection_clear_targets(gui.drawarea, selection);
+ gtk_selection_add_targets(gui.drawarea, selection,
targets, n_targets);
}
@@ -3906,17 +4022,37 @@ gui_mch_init(void)
#endif
// Determine which events we will filter.
- gtk_widget_set_events(gui.drawarea,
- GDK_EXPOSURE_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_SCROLL_MASK |
- GDK_KEY_PRESS_MASK |
- GDK_KEY_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK);
+ gint event_mask =
+ GDK_EXPOSURE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK;
+#if GTK_CHECK_VERSION(3,4,0)
+ if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
+ {
+ // for X11, if we were using smooth scroll events, we
+ // would get an scroll without deltas on the very first user scroll* and
+ // get both "unsmooth" scroll and smooth scroll events after
+ // copying into the primary selection
+ //
+ // *: https://bugzilla.gnome.org/show_bug.cgi?id=675959
+ event_mask |= GDK_SCROLL_MASK;
+ }
+ else
+ {
+ // for Wayland, touchpads don't generate "unsmooth" scroll events. Both
+ // touchpads and wheels generate smooth scroll events expectedly.
+ event_mask |= GDK_SMOOTH_SCROLL_MASK;
+ }
+#else
+ event_mask |= GDK_SCROLL_MASK;
+#endif
+ gtk_widget_set_events(gui.drawarea, event_mask);
gtk_widget_show(gui.drawarea);
gui_gtk_form_put(GTK_FORM(gui.formwin), gui.drawarea, 0, 0);
@@ -4032,20 +4168,7 @@ gui_mch_init(void)
g_signal_connect(G_OBJECT(gui.drawarea), "button-release-event",
G_CALLBACK(button_release_event), NULL);
g_signal_connect(G_OBJECT(gui.drawarea), "scroll-event",
- G_CALLBACK(&scroll_event), NULL);
-
- /*
- * Add selection handler functions.
- */
- g_signal_connect(G_OBJECT(gui.drawarea), "selection-clear-event",
- G_CALLBACK(selection_clear_event), NULL);
- g_signal_connect(G_OBJECT(gui.drawarea), "selection-received",
- G_CALLBACK(selection_received_cb), NULL);
-
- gui_gtk_set_selection_targets();
-
- g_signal_connect(G_OBJECT(gui.drawarea), "selection-get",
- G_CALLBACK(selection_get_cb), NULL);
+ G_CALLBACK(scroll_event), NULL);
// Pretend we don't have input focus, we will get an event if we do.
gui.in_focus = FALSE;
@@ -4527,6 +4650,10 @@ gui_mch_open(void)
#endif
g_signal_connect(G_OBJECT(gui.formwin), "configure-event",
G_CALLBACK(form_configure_event), NULL);
+#if GTK_CHECK_VERSION(3,10,0)
+ g_signal_connect(G_OBJECT(gui.formwin), "notify::scale-factor",
+ G_CALLBACK(scale_factor_event), NULL);
+#endif
#ifdef FEAT_DND
// Set up for receiving DND items.
@@ -4579,6 +4706,17 @@ gui_mch_open(void)
#endif
}
+ /*
+ * Add selection handler functions.
+ */
+ g_signal_connect(G_OBJECT(gui.drawarea), "selection-clear-event",
+ G_CALLBACK(selection_clear_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "selection-received",
+ G_CALLBACK(selection_received_cb), NULL);
+
+ g_signal_connect(G_OBJECT(gui.drawarea), "selection-get",
+ G_CALLBACK(selection_get_cb), NULL);
+
return OK;
}
@@ -4599,8 +4737,12 @@ gui_mch_exit(int rc UNUSED)
int
gui_mch_get_winpos(int *x, int *y)
{
- gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
- return OK;
+ if (gui_mch_get_display())
+ {
+ gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
+ return OK;
+ }
+ return FAIL;
}
/*
@@ -6225,9 +6367,10 @@ gui_mch_haskey(char_u *name)
int
gui_get_x11_windis(Window *win, Display **dis)
{
- if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
+ Display * dpy = gui_mch_get_display();
+ if (dpy)
{
- *dis = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
+ *dis = dpy;
*win = GDK_WINDOW_XID(gtk_widget_get_window(gui.mainwin));
return OK;
}
@@ -6238,18 +6381,18 @@ gui_get_x11_windis(Window *win, Display **dis)
}
#endif
-#if defined(FEAT_CLIENTSERVER) \
- || (defined(FEAT_X11) && defined(FEAT_CLIPBOARD)) || defined(PROTO)
-
Display *
gui_mch_get_display(void)
{
- if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
+ if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL
+#if GTK_CHECK_VERSION(3,0,0)
+ && GDK_IS_X11_DISPLAY(gtk_widget_get_display(gui.mainwin))
+#endif
+ )
return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
else
return NULL;
}
-#endif
void
gui_mch_beep(void)
@@ -6911,9 +7054,10 @@ clip_mch_request_selection(Clipboard_T *cbd)
return;
}
- // Final fallback position - use the X CUT_BUFFER0 store
- yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
- cbd);
+ if (gui_mch_get_display())
+ // Final fallback position - use the X CUT_BUFFER0 store
+ yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
+ cbd);
}
/*
@@ -6935,10 +7079,18 @@ clip_mch_lose_selection(Clipboard_T *cbd UNUSED)
int
clip_mch_own_selection(Clipboard_T *cbd)
{
+ // If we're blocking autocmds, we are filling the register to offer the
+ // selection (inside selection-get)
+ if (is_autocmd_blocked())
+ return OK;
+
int success;
success = gtk_selection_owner_set(gui.drawarea, cbd->gtk_sel_atom,
gui.event_time);
+ // don't update on every visual selection change
+ if (!(cbd->owned && VIsual_active))
+ gui_gtk_set_selection_targets(cbd->gtk_sel_atom);
gui_mch_update();
return (success) ? OK : FAIL;
}
@@ -7071,9 +7223,11 @@ gui_mch_setmouse(int x, int y)
// Sorry for the Xlib call, but we can't avoid it, since there is no
// internal GDK mechanism present to accomplish this. (and for good
// reason...)
- XWarpPointer(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.drawarea)),
- (Window)0, GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
- 0, 0, 0U, 0U, x, y);
+ Display * dpy = gui_mch_get_display();
+ if (dpy)
+ XWarpPointer(dpy, (Window)0,
+ GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
+ 0, 0, 0U, 0U, x, y);
}
diff --git a/src/gui_w32.c b/src/gui_w32.c
index eb4c841..f628dd6 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -50,6 +50,86 @@ static int gui_mswin_get_menu_height(int fix_window);
# define gui_mswin_get_menu_height(fix_window) 0
#endif
+typedef struct keycode_trans_strategy {
+ void (*ptr_on_char) (HWND /*hwnd UNUSED*/, UINT /*cch*/, int /*cRepeat UNUSED*/);
+ void (*ptr_on_sys_char) (HWND /*hwnd UNUSED*/, UINT /*cch*/, int /*cRepeat UNUSED*/);
+ void (*ptr_process_message_usual_key) (UINT /*vk*/, const MSG* /*pmsg*/);
+ int (*ptr_get_active_modifiers)(void);
+ int (*is_experimental)(void);
+} keycode_trans_strategy;
+
+// forward declarations for input instance initializer
+static void _OnChar_experimental(HWND /*hwnd UNUSED*/, UINT /*cch*/, int /*cRepeat UNUSED*/);
+static void _OnSysChar_experimental(HWND /*hwnd UNUSED*/, UINT /*cch*/, int /*cRepeat UNUSED*/);
+static void process_message_usual_key_experimental(UINT /*vk*/, const MSG* /*pmsg*/);
+static int get_active_modifiers_experimental(void);
+static int is_experimental_true(void);
+
+keycode_trans_strategy keycode_trans_strategy_experimental = {
+ _OnChar_experimental // ptr_on_char
+ , _OnSysChar_experimental // ptr_on_sys_char
+ , process_message_usual_key_experimental // ptr_process_message_usual_key
+ , get_active_modifiers_experimental
+ , is_experimental_true
+};
+
+// forward declarations for input instance initializer
+static void _OnChar_classic(HWND /*hwnd UNUSED*/, UINT /*cch*/, int /*cRepeat UNUSED*/);
+static void _OnSysChar_classic(HWND /*hwnd UNUSED*/, UINT /*cch*/, int /*cRepeat UNUSED*/);
+static void process_message_usual_key_classic(UINT /*vk*/, const MSG* /*pmsg*/);
+static int get_active_modifiers_classic(void);
+static int is_experimental_false(void);
+
+keycode_trans_strategy keycode_trans_strategy_classic = {
+ _OnChar_classic // ptr_on_char
+ , _OnSysChar_classic // ptr_on_sys_char
+ , process_message_usual_key_classic // ptr_process_message_usual_key
+ , get_active_modifiers_classic
+ , is_experimental_false
+};
+
+keycode_trans_strategy *keycode_trans_strategy_used = NULL;
+
+static int is_experimental_true(void)
+{
+ return 1;
+}
+
+static int is_experimental_false(void)
+{
+ return 0;
+}
+
+/*
+ * Initialize the keycode translation strategy.
+ */
+static void keycode_trans_strategy_init(void)
+{
+ const char *strategy = NULL;
+
+ // set default value as fallback
+ keycode_trans_strategy_used = &keycode_trans_strategy_classic;
+
+ strategy = getenv("VIM_KEYCODE_TRANS_STRATEGY");
+ if (strategy == NULL)
+ {
+ return;
+ }
+
+ if (STRICMP(strategy, "classic") == 0)
+ {
+ keycode_trans_strategy_used = &keycode_trans_strategy_classic;
+ return;
+ }
+
+ if (STRICMP(strategy, "experimental") == 0)
+ {
+ keycode_trans_strategy_used = &keycode_trans_strategy_experimental;
+ return;
+ }
+
+}
+
#if defined(FEAT_RENDER_OPTIONS) || defined(PROTO)
int
gui_mch_set_rendering_options(char_u *s)
@@ -392,16 +472,6 @@ static int (WINAPI *pGetSystemMetricsForDpi)(int, UINT) = NULL;
static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext) = NULL;
static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT) = NULL;
- static UINT WINAPI
-stubGetDpiForSystem(void)
-{
- HWND hwnd = GetDesktopWindow();
- HDC hdc = GetWindowDC(hwnd);
- UINT dpi = GetDeviceCaps(hdc, LOGPIXELSY);
- ReleaseDC(hwnd, hdc);
- return dpi;
-}
-
static int WINAPI
stubGetSystemMetricsForDpi(int nIndex, UINT dpi UNUSED)
{
@@ -744,7 +814,7 @@ _OnDeadChar(
UINT ch UNUSED,
int cRepeat UNUSED)
{
- dead_key = 1;
+ dead_key = DEAD_KEY_SET_DEFAULT;
}
/*
@@ -841,8 +911,17 @@ char_to_string(int ch, char_u *string, int slen, int had_alt)
return len;
}
+/*
+ * Experimental implementation, introduced in v8.2.4807
+ * "processing key event in Win32 GUI is not ideal"
+ *
+ * TODO: since introduction, this experimental function started
+ * to be used as well outside of original key press/processing
+ * area, and usages not via "get_active_modifiers_via_ptr" should
+ * be watched.
+ */
static int
-get_active_modifiers(void)
+get_active_modifiers_experimental(void)
{
int modifiers = 0;
@@ -869,6 +948,46 @@ get_active_modifiers(void)
}
/*
+ * "Classic" implementation, existing prior to v8.2.4807
+ */
+ static int
+get_active_modifiers_classic(void)
+{
+ int modifiers = 0;
+
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ modifiers |= MOD_MASK_SHIFT;
+ /*
+ * Don't use caps-lock as shift, because these are special keys
+ * being considered here, and we only want letters to get
+ * shifted -- webb
+ */
+ /*
+ if (GetKeyState(VK_CAPITAL) & 0x0001)
+ modifiers ^= MOD_MASK_SHIFT;
+ */
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ modifiers |= MOD_MASK_CTRL;
+ if (GetKeyState(VK_MENU) & 0x8000)
+ modifiers |= MOD_MASK_ALT;
+
+ return modifiers;
+}
+
+ static int
+get_active_modifiers(void)
+{
+ return get_active_modifiers_experimental();
+}
+
+ static int
+get_active_modifiers_via_ptr(void)
+{
+ // marshal to corresponding implementation
+ return keycode_trans_strategy_used->ptr_get_active_modifiers();
+}
+
+/*
* Key hit, add it to the input buffer.
*/
static void
@@ -877,6 +996,20 @@ _OnChar(
UINT cch,
int cRepeat UNUSED)
{
+ // marshal to corresponding implementation
+ keycode_trans_strategy_used->ptr_on_char(hwnd, cch, cRepeat);
+}
+
+/*
+ * Experimental implementation, introduced in v8.2.4807
+ * "processing key event in Win32 GUI is not ideal"
+ */
+ static void
+_OnChar_experimental(
+ HWND hwnd UNUSED,
+ UINT cch,
+ int cRepeat UNUSED)
+{
char_u string[40];
int len = 0;
int modifiers;
@@ -890,7 +1023,7 @@ _OnChar(
if (dead_key != DEAD_KEY_TRANSIENT_IN_ON_CHAR)
dead_key = DEAD_KEY_OFF;
- modifiers = get_active_modifiers();
+ modifiers = get_active_modifiers_experimental();
ch = simplify_key(ch, &modifiers);
@@ -927,6 +1060,30 @@ _OnChar(
}
/*
+ * "Classic" implementation, existing prior to v8.2.4807
+ */
+ static void
+_OnChar_classic(
+ HWND hwnd UNUSED,
+ UINT ch,
+ int cRepeat UNUSED)
+{
+ char_u string[40];
+ int len = 0;
+
+ dead_key = 0;
+
+ len = char_to_string(ch, string, 40, FALSE);
+ if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
+ {
+ trash_input_buf();
+ got_int = TRUE;
+ }
+
+ add_to_input_buf(string, len);
+}
+
+/*
* Alt-Key hit, add it to the input buffer.
*/
static void
@@ -935,6 +1092,20 @@ _OnSysChar(
UINT cch,
int cRepeat UNUSED)
{
+ // marshal to corresponding implementation
+ keycode_trans_strategy_used->ptr_on_sys_char(hwnd, cch, cRepeat);
+}
+
+/*
+ * Experimental implementation, introduced in v8.2.4807
+ * "processing key event in Win32 GUI is not ideal"
+ */
+ static void
+_OnSysChar_experimental(
+ HWND hwnd UNUSED,
+ UINT cch,
+ int cRepeat UNUSED)
+{
char_u string[40]; // Enough for multibyte character
int len;
int modifiers;
@@ -946,7 +1117,69 @@ _OnSysChar(
// ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
// that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
// CAPSLOCK is pressed) at this point.
- modifiers = get_active_modifiers();
+ modifiers = get_active_modifiers_experimental();
+ ch = simplify_key(ch, &modifiers);
+ // remove the SHIFT modifier for keys where it's already included, e.g.,
+ // '(' and '*'
+ modifiers = may_remove_shift_modifier(modifiers, ch);
+
+ // Unify modifiers somewhat. No longer use ALT to set the 8th bit.
+ ch = extract_modifiers(ch, &modifiers, FALSE, NULL);
+ if (ch == CSI)
+ ch = K_CSI;
+
+ len = 0;
+ if (modifiers)
+ {
+ string[len++] = CSI;
+ string[len++] = KS_MODIFIER;
+ string[len++] = modifiers;
+ }
+
+ if (IS_SPECIAL((int)ch))
+ {
+ string[len++] = CSI;
+ string[len++] = K_SECOND((int)ch);
+ string[len++] = K_THIRD((int)ch);
+ }
+ else
+ {
+ // Although the documentation isn't clear about it, we assume "ch" is
+ // a Unicode character.
+ len += char_to_string(ch, string + len, 40 - len, TRUE);
+ }
+
+ add_to_input_buf(string, len);
+}
+
+/*
+ * "Classic" implementation, existing prior to v8.2.4807
+ */
+ static void
+_OnSysChar_classic(
+ HWND hwnd UNUSED,
+ UINT cch,
+ int cRepeat UNUSED)
+{
+ char_u string[40]; // Enough for multibyte character
+ int len;
+ int modifiers;
+ int ch = cch; // special keys are negative
+
+ dead_key = 0;
+
+ // TRACE("OnSysChar(%d, %c)\n", ch, ch);
+
+ // OK, we have a character key (given by ch) which was entered with the
+ // ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
+ // that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
+ // CAPSLOCK is pressed) at this point.
+ modifiers = MOD_MASK_ALT;
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ modifiers |= MOD_MASK_SHIFT;
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ modifiers |= MOD_MASK_CTRL;
+
ch = simplify_key(ch, &modifiers);
// remove the SHIFT modifier for keys where it's already included, e.g.,
// '(' and '*'
@@ -1915,6 +2148,137 @@ outputDeadKey_rePost(MSG originalMsg)
}
/*
+ * Refactored out part of process_message(), responsible for
+ * handling the case of "not a special key"
+ */
+static void process_message_usual_key(UINT vk, const MSG *pmsg)
+{
+ // marshal to corresponding implementation
+ keycode_trans_strategy_used->ptr_process_message_usual_key(vk, pmsg);
+}
+
+/*
+ * Experimental implementation, introduced in v8.2.4807
+ * "processing key event in Win32 GUI is not ideal"
+ */
+static void process_message_usual_key_experimental(UINT vk, const MSG *pmsg)
+{
+ WCHAR ch[8];
+ int len;
+ int i;
+ UINT scan_code;
+ BYTE keyboard_state[256];
+
+ // Construct the state table with only a few modifiers, we don't
+ // really care about the presence of Ctrl/Alt as those modifiers are
+ // handled by Vim separately.
+ memset(keyboard_state, 0, 256);
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ keyboard_state[VK_SHIFT] = 0x80;
+ if (GetKeyState(VK_CAPITAL) & 0x0001)
+ keyboard_state[VK_CAPITAL] = 0x01;
+ // Alt-Gr is synthesized as Alt + Ctrl.
+ if ((GetKeyState(VK_RMENU) & 0x8000)
+ && (GetKeyState(VK_CONTROL) & 0x8000))
+ {
+ keyboard_state[VK_MENU] = 0x80;
+ keyboard_state[VK_CONTROL] = 0x80;
+ }
+
+ // Translate the virtual key according to the current keyboard
+ // layout.
+ scan_code = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
+ // Convert the scan-code into a sequence of zero or more unicode
+ // codepoints.
+ // If this is a dead key ToUnicode returns a negative value.
+ len = ToUnicode(vk, scan_code, keyboard_state, ch, ARRAY_LENGTH(ch),
+ 0);
+ if (len < 0)
+ dead_key = DEAD_KEY_SET_DEFAULT;
+
+ if (len <= 0)
+ {
+ int wm_char = NUL;
+
+ if (dead_key == DEAD_KEY_SET_DEFAULT
+ && (GetKeyState(VK_CONTROL) & 0x8000))
+ {
+ if ( // AZERTY CTRL+dead_circumflex
+ (vk == 221 && scan_code == 26)
+ // QWERTZ CTRL+dead_circumflex
+ || (vk == 220 && scan_code == 41))
+ wm_char = '[';
+ if ( // QWERTZ CTRL+dead_two-overdots
+ (vk == 192 && scan_code == 27))
+ wm_char = ']';
+ }
+ if (wm_char != NUL)
+ {
+ // post WM_CHAR='[' - which will be interpreted with CTRL
+ // still hold as ESC
+ PostMessageW(pmsg->hwnd, WM_CHAR, wm_char, pmsg->lParam);
+ // ask _OnChar() to not touch this state, wait for next key
+ // press and maintain knowledge that we are "poisoned" with
+ // "dead state"
+ dead_key = DEAD_KEY_TRANSIENT_IN_ON_CHAR;
+ }
+ return;
+ }
+
+ // Post the message as TranslateMessage would do.
+ if (pmsg->message == WM_KEYDOWN)
+ {
+ for (i = 0; i < len; i++)
+ PostMessageW(pmsg->hwnd, WM_CHAR, ch[i], pmsg->lParam);
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ PostMessageW(pmsg->hwnd, WM_SYSCHAR, ch[i], pmsg->lParam);
+ }
+}
+
+/*
+ * "Classic" implementation, existing prior to v8.2.4807
+ */
+static void process_message_usual_key_classic(UINT vk, const MSG *pmsg)
+{
+ char_u string[40];
+
+ // Some keys need C-S- where they should only need C-.
+ // Ignore 0xff, Windows XP sends it when NUMLOCK has changed since
+ // system startup (Helmut Stiegler, 2003 Oct 3).
+ if (vk != 0xff
+ && (GetKeyState(VK_CONTROL) & 0x8000)
+ && !(GetKeyState(VK_SHIFT) & 0x8000)
+ && !(GetKeyState(VK_MENU) & 0x8000))
+ {
+ // CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE
+ if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^')
+ {
+ string[0] = Ctrl_HAT;
+ add_to_input_buf(string, 1);
+ }
+ // vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY!
+ else if (vk == 0xBD) // QWERTY for CTRL-'-'
+ {
+ string[0] = Ctrl__;
+ add_to_input_buf(string, 1);
+ }
+ // CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0
+ else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@')
+ {
+ string[0] = Ctrl_AT;
+ add_to_input_buf(string, 1);
+ }
+ else
+ TranslateMessage(pmsg);
+ }
+ else
+ TranslateMessage(pmsg);
+}
+
+/*
* Process a single Windows message.
* If one is not available we hang until one is.
*/
@@ -1930,7 +2294,14 @@ process_message(void)
#ifdef FEAT_MENU
static char_u k10[] = {K_SPECIAL, 'k', ';', 0};
#endif
- BYTE keyboard_state[256];
+ static int keycode_trans_strategy_initialized = 0;
+
+ // lazy initialize - first time only
+ if (!keycode_trans_strategy_initialized)
+ {
+ keycode_trans_strategy_initialized = 1;
+ keycode_trans_strategy_init();
+ }
GetMessageW(&msg, NULL, 0, 0);
@@ -1990,8 +2361,11 @@ process_message(void)
* We are at the moment after WM_CHAR with DEAD_KEY_SKIP_ON_CHAR event
* was handled by _WndProc, this keypress we want to process normally
*/
- if (dead_key == DEAD_KEY_SKIP_ON_CHAR)
+ if (keycode_trans_strategy_used->is_experimental()
+ && dead_key == DEAD_KEY_SKIP_ON_CHAR)
+ {
dead_key = DEAD_KEY_OFF;
+ }
if (dead_key != DEAD_KEY_OFF)
{
@@ -2013,7 +2387,8 @@ process_message(void)
* outputDeadKey_rePost() since we do not wish to reset dead_key
* value.
*/
- if (dead_key == DEAD_KEY_TRANSIENT_IN_ON_CHAR)
+ if (keycode_trans_strategy_used->is_experimental() &&
+ dead_key == DEAD_KEY_TRANSIENT_IN_ON_CHAR)
{
outputDeadKey_rePost_Ex(msg,
/*dead_key2set=*/DEAD_KEY_SKIP_ON_CHAR);
@@ -2100,7 +2475,7 @@ process_message(void)
NULL, NULL) == NULL)
break;
#endif
- modifiers = get_active_modifiers();
+ modifiers = get_active_modifiers_via_ptr();
if (special_keys[i].vim_code1 == NUL)
key = special_keys[i].vim_code0;
@@ -2141,78 +2516,7 @@ process_message(void)
// Not a special key.
if (special_keys[i].key_sym == 0)
{
- WCHAR ch[8];
- int len;
- int i;
- UINT scan_code;
-
- // Construct the state table with only a few modifiers, we don't
- // really care about the presence of Ctrl/Alt as those modifiers are
- // handled by Vim separately.
- memset(keyboard_state, 0, 256);
- if (GetKeyState(VK_SHIFT) & 0x8000)
- keyboard_state[VK_SHIFT] = 0x80;
- if (GetKeyState(VK_CAPITAL) & 0x0001)
- keyboard_state[VK_CAPITAL] = 0x01;
- // Alt-Gr is synthesized as Alt + Ctrl.
- if ((GetKeyState(VK_RMENU) & 0x8000)
- && (GetKeyState(VK_CONTROL) & 0x8000))
- {
- keyboard_state[VK_MENU] = 0x80;
- keyboard_state[VK_CONTROL] = 0x80;
- }
-
- // Translate the virtual key according to the current keyboard
- // layout.
- scan_code = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
- // Convert the scan-code into a sequence of zero or more unicode
- // codepoints.
- // If this is a dead key ToUnicode returns a negative value.
- len = ToUnicode(vk, scan_code, keyboard_state, ch, ARRAY_LENGTH(ch),
- 0);
- if (len < 0)
- dead_key = DEAD_KEY_SET_DEFAULT;
-
- if (len <= 0)
- {
- int wm_char = NUL;
-
- if (dead_key == DEAD_KEY_SET_DEFAULT
- && (GetKeyState(VK_CONTROL) & 0x8000))
- {
- if ( // AZERTY CTRL+dead_circumflex
- (vk == 221 && scan_code == 26)
- // QWERTZ CTRL+dead_circumflex
- || (vk == 220 && scan_code == 41))
- wm_char = '[';
- if ( // QWERTZ CTRL+dead_two-overdots
- (vk == 192 && scan_code == 27))
- wm_char = ']';
- }
- if (wm_char != NUL)
- {
- // post WM_CHAR='[' - which will be interpreted with CTRL
- // still hold as ESC
- PostMessageW(msg.hwnd, WM_CHAR, wm_char, msg.lParam);
- // ask _OnChar() to not touch this state, wait for next key
- // press and maintain knowledge that we are "poisoned" with
- // "dead state"
- dead_key = DEAD_KEY_TRANSIENT_IN_ON_CHAR;
- }
- return;
- }
-
- // Post the message as TranslateMessage would do.
- if (msg.message == WM_KEYDOWN)
- {
- for (i = 0; i < len; i++)
- PostMessageW(msg.hwnd, WM_CHAR, ch[i], msg.lParam);
- }
- else
- {
- for (i = 0; i < len; i++)
- PostMessageW(msg.hwnd, WM_SYSCHAR, ch[i], msg.lParam);
- }
+ process_message_usual_key(vk, &msg);
}
}
#ifdef FEAT_MBYTE_IME
@@ -5286,7 +5590,7 @@ load_dpi_func(void)
fail:
// Disable PerMonitorV2 APIs.
- pGetDpiForSystem = stubGetDpiForSystem;
+ pGetDpiForSystem = vimGetDpiForSystem;
pGetDpiForWindow = NULL;
pGetSystemMetricsForDpi = stubGetSystemMetricsForDpi;
pSetThreadDpiAwarenessContext = NULL;
@@ -8885,6 +9189,43 @@ test_gui_w32_sendevent_keyboard(dict_T *args)
return TRUE;
}
+ static int
+test_gui_w32_sendevent_set_keycode_trans_strategy(dict_T *args)
+{
+ int handled = 0;
+ char_u *strategy = dict_get_string(args, "strategy", TRUE);
+
+ if (strategy)
+ {
+ if (STRICMP(strategy, "classic") == 0)
+ {
+ handled = 1;
+ keycode_trans_strategy_used = &keycode_trans_strategy_classic;
+ }
+ else if (STRICMP(strategy, "experimental") == 0)
+ {
+ handled = 1;
+ keycode_trans_strategy_used = &keycode_trans_strategy_experimental;
+ }
+ }
+
+ if (!handled)
+ {
+ if (strategy == NULL)
+ {
+ semsg(_(e_missing_argument_str), "strategy");
+ }
+ else
+ {
+ semsg(_(e_invalid_value_for_argument_str_str), "strategy", strategy);
+ vim_free(strategy);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
int
test_gui_w32_sendevent(char_u *event, dict_T *args)
{
@@ -8892,6 +9233,8 @@ test_gui_w32_sendevent(char_u *event, dict_T *args)
return test_gui_w32_sendevent_keyboard(args);
else if (STRICMP(event, "mouse") == 0)
return test_gui_w32_sendevent_mouse(args);
+ else if (STRICMP(event, "set_keycode_trans_strategy") == 0)
+ return test_gui_w32_sendevent_set_keycode_trans_strategy(args);
else
{
semsg(_(e_invalid_value_for_argument_str_str), "event", event);
diff --git a/src/gui_xim.c b/src/gui_xim.c
index c9b1c6c..345b3a4 100644
--- a/src/gui_xim.c
+++ b/src/gui_xim.c
@@ -325,7 +325,7 @@ im_preedit_window_open(void)
#if GTK_CHECK_VERSION(3,16,0)
{
GtkStyleContext * const context
- = gtk_widget_get_style_context(gui.drawarea);
+ = gtk_widget_get_style_context(preedit_label);
GtkCssProvider * const provider = gtk_css_provider_new();
gchar *css = NULL;
const char * const fontname
@@ -349,7 +349,7 @@ im_preedit_window_open(void)
fontsize_propval = g_strdup_printf("inherit");
css = g_strdup_printf(
- "widget#vim-gui-preedit-area {\n"
+ "#vim-gui-preedit-area {\n"
" font-family: %s,monospace;\n"
" font-size: %s;\n"
" color: #%.2lx%.2lx%.2lx;\n"
@@ -1063,6 +1063,9 @@ xim_reset(void)
int
xim_queue_key_press_event(GdkEventKey *event, int down)
{
+#ifdef FEAT_GUI_GTK
+ if (event->state & GDK_SUPER_MASK) return FALSE;
+#endif
if (down)
{
// Workaround GTK2 XIM 'feature' that always converts keypad keys to
diff --git a/src/help.c b/src/help.c
index c33985e..a792bf3 100644
--- a/src/help.c
+++ b/src/help.c
@@ -720,7 +720,7 @@ fix_help_buffer(void)
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
{
line = ml_get_buf(curbuf, lnum, FALSE);
- len = (int)STRLEN(line);
+ len = ml_get_buf_len(curbuf, lnum);
if (in_example && len > 0 && !VIM_ISWHITE(line[0]))
{
// End of example: non-white or '<' in first column.
diff --git a/src/highlight.c b/src/highlight.c
index 318564c..9b3b072 100644
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -59,6 +59,7 @@ typedef struct
int sg_cterm_bg; // terminal bg color number + 1
int sg_cterm_ul; // terminal ul color number + 1
int sg_cterm_attr; // Screen attr for color term mode
+ int sg_cterm_font; // terminal alternative font (0 for normal)
// for when using the GUI
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
guicolor_T sg_gui_fg; // GUI foreground color handle
@@ -220,8 +221,8 @@ static char *(highlight_init_light[]) = {
CENT("SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue",
"SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue"),
#endif
- CENT("Visual term=reverse",
- "Visual term=reverse guibg=LightGrey"),
+ CENT("Visual ctermbg=Grey ctermfg=Black",
+ "Visual ctermbg=Grey ctermfg=Black guibg=LightGrey guifg=Black"),
#ifdef FEAT_DIFF
CENT("DiffAdd term=bold ctermbg=LightBlue",
"DiffAdd term=bold ctermbg=LightBlue guibg=LightBlue"),
@@ -309,8 +310,8 @@ static char *(highlight_init_dark[]) = {
CENT("SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan",
"SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan"),
#endif
- CENT("Visual term=reverse",
- "Visual term=reverse guibg=DarkGrey"),
+ CENT("Visual ctermbg=Grey ctermfg=Black",
+ "Visual ctermbg=Grey ctermfg=Black guibg=#575757 guifg=LightGrey"),
#ifdef FEAT_DIFF
CENT("DiffAdd term=bold ctermbg=DarkBlue",
"DiffAdd term=bold ctermbg=DarkBlue guibg=DarkBlue"),
@@ -432,19 +433,16 @@ init_highlight(
for (i = 0; pp[i] != NULL; ++i)
do_highlight((char_u *)pp[i], reset, TRUE);
- // Reverse looks ugly, but grey may not work for 8 colors. Thus let it
- // depend on the number of colors available.
+ // Reverse looks ugly, but grey may not work for less than 8 colors. Thus
+ // let it depend on the number of colors available.
+ if (t_colors < 8)
+ do_highlight((char_u *)"Visual term=reverse cterm=reverse ctermbg=NONE ctermfg=NONE",
+ FALSE, TRUE);
// With 8 colors brown is equal to yellow, need to use black for Search fg
// to avoid Statement highlighted text disappears.
// Clear the attributes, needed when changing the t_Co value.
- if (t_colors > 8)
- do_highlight((char_u *)(*p_bg == 'l'
- ? "Visual cterm=NONE ctermbg=LightGrey"
- : "Visual cterm=NONE ctermbg=DarkGrey"), FALSE, TRUE);
- else
+ if (t_colors <= 8)
{
- do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE",
- FALSE, TRUE);
if (*p_bg == 'l')
do_highlight((char_u *)"Search ctermfg=black", FALSE, TRUE);
}
@@ -1035,6 +1033,39 @@ highlight_set_ctermul(int idx, int color, int is_normal_group)
}
/*
+ * Set the cterm font for the highlight group at 'idx'.
+ * 'arg' is the color name or the numeric value as a string.
+ * 'init' is set to TRUE when initializing highlighting.
+ * Called for the ":highlight" command and the "hlset()" function.
+ *
+ * Returns TRUE if the font is set.
+ */
+ static int
+highlight_set_cterm_font(
+ int idx,
+ char_u *arg,
+ int init)
+{
+ int font;
+
+ if (init && (HL_TABLE()[idx].sg_set & SG_CTERM))
+ return FALSE;
+
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_CTERM;
+
+ if (VIM_ISDIGIT(*arg))
+ font = atoi((char *)arg);
+ else if (STRICMP(arg, "NONE") == 0)
+ font = -1;
+ else
+ return FALSE;
+
+ HL_TABLE()[idx].sg_cterm_font = font + 1;
+ return TRUE;
+}
+
+/*
* Set the cterm fg/bg/ul color for the highlight group at 'idx'.
* 'key' is one of 'CTERMFG' or 'CTERMBG' or 'CTERMUL'.
* 'keystart' is the color name/value.
@@ -1679,6 +1710,14 @@ do_highlight(
break;
}
}
+ else if (STRCMP(key, "CTERMFONT") == 0)
+ {
+ if (!highlight_set_cterm_font(idx, arg, init))
+ {
+ error = TRUE;
+ break;
+ }
+ }
else if (STRCMP(key, "GUIFG") == 0)
{
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
@@ -1865,6 +1904,7 @@ hl_has_settings(int idx, int check_link)
|| HL_TABLE()[idx].sg_cterm_attr != 0
|| HL_TABLE()[idx].sg_cterm_fg != 0
|| HL_TABLE()[idx].sg_cterm_bg != 0
+ || HL_TABLE()[idx].sg_cterm_font != 0
#ifdef FEAT_GUI
|| HL_TABLE()[idx].sg_gui_attr != 0
|| HL_TABLE()[idx].sg_gui_fg_name != NULL
@@ -1892,6 +1932,7 @@ highlight_clear(int idx)
HL_TABLE()[idx].sg_cterm_fg = 0;
HL_TABLE()[idx].sg_cterm_bg = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
+ HL_TABLE()[idx].sg_cterm_font = 0;
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
HL_TABLE()[idx].sg_gui = 0;
VIM_CLEAR(HL_TABLE()[idx].sg_gui_fg_name);
@@ -2539,6 +2580,8 @@ get_attr_entry(garray_T *table, attrentry_T *aep)
== taep->ae_u.cterm.bg_color
&& aep->ae_u.cterm.ul_color
== taep->ae_u.cterm.ul_color
+ && aep->ae_u.cterm.font
+ == taep->ae_u.cterm.font
#ifdef FEAT_TERMGUICOLORS
&& aep->ae_u.cterm.fg_rgb
== taep->ae_u.cterm.fg_rgb
@@ -2609,6 +2652,7 @@ get_attr_entry(garray_T *table, attrentry_T *aep)
taep->ae_u.cterm.fg_color = aep->ae_u.cterm.fg_color;
taep->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
taep->ae_u.cterm.ul_color = aep->ae_u.cterm.ul_color;
+ taep->ae_u.cterm.font = aep->ae_u.cterm.font;
#ifdef FEAT_TERMGUICOLORS
taep->ae_u.cterm.fg_rgb = aep->ae_u.cterm.fg_rgb;
taep->ae_u.cterm.bg_rgb = aep->ae_u.cterm.bg_rgb;
@@ -2639,6 +2683,7 @@ get_cterm_attr_idx(int attr, int fg, int bg)
at_en.ae_u.cterm.fg_color = fg;
at_en.ae_u.cterm.bg_color = bg;
at_en.ae_u.cterm.ul_color = 0;
+ at_en.ae_u.cterm.font = 0;
return get_attr_entry(&cterm_attr_table, &at_en);
}
#endif
@@ -2809,6 +2854,8 @@ hl_combine_attr(int char_attr, int prim_attr)
new_en.ae_u.cterm.bg_color = prim_aep->ae_u.cterm.bg_color;
if (prim_aep->ae_u.cterm.ul_color > 0)
new_en.ae_u.cterm.ul_color = prim_aep->ae_u.cterm.ul_color;
+ if (prim_aep->ae_u.cterm.font > 0)
+ new_en.ae_u.cterm.font = prim_aep->ae_u.cterm.font;
#ifdef FEAT_TERMGUICOLORS
// If both fg and bg are not set fall back to cterm colors.
// Helps for SpellBad which uses undercurl in the GUI.
@@ -2948,6 +2995,8 @@ highlight_list_one(int id)
sgp->sg_cterm_bg, NULL, "ctermbg");
didh = highlight_list_arg(id, didh, LIST_INT,
sgp->sg_cterm_ul, NULL, "ctermul");
+ didh = highlight_list_arg(id, didh, LIST_INT,
+ sgp->sg_cterm_font, NULL, "ctermfont");
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
didh = highlight_list_arg(id, didh, LIST_ATTR,
@@ -3138,7 +3187,7 @@ highlight_color(
return (HL_TABLE()[id - 1].sg_gui_sp_name);
return (HL_TABLE()[id - 1].sg_gui_bg_name);
}
- if (font || sp)
+ if (sp)
return NULL;
if (modec == 'c')
{
@@ -3146,6 +3195,8 @@ highlight_color(
n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
else if (ul)
n = HL_TABLE()[id - 1].sg_cterm_ul - 1;
+ else if (font)
+ n = HL_TABLE()[id - 1].sg_cterm_font - 1;
else
n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
if (n < 0)
@@ -3296,7 +3347,8 @@ set_hl_attr(
// For the color term mode: If there are other than "normal"
// highlighting attributes, need to allocate an attr number.
- if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0 && sgp->sg_cterm_ul == 0
+ if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0 &&
+ sgp->sg_cterm_ul == 0 && sgp->sg_cterm_font == 0
# ifdef FEAT_TERMGUICOLORS
&& sgp->sg_gui_fg == INVALCOLOR
&& sgp->sg_gui_bg == INVALCOLOR
@@ -3310,6 +3362,7 @@ set_hl_attr(
at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
at_en.ae_u.cterm.ul_color = sgp->sg_cterm_ul;
+ at_en.ae_u.cterm.font = sgp->sg_cterm_font;
# ifdef FEAT_TERMGUICOLORS
at_en.ae_u.cterm.fg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_fg);
at_en.ae_u.cterm.bg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_bg);
@@ -3717,6 +3770,8 @@ combine_stl_hlt(
hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg)
hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
+ if (hlt[id - 1].sg_cterm_font != hlt[id_S - 1].sg_cterm_font)
+ hlt[hlcnt + i].sg_cterm_font = hlt[id - 1].sg_cterm_font;
# if defined(FEAT_GUI) || defined(FEAT_EVAL)
hlt[hlcnt + i].sg_gui ^=
hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
@@ -4180,6 +4235,10 @@ highlight_get_info(int hl_idx, int resolve_link)
if (dict_add_string(dict, "ctermul",
highlight_color(hlgid, (char_u *)"ul", 'c')) == FAIL)
goto error;
+ if (sgp->sg_cterm_font != 0)
+ if (dict_add_string(dict, "ctermfont",
+ highlight_color(hlgid, (char_u *)"font", 'c')) == FAIL)
+ goto error;
if (sgp->sg_gui != 0)
{
attr_dict = highlight_get_attr_dict(sgp->sg_gui);
@@ -4408,6 +4467,7 @@ hlg_add_or_update(dict_T *dict)
char_u *ctermfg;
char_u *ctermbg;
char_u *ctermul;
+ char_u *ctermfont;
char_u *guifg;
char_u *guibg;
char_u *guisp;
@@ -4492,6 +4552,10 @@ hlg_add_or_update(dict_T *dict)
if (error)
return FALSE;
+ ctermfont = hldict_get_string(dict, (char_u *)"ctermfont", &error);
+ if (error)
+ return FALSE;
+
if (!hldict_attr_to_str(dict, (char_u *)"gui", gui_attr, sizeof(gui_attr)))
return FALSE;
@@ -4516,7 +4580,7 @@ hlg_add_or_update(dict_T *dict)
// If none of the attributes are specified, then do nothing.
if (term_attr[0] == NUL && start == NULL && stop == NULL
&& cterm_attr[0] == NUL && ctermfg == NULL && ctermbg == NULL
- && ctermul == NULL && gui_attr[0] == NUL
+ && ctermul == NULL && ctermfont == NULL && gui_attr[0] == NUL
# ifdef FEAT_GUI
&& font == NULL
# endif
@@ -4536,6 +4600,7 @@ hlg_add_or_update(dict_T *dict)
p = add_attr_and_value(p, (char_u *)" ctermfg=", 9, ctermfg);
p = add_attr_and_value(p, (char_u *)" ctermbg=", 9, ctermbg);
p = add_attr_and_value(p, (char_u *)" ctermul=", 9, ctermul);
+ p = add_attr_and_value(p, (char_u *)" ctermfont=", 9, ctermfont);
p = add_attr_and_value(p, (char_u *)" gui=", 5, gui_attr);
# ifdef FEAT_GUI
p = add_attr_and_value(p, (char_u *)" font=", 6, font);
diff --git a/src/if_lua.c b/src/if_lua.c
index 159a675..4d19c3e 100644
--- a/src/if_lua.c
+++ b/src/if_lua.c
@@ -2692,9 +2692,12 @@ ex_luado(exarg_T *eap)
luaV_emsg(L);
break;
}
+
// Catch the command switching to another buffer.
- if (curbuf != was_curbuf)
+ // Check the line number, the command may have deleted lines.
+ if (curbuf != was_curbuf || l > curbuf->b_ml.ml_line_count)
break;
+
if (lua_isstring(L, -1)) // update line?
{
#ifdef HAVE_SANDBOX
diff --git a/src/if_perl.xs b/src/if_perl.xs
index dd504d3..4f2f8ac 100644
--- a/src/if_perl.xs
+++ b/src/if_perl.xs
@@ -1368,7 +1368,7 @@ ex_perldo(exarg_T *eap)
PUSHMARK(sp);
perl_call_pv("VIM::perldo", G_SCALAR | G_EVAL);
str = SvPV(GvSV(PL_errgv), length);
- if (length || curbuf != was_curbuf)
+ if (length || curbuf != was_curbuf || i > curbuf->b_ml.ml_line_count)
break;
SPAGAIN;
if (SvTRUEx(POPs))
diff --git a/src/if_py_both.h b/src/if_py_both.h
index 42db510..3e5993b 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -6136,7 +6136,8 @@ run_do(const char *cmd, void *arg UNUSED
goto err;
// Check that the command didn't switch to another buffer.
- if (curbuf != was_curbuf)
+ // Check the line number, the command my have deleted lines.
+ if (curbuf != was_curbuf || lnum > curbuf->b_ml.ml_line_count)
{
Py_XDECREF(ret);
goto err;
diff --git a/src/if_ruby.c b/src/if_ruby.c
index 7fab211..a018dcd 100644
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -885,7 +885,7 @@ ex_rubydo(exarg_T *eap)
error_print(state);
break;
}
- if (was_curbuf != curbuf)
+ if (was_curbuf != curbuf || i > curbuf->b_ml.ml_line_count)
break;
line = rb_lastline_get();
if (!NIL_P(line))
diff --git a/src/if_tcl.c b/src/if_tcl.c
index d3d4639..eab321b 100644
--- a/src/if_tcl.c
+++ b/src/if_tcl.c
@@ -2012,7 +2012,8 @@ ex_tcldo(exarg_T *eap)
#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8
|| Tcl_LimitExceeded(tclinfo.interp)
#endif
- || curbuf != was_curbuf)
+ || curbuf != was_curbuf
+ || (linenr_T)rs > curbuf->b_ml.ml_line_count)
break;
line = (char *)Tcl_GetVar(tclinfo.interp, var_line, 0);
if (line)
diff --git a/src/indent.c b/src/indent.c
index 1858ecf..56032fa 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -434,20 +434,17 @@ get_indent_buf(buf_T *buf, linenr_T lnum)
get_indent_str(
char_u *ptr,
int ts,
- int list) // if TRUE, count only screen size for tabs
+ int no_ts) // if TRUE, count a tab as ^I
{
int count = 0;
for ( ; *ptr; ++ptr)
{
- if (*ptr == TAB)
+ if (*ptr == TAB) // count a tab for what it is worth
{
- if (!list || curwin->w_lcs_chars.tab1)
- // count a tab for what it is worth
+ if (!no_ts)
count += ts - (count % ts);
else
- // In list mode, when tab is not set, count screen char width
- // for Tab, displays: ^I
count += ptr2cells(ptr);
}
else if (*ptr == ' ')
@@ -462,10 +459,10 @@ get_indent_str(
/*
* Count the size (in window cells) of the indent in line "ptr", using
* variable tabstops.
- * if "list" is TRUE, count only screen size for tabs.
+ * If "no_ts" is TRUE, count a tab as ^I.
*/
int
-get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
+get_indent_str_vtab(char_u *ptr, int ts, int *vts, int no_ts)
{
int count = 0;
@@ -473,11 +470,9 @@ get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
{
if (*ptr == TAB) // count a tab for what it is worth
{
- if (!list || curwin->w_lcs_chars.tab1)
+ if (!no_ts)
count += tabstop_padding(count, ts, vts);
else
- // In list mode, when tab is not set, count screen char width
- // for Tab, displays: ^I
count += ptr2cells(ptr);
}
else if (*ptr == ' ')
@@ -925,61 +920,70 @@ get_breakindent_win(
{
static int prev_indent = 0; // cached indent value
static long prev_ts = 0L; // cached tabstop value
- static int prev_fnum = 0; // cached buffer number
- static char_u *prev_line = NULL; // cached copy of "line"
- static varnumber_T prev_tick = 0; // changedtick of cached value
# ifdef FEAT_VARTABS
static int *prev_vts = NULL; // cached vartabs values
# endif
- static int prev_list = 0; // cached list value
+ static int prev_fnum = 0; // cached buffer number
+ static char_u *prev_line = NULL; // cached copy of "line"
+ static varnumber_T prev_tick = 0; // changedtick of cached value
+ static int prev_list = 0; // cached list indent
static int prev_listopt = 0; // cached w_p_briopt_list value
+ static int prev_no_ts = FALSE; // cached no_ts value
+ static unsigned prev_dy_uhex = 0; // cached 'display' "uhex" value
// cached formatlistpat value
static char_u *prev_flp = NULL;
int bri = 0;
// window width minus window margin space, i.e. what rests for text
const int eff_wwidth = wp->w_width
- - ((wp->w_p_nu || wp->w_p_rnu)
- && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
- ? number_width(wp) + 1 : 0);
-
- // used cached indent, unless
- // - buffer changed
- // - 'tabstop' changed
- // - buffer was changed
- // - 'briopt_list changed' changed or
- // - 'formatlistpattern' changed
- // - line changed
- // - 'vartabs' changed
+ - win_col_off(wp) + win_col_off2(wp);
+
+ // In list mode, if 'listchars' "tab" isn't set, a TAB is displayed as ^I.
+ int no_ts = wp->w_p_list && wp->w_lcs_chars.tab1 == NUL;
+
+ // Used cached indent, unless
+ // - buffer changed, or
+ // - 'tabstop' changed, or
+ // - 'vartabstop' changed, or
+ // - buffer was changed, or
+ // - 'breakindentopt' "list" changed, or
+ // - 'list' or 'listchars' "tab" changed, or
+ // - 'display' "uhex" flag changed, or
+ // - 'formatlistpat' changed, or
+ // - line changed.
if (prev_fnum != wp->w_buffer->b_fnum
|| prev_ts != wp->w_buffer->b_p_ts
+# ifdef FEAT_VARTABS
+ || prev_vts != wp->w_buffer->b_p_vts_array
+# endif
|| prev_tick != CHANGEDTICK(wp->w_buffer)
|| prev_listopt != wp->w_briopt_list
+ || prev_no_ts != no_ts
+ || prev_dy_uhex != (dy_flags & DY_UHEX)
|| prev_flp == NULL
|| STRCMP(prev_flp, get_flp_value(wp->w_buffer)) != 0
|| prev_line == NULL || STRCMP(prev_line, line) != 0
-# ifdef FEAT_VARTABS
- || prev_vts != wp->w_buffer->b_p_vts_array
-# endif
)
{
prev_fnum = wp->w_buffer->b_fnum;
vim_free(prev_line);
prev_line = vim_strsave(line);
prev_ts = wp->w_buffer->b_p_ts;
- prev_tick = CHANGEDTICK(wp->w_buffer);
# ifdef FEAT_VARTABS
prev_vts = wp->w_buffer->b_p_vts_array;
if (wp->w_briopt_vcol == 0)
prev_indent = get_indent_str_vtab(line,
(int)wp->w_buffer->b_p_ts,
- wp->w_buffer->b_p_vts_array, wp->w_p_list);
+ wp->w_buffer->b_p_vts_array, no_ts);
# else
if (wp->w_briopt_vcol == 0)
prev_indent = get_indent_str(line,
- (int)wp->w_buffer->b_p_ts, wp->w_p_list);
+ (int)wp->w_buffer->b_p_ts, no_ts);
# endif
+ prev_tick = CHANGEDTICK(wp->w_buffer);
prev_listopt = wp->w_briopt_list;
prev_list = 0;
+ prev_no_ts = no_ts;
+ prev_dy_uhex = (dy_flags & DY_UHEX);
vim_free(prev_flp);
prev_flp = vim_strsave(get_flp_value(wp->w_buffer));
// add additional indent for numbered lists
@@ -1605,7 +1609,7 @@ copy_indent(int size, char_u *src)
{
// Allocate memory for the result: the copied indent, new indent
// and the rest of the line.
- line_len = (int)STRLEN(ml_get_curline()) + 1;
+ line_len = ml_get_curline_len() + 1;
line = alloc(ind_len + line_len);
if (line == NULL)
return FALSE;
diff --git a/src/insexpand.c b/src/insexpand.c
index e870147..9b5e5de 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -653,7 +653,10 @@ ins_compl_infercase_gettext(
// getting to six bytes from the edge of IObuff switch to using a
// growarray. Add the character in the next round.
if (ga_grow(&gap, IOSIZE) == FAIL)
+ {
+ vim_free(wca);
return (char_u *)"[failed]";
+ }
*p = NUL;
STRCPY(gap.ga_data, IObuff);
gap.ga_len = (int)STRLEN(IObuff);
@@ -1350,7 +1353,13 @@ ins_compl_show_pum(void)
}
if (compl_match_array == NULL)
+ {
+#ifdef FEAT_EVAL
+ if (compl_started && has_completechanged())
+ trigger_complete_changed_event(cur);
+#endif
return;
+ }
// In Replace mode when a $ is displayed at the end of the line only
// part of the screen would be updated. We do need to redraw here.
@@ -1363,6 +1372,10 @@ ins_compl_show_pum(void)
pum_display(compl_match_array, compl_match_arraysize, cur);
curwin->w_cursor.col = col;
+ // After adding leader, set the current match to shown match.
+ if (compl_started && compl_curr_match != compl_shown_match)
+ compl_curr_match = compl_shown_match;
+
#ifdef FEAT_EVAL
if (has_completechanged())
trigger_complete_changed_event(cur);
@@ -3035,73 +3048,6 @@ ins_compl_update_sequence_numbers(void)
}
}
- static int
-info_add_completion_info(list_T *li)
-{
- compl_T *match;
- int forward = compl_dir_forward();
-
- if (compl_first_match == NULL)
- return OK;
-
- match = compl_first_match;
- // There are four cases to consider here:
- // 1) when just going forward through the menu,
- // compl_first_match should point to the initial entry with
- // number zero and CP_ORIGINAL_TEXT flag set
- // 2) when just going backwards,
- // compl-first_match should point to the last entry before
- // the entry with the CP_ORIGINAL_TEXT flag set
- // 3) when first going forwards and then backwards, e.g.
- // pressing C-N, C-P, compl_first_match points to the
- // last entry before the entry with the CP_ORIGINAL_TEXT
- // flag set and next-entry moves opposite through the list
- // compared to case 2, so pretend the direction is forward again
- // 4) when first going backwards and then forwards, e.g.
- // pressing C-P, C-N, compl_first_match points to the
- // first entry with the CP_ORIGINAL_TEXT
- // flag set and next-entry moves in opposite direction through the list
- // compared to case 1, so pretend the direction is backwards again
- //
- // But only do this when the 'noselect' option is not active!
-
- if (!compl_no_select)
- {
- if (forward && !match_at_original_text(match))
- forward = FALSE;
- else if (!forward && match_at_original_text(match))
- forward = TRUE;
- }
-
- // Skip the element with the CP_ORIGINAL_TEXT flag at the beginning, in case of
- // forward completion, or at the end, in case of backward completion.
- match = forward ? match->cp_next : (compl_no_select && match_at_original_text(match) ? match->cp_prev : match->cp_prev->cp_prev);
-
- while (match != NULL && !match_at_original_text(match))
- {
- dict_T *di = dict_alloc();
-
- if (di == NULL)
- return FAIL;
- if (list_append_dict(li, di) == FAIL)
- return FAIL;
- dict_add_string(di, "word", match->cp_str);
- dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]);
- dict_add_string(di, "menu", match->cp_text[CPT_MENU]);
- dict_add_string(di, "kind", match->cp_text[CPT_KIND]);
- dict_add_string(di, "info", match->cp_text[CPT_INFO]);
- if (match->cp_user_data.v_type == VAR_UNKNOWN)
- // Add an empty string for backwards compatibility
- dict_add_string(di, "user_data", (char_u *)"");
- else
- dict_add_tv(di, "user_data", &match->cp_user_data);
-
- match = forward ? match->cp_next : match->cp_prev;
- }
-
- return OK;
-}
-
/*
* Get complete information
*/
@@ -3147,24 +3093,60 @@ get_complete_info(list_T *what_list, dict_T *retdict)
if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE))
ret = dict_add_number(retdict, "pum_visible", pum_visible());
- if (ret == OK && (what_flag & CI_WHAT_ITEMS))
+ if (ret == OK && (what_flag & CI_WHAT_ITEMS || what_flag & CI_WHAT_SELECTED))
{
- list_T *li;
+ list_T *li = NULL;
+ dict_T *di;
+ compl_T *match;
+ int selected_idx = -1;
- li = list_alloc();
- if (li == NULL)
- return;
- ret = dict_add_list(retdict, "items", li);
- if (ret == OK)
- ret = info_add_completion_info(li);
- }
-
- if (ret == OK && (what_flag & CI_WHAT_SELECTED))
- {
- if (compl_curr_match != NULL && compl_curr_match->cp_number == -1)
- ins_compl_update_sequence_numbers();
- ret = dict_add_number(retdict, "selected", compl_curr_match != NULL
- ? compl_curr_match->cp_number - 1 : -1);
+ if (what_flag & CI_WHAT_ITEMS)
+ {
+ li = list_alloc();
+ if (li == NULL)
+ return;
+ ret = dict_add_list(retdict, "items", li);
+ }
+ if (ret == OK && what_flag & CI_WHAT_SELECTED)
+ if (compl_curr_match != NULL && compl_curr_match->cp_number == -1)
+ ins_compl_update_sequence_numbers();
+ if (ret == OK && compl_first_match != NULL)
+ {
+ int list_idx = 0;
+ match = compl_first_match;
+ do
+ {
+ if (!match_at_original_text(match))
+ {
+ if (what_flag & CI_WHAT_ITEMS)
+ {
+ di = dict_alloc();
+ if (di == NULL)
+ return;
+ ret = list_append_dict(li, di);
+ if (ret != OK)
+ return;
+ dict_add_string(di, "word", match->cp_str);
+ dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]);
+ dict_add_string(di, "menu", match->cp_text[CPT_MENU]);
+ dict_add_string(di, "kind", match->cp_text[CPT_KIND]);
+ dict_add_string(di, "info", match->cp_text[CPT_INFO]);
+ if (match->cp_user_data.v_type == VAR_UNKNOWN)
+ // Add an empty string for backwards compatibility
+ dict_add_string(di, "user_data", (char_u *)"");
+ else
+ dict_add_tv(di, "user_data", &match->cp_user_data);
+ }
+ if (compl_curr_match != NULL && compl_curr_match->cp_number == match->cp_number)
+ selected_idx = list_idx;
+ list_idx += 1;
+ }
+ match = match->cp_next;
+ }
+ while (match != NULL && !is_first_match(match));
+ }
+ if (ret == OK && (what_flag & CI_WHAT_SELECTED))
+ ret = dict_add_number(retdict, "selected", selected_idx);
}
if (ret == OK && (what_flag & CI_WHAT_INSERTED))
@@ -3286,8 +3268,7 @@ process_next_cpt_value(
// buffer, so that word at start of buffer is found
// correctly.
st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count;
- st->first_match_pos.col =
- (colnr_T)STRLEN(ml_get(st->first_match_pos.lnum));
+ st->first_match_pos.col = ml_get_len(st->first_match_pos.lnum);
}
st->last_match_pos = st->first_match_pos;
compl_type = 0;
@@ -3396,7 +3377,7 @@ get_next_include_file_completion(int compl_type)
(compl_type == CTRL_X_PATH_DEFINES
&& !(compl_cont_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
- (linenr_T)1, (linenr_T)MAXLNUM);
+ (linenr_T)1, (linenr_T)MAXLNUM, FALSE);
}
#endif
diff --git a/src/keymap.h b/src/keymap.h
index 6fddc7f..29e2a05 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -500,8 +500,8 @@ enum key_extra
#define MOD_MASK_2CLICK 0x20 // use MOD_MASK_MULTI_CLICK
#define MOD_MASK_3CLICK 0x40 // use MOD_MASK_MULTI_CLICK
#define MOD_MASK_4CLICK 0x60 // use MOD_MASK_MULTI_CLICK
-#ifdef MACOS_X
-# define MOD_MASK_CMD 0x80
+#if defined(MACOS_X) || defined(FEAT_GUI_GTK)
+# define MOD_MASK_CMD 0x80 // aka SUPER
#endif
#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK|MOD_MASK_4CLICK)
diff --git a/src/list.c b/src/list.c
index b50cb03..e9f1ae3 100644
--- a/src/list.c
+++ b/src/list.c
@@ -2325,7 +2325,7 @@ f_uniq(typval_T *argvars, typval_T *rettv)
}
/*
- * Handle one item for map() and filter().
+ * Handle one item for map(), filter(), foreach().
* Sets v:val to "tv". Caller must set v:key.
*/
int
@@ -2341,6 +2341,17 @@ filter_map_one(
int retval = FAIL;
copy_tv(tv, get_vim_var_tv(VV_VAL));
+
+ newtv->v_type = VAR_UNKNOWN;
+ if (filtermap == FILTERMAP_FOREACH && expr->v_type == VAR_STRING)
+ {
+ // foreach() is not limited to an expression
+ do_cmdline_cmd(expr->vval.v_string);
+ if (!did_emsg)
+ retval = OK;
+ goto theend;
+ }
+
argv[0] = *get_vim_var_tv(VV_KEY);
argv[1] = *get_vim_var_tv(VV_VAL);
if (eval_expr_typval(expr, FALSE, argv, 2, fc, newtv) == FAIL)
@@ -2360,6 +2371,8 @@ filter_map_one(
if (error)
goto theend;
}
+ else if (filtermap == FILTERMAP_FOREACH)
+ clear_tv(newtv);
retval = OK;
theend:
clear_tv(get_vim_var_tv(VV_VAL));
@@ -2367,8 +2380,8 @@ theend:
}
/*
- * Implementation of map() and filter() for a List. Apply "expr" to every item
- * in List "l" and return the result in "rettv".
+ * Implementation of map(), filter(), foreach() for a List. Apply "expr" to
+ * every item in List "l" and return the result in "rettv".
*/
static void
list_filter_map(
@@ -2421,7 +2434,8 @@ list_filter_map(
int stride = l->lv_u.nonmat.lv_stride;
// List from range(): loop over the numbers
- if (filtermap != FILTERMAP_MAPNEW)
+ // NOTE: foreach() returns the range_list_item
+ if (filtermap != FILTERMAP_MAPNEW && filtermap != FILTERMAP_FOREACH)
{
l->lv_first = NULL;
l->lv_u.mat.lv_last = NULL;
@@ -2444,27 +2458,30 @@ list_filter_map(
clear_tv(&newtv);
break;
}
- if (filtermap != FILTERMAP_FILTER)
+ if (filtermap != FILTERMAP_FOREACH)
{
- if (filtermap == FILTERMAP_MAP && argtype != NULL
+ if (filtermap != FILTERMAP_FILTER)
+ {
+ if (filtermap == FILTERMAP_MAP && argtype != NULL
&& check_typval_arg_type(
- argtype->tt_member, &newtv,
- func_name, 0) == FAIL)
+ argtype->tt_member, &newtv,
+ func_name, 0) == FAIL)
+ {
+ clear_tv(&newtv);
+ break;
+ }
+ // map(), mapnew(): always append the new value to the
+ // list
+ if (list_append_tv_move(filtermap == FILTERMAP_MAP
+ ? l : l_ret, &newtv) == FAIL)
+ break;
+ }
+ else if (!rem)
{
- clear_tv(&newtv);
- break;
+ // filter(): append the list item value when not rem
+ if (list_append_tv_move(l, &tv) == FAIL)
+ break;
}
- // map(), mapnew(): always append the new value to the
- // list
- if (list_append_tv_move(filtermap == FILTERMAP_MAP
- ? l : l_ret, &newtv) == FAIL)
- break;
- }
- else if (!rem)
- {
- // filter(): append the list item value when not rem
- if (list_append_tv_move(l, &tv) == FAIL)
- break;
}
val += stride;
@@ -2508,7 +2525,7 @@ list_filter_map(
break;
}
else if (filtermap == FILTERMAP_FILTER && rem)
- listitem_remove(l, li);
+ listitem_remove(l, li);
++idx;
}
}
@@ -2519,7 +2536,7 @@ list_filter_map(
}
/*
- * Implementation of map() and filter().
+ * Implementation of map(), filter() and foreach().
*/
static void
filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
@@ -2527,16 +2544,19 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
typval_T *expr;
char *func_name = filtermap == FILTERMAP_MAP ? "map()"
: filtermap == FILTERMAP_MAPNEW ? "mapnew()"
- : "filter()";
+ : filtermap == FILTERMAP_FILTER ? "filter()"
+ : "foreach()";
char_u *arg_errmsg = (char_u *)(filtermap == FILTERMAP_MAP
? N_("map() argument")
: filtermap == FILTERMAP_MAPNEW
? N_("mapnew() argument")
- : N_("filter() argument"));
+ : filtermap == FILTERMAP_FILTER
+ ? N_("filter() argument")
+ : N_("foreach() argument"));
int save_did_emsg;
type_T *type = NULL;
- // map() and filter() return the first argument, also on failure.
+ // map(), filter(), foreach() return the first argument, also on failure.
if (filtermap != FILTERMAP_MAPNEW && argvars[0].v_type != VAR_STRING)
copy_tv(&argvars[0], rettv);
@@ -2630,6 +2650,15 @@ f_mapnew(typval_T *argvars, typval_T *rettv)
}
/*
+ * "foreach()" function
+ */
+ void
+f_foreach(typval_T *argvars, typval_T *rettv)
+{
+ filter_map(argvars, rettv, FILTERMAP_FOREACH);
+}
+
+/*
* "add(list, item)" function
*/
static void
diff --git a/src/mbyte.c b/src/mbyte.c
index ee2834c..d6fb7ec 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -3454,6 +3454,8 @@ static convertStruct toLower[] =
{0x1e900,0x1e921,1,34}
};
+// Note: UnicodeData.txt does not define U+1E9E as being the corresponding upper
+// case letter for U+00DF (ß), however it is part of the toLower table
static convertStruct toUpper[] =
{
{0x61,0x7a,1,-32},
@@ -4186,32 +4188,12 @@ mb_copy_char(char_u **fp, char_u **tp)
int
mb_off_next(char_u *base, char_u *p)
{
- int i;
- int j;
+ int head_off = (*mb_head_off)(base, p);
- if (enc_utf8)
- {
- if (*p < 0x80) // be quick for ASCII
- return 0;
-
- // Find the next character that isn't 10xx.xxxx
- for (i = 0; (p[i] & 0xc0) == 0x80; ++i)
- ;
- if (i > 0)
- {
- // Check for illegal sequence.
- for (j = 0; p - j > base; ++j)
- if ((p[-j] & 0xc0) != 0x80)
- break;
- if (utf8len_tab[p[-j]] != i + j)
- return 0;
- }
- return i;
- }
+ if (head_off == 0)
+ return 0;
- // Only need to check if we're on a trail byte, it doesn't matter if we
- // want the offset to the next or current character.
- return (*mb_head_off)(base, p);
+ return (*mb_ptr2len)(p - head_off) - head_off;
}
/*
@@ -4396,7 +4378,7 @@ mb_adjustpos(buf_T *buf, pos_T *lp)
if (lp->col > 0 || lp->coladd > 1)
{
p = ml_get_buf(buf, lp->lnum, FALSE);
- if (*p == NUL || (int)STRLEN(p) < lp->col)
+ if (*p == NUL || ml_get_buf_len(buf, lp->lnum) < lp->col)
lp->col = 0;
else
lp->col -= (*mb_head_off)(p, p + lp->col);
@@ -5613,7 +5595,8 @@ tv_nr_compare(const void *a1, const void *a2)
listitem_T *li1 = *(listitem_T **)a1;
listitem_T *li2 = *(listitem_T **)a2;
- return li1->li_tv.vval.v_number - li2->li_tv.vval.v_number;
+ return li1->li_tv.vval.v_number == li2->li_tv.vval.v_number ? 0 :
+ li1->li_tv.vval.v_number > li2->li_tv.vval.v_number ? 1 : -1;
}
void
diff --git a/src/memline.c b/src/memline.c
index cf2dc8c..5ca50fc 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -1754,7 +1754,7 @@ ml_recover(int checkext)
for (idx = 1; idx <= lnum; ++idx)
{
// Need to copy one line, fetching the other one may flush it.
- p = vim_strsave(ml_get(idx));
+ p = vim_strnsave(ml_get(idx), ml_get_len(idx));
i = STRCMP(p, ml_get(idx + lnum));
vim_free(p);
if (i != 0)
@@ -2675,6 +2675,48 @@ ml_get_cursor(void)
curwin->w_cursor.col);
}
+// return length (excluding the NUL) of the given line
+ colnr_T
+ml_get_len(linenr_T lnum)
+{
+ return ml_get_buf_len(curbuf, lnum);
+}
+
+// return length (excluding the NUL) of the text after position "pos"
+ colnr_T
+ml_get_pos_len(pos_T *pos)
+{
+ return ml_get_buf_len(curbuf, pos->lnum) - pos->col;
+}
+
+// return length (excluding the NUL) of the cursor line
+ colnr_T
+ml_get_curline_len(void)
+{
+ return ml_get_buf_len(curbuf, curwin->w_cursor.lnum);
+}
+
+// return length (excluding the NUL) of the cursor position
+ colnr_T
+ml_get_cursor_len(void)
+{
+ return ml_get_buf_len(curbuf, curwin->w_cursor.lnum) - curwin->w_cursor.col;
+}
+
+// return length (excluding the NUL) of the given line in the given buffer
+ colnr_T
+ml_get_buf_len(buf_T *buf, linenr_T lnum)
+{
+ char_u *line;
+
+ if (*(line = ml_get_buf(buf, lnum, FALSE)) == NUL)
+ return 0;
+
+ if (buf->b_ml.ml_line_textlen <= 0)
+ buf->b_ml.ml_line_textlen = (int)STRLEN(line) + 1;
+ return buf->b_ml.ml_line_textlen - 1;
+}
+
/*
* Return a pointer to a line in a specific buffer
*
@@ -2706,6 +2748,7 @@ ml_get_buf(
errorret:
STRCPY(questions, "???");
buf->b_ml.ml_line_len = 4;
+ buf->b_ml.ml_line_textlen = buf->b_ml.ml_line_len;
buf->b_ml.ml_line_lnum = lnum;
return questions;
}
@@ -2715,6 +2758,7 @@ errorret:
if (buf->b_ml.ml_mfp == NULL) // there are no lines
{
buf->b_ml.ml_line_len = 1;
+ buf->b_ml.ml_line_textlen = buf->b_ml.ml_line_len;
return (char_u *)"";
}
@@ -2727,7 +2771,6 @@ errorret:
if (buf->b_ml.ml_line_lnum != lnum || mf_dont_release)
{
unsigned start, end;
- colnr_T len;
int idx;
ml_flush_line(buf);
@@ -2763,10 +2806,18 @@ errorret:
end = dp->db_txt_end;
else
end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
- len = end - start;
buf->b_ml.ml_line_ptr = (char_u *)dp + start;
- buf->b_ml.ml_line_len = len;
+ buf->b_ml.ml_line_len = end - start;
+#if defined(FEAT_BYTEOFF) && defined(FEAT_PROP_POPUP)
+ // Text properties come after a NUL byte, so ml_line_len should be
+ // larger than the size of textprop_T if there is any.
+ if (buf->b_has_textprop
+ && (size_t)buf->b_ml.ml_line_len > sizeof(textprop_T))
+ buf->b_ml.ml_line_textlen = 0; // call STRLEN() later when needed
+ else
+#endif
+ buf->b_ml.ml_line_textlen = buf->b_ml.ml_line_len;
buf->b_ml.ml_line_lnum = lnum;
buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED);
}
@@ -3400,10 +3451,10 @@ ml_append_int(
#ifdef FEAT_NETBEANS_INTG
if (netbeans_active())
{
- if (STRLEN(line) > 0)
- netbeans_inserted(buf, lnum+1, (colnr_T)0, line, (int)STRLEN(line));
- netbeans_inserted(buf, lnum+1, (colnr_T)STRLEN(line),
- (char_u *)"\n", 1);
+ int line_len = (int)STRLEN(line);
+ if (line_len > 0)
+ netbeans_inserted(buf, lnum+1, (colnr_T)0, line, line_len);
+ netbeans_inserted(buf, lnum+1, (colnr_T)line_len, (char_u *)"\n", 1);
}
#endif
#ifdef FEAT_JOB_CHANNEL
@@ -3531,7 +3582,7 @@ ml_replace(linenr_T lnum, char_u *line, int copy)
* Replace a line for the current buffer. Like ml_replace() with:
* "len_arg" is the length of the text, excluding NUL.
* If "has_props" is TRUE then "line_arg" includes the text properties and
- * "len_arg" includes the NUL of the text.
+ * "len_arg" includes the NUL of the text and text properties.
* When "copy" is TRUE copy the text into allocated memory, otherwise
* "line_arg" must be allocated and will be consumed here.
*/
@@ -3571,7 +3622,7 @@ ml_replace_len(
#ifdef FEAT_NETBEANS_INTG
if (netbeans_active())
{
- netbeans_removed(curbuf, lnum, 0, (long)STRLEN(ml_get(lnum)));
+ netbeans_removed(curbuf, lnum, 0, (long)ml_get_len(lnum));
netbeans_inserted(curbuf, lnum, 0, line, (int)STRLEN(line));
}
#endif
@@ -3617,6 +3668,7 @@ ml_replace_len(
curbuf->b_ml.ml_line_ptr = line;
curbuf->b_ml.ml_line_len = len;
+ curbuf->b_ml.ml_line_textlen = !has_props ? len_arg + 1 : 0;
curbuf->b_ml.ml_line_lnum = lnum;
curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
@@ -5192,15 +5244,15 @@ findswapname(
{
char_u *name;
int dialog_result;
+ size_t len = STRLEN(_("Swap file \""));
name = alloc(STRLEN(fname)
- + STRLEN(_("Swap file \""))
+ + len
+ STRLEN(_("\" already exists!")) + 5);
if (name != NULL)
{
STRCPY(name, _("Swap file \""));
- home_replace(NULL, fname, name + STRLEN(name),
- 1000, TRUE);
+ home_replace(NULL, fname, name + len, 1000, TRUE);
STRCAT(name, _("\" already exists!"));
}
dialog_result = do_dialog(VIM_WARNING,
diff --git a/src/misc1.c b/src/misc1.c
index bf70e38..3085fc7 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -1404,9 +1404,6 @@ expand_env_esc(
int mustfree; // var was allocated, need to free it later
int at_start = TRUE; // at start of a name
int startstr_len = 0;
-#if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA)
- char_u *save_dst = dst;
-#endif
if (startstr != NULL)
startstr_len = (int)STRLEN(startstr);
@@ -1631,7 +1628,7 @@ expand_env_esc(
// with it, skip a character
if (after_pathsep(dst, dst + c)
#if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA)
- && (dst == save_dst || dst[-1] != ':')
+ && dst[c - 1] != ':'
#endif
&& vim_ispathsep(*tail))
++tail;
diff --git a/src/misc2.c b/src/misc2.c
index 169eb51..6df0d39 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -130,6 +130,7 @@ coladvance2(
colnr_T wcol = wcol_arg;
int idx;
char_u *line;
+ int linelen;
colnr_T col = 0;
int csize = 0;
int one_more;
@@ -142,10 +143,11 @@ coladvance2(
|| (VIsual_active && *p_sel != 'o')
|| ((get_ve_flags() & VE_ONEMORE) && wcol < MAXCOL);
line = ml_get_buf(curbuf, pos->lnum, FALSE);
+ linelen = ml_get_buf_len(curbuf, pos->lnum);
if (wcol >= MAXCOL)
{
- idx = (int)STRLEN(line) - 1 + one_more;
+ idx = linelen - 1 + one_more;
col = wcol;
if ((addspaces || finetune) && !VIsual_active)
@@ -255,7 +257,6 @@ coladvance2(
else
{
// Break a tab
- int linelen = (int)STRLEN(line);
int correct = wcol - col - csize + 1; // negative!!
char_u *newline;
int t, s = 0;
@@ -412,7 +413,7 @@ dec(pos_T *lp)
{
// past end of line
p = ml_get(lp->lnum);
- lp->col = (colnr_T)STRLEN(p);
+ lp->col = ml_get_len(lp->lnum);
if (has_mbyte)
lp->col -= (*mb_head_off)(p, p + lp->col);
return 0;
@@ -435,7 +436,7 @@ dec(pos_T *lp)
// there is a prior line
lp->lnum--;
p = ml_get(lp->lnum);
- lp->col = (colnr_T)STRLEN(p);
+ lp->col = ml_get_len(lp->lnum);
if (has_mbyte)
lp->col -= (*mb_head_off)(p, p + lp->col);
return 1;
@@ -515,7 +516,6 @@ get_cursor_rel_lnum(
void
check_pos(buf_T *buf, pos_T *pos)
{
- char_u *line;
colnr_T len;
if (pos->lnum > buf->b_ml.ml_line_count)
@@ -523,8 +523,7 @@ check_pos(buf_T *buf, pos_T *pos)
if (pos->col > 0)
{
- line = ml_get_buf(buf, pos->lnum, FALSE);
- len = (colnr_T)STRLEN(line);
+ len = ml_get_buf_len(buf, pos->lnum);
if (pos->col > len)
pos->col = len;
}
@@ -570,7 +569,7 @@ check_cursor_col_win(win_T *win)
colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd;
unsigned int cur_ve_flags = get_ve_flags();
- len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE));
+ len = ml_get_buf_len(win->w_buffer, win->w_cursor.lnum);
if (len == 0)
win->w_cursor.col = 0;
else if (win->w_cursor.col >= len)
@@ -649,7 +648,7 @@ check_visual_pos(void)
}
else
{
- int len = (int)STRLEN(ml_get(VIsual.lnum));
+ int len = ml_get_len(VIsual.lnum);
if (VIsual.col > len)
{
@@ -817,7 +816,7 @@ static struct modmasktable
{MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2'},
{MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3'},
{MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4'},
-#ifdef MACOS_X
+#if defined(MACOS_X) || defined(FEAT_GUI_GTK)
{MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D'},
#endif
// 'A' must be the last one
@@ -1130,7 +1129,7 @@ simplify_key(int key, int *modifiers)
int key0;
int key1;
- if (!(*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT)))
+ if (!(*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
return key;
// TAB is a special case
@@ -1582,6 +1581,9 @@ may_remove_shift_modifier(int modifiers, int key)
{
if ((modifiers == MOD_MASK_SHIFT
|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
+#ifdef FEAT_GUI_GTK
+ || modifiers == (MOD_MASK_SHIFT | MOD_MASK_CMD)
+#endif
|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
&& ((key >= '!' && key <= '/')
|| (key >= ':' && key <= 'Z')
diff --git a/src/mouse.c b/src/mouse.c
index b283c64..af14af0 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -1696,7 +1696,7 @@ retnomove:
}
#if defined(FEAT_CLIPBOARD)
// Continue a modeless selection in another window.
- if (cmdwin_type != 0 && row < curwin->w_winrow)
+ if (cmdwin_type != 0 && row < cmdwin_win->w_winrow)
return IN_OTHER_WIN;
#endif
#ifdef FEAT_PROP_POPUP
@@ -1824,7 +1824,7 @@ retnomove:
# ifdef FEAT_RIGHTLEFT
wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
# endif
- col >= wp->w_p_fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1)
+ col >= wp->w_p_fdc + (wp != cmdwin_win ? 0 : 1)
)
#endif
&& (flags & MOUSE_MAY_STOP_VIS))))
@@ -1832,7 +1832,7 @@ retnomove:
end_visual_mode_keep_button();
redraw_curbuf_later(UPD_INVERTED); // delete the inversion
}
- if (cmdwin_type != 0 && wp != curwin)
+ if (cmdwin_type != 0 && wp != cmdwin_win)
{
// A click outside the command-line window: Use modeless
// selection if possible. Allow dragging the status lines.
@@ -1844,7 +1844,7 @@ retnomove:
#else
row = 0;
col += wp->w_wincol;
- wp = curwin;
+ wp = cmdwin_win;
#endif
}
#if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
@@ -1937,7 +1937,7 @@ retnomove:
#if defined(FEAT_CLIPBOARD)
// Continue a modeless selection in another window.
- if (cmdwin_type != 0 && row < curwin->w_winrow)
+ if (cmdwin_type != 0 && row < cmdwin_win->w_winrow)
return IN_OTHER_WIN;
#endif
#ifdef FEAT_PROP_POPUP
@@ -2075,7 +2075,7 @@ retnomove:
# ifdef FEAT_RIGHTLEFT
curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
# endif
- col >= curwin->w_p_fdc + (cmdwin_type == 0 ? 0 : 1)
+ col >= curwin->w_p_fdc + (cmdwin_win != curwin ? 0 : 1)
)
mouse_char = ' ';
#endif
@@ -2098,35 +2098,7 @@ retnomove:
redraw_cmdline = TRUE; // show visual mode later
}
- if (col_from_screen == MAXCOL)
- {
- // When clicking after end of line, still need to set correct curswant
- int off_l = LineOffset[prev_row] + curwin->w_wincol;
- if (ScreenCols[off_l] < MAXCOL)
- {
- // Binary search to find last char in line
- int off_r = LineOffset[prev_row] + prev_col;
- int off_click = off_r;
- while (off_l < off_r)
- {
- int off_m = (off_l + off_r + 1) / 2;
- if (ScreenCols[off_m] < MAXCOL)
- off_l = off_m;
- else
- off_r = off_m - 1;
- }
- colnr_T eol_vcol = ScreenCols[off_r];
- if (eol_vcol < 0)
- // Empty line or whole line before w_leftcol,
- // with columns before buffer text
- eol_vcol = curwin->w_leftcol - 1;
- col = eol_vcol + (off_click - off_r);
- }
- else
- // Empty line or whole line before w_leftcol
- col = prev_col - curwin->w_wincol + curwin->w_leftcol;
- }
- else if (col_from_screen >= 0)
+ if (col_from_screen >= 0)
{
// Use the virtual column from ScreenCols[], it is accurate also after
// concealed characters.
@@ -2224,10 +2196,6 @@ nv_mousescroll(cmdarg_T *cap)
// Call the common mouse scroll function shared with other modes.
do_mousescroll(cap);
-#ifdef FEAT_SYN_HL
- if (curwin != old_curwin && curwin->w_p_cul)
- redraw_for_cursorline(curwin);
-#endif
curwin->w_redr_status = TRUE;
curwin = old_curwin;
curbuf = curwin->w_buffer;
diff --git a/src/move.c b/src/move.c
index 861d84b..9ea24c8 100644
--- a/src/move.c
+++ b/src/move.c
@@ -19,6 +19,7 @@
#include "vim.h"
+static void redraw_for_cursorline(win_T *wp);
static int scrolljump_value(void);
static int check_top_offset(void);
static void curs_rows(win_T *wp);
@@ -155,7 +156,7 @@ comp_botline(win_T *wp)
* Redraw when w_cline_row changes and 'relativenumber' or 'cursorline' is
* set.
*/
- void
+ static void
redraw_for_cursorline(win_T *wp)
{
if ((wp->w_p_rnu
@@ -1067,7 +1068,7 @@ validate_cursor_col(void)
win_col_off(win_T *wp)
{
return (((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
- + (cmdwin_type == 0 || wp != curwin ? 0 : 1)
+ + (wp != cmdwin_win ? 0 : 1)
#ifdef FEAT_FOLDING
+ wp->w_p_fdc
#endif
diff --git a/src/netbeans.c b/src/netbeans.c
index ebdf3a4..3b68869 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -932,7 +932,7 @@ nb_partialremove(linenr_T lnum, colnr_T first, colnr_T last)
int lastbyte = last;
oldtext = ml_get(lnum);
- oldlen = (int)STRLEN(oldtext);
+ oldlen = ml_get_len(lnum);
if (first >= (colnr_T)oldlen || oldlen == 0) // just in case
return;
if (lastbyte >= oldlen)
@@ -957,8 +957,8 @@ nb_joinlines(linenr_T first, linenr_T other)
int len_first, len_other;
char_u *p;
- len_first = (int)STRLEN(ml_get(first));
- len_other = (int)STRLEN(ml_get(other));
+ len_first = ml_get_len(first);
+ len_other = ml_get_len(other);
p = alloc(len_first + len_other + 1);
if (p == NULL)
return;
@@ -1285,8 +1285,7 @@ nb_do_cmd(
netbeansFireChanges = oldFire;
netbeansSuppressNoLines = oldSuppress;
- u_blockfree(buf->bufp);
- u_clearall(buf->bufp);
+ u_clearallandblockfree(buf->bufp);
}
nb_reply_nil(cmdno);
// =====================================================================
@@ -1403,7 +1402,7 @@ nb_do_cmd(
int col = pos == NULL ? 0 : pos->col;
// Insert halfway a line.
- newline = alloc(STRLEN(oldline) + len + 1);
+ newline = alloc(ml_get_len(lnum) + len + 1);
if (newline != NULL)
{
mch_memmove(newline, oldline, (size_t)col);
@@ -1456,8 +1455,7 @@ nb_do_cmd(
netbeansFireChanges = oldFire;
// Undo info is invalid now...
- u_blockfree(curbuf);
- u_clearall(curbuf);
+ u_clearallandblockfree(curbuf);
}
vim_free(to_free);
nb_reply_nil(cmdno); // or !error
@@ -3316,8 +3314,7 @@ get_buf_size(buf_T *bufp)
eol_size = 1;
for (lnum = 1; lnum <= bufp->b_ml.ml_line_count; ++lnum)
{
- char_count += (long)STRLEN(ml_get_buf(bufp, lnum, FALSE))
- + eol_size;
+ char_count += ml_get_buf_len(bufp, lnum) + eol_size;
// Check for a CTRL-C every 100000 characters
if (char_count > last_check)
{
diff --git a/src/normal.c b/src/normal.c
index fd89b00..5ef3a92 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -568,10 +568,10 @@ normal_cmd_get_more_chars(
++no_mapping;
// Vim may be in a different mode when the user types the next key,
// but when replaying a recording the next key is already in the
- // typeahead buffer, so record a <Nop> before that to prevent the
- // vpeekc() above from applying wrong mappings when replaying.
+ // typeahead buffer, so record an <Ignore> before that to prevent
+ // the vpeekc() above from applying wrong mappings when replaying.
++no_u_sync;
- gotchars_nop();
+ gotchars_ignore();
--no_u_sync;
}
}
@@ -3225,8 +3225,7 @@ nv_colon(cmdarg_T *cap)
clearop(cap->oap);
else if (cap->oap->op_type != OP_NOP
&& (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
- || cap->oap->start.col >
- (colnr_T)STRLEN(ml_get(cap->oap->start.lnum))
+ || cap->oap->start.col > ml_get_len(cap->oap->start.lnum)
|| did_emsg
))
// The start of the operator has become invalid by the Ex command.
@@ -3675,7 +3674,7 @@ get_visual_text(
if (VIsual_mode == 'V')
{
*pp = ml_get_curline();
- *lenp = (int)STRLEN(*pp);
+ *lenp = (int)ml_get_curline_len();
}
else
{
@@ -4074,6 +4073,9 @@ nv_gotofile(cmdarg_T *cap)
return;
#endif
+ if (!check_can_set_curbuf_disabled())
+ return;
+
ptr = grab_file_name(cap->count1, &lnum);
if (ptr != NULL)
@@ -4476,7 +4478,8 @@ nv_brackets(cmdarg_T *cap)
SAFE_isupper(cap->nchar) ? ACTION_SHOW_ALL :
SAFE_islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO,
cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1,
- (linenr_T)MAXLNUM);
+ (linenr_T)MAXLNUM,
+ FALSE);
vim_free(ptr);
curwin->w_set_curswant = TRUE;
}
@@ -4768,7 +4771,6 @@ nv_kundo(cmdarg_T *cap)
static void
nv_replace(cmdarg_T *cap)
{
- char_u *ptr;
int had_ctrl_v;
long n;
@@ -4835,9 +4837,8 @@ nv_replace(cmdarg_T *cap)
}
// Abort if not enough characters to replace.
- ptr = ml_get_cursor();
- if (STRLEN(ptr) < (unsigned)cap->count1
- || (has_mbyte && mb_charlen(ptr) < cap->count1))
+ if ((size_t)ml_get_cursor_len() < (unsigned)cap->count1
+ || (has_mbyte && mb_charlen(ml_get_cursor()) < cap->count1))
{
clearopbeep(cap->oap);
return;
@@ -4917,11 +4918,13 @@ nv_replace(cmdarg_T *cap)
}
else
{
+ char_u *ptr;
+
// Replace the characters within one line.
for (n = cap->count1; n > 0; --n)
{
- // Get ptr again, because u_save and/or showmatch() will have
- // released the line. This may also happen in ins_copychar().
+ // Get ptr again, because ins_copychar() and showmatch()
+ // will have released the line.
// At the same time we let know that the line will be changed.
if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y)
{
@@ -4945,6 +4948,7 @@ nv_replace(cmdarg_T *cap)
if (netbeans_active())
{
colnr_T start = (colnr_T)(curwin->w_cursor.col - cap->count1);
+ ptr = ml_get_curline();
netbeans_removed(curbuf, curwin->w_cursor.lnum, start,
cap->count1);
@@ -5130,7 +5134,7 @@ n_swapchar(cmdarg_T *cap)
if (did_change)
{
ptr = ml_get(pos.lnum);
- count = (int)STRLEN(ptr) - pos.col;
+ count = (int)ml_get_len(pos.lnum) - pos.col;
netbeans_removed(curbuf, pos.lnum, pos.col,
(long)count);
// line may have been flushed, get it again
@@ -5919,7 +5923,7 @@ nv_gi_cmd(cmdarg_T *cap)
{
curwin->w_cursor = curbuf->b_last_insert;
check_cursor_lnum();
- i = (int)STRLEN(ml_get_curline());
+ i = (int)ml_get_curline_len();
if (curwin->w_cursor.col > (colnr_T)i)
{
if (virtual_active())
@@ -6717,7 +6721,7 @@ unadjust_for_sel(void)
else if (pp->lnum > 1)
{
--pp->lnum;
- pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
+ pp->col = ml_get_len(pp->lnum);
return TRUE;
}
}
@@ -7323,6 +7327,9 @@ nv_put_opt(cmdarg_T *cap, int fix_indent)
int dir;
int flags = 0;
int keep_registers = FALSE;
+#ifdef FEAT_FOLDING
+ int save_fen = curwin->w_p_fen;
+#endif
if (cap->oap->op_type != OP_NOP)
{
@@ -7388,6 +7395,12 @@ nv_put_opt(cmdarg_T *cap, int fix_indent)
reg1 = get_register(regname, TRUE);
}
+#ifdef FEAT_FOLDING
+ // Temporarily disable folding, as deleting a fold marker may cause
+ // the cursor to be included in a fold.
+ curwin->w_p_fen = FALSE;
+#endif
+
// Now delete the selected text. Avoid messages here.
cap->cmdchar = 'd';
cap->nchar = NUL;
@@ -7435,10 +7448,14 @@ nv_put_opt(cmdarg_T *cap, int fix_indent)
if (reg2 != NULL)
put_register(regname, reg2);
- // What to reselect with "gv"? Selecting the just put text seems to
- // be the most useful, since the original text was removed.
if (was_visual)
{
+#ifdef FEAT_FOLDING
+ if (save_fen)
+ curwin->w_p_fen = TRUE;
+#endif
+ // What to reselect with "gv"? Selecting the just put text seems to
+ // be the most useful, since the original text was removed.
curbuf->b_visual.vi_start = curbuf->b_op_start;
curbuf->b_visual.vi_end = curbuf->b_op_end;
// need to adjust cursor position
diff --git a/src/ops.c b/src/ops.c
index f6d765b..dbdf119 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -212,7 +212,7 @@ op_shift(oparg_T *oap, int curs_top, int amount)
// Set "'[" and "']" marks.
curbuf->b_op_start = oap->start;
curbuf->b_op_end.lnum = oap->end.lnum;
- curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ curbuf->b_op_end.col = ml_get_len(oap->end.lnum);
if (curbuf->b_op_end.col > 0)
--curbuf->b_op_end.col;
}
@@ -476,7 +476,7 @@ shift_block(oparg_T *oap, int amount)
STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white);
}
// replace the line
- added = new_line_len - (int)STRLEN(oldp);
+ added = new_line_len - ml_get_curline_len();
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added);
State = oldstate;
@@ -554,7 +554,7 @@ block_insert(
spaces = 0;
// Make sure the allocated size matches what is actually copied below.
- newp = alloc(STRLEN(oldp) + spaces + s_len
+ newp = alloc(ml_get_len(lnum) + spaces + s_len
+ (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0)
+ count + 1);
if (newp == NULL)
@@ -800,7 +800,7 @@ op_delete(oparg_T *oap)
// Thus the number of characters may increase!
n = bd.textlen - bd.startspaces - bd.endspaces;
oldp = ml_get(lnum);
- newp = alloc(STRLEN(oldp) + 1 - n);
+ newp = alloc(ml_get_len(lnum) + 1 - n);
if (newp == NULL)
continue;
// copy up to deleted part
@@ -849,8 +849,8 @@ op_delete(oparg_T *oap)
}
else
beginline(0); // cursor in column 0
- truncate_line(FALSE); // delete the rest of the line
- // leave cursor past last char in line
+ truncate_line(FALSE); // delete the rest of the line,
+ // leaving cursor past last char in line
if (oap->line_count > 1)
u_clearline(); // "U" command not possible after "2cc"
}
@@ -920,8 +920,7 @@ op_delete(oparg_T *oap)
{
// fix up things for virtualedit-delete:
// break the tabs which are going to get in our way
- char_u *curline = ml_get_curline();
- int len = (int)STRLEN(curline);
+ int len = ml_get_curline_len();
if (oap->end.coladd != 0
&& (int)oap->end.col >= len - 1
@@ -990,13 +989,20 @@ setmarks:
static void
mb_adjust_opend(oparg_T *oap)
{
- char_u *p;
+ char_u *line;
+ char_u *ptr;
if (!oap->inclusive)
return;
- p = ml_get(oap->end.lnum);
- oap->end.col += mb_tail_off(p, p + oap->end.col);
+ line = ml_get(oap->end.lnum);
+ ptr = line + oap->end.col;
+ if (*ptr != NUL)
+ {
+ ptr -= (*mb_head_off)(line, ptr);
+ ptr += (*mb_ptr2len)(ptr) - 1;
+ oap->end.col = ptr - line;
+ }
}
/*
@@ -1109,7 +1115,7 @@ op_replace(oparg_T *oap, int c)
n += numc - bd.textlen;
oldp = ml_get_curline();
- oldlen = STRLEN(oldp);
+ oldlen = ml_get_curline_len();
newp = alloc(oldlen + 1 + n);
if (newp == NULL)
continue;
@@ -1167,7 +1173,7 @@ op_replace(oparg_T *oap, int c)
{
oap->start.col = 0;
curwin->w_cursor.col = 0;
- oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ oap->end.col = ml_get_len(oap->end.lnum);
if (oap->end.col)
--oap->end.col;
}
@@ -1313,7 +1319,7 @@ op_tilde(oparg_T *oap)
{
oap->start.col = 0;
pos.col = 0;
- oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ oap->end.col = ml_get_len(oap->end.lnum);
if (oap->end.col)
--oap->end.col;
}
@@ -1327,8 +1333,8 @@ op_tilde(oparg_T *oap)
for (;;)
{
did_change |= swapchars(oap->op_type, &pos,
- pos.lnum == oap->end.lnum ? oap->end.col + 1:
- (int)STRLEN(ml_get_pos(&pos)));
+ pos.lnum == oap->end.lnum ? oap->end.col + 1
+ : ml_get_pos_len(&pos));
if (LTOREQ_POS(oap->end, pos) || inc(&pos) == -1)
break;
}
@@ -1346,7 +1352,7 @@ op_tilde(oparg_T *oap)
while (pos.lnum < oap->end.lnum)
{
ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
- count = (int)STRLEN(ptr) - pos.col;
+ count = ml_get_buf_len(curbuf, pos.lnum) - pos.col;
netbeans_removed(curbuf, pos.lnum, pos.col, (long)count);
// get the line again, it may have been flushed
ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
@@ -1431,18 +1437,19 @@ swapchar(int op_type, pos_T *pos)
if (c >= 0x80 && op_type == OP_ROT13)
return FALSE;
- if (op_type == OP_UPPER && c == 0xdf
- && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0))
+ // ~ is OP_NOP, g~ is OP_TILDE, gU is OP_UPPER
+ if ((op_type == OP_UPPER || op_type == OP_NOP || op_type == OP_TILDE)
+ && c == 0xdf
+ && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0))
{
pos_T sp = curwin->w_cursor;
- // Special handling of German sharp s: change to "SS".
+ // Special handling for lowercase German sharp s (ß): convert to uppercase (ẞ).
curwin->w_cursor = *pos;
del_char(FALSE);
- ins_char('S');
- ins_char('S');
+ ins_char(0x1E9E);
curwin->w_cursor = sp;
- inc(pos);
+ return TRUE;
}
if (enc_dbcs != 0 && c >= 0x100) // No lower/uppercase letter
@@ -1487,16 +1494,13 @@ swapchar(int op_type, pos_T *pos)
void
op_insert(oparg_T *oap, long count1)
{
- long ins_len, pre_textlen = 0;
- char_u *firstline, *ins_text;
+ long pre_textlen = 0;
colnr_T ind_pre_col = 0, ind_post_col;
int ind_pre_vcol = 0, ind_post_vcol = 0;
struct block_def bd;
int i;
pos_T t1;
pos_T start_insert;
- // offset when cursor was moved in insert mode
- int offset = 0;
// edit() changes this - record it for OP_APPEND
bd.is_MAX = (curwin->w_curswant == MAXCOL);
@@ -1533,11 +1537,9 @@ op_insert(oparg_T *oap, long count1)
// Get indent information
ind_pre_col = (colnr_T)getwhitecols_curline();
ind_pre_vcol = get_indent();
- firstline = ml_get(oap->start.lnum) + bd.textcol;
-
+ pre_textlen = ml_get_len(oap->start.lnum) - bd.textcol;
if (oap->op_type == OP_APPEND)
- firstline += bd.textlen;
- pre_textlen = (long)STRLEN(firstline);
+ pre_textlen -= bd.textlen;
}
if (oap->op_type == OP_APPEND)
@@ -1591,10 +1593,14 @@ op_insert(oparg_T *oap, long count1)
if (oap->block_mode)
{
+ long ins_len;
+ char_u *firstline, *ins_text;
struct block_def bd2;
int did_indent = FALSE;
size_t len;
int add;
+ // offset when cursor was moved in insert mode
+ int offset = 0;
// If indent kicked in, the firstline might have changed
// but only do that, if the indent actually increased.
@@ -1678,7 +1684,7 @@ op_insert(oparg_T *oap, long count1)
* copy of the required string.
*/
firstline = ml_get(oap->start.lnum);
- len = STRLEN(firstline);
+ len = ml_get_len(oap->start.lnum);
add = bd.textcol;
if (oap->op_type == OP_APPEND)
{
@@ -1698,11 +1704,10 @@ op_insert(oparg_T *oap, long count1)
}
}
if ((size_t)add > len)
- firstline += len; // short line, point to the NUL
- else
- firstline += add;
- if (pre_textlen >= 0 && (ins_len =
- (long)STRLEN(firstline) - pre_textlen - offset) > 0)
+ add = len; // short line, point to the NUL
+ firstline += add;
+ len -= add;
+ if (pre_textlen >= 0 && (ins_len = len - pre_textlen - offset) > 0)
{
ins_text = vim_strnsave(firstline, ins_len);
if (ins_text != NULL)
@@ -1770,7 +1775,7 @@ op_change(oparg_T *oap)
|| gchar_cursor() == NUL))
coladvance_force(getviscol());
firstline = ml_get(oap->start.lnum);
- pre_textlen = (long)STRLEN(firstline);
+ pre_textlen = ml_get_len(oap->start.lnum);
pre_indent = (long)getwhitecols(firstline);
bd.textcol = curwin->w_cursor.col;
}
@@ -1804,7 +1809,7 @@ op_change(oparg_T *oap)
bd.textcol += new_indent - pre_indent;
}
- ins_len = (long)STRLEN(firstline) - pre_textlen;
+ ins_len = ml_get_len(oap->start.lnum) - pre_textlen;
if (ins_len > 0)
{
// Subsequent calls to ml_get() flush the firstline data - take a
@@ -1830,7 +1835,8 @@ op_change(oparg_T *oap)
else
vpos.coladd = 0;
oldp = ml_get(linenr);
- newp = alloc(STRLEN(oldp) + vpos.coladd + ins_len + 1);
+ newp = alloc(ml_get_len(linenr)
+ + vpos.coladd + ins_len + 1);
if (newp == NULL)
continue;
// copy up to block start
@@ -2414,6 +2420,84 @@ block_prep(
}
/*
+ * Get block text from "start" to "end"
+ */
+ void
+charwise_block_prep(
+ pos_T start,
+ pos_T end,
+ struct block_def *bdp,
+ linenr_T lnum,
+ int inclusive)
+{
+ colnr_T startcol = 0, endcol = MAXCOL;
+ int is_oneChar = FALSE;
+ colnr_T cs, ce;
+ char_u *p;
+
+ p = ml_get(lnum);
+ bdp->startspaces = 0;
+ bdp->endspaces = 0;
+
+ if (lnum == start.lnum)
+ {
+ startcol = start.col;
+ if (virtual_op)
+ {
+ getvcol(curwin, &start, &cs, NULL, &ce);
+ if (ce != cs && start.coladd > 0)
+ {
+ // Part of a tab selected -- but don't
+ // double-count it.
+ bdp->startspaces = (ce - cs + 1)
+ - start.coladd;
+ if (bdp->startspaces < 0)
+ bdp->startspaces = 0;
+ startcol++;
+ }
+ }
+ }
+
+ if (lnum == end.lnum)
+ {
+ endcol = end.col;
+ if (virtual_op)
+ {
+ getvcol(curwin, &end, &cs, NULL, &ce);
+ if (p[endcol] == NUL || (cs + end.coladd < ce
+ // Don't add space for double-wide
+ // char; endcol will be on last byte
+ // of multi-byte char.
+ && (*mb_head_off)(p, p + endcol) == 0))
+ {
+ if (start.lnum == end.lnum
+ && start.col == end.col)
+ {
+ // Special case: inside a single char
+ is_oneChar = TRUE;
+ bdp->startspaces = end.coladd
+ - start.coladd + inclusive;
+ endcol = startcol;
+ }
+ else
+ {
+ bdp->endspaces = end.coladd
+ + inclusive;
+ endcol -= inclusive;
+ }
+ }
+ }
+ }
+ if (endcol == MAXCOL)
+ endcol = ml_get_len(lnum);
+ if (startcol > endcol || is_oneChar)
+ bdp->textlen = 0;
+ else
+ bdp->textlen = endcol - startcol + inclusive;
+ bdp->textstart = p + startcol;
+}
+
+/*
* Handle the add/subtract operator.
*/
void
@@ -2479,13 +2563,13 @@ op_addsub(
{
curwin->w_cursor.col = 0;
pos.col = 0;
- length = (colnr_T)STRLEN(ml_get(pos.lnum));
+ length = ml_get_len(pos.lnum);
}
else // oap->motion_type == MCHAR
{
if (pos.lnum == oap->start.lnum && !oap->inclusive)
dec(&(oap->end));
- length = (colnr_T)STRLEN(ml_get(pos.lnum));
+ length = ml_get_len(pos.lnum);
pos.col = 0;
if (pos.lnum == oap->start.lnum)
{
@@ -2494,7 +2578,7 @@ op_addsub(
}
if (pos.lnum == oap->end.lnum)
{
- length = (int)STRLEN(ml_get(oap->end.lnum));
+ length = ml_get_len(oap->end.lnum);
if (oap->end.col >= length)
oap->end.col = length - 1;
length = oap->end.col - pos.col + 1;
@@ -2566,6 +2650,7 @@ do_addsub(
uvarnumber_T n;
uvarnumber_T oldn;
char_u *ptr;
+ int linelen;
int c;
int todel;
int do_hex;
@@ -2599,9 +2684,10 @@ do_addsub(
curwin->w_cursor = *pos;
ptr = ml_get(pos->lnum);
+ linelen = ml_get_len(pos->lnum);
col = pos->col;
- if (*ptr == NUL || col + !!save_coladd >= (int)STRLEN(ptr))
+ if (col + !!save_coladd >= linelen)
goto theend;
/*
@@ -2781,8 +2867,7 @@ do_addsub(
// get the number value (unsigned)
if (visual && VIsual_mode != 'V')
maxlen = (curbuf->b_visual.vi_curswant == MAXCOL
- ? (int)STRLEN(ptr) - col
- : length);
+ ? linelen - col : length);
int overflow = FALSE;
vim_str2nr(ptr + col, &pre, &length,
@@ -2962,14 +3047,12 @@ do_addsub(
// del_char() will also mark line needing displaying
if (todel > 0)
{
- int bytes_after = (int)STRLEN(ml_get_curline())
- - curwin->w_cursor.col;
+ int bytes_after = ml_get_curline_len() - curwin->w_cursor.col;
// Delete the one character before the insert.
curwin->w_cursor = save_pos;
(void)del_char(FALSE);
- curwin->w_cursor.col = (colnr_T)(STRLEN(ml_get_curline())
- - bytes_after);
+ curwin->w_cursor.col = ml_get_curline_len() - bytes_after;
--todel;
}
while (todel-- > 0)
@@ -3275,7 +3358,7 @@ cursor_pos_info(dict_T *dict)
validate_virtcol();
col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
(int)curwin->w_virtcol + 1);
- col_print(buf2, sizeof(buf2), (int)STRLEN(p),
+ col_print(buf2, sizeof(buf2), ml_get_curline_len(),
linetabsize_str(p));
if (char_count_cursor == byte_count_cursor
@@ -3772,13 +3855,12 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
if (LT_POS(VIsual, curwin->w_cursor))
{
VIsual.col = 0;
- curwin->w_cursor.col =
- (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum));
+ curwin->w_cursor.col = ml_get_len(curwin->w_cursor.lnum);
}
else
{
curwin->w_cursor.col = 0;
- VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum));
+ VIsual.col = ml_get_len(VIsual.lnum);
}
VIsual_mode = 'v';
}
@@ -3809,7 +3891,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
|| oap->motion_type == MLINE)
&& hasFolding(curwin->w_cursor.lnum, NULL,
&curwin->w_cursor.lnum))
- curwin->w_cursor.col = (colnr_T)STRLEN(ml_get_curline());
+ curwin->w_cursor.col = ml_get_curline_len();
}
#endif
oap->end = curwin->w_cursor;
@@ -3830,7 +3912,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
NULL))
curwin->w_cursor.col = 0;
if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum))
- oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum));
+ oap->start.col = ml_get_len(oap->start.lnum);
}
#endif
oap->end = oap->start;
@@ -4040,7 +4122,7 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
oap->motion_type = MLINE;
else
{
- oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ oap->end.col = ml_get_len(oap->end.lnum);
if (oap->end.col)
{
--oap->end.col;
diff --git a/src/option.c b/src/option.c
index 2372c1a..8123a2a 100644
--- a/src/option.c
+++ b/src/option.c
@@ -450,9 +450,10 @@ set_init_default_encoding(void)
char_u *p;
int opt_idx;
-# ifdef MSWIN
+# if defined(MSWIN) || defined(__MVS__)
// MS-Windows has builtin support for conversion to and from Unicode, using
// "utf-8" for 'encoding' should work best for most users.
+ // z/OS built should default to UTF-8 mode as setlocale does not respect utf-8 environment variable locales
p = vim_strsave((char_u *)ENC_DFLT);
# else
// enc_locale() will try to find the encoding of the current locale.
@@ -2857,10 +2858,10 @@ didset_options2(void)
check_opt_wim();
// Parse default for 'listchars'.
- (void)set_listchars_option(curwin, curwin->w_p_lcs, TRUE);
+ (void)set_listchars_option(curwin, curwin->w_p_lcs, TRUE, NULL, 0);
// Parse default for 'fillchars'.
- (void)set_fillchars_option(curwin, curwin->w_p_fcs, TRUE);
+ (void)set_fillchars_option(curwin, curwin->w_p_fcs, TRUE, NULL, 0);
#ifdef FEAT_CLIPBOARD
// Parse default for 'clipboard'
@@ -3268,27 +3269,6 @@ did_set_binary(optset_T *args)
return NULL;
}
-#if defined(FEAT_LINEBREAK) || defined(PROTO)
-/*
- * Called when the 'breakat' option changes value.
- */
- char *
-did_set_breakat(optset_T *args UNUSED)
-{
- char_u *p;
- int i;
-
- for (i = 0; i < 256; i++)
- breakat_flags[i] = FALSE;
-
- if (p_breakat != NULL)
- for (p = p_breakat; *p; p++)
- breakat_flags[*p] = TRUE;
-
- return NULL;
-}
-#endif
-
/*
* Process the updated 'buflisted' option value.
*/
@@ -4616,8 +4596,10 @@ set_bool_option(
#endif
comp_col(); // in case 'ruler' or 'showcmd' changed
+
if (curwin->w_curswant != MAXCOL
- && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
+ && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0
+ && (options[opt_idx].flags & P_HLONLY) == 0)
curwin->w_set_curswant = TRUE;
if ((opt_flags & OPT_NO_REDRAW) == 0)
@@ -4859,9 +4841,12 @@ set_num_option(
#endif
comp_col(); // in case 'columns' or 'ls' changed
+
if (curwin->w_curswant != MAXCOL
- && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
+ && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0
+ && (options[opt_idx].flags & P_HLONLY) == 0)
curwin->w_set_curswant = TRUE;
+
if ((opt_flags & OPT_NO_REDRAW) == 0)
check_redraw(options[opt_idx].flags);
@@ -4882,11 +4867,14 @@ check_redraw(long_u flags)
status_redraw_all();
if ((flags & P_RBUF) || (flags & P_RWIN) || all)
- changed_window_setting();
+ {
+ if (flags & P_HLONLY)
+ redraw_later(UPD_NOT_VALID);
+ else
+ changed_window_setting();
+ }
if (flags & P_RBUF)
redraw_curbuf_later(UPD_NOT_VALID);
- if (flags & P_RWINONLY)
- redraw_later(UPD_NOT_VALID);
if (doclear)
redraw_all_later(UPD_CLEAR);
else if (all)
@@ -6218,12 +6206,14 @@ unset_global_local_option(char_u *name, void *from)
break;
case PV_LCS:
clear_string_option(&((win_T *)from)->w_p_lcs);
- set_listchars_option((win_T *)from, ((win_T *)from)->w_p_lcs, TRUE);
+ set_listchars_option((win_T *)from, ((win_T *)from)->w_p_lcs, TRUE,
+ NULL, 0);
redraw_later(UPD_NOT_VALID);
break;
case PV_FCS:
clear_string_option(&((win_T *)from)->w_p_fcs);
- set_fillchars_option((win_T *)from, ((win_T *)from)->w_p_fcs, TRUE);
+ set_fillchars_option((win_T *)from, ((win_T *)from)->w_p_fcs, TRUE,
+ NULL, 0);
redraw_later(UPD_NOT_VALID);
break;
case PV_VE:
@@ -6430,6 +6420,7 @@ get_varp(struct vimoption *p)
#ifdef FEAT_LINEBREAK
case PV_NUW: return (char_u *)&(curwin->w_p_nuw);
#endif
+ case PV_WFB: return (char_u *)&(curwin->w_p_wfb);
case PV_WFH: return (char_u *)&(curwin->w_p_wfh);
case PV_WFW: return (char_u *)&(curwin->w_p_wfw);
#if defined(FEAT_QUICKFIX)
@@ -6629,8 +6620,8 @@ after_copy_winopt(win_T *wp)
fill_culopt_flags(NULL, wp);
check_colorcolumn(wp);
#endif
- set_listchars_option(wp, wp->w_p_lcs, TRUE);
- set_fillchars_option(wp, wp->w_p_fcs, TRUE);
+ set_listchars_option(wp, wp->w_p_lcs, TRUE, NULL, 0);
+ set_fillchars_option(wp, wp->w_p_fcs, TRUE, NULL, 0);
}
static char_u *
diff --git a/src/option.h b/src/option.h
index 646056b..bf889e4 100644
--- a/src/option.h
+++ b/src/option.h
@@ -38,8 +38,8 @@
#define P_RSTAT 0x1000 // redraw status lines
#define P_RWIN 0x2000 // redraw current window and recompute text
#define P_RBUF 0x4000 // redraw current buffer and recompute text
-#define P_RALL 0x6000 // redraw all windows
-#define P_RCLR 0x7000 // clear and redraw all
+#define P_RALL 0x6000 // redraw all windows and recompute text
+#define P_RCLR 0x7000 // clear and redraw all and recompute text
#define P_COMMA 0x8000 // comma separated list
#define P_ONECOMMA 0x18000L // P_COMMA and cannot have two consecutive
@@ -58,7 +58,7 @@
#define P_CURSWANT 0x4000000L // update curswant required; not needed when
// there is a redraw flag
#define P_NDNAME 0x8000000L // only normal dir name chars allowed
-#define P_RWINONLY 0x10000000L // only redraw current window
+#define P_HLONLY 0x10000000L // option only changes highlight, not text
#define P_MLE 0x20000000L // under control of 'modelineexpr'
#define P_FUNC 0x40000000L // accept a function reference or a lambda
#define P_COLON 0x80000000L // values use colons to create sublists
@@ -130,7 +130,7 @@ typedef enum {
#define ENC_UCSBOM "ucs-bom" // check for BOM at start of file
// default value for 'encoding'
-#ifdef MSWIN
+#if defined(MSWIN) || defined(__MVS__)
# define ENC_DFLT "utf-8"
#else
# define ENC_DFLT "latin1"
@@ -637,7 +637,7 @@ EXTERN char_u *p_guifontset; // 'guifontset'
EXTERN char_u *p_guifontwide; // 'guifontwide'
EXTERN int p_guipty; // 'guipty'
#endif
-#ifdef FEAT_GUI_GTK
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
EXTERN char_u *p_guiligatures; // 'guiligatures'
# endif
#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
@@ -1309,6 +1309,7 @@ enum
#ifdef FEAT_STL_OPT
, WV_STL
#endif
+ , WV_WFB
, WV_WFH
, WV_WFW
, WV_WRAP
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 783b851..4ee2e20 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -215,6 +215,7 @@
# define PV_STL OPT_BOTH(OPT_WIN(WV_STL))
#endif
#define PV_UL OPT_BOTH(OPT_BUF(BV_UL))
+# define PV_WFB OPT_WIN(WV_WFB)
# define PV_WFH OPT_WIN(WV_WFH)
# define PV_WFW OPT_WIN(WV_WFW)
#define PV_WRAP OPT_WIN(WV_WRAP)
@@ -402,7 +403,7 @@ static struct vimoption options[] =
{"autowriteall","awa", P_BOOL|P_VI_DEF,
(char_u *)&p_awa, PV_NONE, NULL, NULL,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"background", "bg", P_STRING|P_VI_DEF|P_RCLR,
+ {"background", "bg", P_STRING|P_VI_DEF|P_RCLR|P_HLONLY,
(char_u *)&p_bg, PV_NONE, did_set_background, expand_set_background,
{
#if (defined(MSWIN)) && !defined(FEAT_GUI)
@@ -609,7 +610,7 @@ static struct vimoption options[] =
{"cmdwinheight", "cwh", P_NUM|P_VI_DEF,
(char_u *)&p_cwh, PV_NONE, NULL, NULL,
{(char_u *)7L, (char_u *)0L} SCTX_INIT},
- {"colorcolumn", "cc", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_RWIN,
+ {"colorcolumn", "cc", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_RWIN|P_HLONLY,
#ifdef FEAT_SYN_HL
(char_u *)VAR_WIN, PV_CC, did_set_colorcolumn, NULL,
#else
@@ -774,21 +775,21 @@ static struct vimoption options[] =
{"cursorbind", "crb", P_BOOL|P_VI_DEF,
(char_u *)VAR_WIN, PV_CRBIND, NULL, NULL,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"cursorcolumn", "cuc", P_BOOL|P_VI_DEF|P_RWINONLY,
+ {"cursorcolumn", "cuc", P_BOOL|P_VI_DEF|P_RWIN|P_HLONLY,
#ifdef FEAT_SYN_HL
(char_u *)VAR_WIN, PV_CUC, NULL, NULL,
#else
(char_u *)NULL, PV_NONE, NULL, NULL,
#endif
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"cursorline", "cul", P_BOOL|P_VI_DEF|P_RWINONLY,
+ {"cursorline", "cul", P_BOOL|P_VI_DEF|P_RWIN|P_HLONLY,
#ifdef FEAT_SYN_HL
(char_u *)VAR_WIN, PV_CUL, NULL, NULL,
#else
(char_u *)NULL, PV_NONE, NULL, NULL,
#endif
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"cursorlineopt", "culopt", P_STRING|P_VI_DEF|P_RWIN|P_ONECOMMA|P_NODUP,
+ {"cursorlineopt", "culopt", P_STRING|P_VI_DEF|P_RWIN|P_HLONLY|P_ONECOMMA|P_NODUP,
#ifdef FEAT_SYN_HL
(char_u *)VAR_WIN, PV_CULOPT,
did_set_cursorlineopt, expand_set_cursorlineopt,
@@ -1212,7 +1213,7 @@ static struct vimoption options[] =
{(char_u *)50L, (char_u *)0L} SCTX_INIT},
{"guiligatures", "gli", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP,
-#if defined(FEAT_GUI_GTK)
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
(char_u *)&p_guiligatures, PV_NONE,
did_set_guiligatures, NULL,
{(char_u *)"", (char_u *)0L}
@@ -1304,7 +1305,7 @@ static struct vimoption options[] =
(char_u *)NULL, PV_NONE, NULL, NULL,
#endif
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"hlsearch", "hls", P_BOOL|P_VI_DEF|P_VIM|P_RALL,
+ {"hlsearch", "hls", P_BOOL|P_VI_DEF|P_VIM|P_RALL|P_HLONLY,
#if defined(FEAT_SEARCH_EXTRA)
(char_u *)&p_hls, PV_NONE, did_set_hlsearch, NULL,
#else
@@ -2350,14 +2351,14 @@ static struct vimoption options[] =
{"sourceany", NULL, P_BOOL|P_VI_DEF,
(char_u *)NULL, PV_NONE, NULL, NULL,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"spell", NULL, P_BOOL|P_VI_DEF|P_RWIN,
+ {"spell", NULL, P_BOOL|P_VI_DEF|P_RWIN|P_HLONLY,
#ifdef FEAT_SPELL
(char_u *)VAR_WIN, PV_SPELL, did_set_spell, NULL,
#else
(char_u *)NULL, PV_NONE, NULL, NULL,
#endif
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
- {"spellcapcheck", "spc", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF,
+ {"spellcapcheck", "spc", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_HLONLY,
#ifdef FEAT_SPELL
(char_u *)&p_spc, PV_SPC, did_set_spellcapcheck, NULL,
{(char_u *)"[.?!]\\_[\\])'\" ]\\+", (char_u *)0L}
@@ -2377,7 +2378,7 @@ static struct vimoption options[] =
#endif
SCTX_INIT},
{"spelllang", "spl", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA
- |P_RBUF|P_EXPAND,
+ |P_RBUF|P_HLONLY|P_EXPAND,
#ifdef FEAT_SPELL
(char_u *)&p_spl, PV_SPL, did_set_spelllang, NULL,
{(char_u *)"en", (char_u *)0L}
@@ -2387,7 +2388,7 @@ static struct vimoption options[] =
#endif
SCTX_INIT},
{"spelloptions", "spo", P_STRING|P_ALLOCED|P_VI_DEF
- |P_ONECOMMA|P_NODUP|P_RBUF,
+ |P_ONECOMMA|P_NODUP|P_RBUF|P_HLONLY,
#ifdef FEAT_SPELL
(char_u *)&p_spo, PV_SPO, did_set_spelloptions, expand_set_spelloptions,
{(char_u *)"", (char_u *)0L}
@@ -2596,7 +2597,7 @@ static struct vimoption options[] =
(char_u *)FALSE,
#endif
(char_u *)0L} SCTX_INIT},
- {"textwidth", "tw", P_NUM|P_VI_DEF|P_VIM|P_RBUF,
+ {"textwidth", "tw", P_NUM|P_VI_DEF|P_VIM|P_RBUF|P_HLONLY,
(char_u *)&p_tw, PV_TW, did_set_textwidth, NULL,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
{"thesaurus", "tsr", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME,
@@ -2850,6 +2851,9 @@ static struct vimoption options[] =
{"window", "wi", P_NUM|P_VI_DEF,
(char_u *)&p_window, PV_NONE, did_set_window, NULL,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
+ {"winfixbuf", "wfb", P_BOOL|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_WFB, NULL, NULL,
+ {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
{"winfixheight", "wfh", P_BOOL|P_VI_DEF|P_RSTAT,
(char_u *)VAR_WIN, PV_WFH, NULL, NULL,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
@@ -2931,6 +2935,7 @@ static struct vimoption options[] =
p_term("t_cd", T_CD)
p_term("t_ce", T_CE)
p_term("t_Ce", T_UCE)
+ p_term("t_CF", T_CFO)
p_term("t_cl", T_CL)
p_term("t_cm", T_CM)
p_term("t_Co", T_CCO)
diff --git a/src/optionstr.c b/src/optionstr.c
index 65a80af..e5f4946 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -233,7 +233,7 @@ illegal_char(char *errbuf, size_t errbuflen, int c)
{
if (errbuf == NULL)
return "";
- vim_snprintf((char *)errbuf, errbuflen, _(e_illegal_character_str),
+ vim_snprintf(errbuf, errbuflen, _(e_illegal_character_str),
(char *)transchar(c));
return errbuf;
}
@@ -1208,6 +1208,25 @@ expand_set_belloff(optexpand_T *args, int *numMatches, char_u ***matches)
#if defined(FEAT_LINEBREAK) || defined(PROTO)
/*
+ * The 'breakat' option is changed.
+ */
+ char *
+did_set_breakat(optset_T *args UNUSED)
+{
+ char_u *p;
+ int i;
+
+ for (i = 0; i < 256; i++)
+ breakat_flags[i] = FALSE;
+
+ if (p_breakat != NULL)
+ for (p = p_breakat; *p; p++)
+ breakat_flags[*p] = TRUE;
+
+ return NULL;
+}
+
+/*
* The 'breakindentopt' option is changed.
*/
char *
@@ -1350,7 +1369,8 @@ expand_set_clipboard(optexpand_T *args, int *numMatches, char_u ***matches)
* The global 'listchars' or 'fillchars' option is changed.
*/
static char *
-did_set_global_listfillchars(char_u *val, int opt_lcs, int opt_flags)
+did_set_global_listfillchars(char_u *val, int opt_lcs, int opt_flags,
+ char *errbuf, size_t errbuflen)
{
char *errmsg = NULL;
char_u **local_ptr = opt_lcs ? &curwin->w_p_lcs : &curwin->w_p_fcs;
@@ -1359,10 +1379,12 @@ did_set_global_listfillchars(char_u *val, int opt_lcs, int opt_flags)
// local value
if (opt_lcs)
errmsg = set_listchars_option(curwin, val,
- **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
+ **local_ptr == NUL || !(opt_flags & OPT_GLOBAL),
+ errbuf, errbuflen);
else
errmsg = set_fillchars_option(curwin, val,
- **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
+ **local_ptr == NUL || !(opt_flags & OPT_GLOBAL),
+ errbuf, errbuflen);
if (errmsg != NULL)
return errmsg;
@@ -1382,12 +1404,12 @@ did_set_global_listfillchars(char_u *val, int opt_lcs, int opt_flags)
if (opt_lcs)
{
if (*wp->w_p_lcs == NUL)
- (void)set_listchars_option(wp, wp->w_p_lcs, TRUE);
+ (void)set_listchars_option(wp, wp->w_p_lcs, TRUE, NULL, 0);
}
else
{
if (*wp->w_p_fcs == NUL)
- (void)set_fillchars_option(wp, wp->w_p_fcs, TRUE);
+ (void)set_fillchars_option(wp, wp->w_p_fcs, TRUE, NULL, 0);
}
}
@@ -1408,11 +1430,13 @@ did_set_chars_option(optset_T *args)
if ( varp == &p_lcs // global 'listchars'
|| varp == &p_fcs) // global 'fillchars'
errmsg = did_set_global_listfillchars(*varp, varp == &p_lcs,
- args->os_flags);
+ args->os_flags, args->os_errbuf, args->os_errbuflen);
else if (varp == &curwin->w_p_lcs) // local 'listchars'
- errmsg = set_listchars_option(curwin, *varp, TRUE);
+ errmsg = set_listchars_option(curwin, *varp, TRUE,
+ args->os_errbuf, args->os_errbuflen);
else if (varp == &curwin->w_p_fcs) // local 'fillchars'
- errmsg = set_fillchars_option(curwin, *varp, TRUE);
+ errmsg = set_fillchars_option(curwin, *varp, TRUE,
+ args->os_errbuf, args->os_errbuflen);
return errmsg;
}
@@ -2414,7 +2438,7 @@ did_set_guifontwide(optset_T *args UNUSED)
}
#endif
-#if defined(FEAT_GUI_GTK) || defined(PROTO)
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) || defined(PROTO)
/*
* The 'guiligatures' option is changed.
*/
@@ -3416,7 +3440,12 @@ did_set_showbreak(optset_T *args)
char *
did_set_showcmdloc(optset_T *args UNUSED)
{
- return did_set_opt_strings(p_sloc, p_sloc_values, FALSE);
+ char *errmsg = did_set_opt_strings(p_sloc, p_sloc_values, FALSE);
+
+ if (errmsg == NULL)
+ comp_col();
+
+ return errmsg;
}
int
@@ -4486,7 +4515,8 @@ did_set_string_option(
#endif
if (curwin->w_curswant != MAXCOL
- && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0)
+ && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0
+ && (get_option_flags(opt_idx) & P_HLONLY) == 0)
curwin->w_set_curswant = TRUE;
if ((opt_flags & OPT_NO_REDRAW) == 0)
@@ -4505,7 +4535,7 @@ did_set_string_option(
|| varp == &p_guifontset // 'guifontset'
# endif
|| varp == &p_guifontwide // 'guifontwide'
-# ifdef FEAT_GUI_GTK
+# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
|| varp == &p_guiligatures // 'guiligatures'
# endif
)
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 21b7db3..512fa40 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -2747,19 +2747,22 @@ quality_id2name(DWORD id)
return qp->name;
}
+// The default font height in 100% scaling (96dpi).
+// (-12 in 96dpi equates to roughly 9pt)
+#define DEFAULT_FONT_HEIGHT (-12)
+
static const LOGFONTW s_lfDefault =
{
- -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
+ DEFAULT_FONT_HEIGHT,
+ 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE,
- L"Fixedsys" // see _ReadVimIni
+ L"" // Default font name will be set later based on current language.
};
-// Initialise the "current height" to -12 (same as s_lfDefault) just
-// in case the user specifies a font in "guifont" with no size before a font
-// with an explicit size has been set. This defaults the size to this value
-// (-12 equates to roughly 9pt).
-int current_font_height = -12; // also used in gui_w32.c
+// This will be initialized when set_default_logfont() is called first time.
+// The value will be based on the system DPI.
+int current_font_height = 0; // also used in gui_w32.c
/*
* Convert a string representing a point size into pixels. The string should
@@ -3027,6 +3030,47 @@ utf16ascncmp(const WCHAR *w, const char *p, size_t n)
}
/*
+ * Equivalent of GetDpiForSystem().
+ */
+ UINT WINAPI
+vimGetDpiForSystem(void)
+{
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+ UINT dpi = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(hwnd, hdc);
+ return dpi;
+}
+
+/*
+ * Set default logfont based on current language.
+ */
+ static void
+set_default_logfont(LOGFONTW *lf)
+{
+ // Default font name for current language on MS-Windows.
+ // If not translated, falls back to "Consolas".
+ // This must be a fixed-pitch font.
+ const char *defaultfontname = N_("DefaultFontNameForWindows");
+ char *fontname = _(defaultfontname);
+
+ if (strcmp(fontname, defaultfontname) == 0)
+ fontname = "Consolas";
+
+ *lf = s_lfDefault;
+ lf->lfHeight = DEFAULT_FONT_HEIGHT * (int)vimGetDpiForSystem() / 96;
+ if (current_font_height == 0)
+ current_font_height = lf->lfHeight;
+
+ WCHAR *wfontname = enc_to_utf16((char_u*)fontname, NULL);
+ if (wfontname != NULL)
+ {
+ wcscpy_s(lf->lfFaceName, LF_FACESIZE, wfontname);
+ vim_free(wfontname);
+ }
+}
+
+/*
* Get font info from "name" into logfont "lf".
* Return OK for a valid name, FAIL otherwise.
*/
@@ -3043,7 +3087,7 @@ get_logfont(
static LOGFONTW *lastlf = NULL;
WCHAR *wname;
- *lf = s_lfDefault;
+ set_default_logfont(lf);
if (name == NULL)
return OK;
@@ -3083,7 +3127,7 @@ get_logfont(
lf->lfFaceName[p - wname] = NUL;
// First set defaults
- lf->lfHeight = -12;
+ lf->lfHeight = DEFAULT_FONT_HEIGHT * (int)vimGetDpiForSystem() / 96;
lf->lfWidth = 0;
lf->lfWeight = FW_NORMAL;
lf->lfItalic = FALSE;
diff --git a/src/os_unix.c b/src/os_unix.c
index af8f006..e98911e 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -2320,12 +2320,11 @@ mch_settitle(char_u *title, char_u *icon)
#ifdef FEAT_X11
if (get_x11_windis() == OK)
type = 1;
-#else
-# if defined(FEAT_GUI_PHOTON) \
+#endif
+#if defined(FEAT_GUI_PHOTON) \
|| defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)
if (gui.in_use)
type = 1;
-# endif
#endif
/*
@@ -3049,7 +3048,7 @@ mch_copy_sec(char_u *from_file, char_u *to_file)
size = listxattr((char *)from_file, NULL, 0);
// not supported or no attributes to copy
- if (errno == ENOTSUP || size == 0)
+ if (size <= 0)
return;
for (index = 0 ; index < (int)(sizeof(smack_copied_attributes)
@@ -3113,8 +3112,8 @@ mch_copy_sec(char_u *from_file, char_u *to_file)
mch_copy_xattr(char_u *from_file, char_u *to_file)
{
char *xattr_buf;
- size_t size;
- size_t tsize;
+ ssize_t size;
+ ssize_t tsize;
ssize_t keylen, vallen, max_vallen = 0;
char *key;
char *val = NULL;
@@ -3126,7 +3125,7 @@ mch_copy_xattr(char_u *from_file, char_u *to_file)
// get the length of the extended attributes
size = listxattr((char *)from_file, NULL, 0);
// not supported or no attributes to copy
- if (errno == ENOTSUP || size == 0)
+ if (size <= 0)
return;
xattr_buf = (char*)alloc(size);
if (xattr_buf == NULL)
diff --git a/src/os_win32.c b/src/os_win32.c
index dbfc4ee..9947150 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -5155,8 +5155,7 @@ mch_system_piped(char *cmd, int options)
)
{
len = 0;
- if (!(options & SHELL_EXPAND)
- && ((options &
+ if (((options &
(SHELL_READ|SHELL_WRITE|SHELL_COOKED))
!= (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
# ifdef FEAT_GUI
@@ -5176,7 +5175,7 @@ mch_system_piped(char *cmd, int options)
{
/*
* For pipes: Check for CTRL-C: send interrupt signal to
- * child. Check for CTRL-D: EOF, close pipe to child.
+ * child.
*/
if (len == 1 && cmd != NULL)
{
@@ -5186,10 +5185,22 @@ mch_system_piped(char *cmd, int options)
// now put 9 as SIGKILL
TerminateProcess(pi.hProcess, 9);
}
- if (ta_buf[ta_len] == Ctrl_D)
+ }
+
+ /*
+ * Check for CTRL-D: EOF, close pipe to child.
+ * Ctrl_D may be decorated by _OnChar()
+ */
+ if ((len == 1 || len == 4 ) && cmd != NULL)
+ {
+ if (ta_buf[0] == Ctrl_D
+ || (ta_buf[0] == CSI
+ && ta_buf[1] == KS_MODIFIER
+ && ta_buf[3] == Ctrl_D))
{
CloseHandle(g_hChildStd_IN_Wr);
g_hChildStd_IN_Wr = NULL;
+ len = 0;
}
}
diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak
index eaf6867..fa6a1ba 100644
--- a/src/po/Make_mvc.mak
+++ b/src/po/Make_mvc.mak
@@ -1,16 +1,36 @@
# Makefile for the Vim message translations for MSVC
# (based on make_ming.mak)
#
-# Mike Williams <mrw@eandem.co.uk>
+# Mike Williams, <mrw@eandem.co.uk>
+# 06.01.24, Restorer, <restorer@mail2k.ru>
#
# Please read README_mvc.txt before using this file.
#
-!IF [powershell -nologo -noprofile "exit $$psversiontable.psversion.major"] == 2
+!IF [powershell.exe -nologo -noprofile "exit $$psversiontable.psversion.major"] == 2
!ERROR The program "PowerShell" version 3.0 or higher is required to work
!ENDIF
-# get LANGUAGES, MOFILES, MOCONVERTED and others
+!IFNDEF LANGUAGE
+! IF [powershell.exe -nologo -noprofile $$lng=(Get-UICulture).TwoLetterISOLanguageName; \
+ $$Env:LANGUAGE=$$lng;Set-Content -Path .\lng.tmp -Value "LANGUAGE=$$lng"]
+! ENDIF
+# In order for the "install" and "cleanup-po" rule to work.
+# The others work with just setting the environment variable.
+# And to show in the message.
+! INCLUDE lng.tmp
+! IF [del /q .\lng.tmp]
+! ENDIF
+! MESSAGE
+! MESSAGE The %LANGUAGE% environment variable is not set.
+! MESSAGE This variable will be temporarily set to "$(LANGUAGE)" while "nmake.exe" is running.
+! MESSAGE See README_mvc.txt for more information on the %LANGUAGE% environment variable.
+! MESSAGE
+!ELSE
+! MESSAGE LANGUAGE is already set "$(LANGUAGE)"
+!ENDIF
+
+# Get LANGUAGES, MOFILES, MOCONVERTED and others.
!INCLUDE Make_all.mak
!IFNDEF VIMRUNTIME
@@ -18,25 +38,34 @@ VIMRUNTIME = ..\..\runtime
!ENDIF
PACKAGE = vim
-# Correct the following line for the where executeable file vim is installed.
-VIM = ..\vim
+# Correct the following line for the where executeable file vim is
+# installed. Please do not put the path in quotes.
+VIM = ..\vim.exe
# Correct the following line for the directory where gettext et al is
# installed. Please do not put the path in quotes.
GETTEXT_PATH = D:\Programs\GetText\bin
-MSGFMT = "$(GETTEXT_PATH)\msgfmt" -v
-XGETTEXT = "$(GETTEXT_PATH)\xgettext"
-MSGMERGE = "$(GETTEXT_PATH)\msgmerge"
+# Starting from version 0.22, msgfmt forcibly converts text to UTF-8 regardless
+# of the value of the "charset" field.
+!IF [%comspec% /v:on /e:on /c "for /F "tokens=4 delims= " %G in \
+ ('"$(GETTEXT_PATH)\msgfmt.exe" --version^|findstr /rc:[0-9^]\.[0-9^][0-9^]') do \
+ @(set "v=%G" && if !v:~2^,2! GEQ 22 exit /b 1)"]
+MSGFMT = "$(GETTEXT_PATH)\msgfmt.exe" -v --no-convert
+!ELSE
+MSGFMT = "$(GETTEXT_PATH)\msgfmt.exe" -v
+!ENDIF
+XGETTEXT = "$(GETTEXT_PATH)\xgettext.exe"
+MSGMERGE = "$(GETTEXT_PATH)\msgmerge.exe"
# In case some package like GnuWin32, UnixUtils, gettext
# or something similar is installed on the system.
# If the "iconv" program is installed on the system, but it is not registered
# in the %PATH% environment variable, then specify the full path to this file.
!IF EXIST ("iconv.exe")
-ICONV = "iconv.exe"
+ICONV = iconv.exe
!ELSEIF EXIST ("$(GETTEXT_PATH)\iconv.exe")
-ICONV="$(GETTEXT_PATH)\iconv.exe"
+ICONV = "$(GETTEXT_PATH)\iconv.exe"
!ENDIF
# In case some package like GnuWin32, UnixUtils
@@ -54,8 +83,10 @@ CP = copy /y
RM = del /q
MKD = mkdir
LS = dir
+PS = PowerShell.exe
LSFLAGS = /b /on /l /s
+PSFLAGS = -NoLogo -NoProfile -Command
INSTALLDIR = $(VIMRUNTIME)\lang\$(LANGUAGE)\LC_MESSAGES
@@ -64,8 +95,12 @@ INSTALLDIR = $(VIMRUNTIME)\lang\$(LANGUAGE)\LC_MESSAGES
all: $(MOFILES) $(MOCONVERTED)
+originals : $(MOFILES)
+
+converted: $(MOCONVERTED)
+
.po.ck:
- $(VIM) -u NONE --noplugins -e -s -X --cmd "set enc=utf-8" -S check.vim \
+ "$(VIM)" -u NONE --noplugins -e -s -X --cmd "set enc=utf-8" -S check.vim \
-c "if error == 0 | q | else | num 2 | cq | endif" $<
$(TOUCH_TARGET)
@@ -74,13 +109,8 @@ check: $(CHECKFILES)
checkclean:
$(RM) *.ck
-converted: $(MOCONVERTED)
-
-checklanguage:
- @if "$(LANGUAGE)"=="" (echo Set the environment variable ^%LANGUAGE^%. See README_mvc.txt. && exit 1)
-
nl.po:
- @( echo \# > nl.po )
+ @( echo ^# >> nl.po )
# Norwegian/Bokmal: "nb" is an alias for "no".
nb.po: no.po
@@ -95,16 +125,14 @@ ja.sjis.po: ja.po
!ELSEIF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t CP932 $? | .\sjiscorr.exe > $@
!ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(932))
type $@ | .\sjiscorr.exe > tmp.$@
@$(MV) tmp.$@ $@
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(932)) \
-replace \"`r`n\", \"`n\"; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
@@ -113,7 +141,7 @@ ja.sjis.po: ja.po
sjiscorr: sjiscorr.c
$(CC) sjiscorr.c
-# Convert ja.po to create ja.euc-jp.po
+# Convert ja.po to create ja.euc-jp.po.
ja.euc-jp.po: ja.po
-$(RM) $@
!IF EXIST ("$(GETTEXT_PATH)\msgconv.exe")
@@ -122,24 +150,21 @@ ja.euc-jp.po: ja.po
! IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t EUC-JP $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(20932))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(20932)) -replace \
'charset=utf-8', 'charset=EUC-JP'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(20932))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(20932)) -replace \
'# Original translations', \
- '# Generated from ja.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(20932))
@@ -152,24 +177,21 @@ cs.cp1250.po: cs.po
! IF DEFINED (ICONV)
$(ICONV) -f ISO-8859-2 -t CP1250 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(28592)), \
[System.Text.Encoding]::GetEncoding(1250))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1250)) -replace \
'charset=iso-8859-2', 'charset=CP1250'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1250))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1250)) -replace \
'# Original translations', \
- '# Generated from cs.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1250))
@@ -182,24 +204,21 @@ pl.cp1250.po: pl.po
! IF DEFINED (ICONV)
$(ICONV) -f ISO-8859-2 -t CP1250 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(28592)), \
[System.Text.Encoding]::GetEncoding(1250))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1250)) -replace \
'charset=iso-8859-2', 'charset=CP1250'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1250))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1250)) -replace \
'# Original translations', \
- '# Generated from pl.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1250))
@@ -212,20 +231,17 @@ pl.UTF-8.po: pl.po
! IF DEFINED (ICONV)
$(ICONV) -f ISO-8859-2 -t UTF-8 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(28592)))
! ENDIF
- powershell -nologo -noprofile -Command \
- (Get-Content -Raw -Encoding UTF8 $@ \
+ $(PS) $(PSFLAGS) (Get-Content -Raw -Encoding UTF8 $@ \
^| % {$$_-replace 'charset=iso-8859-2', 'charset=UTF-8'}) \
^| 1>nul New-Item -Force -Path . -ItemType file -Name $@
!ENDIF
- powershell -nologo -noprofile -Command \
- (Get-Content -Raw -Encoding UTF8 $@ \
+ $(PS) $(PSFLAGS) (Get-Content -Raw -Encoding UTF8 $@ \
^| % {$$_-replace '# Original translations', \
- '# Generated from pl.po, DO NOT EDIT'}) \
+ '# Generated from $?, DO NOT EDIT'}) \
^| 1>nul New-Item -Force -Path . -ItemType file -Name $@
# Convert sk.po to create sk.cp1250.po.
@@ -237,24 +253,21 @@ sk.cp1250.po: sk.po
! IF DEFINED (ICONV)
$(ICONV) -f ISO-8859-2 -t CP1250 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(28592)), \
[System.Text.Encoding]::GetEncoding(1250))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1250)) -replace \
'charset=iso-8859-2', 'charset=CP1250'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1250))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1250)) -replace \
'# Original translations', \
- '# Generated from sk.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1250))
@@ -267,25 +280,22 @@ zh_CN.po: zh_CN.UTF-8.po
! IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t GB2312 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(936))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(936)) -replace \
'charset=UTF-8', 'charset=GB2312'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(936))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(936)) -replace \
'# Original translations', \
- '# Generated from zh_CN.UTF-8.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(936))
@@ -297,23 +307,21 @@ zh_CN.cp936.po: zh_CN.UTF-8.po
!IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t CP936 $? > $@
!ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(20936))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(20936)) \
-replace 'charset=UTF-8', 'charset=GBK'\
-replace '# Original translations', \
- '# Generated from zh_CN.UTF-8.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(20936))
-# Convert zh_TW.UTF-8.po to create zh_TW.po
+# Convert zh_TW.UTF-8.po to create zh_TW.po.
zh_TW.po: zh_TW.UTF-8.po
-$(RM) $@
!IF EXIST ("$(GETTEXT_PATH)\msgconv.exe")
@@ -322,31 +330,29 @@ zh_TW.po: zh_TW.UTF-8.po
! IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t BIG5 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(950))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(950)) -replace \
'charset=UTF-8', 'charset=BIG5'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(950))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(950)) -replace \
'# Original translations', \
- '# Generated from zh_TW.UTF-8.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(950))
-# Convert zh_TW.UTF-8.po to create zh_TW.po with backslash characters
+# Convert zh_TW.UTF-8.po to create zh_TW.po with backslash characters.
# Requires doubling backslashes in the second byte. Don't depend on big5corr,
# it should only be compiled when zh_TW.po is outdated.
+
#
# 06.11.23, added by Restorer:
# For more details, see:
@@ -368,22 +374,20 @@ zh_TW.po: zh_TW.UTF-8.po
#!ELSEIF DEFINED (ICONV)
# $(ICONV) -f UTF-8 -t BIG5 $? | .\big5corr.exe > $@
#!ELSE
-# powershell -nologo -noprofile -Command \
-# [System.IO.File]::WriteAllText(\"$@\", \
+# $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
# [System.IO.File]::ReadAllText(\"$?\", \
# [System.Text.Encoding]::GetEncoding(65001)), \
# [System.Text.Encoding]::GetEncoding(950))
# type $@ | .\big5corr.exe > tmp.$@
# @$(MV) tmp.$@ $@
#!ENDIF
-# powershell -nologo -noprofile -Command \
-# $$out = [System.IO.File]::ReadAllText(\"$@\", \
+# $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
# [System.Text.Encoding]::GetEncoding(950)) \
# -replace \"`r`n\", \"`n\"; \
# [System.IO.File]::WriteAllText(\"$@\", $$out, \
# [System.Text.Encoding]::GetEncoding(950))
-# see above in the zh_TW.po conversion section for backslashes.
+# See above in the zh_TW.po conversion section for backslashes.
#big5corr: big5corr.c
# $(CC) big5corr.c
@@ -396,25 +400,22 @@ ko.po: ko.UTF-8.po
! IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t EUC-KR $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(51949))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(51949)) -replace \
'charset=UTF-8', 'charset=EUC-KR'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(51949))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(51949)) -replace \
'# Original translations', \
- '# Generated from ko.UTF-8.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(51949))
@@ -427,25 +428,22 @@ ru.cp1251.po: ru.po
! IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t CP1251 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(1251))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1251)) -replace \
'charset=UTF-8', 'charset=CP1251'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1251))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1251)) -replace \
'# Original translations', \
- '# Generated from ru.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1251))
@@ -458,25 +456,22 @@ uk.cp1251.po: uk.po
! IF DEFINED (ICONV)
$(ICONV) -f UTF-8 -t CP1251 $? > $@
! ELSE
- powershell -nologo -noprofile -Command \
- [System.IO.File]::WriteAllText(\"$@\", \
+ $(PS) $(PSFLAGS) [System.IO.File]::WriteAllText(\"$@\", \
[System.IO.File]::ReadAllText(\"$?\", \
[System.Text.Encoding]::GetEncoding(65001)), \
[System.Text.Encoding]::GetEncoding(1251))
! ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1251)) -replace \
'charset=UTF-8', 'charset=CP1251'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1251))
!ENDIF
- powershell -nologo -noprofile -Command \
- $$out = [System.IO.File]::ReadAllText(\"$@\", \
+ $(PS) $(PSFLAGS) $$out = [System.IO.File]::ReadAllText(\"$@\", \
[System.Text.Encoding]::GetEncoding(1251)) -replace \
'# Original translations', \
- '# Generated from uk.po, DO NOT EDIT'; \
+ '# Generated from $?, DO NOT EDIT'; \
[System.IO.File]::WriteAllText(\"$@\", $$out, \
[System.Text.Encoding]::GetEncoding(1251))
@@ -498,60 +493,61 @@ PO_INPUTLIST = \
files: $(PO_INPUTLIST)
$(LS) $(LSFLAGS) $(PO_INPUTLIST) > .\files
-first_time: checklanguage files
- $(VIM) -u NONE --not-a-term -S tojavascript.vim $(LANGUAGE).po \
+first_time: files
+ "$(VIM)" -u NONE --not-a-term -S tojavascript.vim $(LANGUAGE).po \
$(PO_VIM_INPUTLIST)
set OLD_PO_FILE_INPUT=yes
set OLD_PO_FILE_OUTPUT=yes
$(XGETTEXT) --default-domain=$(LANGUAGE) --add-comments $(XGETTEXT_KEYWORDS) \
--files-from=.\files $(PO_VIM_JSLIST)
- $(VIM) -u NONE --not-a-term -S fixfilenames.vim $(LANGUAGE).po \
+ "$(VIM)" -u NONE --not-a-term -S fixfilenames.vim $(LANGUAGE).po \
$(PO_VIM_INPUTLIST)
$(RM) *.js
$(PACKAGE).pot: files
- $(VIM) -u NONE --not-a-term -S tojavascript.vim $(PACKAGE).pot \
+ "$(VIM)" -u NONE --not-a-term -S tojavascript.vim $(PACKAGE).pot \
$(PO_VIM_INPUTLIST)
set OLD_PO_FILE_INPUT=yes
set OLD_PO_FILE_OUTPUT=yes
$(XGETTEXT) --default-domain=$(PACKAGE) --add-comments $(XGETTEXT_KEYWORDS) \
--files-from=.\files $(PO_VIM_JSLIST)
$(MV) $(PACKAGE).po $(PACKAGE).pot
- $(VIM) -u NONE --not-a-term -S fixfilenames.vim $(PACKAGE).pot \
+ "$(VIM)" -u NONE --not-a-term -S fixfilenames.vim $(PACKAGE).pot \
$(PO_VIM_INPUTLIST)
$(RM) *.js
-# When updating ja.sjis.po there are a bunch of errors and a crash.
+# Only original translations with default encoding should be updated.
# The files that are converted to a different encoding clearly state "DO NOT EDIT".
update-po: $(MOFILES:.mo=)
-# Don't add a dependency here, we only want to update the .po files manually
+# Don't add a dependency here, we only want to update the .po files manually.
$(LANGUAGES):
- @$(MAKE) -nologo -f Make_mvc.mak $(PACKAGE).pot GETTEXT_PATH="$(GETTEXT_PATH)"
+ @$(MAKE) -nologo -f Make_mvc.mak GETTEXT_PATH="$(GETTEXT_PATH)" $(PACKAGE).pot
$(CP) $@.po $@.po.orig
$(MV) $@.po $@.po.old
$(MSGMERGE) $@.po.old $(PACKAGE).pot -o $@.po
$(RM) $@.po.old
-install: checklanguage $(LANGUAGE).mo
- if not exist $(INSTALLDIR) $(MKD) $(INSTALLDIR)
- $(CP) $(LANGUAGE).mo $(INSTALLDIR)\$(PACKAGE).mo
+install: $(LANGUAGE).mo
+ if not exist "$(INSTALLDIR)" $(MKD) "$(INSTALLDIR)"
+ $(CP) $(LANGUAGE).mo "$(INSTALLDIR)\$(PACKAGE).mo"
install-all: all
- for %%l in ($(LANGUAGES)) do @if not exist $(VIMRUNTIME)\lang\%%l\LC_MESSAGES \
- $(MKD) $(VIMRUNTIME)\lang\%%l\LC_MESSAGES
+ for %%l in ($(LANGUAGES)) do @if not exist "$(VIMRUNTIME)\lang\%%l\LC_MESSAGES" \
+ $(MKD) "$(VIMRUNTIME)\lang\%%l\LC_MESSAGES"
for %%l in ($(LANGUAGES)) do @$(CP) %%l.mo \
- $(VIMRUNTIME)\lang\%%l\LC_MESSAGES\$(PACKAGE).mo
+ "$(VIMRUNTIME)\lang\%%l\LC_MESSAGES\$(PACKAGE).mo"
-cleanup-po: checklanguage $(LANGUAGE).po
- $(VIM) -u NONE -e -X -S cleanup.vim -c wq $(LANGUAGE).po
+cleanup-po: $(LANGUAGE).po
+ "$(VIM)" -u NONE -e -X -S cleanup.vim -c wq $(LANGUAGE).po
cleanup-po-all: $(POFILES)
- !$(VIM) -u NONE -e -X -S cleanup.vim -c wq $**
+ !"$(VIM)" -u NONE -e -X -S cleanup.vim -c wq $**
clean: checkclean
$(RM) *.mo
$(RM) *.pot
+ $(RM) *.orig
$(RM) files
$(RM) sjiscorr.obj sjiscorr.exe
# $(RM) big5corr.obj big5corr.exe
diff --git a/src/po/Makefile b/src/po/Makefile
index 24f8104..cc4008f 100644
--- a/src/po/Makefile
+++ b/src/po/Makefile
@@ -3,30 +3,38 @@
# Include stuff found by configure.
include ../auto/config.mk
-# get LANGUAGES, MOFILES, MOCONVERTED and others
+# Get LANGUAGES, MOFILES, MOCONVERTED and others.
include Make_all.mak
# Note: ja.sjis, *.cp1250 and zh_CN.cp936 are only for MS-Windows, they are
-# not installed on Unix
+# not installed on Unix.
PACKAGE = vim
SHELL = /bin/sh
VIM = ../vim
-# MacOS sed is locale aware, set $LANG to avoid problems
+# MacOS sed is locale aware, set $LANG to avoid problems.
SED = LANG=C sed
# The OLD_PO_FILE_INPUT and OLD_PO_FILE_OUTPUT are for the new GNU gettext
# tools 0.10.37, which use a slightly different .po file format that is not
# compatible with Solaris (and old gettext implementations) unless these are
# set. gettext 0.10.36 will not work!
-MSGFMTCMD = OLD_PO_FILE_INPUT=yes $(MSGFMT) -v
+
+# MSGFMTCMD is defined by Configure in ../auto/config.mk
XGETTEXT = OLD_PO_FILE_INPUT=yes OLD_PO_FILE_OUTPUT=yes xgettext
MSGMERGE = OLD_PO_FILE_INPUT=yes OLD_PO_FILE_OUTPUT=yes msgmerge
.SUFFIXES:
.SUFFIXES: .po .mo .pot .ck
-.PHONY: all install uninstall prefixcheck converted check clean checkclean distclean update-po $(LANGUAGES)
+.PHONY: all install uninstall prefixcheck originals converted check clean \
+ checkclean distclean update-po $(LANGUAGES)
+
+all: $(MOFILES) $(MOCONVERTED) $(MSGFMT_DESKTOP)
+
+originals: $(MOFILES)
+
+converted: $(MOCONVERTED)
.po.mo:
$(MSGFMTCMD) -o $@ $<
@@ -36,11 +44,9 @@ MSGMERGE = OLD_PO_FILE_INPUT=yes OLD_PO_FILE_OUTPUT=yes msgmerge
-c "if error == 0 | q | else | num 2 | cq | endif" $<
touch $@
-all: $(MOFILES) $(MOCONVERTED) $(MSGFMT_DESKTOP)
-
check: $(CHECKFILES)
-# installing for real
+# Installing for real.
install: $(MOFILES) $(MOCONVERTED)
@$(MAKE) prefixcheck
for lang in $(LANGUAGES); do \
@@ -66,7 +72,7 @@ uninstall:
rm -f $(LOCALEDIR)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \
done
-# installing for local tryout into ../../runtime/lang
+# Installing for local tryout into ../../runtime/lang.
tryoutinstall: $(MOFILES) $(MOCONVERTED)
@$(MAKE) prefixcheck
for lang in $(LANGUAGES); do \
@@ -84,12 +90,10 @@ tryoutinstall: $(MOFILES) $(MOCONVERTED)
fi; \
done
-converted: $(MOCONVERTED)
-
# nl.po was added later, if it does not exist use a file with just a # in it
# (an empty file doesn't work with old msgfmt).
nl.po:
- @( echo \# > nl.po )
+ @( echo \# >> nl.po )
# Norwegian/Bokmal: "nb" is an alias for "no".
# Copying the file is not efficient, but I don't know of another way to make
@@ -102,78 +106,78 @@ nb.po: no.po
# ja.sjis.po is outdated.
ja.sjis.po: ja.po
@$(MAKE) sjiscorr
- rm -f ja.sjis.po
- iconv -f UTF-8 -t CP932 ja.po | ./sjiscorr > ja.sjis.po
+ rm -f $@
+ iconv -f UTF-8 -t CP932 $< | ./sjiscorr > $@
sjiscorr: sjiscorr.c
$(CC) -o sjiscorr sjiscorr.c
ja.euc-jp.po: ja.po
- iconv -f UTF-8 -t EUC-JP ja.po | \
+ iconv -f UTF-8 -t EUC-JP $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=EUC-JP/' \
- -e 's/# Original translations/# Generated from ja.po, DO NOT EDIT/' \
- > ja.euc-jp.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert cs.po to create cs.cp1250.po.
cs.cp1250.po: cs.po
- rm -f cs.cp1250.po
- iconv -f ISO-8859-2 -t CP1250 cs.po | \
+ rm -f $@
+ iconv -f ISO-8859-2 -t CP1250 $< | \
$(SED) -e 's/charset=[iI][sS][oO]-8859-2/charset=CP1250/' \
- -e 's/# Original translations/# Generated from cs.po, DO NOT EDIT/' \
- > cs.cp1250.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert pl.po to create pl.cp1250.po.
pl.cp1250.po: pl.po
- rm -f pl.cp1250.po
- iconv -f ISO-8859-2 -t CP1250 pl.po | \
+ rm -f $@
+ iconv -f ISO-8859-2 -t CP1250 $< | \
$(SED) -e 's/charset=[iI][sS][oO]-8859-2/charset=CP1250/' \
- -e 's/# Original translations/# Generated from pl.po, DO NOT EDIT/' \
- > pl.cp1250.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert pl.po to create pl.UTF-8.po.
pl.UTF-8.po: pl.po
- rm -f pl.UTF-8.po
- iconv -f ISO-8859-2 -t UTF-8 pl.po | \
+ rm -f $@
+ iconv -f ISO-8859-2 -t UTF-8 $< | \
$(SED) -e 's/charset=[iI][sS][oO]-8859-2/charset=UTF-8/' \
- -e 's/# Original translations/# Generated from pl.po, DO NOT EDIT/' \
- > pl.UTF-8.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert sk.po to create sk.cp1250.po.
sk.cp1250.po: sk.po
- rm -f sk.cp1250.po
- iconv -f ISO-8859-2 -t CP1250 sk.po | \
+ rm -f $@
+ iconv -f ISO-8859-2 -t CP1250 $< | \
$(SED) -e 's/charset=[iI][sS][oO]-8859-2/charset=CP1250/' \
- -e 's/# Original translations/# Generated from sk.po, DO NOT EDIT/' \
- > sk.cp1250.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert zh_CN.UTF-8.po to create zh_CN.po.
zh_CN.po: zh_CN.UTF-8.po
- rm -f zh_CN.po
- iconv -f UTF-8 -t GB2312 zh_CN.UTF-8.po | \
+ rm -f $@
+ iconv -f UTF-8 -t GB2312 $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=GB2312/' \
- -e 's/# Original translations/# Generated from zh_CN.UTF-8.po, DO NOT EDIT/' \
- > zh_CN.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert zh_CN.UTF-8.po to create zh_CN.cp936.po.
# Set 'charset' to gbk to avoid that msfmt generates a warning.
# This used to convert from zh_CN.po, but that results in a conversion error.
zh_CN.cp936.po: zh_CN.UTF-8.po
- rm -f zh_CN.cp936.po
- iconv -f UTF-8 -t CP936 zh_CN.UTF-8.po | \
+ rm -f $@
+ iconv -f UTF-8 -t CP936 $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=GBK/' \
- -e 's/# Original translations/# Generated from zh_CN.UTF-8.po, DO NOT EDIT/' \
- > zh_CN.cp936.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
-# Convert zh_TW.UTF-8.po to create zh_TW.po
+# Convert zh_TW.UTF-8.po to create zh_TW.po.
zh_TW.po: zh_TW.UTF-8.po
- rm -f zh_TW.po
- iconv -f UTF-8 -t BIG5 zh_TW.UTF-8.po | \
+ rm -f $@
+ iconv -f UTF-8 -t BIG5 $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=BIG5/' \
- -e 's/# Original translations/# Generated from zh_TW.UTF-8.po, DO NOT EDIT/' \
- > zh_TW.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
-# Convert zh_TW.UTF-8.po to create zh_TW.po with backslash characters
+# Convert zh_TW.UTF-8.po to create zh_TW.po with backslash characters.
# Requires doubling backslashes in the second byte. Don't depend on big5corr,
# it should only be compiled when zh_TW.po is outdated.
@@ -192,44 +196,44 @@ zh_TW.po: zh_TW.UTF-8.po
#zh_TW.po: zh_TW.UTF-8.po
# @$(MAKE) big5corr
-# rm -f zh_TW.po
-# iconv -f UTF-8 -t BIG5 zh_TW.UTF-8.po | ./big5corr > zh_TW.po
+# rm -f $@
+# iconv -f UTF-8 -t BIG5 $< | ./big5corr > $@
# 06.11.23, added by Restorer
-# see above in the zh_tw.po conversion section for backslashes.
+# See above in the zh_tw.po conversion section for backslashes.
#big5corr: big5corr.c
# $(CC) -o big5corr big5corr.c
# Convert ko.UTF-8.po to create ko.po.
ko.po: ko.UTF-8.po
- rm -f ko.po
- iconv -f UTF-8 -t EUC-KR ko.UTF-8.po | \
+ rm -f $@
+ iconv -f UTF-8 -t EUC-KR $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=EUC-KR/' \
- -e 's/# Original translations/# Generated from ko.UTF-8.po, DO NOT EDIT/' \
- > ko.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert ru.po to create ru.cp1251.po.
ru.cp1251.po: ru.po
- rm -f ru.cp1251.po
- iconv -f UTF-8 -t CP1251 ru.po | \
+ rm -f $@
+ iconv -f UTF-8 -t CP1251 $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=CP1251/' \
- -e 's/# Original translations/# Generated from ru.po, DO NOT EDIT/' \
- > ru.cp1251.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
# Convert uk.po to create uk.cp1251.po.
uk.cp1251.po: uk.po
- rm -f uk.cp1251.po
- iconv -f UTF-8 -t CP1251 uk.po | \
+ rm -f $@
+ iconv -f UTF-8 -t CP1251 $< | \
$(SED) -e 's/charset=[uU][tT][fF]-8/charset=CP1251/' \
- -e 's/# Original translations/# Generated from uk.po, DO NOT EDIT/' \
- > uk.cp1251.po
+ -e 's/# Original translations/# Generated from $<, DO NOT EDIT/' \
+ > $@
prefixcheck:
@if test "x" = "x$(prefix)"; then \
echo "******************************************"; \
- echo " please use make from the src directory "; \
+ echo " Please use make from the src directory "; \
echo "******************************************"; \
exit 1; \
fi
@@ -256,15 +260,15 @@ PO_INPUTLIST = \
vim.desktop.in
$(PACKAGE).pot: $(PO_INPUTLIST) $(PO_VIM_INPUTLIST)
- # Convert the Vim scripts to (what looks like) Javascript
+ # Convert the Vim scripts to (what looks like) Javascript.
$(VIM) -u NONE --not-a-term -S tojavascript.vim $(PACKAGE).pot $(PO_VIM_INPUTLIST)
- # create vim.pot
+ # Create vim.pot.
$(XGETTEXT) --default-domain=$(PACKAGE) --add-comments \
$(XGETTEXT_KEYWORDS) $(PO_INPUTLIST) $(PO_VIM_JSLIST)
mv -f $(PACKAGE).po $(PACKAGE).pot
- # Fix Vim scripts names, so that "gf" works
+ # Fix Vim scripts names, so that "gf" works.
$(VIM) -u NONE --not-a-term -S fixfilenames.vim $(PACKAGE).pot $(PO_VIM_INPUTLIST)
- # Delete the temporary files
+ # Delete the temporary files.
rm *.js
vim.desktop: vim.desktop.in $(POFILES)
@@ -283,11 +287,11 @@ gvim.desktop: gvim.desktop.in $(POFILES) vim.desktop
if command -v desktop-file-validate; then desktop-file-validate tmp_gvim.desktop; fi
mv tmp_gvim.desktop gvim.desktop
-# When updating ja.sjis.po there are a bunch of errors and a crash.
+# Only original translations with default encoding should be updated.
# The files that are converted to a different encoding clearly state "DO NOT EDIT".
update-po: $(MOFILES:.mo=)
-# Don't add a dependency here, we only want to update the .po files manually
+# Don't add a dependency here, we only want to update the .po files manually.
$(LANGUAGES):
@$(MAKE) $(PACKAGE).pot
if test ! -f $@.po.orig; then cp $@.po $@.po.orig; fi
diff --git a/src/po/README.txt b/src/po/README.txt
index 5a09d1f..50aff6a 100644
--- a/src/po/README.txt
+++ b/src/po/README.txt
@@ -30,7 +30,7 @@ The distributed files are generated on Unix, but this should also be possible
on MS-Windows. Download the gettext packages, for example from:
http://sourceforge.net/projects/gettext
- or
+or
https://mlocati.github.io/articles/gettext-iconv-windows.html
You might have to do the commands manually. Example:
@@ -53,7 +53,10 @@ CREATING A NEW PO FILE
We will use "xx.po" as an example here, replace "xx" with the name of your
language.
-- Edit Make_all.mak to add xx to LANGUAGES and xx.mo to MOFILES.
+- Edit Make_all.mak to add xx to LANGUAGES and xx.mo to MOFILES, xx.po to
+ POFILES and xx.ck to CHECKFILES.
+- If the encoding of the translation text differs from the default UTF-8, add a
+ corresponding entry in MOCONVERTED, specifying the required encoding.
- If you haven't done so already, run ./configure in the top vim directory
(i.e. go up two directories) and then come back here afterwards.
- Execute these commands:
@@ -147,13 +150,13 @@ convert ja.po to EUC-JP (supposed as your system encoding):
(1) Convert the file encoding:
mv ja.po ja.po.orig
- iconv -f utf-8 -t euc-jp ja.po.orig > ja.po
+ iconv -f UTF-8 -t EUC-JP ja.po.orig > ja.po
(2) Rewrite charset declaration in the file:
Open ja.po find this line:
- "Content-Type: text/plain; charset=utf-8\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
You should change "charset" like this:
- "Content-Type: text/plain; charset=euc-jp\n"
+ "Content-Type: text/plain; charset=EUC-JP\n"
There are examples in the Makefile for the conversions already supported.
diff --git a/src/po/README_mingw.txt b/src/po/README_mingw.txt
index d00ba30..a7e3259 100644
--- a/src/po/README_mingw.txt
+++ b/src/po/README_mingw.txt
@@ -20,8 +20,10 @@ The make utility must be run from the po directory.
First of all you must set the environment variable LANGUAGE to xx, where xx is
the name of your language. You can do it from the command line or adding a
line to your autoexec.bat file: set LANGUAGE=xx. You must also add your
-language to the Make_all.mak file in the lines LANGUAGES, MOFILES, AND
-POFILES.
+language to the Make_all.mak file in the lines LANGUAGES, MOFILES, POFILES,
+and CHECKFILES. If the encoding of the translation text differs from the
+default UTF-8, add a corresponding entry in MOCONVERTED, specifying the
+required encoding.
If you don't have a xx.po file, you must create it with the command:
diff --git a/src/po/README_mvc.txt b/src/po/README_mvc.txt
index 691e6ae..ae9fa2b 100644
--- a/src/po/README_mvc.txt
+++ b/src/po/README_mvc.txt
@@ -2,18 +2,19 @@ TRANSLATING VIM MESSAGES
This file explains how to create and maintain po files using a number of
GnuWin packages. You will need gettext, libiconv and libexpat. As of
-August 2010 the versions known to work are gettext 0.14.4, libiconv 1.9.2-1
-and expat 2.0.1. gettext and libiconv can be found at:
+January 2024 the versions known to work are gettext 0.14.4, libiconv 1.9.2-1
+and expat 2.5.0. Gettext and libiconv can be found at:
http://gnuwin32.sourceforge.net/
expat can be found at:
http://sourceforge.net/projects/expat/
+or
+ https://github.com/libexpat/libexpat
expat will install into its own directory. You should copy libexpat.dll into
the bin directory created from the gettext/libiconv packages.
-
Or Michele Locati kindly provides precompiled binaries gettext 0.21 and
iconv 1.16 for Windows on his site:
@@ -29,11 +30,13 @@ Set the environment variable LANGUAGE to the language code for the language
you are translating Vim messages to. Language codes are typically two
characters and you can find a list of them at:
- http://www.geocities.com/click2speak/languages.html
+ https://www.loc.gov/standards/iso639-2/php/code_list.php
+ https://www.science.co.il/language/Codes.php
+ https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
-Another possibility is to use the GnuWin32 port of gettext. This is
-recommended especially if you use already gnuwin32 tools to gunzip, bunzip,
-patch etc. these files. You find the GnuWin32 version of gettext here:
+Another possibility is to use the GnuWin32 port of gettext. This is
+recommended especially if you use already GnuWin32 tools to gunzip, bunzip,
+patch etc. these files. You find the GnuWin32 version of gettext here:
http://gnuwin32.sourceforge.net/packages/gettext.htm
@@ -41,13 +44,16 @@ Yet another very strait forward way is to get the sources of gettext from
http://www.gnu.org/software/gettext/gettext.html
-and build your own version of these tools. The documentation states that this
+and build your own version of these tools. The documentation states that this
should be possible with MSVC4.0, MSVC5.0, MSVC6.0 or MSVC7.0, but you can
build it even successfully with MSVC8.0.
The LANGUAGE environment variable can be set from the command line, by adding
a line to your autoexec.bat file, or by defining a user variable from the
-Advanced tab in the System control panel.
+Advanced tab in the System control panel. If the LANGUAGE environment
+variable has not been set in any of the above ways, the value of this variable
+will be set automatically according to the language used in the OS. This
+value will be valid until the "nmake.exe" program terminates.
Next, edit Make_mvc.mak so that GETTEXT_PATH points the binary directory of
the installation.
@@ -56,10 +62,13 @@ the installation.
CREATING A NEW TRANSLATION
When creating a new translation you must add your language code to the
-Make_all.mak file in the lines defining LANGUAGES and MOFILES. To create the
-initial .po file for your language you must use the command:
+Make_all.mak file in the lines defining LANGUAGES and MOFILES, POFILES and
+CHECKFILES. If the encoding of the translation text differs from the default
+UTF-8, add a corresponding entry in MOCONVERTED, specifying the required
+encoding.
+To create the initial .po file for your language you must use the command:
- make -f make_mvc.mak first_time
+ nmake.exe -f Make_mvc.mak first_time
Note: You need to be in the po directory when using this makefile.
@@ -82,7 +91,7 @@ If there are new or changed messages in Vim that need translating, then the
first thing to do is merge them into the existing translations. This is done
with the following command:
- nmake -f Make_mvc.mak xx.po
+ nmake.exe -f Make_mvc.mak xx
where xx is the language code for the language needing translations. The
original .po file is copied to xx.po.orig.
@@ -102,23 +111,30 @@ CHECKING THE TRANSLATION
Check the translation with the following command:
- nmake -f make_mvc.mak xx.mo
+ nmake.exe -f Make_mvc.mak xx.ck
-Correct any syntax errors reported. When there are no more errors, the
-translation is ready to be installed.
+Correct any errors reported. When there are no more errors, the translation
+is ready to be installed.
INSTALLING THE TRANSLATION
Install your translation with the following command:
- nmake -f make_mvc.mak install
+ nmake.exe -f Make_mvc.mak install
This will create the xx\LC_MESSAGES directory in runtime\lang if it does not
already exist.
You can also use the following command to install all languages:
- nmake -f make_mvc.mak install-all
+ nmake.exe -f Make_mvc.mak install-all
+
+
+AFTER ALL OF THESE STEPS
+
+Clean the "po" directory of all temporary and unnecessary files. Execute the
+command:
+ nmake.exe -f Make_mvc.mak clean
vim:tw=78:
diff --git a/src/po/ca.po b/src/po/ca.po
index 44125fb..caf02a9 100644
--- a/src/po/ca.po
+++ b/src/po/ca.po
@@ -256,7 +256,7 @@ msgid "Warning: Using a weak encryption method; see :help 'cm'"
msgstr "Atenció: esteu utilitzant un xifratge poc potent; vegeu :help 'cm'"
msgid "Note: Encryption of swapfile not supported, disabling swap file"
-msgstr "Nota: No es suporta xifratge en el fitxer d'intercanvi, es desabilita"
+msgstr "Nota: No se suporta xifratge en el fitxer d'intercanvi, es deshabilita"
msgid "Enter encryption key: "
msgstr "Introduïu la clau de xifratge: "
@@ -265,7 +265,7 @@ msgid "Enter same key again: "
msgstr "Introduïu la mateixa clau un altre cop: "
msgid "Keys don't match!"
-msgstr "La claus no coincideixen!"
+msgstr "Les claus no coincideixen!"
msgid "[crypted]"
msgstr "[xifrat]"
@@ -499,7 +499,7 @@ msgid ""
"Do you wish to try?"
msgstr ""
"El fitxer \"%s\" és de només lectura.\n"
-"Tot i això pot ser possible escriure-hi.\n"
+"Tot i això és possible escriure-hi.\n"
"Voleu intentar-ho?"
# :browse edit
@@ -1554,7 +1554,7 @@ msgid "-register\t\tRegister this gvim for OLE"
msgstr "-register\t\tRegistra aquest gvim a OLE"
msgid "-unregister\t\tUnregister gvim for OLE"
-msgstr "-unregister\t\tDóna de baixa aquest gvim a OLE"
+msgstr "-unregister\t\tDona de baixa aquest gvim a OLE"
msgid "-g\t\t\tRun using GUI (like \"gvim\")"
msgstr "-g\t\t\tUsa la interfície gràfica (com \"gvim\")"
@@ -2158,7 +2158,7 @@ msgstr ""
" amb precaució.\n"
msgid "(2) An edit session for this file crashed.\n"
-msgstr "(2) El Vim es va estrellar mentre s'editava aquest fitxer.\n"
+msgstr "(2) El Vim va fallar mentre s'editava aquest fitxer.\n"
msgid " If this is the case, use \":recover\" or \"vim -r "
msgstr " En aquest cas, useu \":recover\" o bé \"vim -r "
@@ -3182,7 +3182,7 @@ msgid "No Syntax items defined for this buffer"
msgstr "No s'han definit elements de sintaxi per a aquest buffer"
msgid "'redrawtime' exceeded, syntax highlighting disabled"
-msgstr "s'ha excedit 'redrawtime', es desabilita el ressaltat"
+msgstr "s'ha excedit 'redrawtime', es deshabilita el ressaltat"
# todo: not set
# valor de 'iskeyword' o "not set"
@@ -4442,7 +4442,7 @@ msgstr "E151: Cap coincidència: %s"
#, c-format
msgid "E152: Cannot open %s for writing"
-msgstr "E152: No es obrir %s per a escriptura"
+msgstr "E152: No es pot obrir %s per a escriptura"
#, c-format
msgid "E153: Unable to open %s for reading"
@@ -7199,7 +7199,7 @@ msgid "E966: Invalid line number: %ld"
msgstr "E966: El número de línia no és vàlid: %ld"
msgid "E967: Text property info corrupted"
-msgstr "E967: L'informació de la propietat de text s'ha corromput"
+msgstr "E967: La informació de la propietat de text s'ha corromput"
msgid "E968: Need at least one of 'id' or 'type'"
msgstr "E968: Es requereix 'id' o 'type'"
@@ -7240,7 +7240,7 @@ msgstr "E978: Operació no vàlida per a un Blob"
#, c-format
msgid "E979: Blob index out of range: %ld"
-msgstr "E979: índexació d'un Blob fora d'interval: %ld"
+msgstr "E979: indexació d'un Blob fora d'interval: %ld"
msgid "E980: Lowlevel input not supported"
msgstr "E980: L'entrada de baix nivell no està suportada"
@@ -8800,7 +8800,7 @@ msgstr ""
"\" Cada línia \"set\" mostra el valor actual de l'opció (a l'esquerra)."
msgid "\" Hit <Enter> on a \"set\" line to execute it."
-msgstr "\" Premeu <Entrar> en una lína \"set\" per a executar-la."
+msgstr "\" Premeu <Entrar> en una línia \"set\" per a executar-la."
msgid "\" A boolean option will be toggled."
msgstr "\" Una opció booleana canviarà d'estat."
@@ -9024,7 +9024,7 @@ msgid "characters to use for the status line, folds and filler lines"
msgstr "caràcters per a la línia d'estat, plecs i final del buffer"
msgid "number of lines used for the command-line"
-msgstr "numero de línies de text per a la línia d'ordres"
+msgstr "número de línies de text per a la línia d'ordres"
msgid "width of the display"
msgstr "amplada de la pantalla"
@@ -9623,7 +9623,7 @@ msgstr "funció que es crida per a l'operador \"g@\""
msgid "when inserting a bracket, briefly jump to its match"
msgstr ""
"quan s'insereix un parèntesi, salta momentàniament al\n"
-"parèntesis corresponent"
+"parèntesi corresponent"
msgid "tenth of a second to show a match for 'showmatch'"
msgstr ""
@@ -9656,7 +9656,7 @@ msgid "list of number of spaces a tab counts for"
msgstr "llista de quantitats d'espais que avança una tabulació"
msgid "list of number of spaces a soft tabsstop counts for"
-msgstr "llista de quatitats d'espais que avança una tabulació tabsstop"
+msgstr "llista de qualitats d'espais que avança una tabulació tabsstop"
msgid "a <Tab> in an indent inserts 'shiftwidth' spaces"
msgstr "un <Tab> en una sagnia insereix 'shiftwidth' espais"
@@ -9992,7 +9992,7 @@ msgid "characters to escape when 'shellxquote' is ("
msgstr "caràcters que s'escapen quan 'shellxquote' és ("
msgid "argument for 'shell' to execute a command"
-msgstr "argument per a 'shell' per a excutar una ordre"
+msgstr "argument per a 'shell' per a executar una ordre"
msgid "used to redirect command output to a file"
msgstr "utilitzat per a redirigir la sortida d'una ordre a un fitxer"
@@ -10056,7 +10056,7 @@ msgid "specifies slash/backslash used for completion"
msgstr "especifica el tipus de barra utilitzat en la compleció"
msgid "language specific"
-msgstr "paràmetres específics del llengüatge"
+msgstr "paràmetres específics del llenguatge"
msgid "specifies the characters in a file name"
msgstr "especifica els caràcters en un nom de fitxer"
@@ -10068,7 +10068,7 @@ msgid "specifies the characters in a keyword"
msgstr "especifica els caràcters en una paraula clau"
msgid "specifies printable characters"
-msgstr "especifica el caràcters imprimibles"
+msgstr "especifica els caràcters imprimibles"
msgid "specifies escape characters in a string"
msgstr "especifica els caràcters d'escapada en una cadena"
@@ -10100,7 +10100,7 @@ msgid "prepare for editing Arabic text"
msgstr "efectua les preparacions per a editar textos en àrab"
msgid "perform shaping of Arabic characters"
-msgstr "dóna forma als caràcters àrabs"
+msgstr "dona forma als caràcters àrabs"
msgid "terminal will perform bidi handling"
msgstr "el terminal gestiona el text bi-direccional"
diff --git a/src/po/hu.po b/src/po/hu.po
index e54c62a..0a11847 100644
--- a/src/po/hu.po
+++ b/src/po/hu.po
@@ -16,7 +16,7 @@ msgstr ""
"Language-Team: Hungarian http://polarhome.com/vim/\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "E82: Cannot allocate any buffer, exiting..."
diff --git a/src/po/it.po b/src/po/it.po
index 42fe7f7..8bdc5e3 100644
--- a/src/po/it.po
+++ b/src/po/it.po
@@ -14,7 +14,8 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2023-12-27 16:38+0100\n"
+"POT-Creation-Date: 2024-03-06 09:13+0100\n"
+"PO-Revision-Date: 2024-03-06 15:00+0100\n"
"Last-Translator: Antonio Colombo <azc100@gmail.com>\n"
"Language-Team: Italian\n"
"Language: it\n"
@@ -163,6 +164,9 @@ msgstr " (file %d di %d)"
msgid " (file (%d) of %d)"
msgstr " (file (%d) di %d)"
+msgid "[Command Line]"
+msgstr "[Riga-di-comando]"
+
msgid "[Prompt]"
msgstr "[Richiesta]"
@@ -647,9 +651,6 @@ msgstr "Errore"
msgid "Interrupt"
msgstr "Interruzione"
-msgid "[Command Line]"
-msgstr "[Riga-di-comando]"
-
msgid "is a directory"
msgstr "è una directory"
@@ -1366,6 +1367,9 @@ msgstr "argomento di mapnew()"
msgid "filter() argument"
msgstr "argomento di filter()"
+msgid "foreach() argument"
+msgstr "argomento di foreach()"
+
msgid "extendnew() argument"
msgstr "argomento di extendnew()"
@@ -2404,6 +2408,12 @@ msgstr "a %s su %s"
msgid "Printing '%s'"
msgstr "Stampato: '%s'"
+#. Default font name for current language on MS-Windows.
+#. If not translated, falls back to "Consolas".
+#. This must be a fixed-pitch font.
+msgid "DefaultFontNameForWindows"
+msgstr "NomeCarattereDefaultPerWindows"
+
msgid "Opening the X display took %ld msec"
msgstr "Attivazione visualizzazione X ha richiesto %ld msec"
@@ -3250,11 +3260,11 @@ msgstr "%s ritorno #%ld"
msgid "%s returning %s"
msgstr "%s ritorno %s"
-msgid "Function %s does not need compiling"
-msgstr "La funzione %s non ha bisogno di compilazione"
+msgid "Function %s%s%s does not need compiling"
+msgstr "La funzione %s%s%s non ha bisogno di compilazione"
msgid "%s (%s, compiled %s)"
-msgstr "%s (%s, compilato %s)"
+msgstr "%s (%s, compilata %s)"
msgid ""
"\n"
@@ -3986,6 +3996,9 @@ msgstr "E104: Escape non consentito nei digrammi"
msgid "E105: Using :loadkeymap not in a sourced file"
msgstr "E105: Uso di :loadkeymap fuori da un file di comandi"
+msgid "E106: Unsupported diff output format: %s"
+msgstr "E106: Formato output di diff non supportato: %s"
+
msgid "E107: Missing parentheses: %s"
msgstr "E107: Mancano parentesi: %s"
@@ -4272,8 +4285,8 @@ msgstr "E196: Digrammi non supportati in questa versione"
msgid "E197: Cannot set language to \"%s\""
msgstr "E197: Non posso impostare lingua a \"%s\""
-msgid "E199: Active window or buffer deleted"
-msgstr "E199: Finestra attiva o buffer cancellato"
+msgid "E199: Active window or buffer changed or deleted"
+msgstr "E199: Finestra attiva o buffer modificato o cancellato"
msgid "E200: *ReadPre autocommands made the file unreadable"
msgstr "E200: Gli autocomandi *ReadPre hanno reso il file illeggibile"
@@ -7769,8 +7782,7 @@ msgstr "E1330: Tipo non valido per variabile Object: %s"
msgid ""
"E1331: Public must be followed by \"var\" or \"static\" or \"final\" or "
"\"const\""
-msgstr "E1331: Public dev'essere seguito da \"var\" o \"static\" o "
-"\"const\""
+msgstr "E1331: Public dev'essere seguito da \"var\" o \"static\" o \"const\""
msgid "E1332: Public variable name cannot start with underscore: %s"
msgstr ""
@@ -7884,9 +7896,7 @@ msgstr ""
msgid ""
"E1368: Static must be followed by \"var\" or \"def\" or \"final\" or "
"\"const\""
-msgstr ""
-"E1368: \"Static\" deve essere seguito da \"var\" o \"def\" o "
-"\"const\""
+msgstr "E1368: \"Static\" deve essere seguito da \"var\" o \"def\" o \"const\""
msgid "E1369: Duplicate variable: %s"
msgstr "E1369: Variabile duplicata: %s"
@@ -8029,8 +8039,8 @@ msgid "E1408: Final variable not supported in an interface"
msgstr "E1408: Variabile Finale non supportata in un'Interfaccia"
msgid "E1409: Cannot change read-only variable \"%s\" in class \"%s\""
-msgstr "E1409: Non posso cambiare variabile in sola-lettura \"%s\" "
-"in Classe \"%s\""
+msgstr ""
+"E1409: Non posso cambiare variabile in sola-lettura \"%s\" in Classe \"%s\""
msgid "E1410: Const variable not supported in an interface"
msgstr "E1410: Variabile di tipo \"Const\" non supportata in un'Interfaccia"
@@ -8038,6 +8048,12 @@ msgstr "E1410: Variabile di tipo \"Const\" non supportata in un'Interfaccia"
msgid "E1411: Missing dot after object \"%s\""
msgstr "E1411: Manca un punto dopo \"Object\" \"%s\""
+msgid "E1412: Builtin object method \"%s\" not supported"
+msgstr "E1412: Metodo Object predefinito \"%s\" non supportato"
+
+msgid "E1413: Builtin class method not supported"
+msgstr "E1413: Metodo Classe predefinito non supportato"
+
msgid "E1500: Cannot mix positional and non-positional arguments: %s"
msgstr ""
"E1500: Non si possono mischiare argomenti posizionali e non posizionali: %s"
@@ -8079,8 +8095,19 @@ msgstr "E1509: Errore in lettura o scrittura degli attributi estesi"
msgid "E1510: Value too large: %s"
msgstr "E1510: Valore troppo grande: %s"
+msgid "E1511: Wrong number of characters for field \"%s\""
+msgstr "E1511: Numero caratteri errato per campo \"%s\""
+
+msgid "E1512: Wrong character width for field \"%s\""
+msgstr "E1512: Larghezza carattere errata per campo \"%s\""
+
+msgid "E1513: Cannot edit buffer. 'winfixbuf' is enabled"
+msgstr "E1513: Non riesco a modificare il buffer. Opzione 'winfixbuf' attiva"
+
#. type of cmdline window or 0
#. result of cmdline window or 0
+#. buffer of cmdline window or NULL
+#. window of cmdline window or NULL
msgid "--No lines in buffer--"
msgstr "--File vuoto--"
@@ -8827,6 +8854,9 @@ msgstr "numero minimo di righe usato per la finestra corrente"
msgid "minimal number of lines used for any window"
msgstr "numero minimo di righe usato per ogni finestra"
+msgid "keep window focused on a single buffer"
+msgstr "mantenere finestra dedicata a un solo buffer"
+
msgid "keep the height of the window"
msgstr "mantenere l'altezza della finestra"
diff --git a/src/po/ru.cp1251.po b/src/po/ru.cp1251.po
index e9d1910..2dd453a 100644
--- a/src/po/ru.cp1251.po
+++ b/src/po/ru.cp1251.po
@@ -21,10 +21,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: RuVim_0.9002185.251223\n"
+"Project-Id-Version: RuVim_0.9010059.260124\n"
"Report-Msgid-Bugs-To: The Vim Project, <vim-dev@vim.org>\n"
-"POT-Creation-Date: 2023-12-25 16:17+0300\n"
-"PO-Revision-Date: 2023-12-25 18:57+0300\n"
+"POT-Creation-Date: 2024-01-26 14:54+0300\n"
+"PO-Revision-Date: 2024-01-26 14:57+0300\n"
"Last-Translator: Restorer, <restorer@mail2k.ru>\n"
"Language-Team: RuVim, https://github.com/RestorerZ/RuVim\n"
"Language: ru_RU\n"
@@ -233,6 +233,7 @@ msgstr "Îêîí÷àíèå"
msgid "Top"
msgstr "Íà÷àëî"
+# #Restorer: ëîêàëèçóåìîå çíà÷åíèå ïðîöåíòà
# :!~ Restorer
#, c-format
msgid "%d%%"
@@ -266,6 +267,10 @@ msgstr " (ôàéë %d èç %d"
msgid " (file (%d) of %d)"
msgstr " (ôàéë (%d) èç %d"
+# :!~ Restorer
+msgid "[Command Line]"
+msgstr "[êîìàíäíàÿ ñòðîêà]"
+
# #Restorer: â ñòðîêå ñîñòîÿíèÿ äëÿ áóôåðà ñ îêíîì çàïðîñà è óâåäîìëåíèÿ
# :!~ Restorer
msgid "[Prompt]"
@@ -701,6 +706,7 @@ msgstr ""
# #Restorer: èñïîëüçóåòñÿ â ôóíêöèè confirm() åñëè íå çàäàíû àðãóìåíò buttons
# #Restorer: èñïîëüçóåòñÿ êàê êíîïêà ïî óìîë÷àíèþ â îêíàõ ñîîáùåíèé ÃÈÏ
# :!~ Restorer
+#.
msgid "&Ok"
msgstr "&OK"
@@ -1078,10 +1084,6 @@ msgstr "Îøèáêà"
msgid "Interrupt"
msgstr "Ïðåðûâàíèå"
-# :!~ Restorer
-msgid "[Command Line]"
-msgstr "[êîìàíäíàÿ ñòðîêà]"
-
# #Restorer: â UNIX-ïîäîáíûõ ñèñòåìàõ
# #Restorer: è åù¸ îøèáêà E502:
# ~!: earlier
@@ -1090,7 +1092,7 @@ msgstr "ÿâëÿåòñÿ êàòàëîãîì"
# :!~ Restorer
msgid "Illegal file name"
-msgstr "Íåäîïóñòèìûå ñèìâîëû èëè ïðåâûøåíà äëèíà íàèìåíîâàíèÿ ôàéëà"
+msgstr "Îáíàðóæåíû íåäîïóñòèìûå ñèìâîëû èëè ïðåâûøåíà äëèíà íàèìåíîâàíèÿ ôàéëà"
# #Restorer: â UNIX-ïîäîáíûõ ñèñòåìàõ
# ~!: earlier
@@ -1373,10 +1375,12 @@ msgstr ""
msgid "OK"
msgstr "OK"
+# #Restorer: íàèìåíîâàíèå êíîïêè â äèàëîãîâîì îêíå
# :!~ Restorer
msgid "Yes"
msgstr "Äà"
+# #Restorer: íàèìåíîâàíèå êíîïêè â äèàëîãîâîì îêíå
# :!~ Restorer
msgid "No"
msgstr "Íåò"
@@ -1574,27 +1578,28 @@ msgstr "Directory\t*.nothing\n"
# :!~ Restorer
#, c-format
msgid "Font0: %s"
-msgstr "íàèìåíîâàíèå øðèôòà font0 %s"
+msgstr "Øðèôò font0 %s"
# :!~ Restorer
#, c-format
msgid "Font%d: %s"
-msgstr "íàèìåíîâàíèå øðèôòà font%d %s"
+msgstr "Øðèôò font%d %s"
# :!~ Restorer
#, c-format
msgid "Font%d width is not twice that of font0"
-msgstr "øèðèíà ñèìâîëîâ font%d äîëæíà áûòü âäâîå áîëüøå øèðèíû ñèìâîëîâ font0"
+msgstr ""
+"øèðèíà ñèìâîëîâ â font%d äîëæíà áûòü âäâîå áîëüøå øèðèíû ñèìâîëîâ â font0"
# :!~ Restorer
#, c-format
msgid "Font0 width: %d"
-msgstr "øèðèíà ñèìâîëîâ font0 %d"
+msgstr "øèðèíà ñèìâîëîâ â font0 %d"
# :!~ Restorer
#, c-format
msgid "Font%d width: %d"
-msgstr "øèðèíà ñèìâîëîâ font%d %d"
+msgstr "øèðèíà ñèìâîëîâ â font%d %d"
# #Restorer: âûâîäèòñÿ â èíôîðìàöèîííîì îêíå
# :!~ Restorer
@@ -1631,17 +1636,17 @@ msgstr "Ïîêàçûâàòü ðàçìåð â ïóíêòàõ"
msgid "Encoding:"
msgstr "Êîäèðîâêà:"
-# #Restorer: íàèìåíîâàíèå ïîëÿ ñî ñïèñêîì øðèôòîâ â îêíå âûáîðà øðèôòà
+# #Restorer: íàèìåíîâàíèå ïîëÿ ñ ïåðå÷íåì øðèôòîâ â îêíå âûáîðà øðèôòà
# ~!: earlier
msgid "Font:"
msgstr "Øðèôò:"
-# #Restorer: íàèìåíîâàíèå ïîëÿ ñî ñïèñêîì íà÷åðòàíèé â îêíå âûáîðà øðèôòà
+# #Restorer: íàèìåíîâàíèå ïîëÿ ñ ïåðå÷íåì íà÷åðòàíèé â îêíå âûáîðà øðèôòà
# :!~ Restorer
msgid "Style:"
msgstr "Íà÷åðòàíèå:"
-# #Restorer: íàèìåíîâàíèå ïîëÿ ñî ñïèñêîì ðàçìåðîâ â îêíå âûáîðà øðèôòà
+# #Restorer: íàèìåíîâàíèå ïîëÿ ñ ïåðå÷íåì ðàçìåðîâ â îêíå âûáîðà øðèôòà
# ~!: earlier
msgid "Size:"
msgstr "Ðàçìåð:"
@@ -1895,6 +1900,7 @@ msgstr "íîìåð ñòðîêè âûõîäèò çà ïðåäåëû çíà÷åíèé äèàïàçîíà"
msgid "not allowed in the Vim sandbox"
msgstr "çàïðåùåíî âûïîëíåíèå â èçîëèðîâàííîé ñðåäå ïðîãðàììû Vim"
+# #Restorer: Check! Is error number duble!
# :!~ Restorer
#, c-format
msgid "E370: Could not load library %s"
@@ -1953,7 +1959,7 @@ msgstr "âûïîëíåíèå ïðåðâàíî ïîëüçîâàòåëåì"
msgid "cannot create buffer/window command: object is being deleted"
msgstr ""
"îáúåêò áóôåðà èëè îêíà â ïðîöåññå óäàëåíèÿ. Íå óäàëîñü ñîçäàòü äëÿ íèõ "
-"êîìàíäû"
+"êîìàíäó"
# :!~ Restorer
msgid ""
@@ -1979,7 +1985,7 @@ msgstr "Íå óäàëîñü çàðåãèñòðèðîâàòü íàèìåíîâàíèå ñåðâåðà êîìàíä"
# :!~ Restorer
#, c-format
msgid "%ld lines to indent... "
-msgstr "Âûïîëíÿåòñÿ èçìåíåíèÿ îòñòóïà â %ld ñòðîêàõ... "
+msgstr "Âûïîëíÿåòñÿ èçìåíåíèå îòñòóïà â %ld ñòðîêàõ... "
# #Restorer: âûâîäèòñÿ ïðè çíà÷åíèè 'report' < %ld
# :!~ Restorer
@@ -2095,7 +2101,7 @@ msgstr "Êîíåö àáçàöà"
# #Restorer: âûâîäèòñÿ ïðè àâòîïîäñòàíîâêå
# :!~ Restorer
msgid "Pattern not found"
-msgstr "Íå íàéäåíû âàðèàíòû äëÿ ïîäñòàíîâêè"
+msgstr "Îòñóòñòâóþò âàðèàíòû äëÿ ïîäñòàíîâêè"
# ~!: earlier
msgid "Back at original"
@@ -2151,6 +2157,11 @@ msgstr "àðãóìåíòà ôóíêöèè filter()"
# #Restorer: äîïèñûâàåòñÿ, íàïðèìåð, ê ñîîáùåíèþ E741 èëè E742
# :!~ Restorer
+msgid "foreach() argument"
+msgstr "àðãóìåíòà ôóíêöèè foreach()"
+
+# #Restorer: äîïèñûâàåòñÿ, íàïðèìåð, ê ñîîáùåíèþ E741 èëè E742
+# :!~ Restorer
msgid "extendnew() argument"
msgstr "àðãóìåíòà ôóíêöèè extendnew()"
@@ -2178,7 +2189,7 @@ msgstr "Íå ðàñïîçíàí àðãóìåíò êîìàíäíîé ñòðîêè"
# :!~ Restorer
msgid "Too many edit arguments"
-msgstr "Ïðåâûøåíî êîëè÷åñòâî ôàéëîâ ïåðåäàâàåìûõ â ïðîãðàììó äëÿ ïðàâêè"
+msgstr "Ïðåâûøåíî êîëè÷åñòâî ôàéëîâ, ïåðåäàâàåìûõ â ïðîãðàììó äëÿ ïðàâêè"
# :!~ Restorer
msgid "Argument missing after"
@@ -2387,7 +2398,7 @@ msgstr "-R\t\t\tÐàáîòà â âàðèàíòå òîëüêî äëÿ ÷òåíèÿ (êàê \"view\")"
# :!~ Restorer
msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tÐàáîòà â âàðèàíòå ñ îãðàíè÷åíèÿìè (êàê \"rvim\")"
+msgstr "-Z\t\t\tÐàáîòà ñ îãðàíè÷åííîé ôóíêöèîíàëüíîñòüþ (êàê \"rvim\")"
# :!~ Restorer
msgid "-m\t\t\tModifications (writing files) not allowed"
@@ -2450,8 +2461,7 @@ msgstr "-f\t\t\tÍå èñïîëüçîâàòü êîìàíäó newcli äëÿ îòêðûòèÿ îêíà"
# #Restorer: óáðàë îäèí \t, ÷òîáû âûãëÿäåëî åäèíîîáðàçíî
# :!~ Restorer
msgid "-dev <device>\t\tUse <device> for I/O"
-msgstr ""
-"-dev <óñòðîéñòâî>\tÈñïîëüçîâàòü äëÿ îïåðàöèé ââîäà-âûâîäà äàííîå <óñòðîéñòâî>"
+msgstr "-dev <óñòðîéñòâî>\tÈñïîëüçîâàòü äëÿ îïåðàöèé ââîäà-âûâîäà <óñòðîéñòâî>"
# :!~ Restorer
msgid "-A\t\t\tStart in Arabic mode"
@@ -2603,7 +2613,6 @@ msgstr ""
msgid "--startuptime <file>\tWrite startup timing messages to <file>"
msgstr "--startuptime <ôàéë>\tÇàïèñàòü õðîíîìåòðàæ çàïóñêà ïðîãðàììû â <ôàéë>"
-# #Restorer: äîáàâèë îäèí \t ÷òîáû âûãëÿäåëî åäèíîîáðàçíî
# :!~ Restorer
msgid "--log <file>\t\tStart logging to <file> early"
msgstr ""
@@ -2614,7 +2623,6 @@ msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
msgstr "-i <ôàéë>\t\tÈñïîëüçîâàíèå âìåñòî ôàéëà .viminfo óêàçàííîãî <ôàéëà>"
# \n\t\t.. äëÿ óìåùåíèÿ â 80 ñòîëáöîâ (Ñ. Àë¸øèí)
-# #Restorer: óáðàë îäèí \t è äîáàâèë ïðîáåëû, ÷òîáû âûãëÿäåëî åäèíîîáðàçíî
# :!~ Restorer
msgid "--clean\t\t'nocompatible', Vim defaults, no plugins, no viminfo"
msgstr ""
@@ -2640,8 +2648,7 @@ msgstr ""
# :!~ Restorer
msgid "-display <display>\tRun Vim on <display>"
-msgstr ""
-"-display <X-ñåðâåð>\tÇàïóñê ïðîãðàììû ñ ïîäêëþ÷åíèåì ê óêàçàííîìó X-ñåðâåðó"
+msgstr "-display <ñåðâåð>\tÏîäêëþ÷åíèå ïðîãðàììû ê X-ñåðâåðó <ñåðâåð>"
# :!~ Restorer
msgid "-iconic\t\tStart Vim iconified"
@@ -2705,7 +2712,7 @@ msgstr ""
# :!~ Restorer
msgid "-display <display>\tRun Vim on <display> (also: --display)"
msgstr ""
-"-display <display>\tÏîäêëþ÷åíèå ïðîãðàììû ê X-ñåðâåðó <ñåðâåð> (--display)"
+"-display <ñåðâåð>\tÏîäêëþ÷åíèå ïðîãðàììû ê X-ñåðâåðó <ñåðâåð> (--display)"
# :!~ Restorer
msgid "--role <role>\tSet a unique role to identify the main window"
@@ -2767,12 +2774,12 @@ msgstr "Ñîñòîÿíèå ïðîòîêîëà «kitty» îáìåíà äàííûìè ñ êëàâèàòóðîé: %s\n"
# #Restorer: âûâîäèòñÿ, íàïðèìåð, ïî êîìàíäå `:abbreviata`
# :!~ Restorer
msgid "No abbreviation found"
-msgstr "Íå íàéäåíû ñîêðàùåíèÿ"
+msgstr "Îòñóòñòâóþò ñîêðàùåíèÿ"
# #Restorer: âûâîäèòñÿ, íàïðèìåð, ïî êîìàíäå `:map`
# :!~ Restorer
msgid "No mapping found"
-msgstr "Íå íàéäåíû êëàâèàòóðíûå êîìàíäû"
+msgstr "Îòñóòñòâóþò êëàâèàòóðíûå êîìàíäû"
# #Restorer: âûâîäèòñÿ ïî êîìàíäå `:marks`
# :!~ Restorer
@@ -2847,7 +2854,7 @@ msgid ""
",\n"
"or the file has been damaged."
msgstr ""
-", \n"
+",\n"
"ëèáî îí áûë ïîâðåæä¸í"
# ~!: earlier
@@ -2875,7 +2882,7 @@ msgid ""
"If you entered a new crypt key but did not write the text file,"
msgstr ""
"\n"
-"Åñëè ïîñëå èçìåíåíèÿ ïàðîëÿ äëÿ øèôðîâàíèÿ, òåêñòîâûé ôàéë íå ñîõðàíÿëè,"
+"Åñëè ïîñëå èçìåíåíèÿ ïàðîëÿ øèôðîâàíèÿ íå áûëî ñîõðàíåíèå òåêñòîâîãî ôàéëà,"
# :!~ Restorer
msgid ""
@@ -2926,7 +2933,7 @@ msgstr "???ÁËÎÊ ÏÐÎÏÓÙÅÍ"
# :!~ Restorer
msgid "??? from here until ???END lines may be messed up"
msgstr ""
-"Ñòðîêè, êîòîðûå âîçìîæíî èñïîð÷åíû, ïîìåùåíû ìåæäó ìåòêàìè ??? è ???END"
+"Ñòðîêè, êîòîðûå, âîçìîæíî, èñïîð÷åíû, ïîìåùåíû ìåæäó ìåòêàìè ??? è ???END"
# :!~ Restorer
msgid "??? from here until ???END lines may have been inserted/deleted"
@@ -3181,19 +3188,19 @@ msgstr ""
# #Restorer: ñäâèíóò ê ãðàíèöå ýêðàíà
# :!~ Restorer
msgid " If this is the case, use \":recover\" or \"vim -r "
-msgstr " ýòîì ñëó÷àå èñïîëüçóéòå êîìàíäó :recover èëè \"vim -r "
+msgstr " ýòîì ñëó÷àå èñïîëüçóéòå êîìàíäó :recover èëè `vim -r "
# :!~ Restorer
msgid ""
"\"\n"
" to recover the changes (see \":help recovery\").\n"
msgstr ""
-"\",\n"
+"`,\n"
"÷òîáû âûïîëíèòü âîññòàíîâëåíèå äàííûõ (ïîäðîáíåå ñì. `:help recovery`).\n"
# :!~ Restorer
msgid " If you did this already, delete the swap file \""
-msgstr "Åñëè ýòî óæå áûë ñäåëàíî, òî óäàëèòå ôàéë ïîäêà÷êè \""
+msgstr "Åñëè ýòî óæå áûëî ñäåëàíî, òî óäàëèòå ôàéë ïîäêà÷êè \""
# :!~ Restorer
msgid ""
@@ -3234,7 +3241,7 @@ msgid ""
"&Quit\n"
"&Abort"
msgstr ""
-"Òîëüêî ÷òåíèå (&O)\n"
+"Îòêðûòü äëÿ ÷òåíèÿ (&O)\n"
"Ðåäàêòèðîâàòü (&E)\n"
"Âîññòàíîâèòü (&R)\n"
"Âûõîä (&Q)\n"
@@ -3250,7 +3257,7 @@ msgid ""
"&Quit\n"
"&Abort"
msgstr ""
-"Òîëüêî ÷òåíèå (&O)\n"
+"Îòêðûòü äëÿ ÷òåíèÿ (&O)\n"
"Ðåäàêòèðîâàòü (&E)\n"
"Âîññòàíîâèòü (&R)\n"
"Óäàëèòü (&D)\n"
@@ -3398,7 +3405,7 @@ msgstr "Âíèìàíèå! Äëÿ äàííîãî òåðìèíàë íåäîñòóïíà ïîäñâåòêà òåêñòà"
# :!~ Restorer
msgid "Type :qa! and press <Enter> to abandon all changes and exit Vim"
msgstr ""
-"×òîáû çàêðûòü ïðîãðàììó ñ îòìåíîé âñåõ ïðàâîê, íàáåðèòå :qa! è íàæìèòå "
+"×òîáû çàêðûòü ïðîãðàììó ñ îòìåíîé âñåõ ïðàâîê, íàáåðèòå :qa! è íàæìèòå "
"<ENTER>"
# :!~ Restorer
@@ -3621,6 +3628,10 @@ msgid "Printing '%s'"
msgstr "Ïå÷àòü '%s'"
# :!~ Restorer
+msgid "DefaultFontNameForWindows"
+msgstr "Consolas"
+
+# :!~ Restorer
#, c-format
msgid "Opening the X display took %ld msec"
msgstr "Ïîäêëþ÷åíèå ê X-ñåðâåðó çàíÿëî %ld ìñ"
@@ -3851,7 +3862,7 @@ msgstr ""
"â ôóíêöèè setqflist(). Äîëæåí áûòü óêàçàí ëèáî ïåðâûé, ëèáî ïîñëåäíèé "
"àðãóìåíò"
-# #Restorer: âûâîäèòñÿ ïðè 'verbose' > 0
+# #Restorer: âûâîäèòñÿ ïðè 'verbose'>0
# :!~ Restorer
msgid "Switching to backtracking RE engine for pattern: "
msgstr "Ïåðåêëþ÷åíèå íà ìåõàíèçì «ïîèñê ñ âîçâðàòîì» äëÿ ïîèñêîâîãî øàáëîíà: "
@@ -3990,13 +4001,13 @@ msgid "recording"
msgstr "ÇÀÏÈÑÜ Â ÐÅÃÈÑÒÐ"
# #Restorer: ïðè ïîèñêå ôàéëà â çàäàííîì êàòàëîãå, åñëè 'verbose'>10
-# ~!: earlier
+# :!~ Restorer
#, c-format
msgid "Searching for \"%s\" under \"%s\" in \"%s\""
msgstr "Ïîèñê \"%s\" â ïîäêàòàëîãå \"%s\" êàòàëîãîâ èç \"%s\""
# #Restorer: ïðè ïîèñêå ôàéëà â çàäàííîì êàòàëîãå, åñëè 'verbose'>10
-# ~!: earlier
+# :!~ Restorer
#, c-format
msgid "Searching for \"%s\" in \"%s\""
msgstr "Ïîèñê \"%s\" â êàòàëîãàõ èç \"%s\""
@@ -4229,7 +4240,7 @@ msgstr "Â ôàéëå %s íà ñòðîêå %d ïðåâûøåíà äëèíà íàèìåíîâàíèÿ àôôèêñà %s"
# :!~ Restorer
msgid "Compressing word tree..."
-msgstr "Ñæàòèå «äåðåâà» ñëîâ ..."
+msgstr "Ñæàòèå «äåðåâà» ñëîâ..."
# :!~ Restorer
#, c-format
@@ -4245,12 +4256,12 @@ msgstr "Ñ÷èòûâàíèå ôàéëà àôôèêñîâ %s..."
#, c-format
msgid "Conversion failure for word in %s line %d: %s"
msgstr ""
-" ôàéëå %s íà ñòðîêå %d ïðîèçîø¸ë ñáîé ïðè èçìåíåíèè êîäèðîâêè òåêñò %s"
+" ôàéëå %s íà ñòðîêå %d ïðîèçîø¸ë ñáîé ïðè èçìåíåíèè êîäèðîâêè òåêñòà %s"
# :!~ Restorer
#, c-format
msgid "Conversion in %s not supported: from %s to %s"
-msgstr "Äëÿ ôàéëà %s íå ïîääåðæèâàåòñÿ ïåðåêîäèðîâàíèå èç %s â %s"
+msgstr "Äëÿ ôàéëà %s íå ïîääåðæèâàåòñÿ èçìåíåíèå êîäèðîâêè òåêñòà èç %s â %s"
# :!~ Restorer
#, c-format
@@ -4405,7 +4416,7 @@ msgstr "Â ôàéëå %s íà ñòðîêå %d îáíàðóæåí íåäîïóñòèìûé ïðèçíàê %s"
# :!~ Restorer
#, c-format
msgid "%s value differs from what is used in another .aff file"
-msgstr " äðóãîì ôàéëå àôôèêñîâ îáíàðóæåíî îòëè÷àþùååñÿ çíà÷åíèå äëÿ %s"
+msgstr " äðóãîì ôàéëå àôôèêñîâ îáíàðóæåíî íåñîâïàäàþùåå çíà÷åíèå äëÿ %s"
# :!~ Restorer
#, c-format
@@ -4442,29 +4453,29 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "Reading word file %s..."
-msgstr "Ñ÷èòûâàíèå ôàéëà ñî ñïèñêîì ñëîâ %s..."
+msgstr "Ñ÷èòûâàíèå ôàéëà ñ ïåðå÷íåì ñëîâ %s..."
# :!~ Restorer
#, c-format
msgid "Conversion failure for word in %s line %ld: %s"
msgstr ""
-" ôàéëå %s íà ñòðîêå %ld ïðîèçîø¸ë ñáîé ïðè èçìåíåíèè êîäèðîâêè òåêñò %s"
+" ôàéëå %s íà ñòðîêå %ld ïðîèçîø¸ë ñáîé ïðè èçìåíåíèè êîäèðîâêè òåêñòà %s"
# :!~ Restorer
#, c-format
msgid "Duplicate /encoding= line ignored in %s line %ld: %s"
-msgstr "Â ôàéëå %s íà ñòðîêå %ld áûë ïðîèãíîðèðîâàí ïîâòîð /encoding= %s"
+msgstr "Â ôàéëå %s íà ñòðîêå %ld íå îáðàáîòàí ïîâòîð /encoding= %s"
# :!~ Restorer
#, c-format
msgid "/encoding= line after word ignored in %s line %ld: %s"
msgstr ""
-"Â ôàéëå %s íà ñòðîêå %ld ïðîèãíîðèðîâàí óêàçàííûé ïîñëå ñëîâà /encoding= %s"
+"Â ôàéëå %s íà ñòðîêå %ld íå îáðàáîòàí óêàçàííûé ïîñëå ñëîâà /encoding= %s"
# :!~ Restorer
#, c-format
msgid "Duplicate /regions= line ignored in %s line %ld: %s"
-msgstr "Â ôàéëå %s íà ñòðîêå %ld áûë ïðîèãíîðèðîâàí ïîâòîð %s"
+msgstr "Â ôàéëå %s íà ñòðîêå %ld íå îáðàáîòàí ïîâòîð /regions= %s"
# :!~ Restorer
#, c-format
@@ -4475,7 +4486,7 @@ msgstr " ôàéëå %s íà ñòðîêå %ld ïðåâûøåíî êîëè÷åñòâî ðåãèîíîâ %s"
#, c-format
msgid "/ line ignored in %s line %ld: %s"
msgstr ""
-"Â ôàéëå %s íà ñòðîêå %ld íå îáðàáîòàí óêàçàííûé ïîñëå ñèìâîëà / òåêñò %s"
+"Â ôàéëå %s íà ñòðîêå %ld íå îáðàáîòàí òåêñò, óêàçàííûé ïîñëå ñèìâîëà '/' %s"
# :!~ Restorer
#, c-format
@@ -4500,11 +4511,12 @@ msgstr "Ñæàòî óçëîâ %s: %ld èç %ld. Îñòàëîñü %ld (%ld%%)"
# :!~ Restorer
msgid "Reading back spell file..."
-msgstr "Ñ÷èòûâàíèå çàïèñàííîãî ôàéëà ïðàâèë íàïèñàíèÿ ..."
+msgstr "Ñ÷èòûâàíèå çàïèñàííîãî ôàéëà ïðàâèë íàïèñàíèÿ..."
# :!~ Restorer
+#.
msgid "Performing soundfolding..."
-msgstr "Ïîñòðîåíèå ïðåôèêñíîãî «äåðåâà» îìîôîíîâ ..."
+msgstr "Ïîñòðîåíèå ïðåôèêñíîãî «äåðåâà» îìîôîíîâ..."
# :!~ Restorer
#, c-format
@@ -4849,7 +4861,7 @@ msgstr "Íå óäàëîñü çàïèñàòü ôàéë. Ôàéë íå ÿâëÿåòñÿ ôàéëîì èçìåíåíèé %s"
# #Restorer: âûâîäèòñÿ, íàïðèìåð, äëÿ êîìàíä `:wundo` è `:rundo` ïðè 'verbose'>0
# :!~ Restorer
msgid "Skipping undo file write, nothing to undo"
-msgstr "Çàïèñü ôàéëà èçìåíåíèé íå âûïîëíåíà. Èçìåíåíèÿ îòñóòñòâóþò."
+msgstr "Èçìåíåíèÿ îòñóòñòâóþò. Çàïèñü ôàéëà èçìåíåíèé íå âûïîëíåíà"
# #Restorer: âûâîäèòñÿ, íàïðèìåð, äëÿ êîìàíä `:wundo` è `:rundo` ïðè 'verbose'>0
# :!~ Restorer
@@ -4971,7 +4983,7 @@ msgstr ""
# #Restorer: âûâîäèòñÿ ïî êîìàíäå `:command`
# :!~ Restorer
msgid "No user-defined commands found"
-msgstr "Íå íàéäåíû ñîçäàííûå ïîëüçîâàòåëåì êîìàíäû"
+msgstr "Ñîçäàííûå ïîëüçîâàòåëåì êîìàíäû íå íàéäåíû"
# #Restorer: âûâîäèòñÿ ïðè 'verbose'>0
# :!~ Restorer
@@ -5009,15 +5021,14 @@ msgstr "%s âåðíóëà %s"
# :!~ Restorer
#, c-format
-msgid "Function %s does not need compiling"
-msgstr "Íå òðåáóåòñÿ êîìïèëÿöèÿ ôóíêöèè %s"
+msgid "Function %s%s%s does not need compiling"
+msgstr "Íå òðåáóåòñÿ êîìïèëÿöèÿ ôóíêöèè %s%s%s"
# #Restorer: ïåðâûé %s çàìåíÿåòñÿ íà VIM_VERSION_LONG_ONLY (òîëüêî íàèìåíîâàíèå
# #Restorer: ïðîãðàììû), âòîðîé %s - VIM_VERSION_DATE_ONLY (äàòà ïåðâîãî âûïóñêà),
# #Restorer: òðåòèé %s - äàòîé òåêóùåé ñáîðêè
# #Restorer: âûâîäèòñÿ ïî êîìàíäå vim.exe -h èëè `:version`
# :!~ Restorer
-# "%s (%s, ñáîðàíî â %s)"
#, c-format
msgid "%s (%s, compiled %s)"
msgstr "%s (%s, ñáîðêà îò %s)"
@@ -5198,59 +5209,59 @@ msgstr "  ýòîé âåðñèè âêëþ÷åíû (+) è îòêëþ÷åíû (-) ñëåäóþùèå êîìïîíåíòû:\n"
# ~!: earlier
msgid " system vimrc file: \""
-msgstr " îáùåñèñòåìíûé ôàéë vimrc: \""
+msgstr " îáùåñèñòåìíûé ôàéë vimrc: \""
# ~!: earlier
msgid " user vimrc file: \""
-msgstr " ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
+msgstr " ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
# ~!: earlier
msgid " 2nd user vimrc file: \""
-msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
+msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
# ~!: earlier
msgid " 3rd user vimrc file: \""
-msgstr " òðåòèé ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
+msgstr " òðåòèé ïîëüçîâàòåëüñêèé ôàéë vimrc: \""
# ~!: earlier
msgid " user exrc file: \""
-msgstr " ïîëüçîâàòåëüñêèé ôàéë exrc: \""
+msgstr " ïîëüçîâàòåëüñêèé ôàéë exrc: \""
# ~!: earlier
msgid " 2nd user exrc file: \""
-msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë exrc: \""
+msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë exrc: \""
# ~!: earlier
msgid " system gvimrc file: \""
-msgstr " îáùåñèñòåìíûé ôàéë gvimrc: \""
+msgstr " îáùåñèñòåìíûé ôàéë gvimrc: \""
# ~!: earlier
msgid " user gvimrc file: \""
-msgstr " ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
+msgstr " ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
# ~!: earlier
msgid "2nd user gvimrc file: \""
-msgstr " âòîðîé ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
+msgstr "âòîðîé ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
# ~!: earlier
msgid "3rd user gvimrc file: \""
-msgstr " òðåòèé ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
+msgstr "òðåòèé ïîëüçîâàòåëüñêèé ôàéë gvimrc: \""
# :!~ Restorer
msgid " defaults file: \""
-msgstr " ôàéë ïðåäóñòàíîâëåííûõ íàñòðîåê: \""
+msgstr " ôàéë ïðåäóñòàíîâëåííûõ íàñòðîåê: \""
# ~!: earlier
msgid " system menu file: \""
-msgstr " îáùåñèñòåìíûé ôàéë ìåíþ: \""
+msgstr " îáùåñèñòåìíûé ôàéë ìåíþ: \""
# ~!: earlier
msgid " fall-back for $VIM: \""
-msgstr " çíà÷åíèå $VIM ïî óìîë÷àíèþ: \""
+msgstr " çíà÷åíèå $VIM ïî óìîë÷àíèþ: \""
# ~!: earlier
msgid " f-b for $VIMRUNTIME: \""
-msgstr " çíà÷åíèå $VIMRUNTIME ïî óìîë÷àíèþ: \""
+msgstr " çíà÷åíèå $VIMRUNTIME ïî óìîë÷àíèþ: \""
# :!~ Restorer
msgid "Compilation: "
@@ -5424,7 +5435,7 @@ msgstr ""
# #Restorer: E1016: Äëÿ îáëàñòè äåéñòâèÿ «ãëîáàëüíàÿ» íå ìîæåò áûòü îáúÿâëåíà ïåðåìåííàÿ %s
# :!~ Restorer
msgid "global"
-msgstr "«ãëîáàëüíûé»"
+msgstr "«îáùèé»"
# #Restorer: ïîäñòàâëÿåòñÿ â «E1016: Cannot declare a %s variable: %s» êàê
# #Restorer: ïåðâàÿ %s. Ìîæåò ëó÷øå íå ïåðåâîäèòü? Ïîêà ñäåëàë. Âûãëÿäèò òàê:
@@ -5459,7 +5470,7 @@ msgid ""
"# Buffer list:\n"
msgstr ""
"\n"
-"# Ñïèñîê áóôåðîâ:\n"
+"# Ïåðå÷åíü áóôåðîâ:\n"
# #Restorer: çàïèñü â viminfo-ôàéë æóðíàëà (history) êîìàíä, ïîèñêà è ïðî÷.
# :!~ Restorer
@@ -5510,13 +5521,14 @@ msgstr ""
msgid "%sviminfo: %s in line: "
msgstr "%s%s â viminfo-ôàéëå íà ñòðîêå "
-# ~!: earlier
+# #Restorer: â viminfo-ôàéëå
+# :!~ Restorer
msgid ""
"\n"
"# global variables:\n"
msgstr ""
"\n"
-"# Ãëîáàëüíûå ïåðåìåííûå:\n"
+"# Îáùèå ïåðåìåííûå:\n"
# #Restorer: çàïèñü â viminfo-ôàéëå
# :!~ Restorer
@@ -5645,7 +5657,7 @@ msgstr "Îòêðûòü ôàéëû â îòäåëüíûõ âêëàäêà&õ ïðîãðàììû Vim"
# :!~ Restorer
msgid "Edit with single &Vim"
-msgstr "Îòêðûòü âñå ôàéëû â îäíîé ïðîãðàììå &Vim"
+msgstr "Îòêðûòü âñå ôàéëû â &îäíîé ïðîãðàììå Vim"
# :!~ Restorer
msgid "Diff with Vim"
@@ -5653,7 +5665,7 @@ msgstr "Ñðàâíèòü ôàéëû â ïðîãðàììå Vim"
# :!~ Restorer
msgid "Edit with &Vim"
-msgstr "Îòêðûòü â ïðîãðàììå &Vim"
+msgstr "Îòêðûòü â &ïðîãðàììå Vim"
# :!~ Restorer
msgid "Edit with existing Vim"
@@ -5727,7 +5739,7 @@ msgstr "E18: Íåäîïóñòèìûå ñèìâîëû â ïðèñâàèâàåìîì âûðàæåíèè"
# :!~ Restorer
msgid "E19: Mark has invalid line number"
-msgstr "E19: Çàêëàäêà óêàçûâàåò íà íå ñóùåñòâóþùóþ ñòðîêó"
+msgstr "E19: Çàêëàäêà óêàçûâàåò íà íåñóùåñòâóþùóþ ñòðîêó"
# :!~ Restorer
msgid "E20: Mark not set"
@@ -5747,7 +5759,7 @@ msgstr "E23: Îòñóòñòâóþò ñîñåäíèå ôàéëû"
# :!~ Restorer
msgid "E24: No such abbreviation"
-msgstr "E24: Îòñóòñòâóåò óêàçàííîå ñîêðàùåíèå"
+msgstr "E24: Íå ñóùåñòâóåò óêàçàííîãî ñîêðàùåíèÿ"
# :!~ Restorer
msgid "E25: GUI cannot be used: Not enabled at compile time"
@@ -5770,15 +5782,15 @@ msgstr "E28: Íå ñóùåñòâóåò ãðóïïû ïîäñâåòêè ñèíòàêñèñà %s"
# :!~ Restorer
msgid "E29: No inserted text yet"
-msgstr "E29: Ðåãèñòð äëÿ ïîñëåäíåãî âñòàâëåííîãî òåêñòà ïóñò"
+msgstr "E29: Ðåãèñòð ïîñëåäíåãî íàáðàííîãî òåêñòà ïóñò"
# :!~ Restorer
msgid "E30: No previous command line"
-msgstr "E30: Ðåãèñòð äëÿ êîìàíä ðåæèìà êîìàíäíîé ñòðîêè ïóñò"
+msgstr "E30: Ðåãèñòð ïîñëåäíåé êîìàíäû ðåæèìà êîìàíäíîé ñòðîêè ïóñò"
# :!~ Restorer
msgid "E31: No such mapping"
-msgstr "E31: Íå ñóùåñòâóåò êëàâèàòóðíîé êîìàíäû"
+msgstr "E31: Íå ñóùåñòâóåò óêàçàííîé êëàâèàòóðíîé êîìàíäû"
# :!~ Restorer
msgid "E32: No file name"
@@ -5957,7 +5969,7 @@ msgstr "E74: Ïðåâûøåíà äëèíà ðåçóëüòàòà âûïîëíåíèÿ êëàâèàòóðíîé êîìàíäû"
# :!~ Restorer
msgid "E75: Name too long"
-msgstr "E75: Ïðåâûøåíà äëèíà ìàðøðóòà ê ôàéëó"
+msgstr "E75: Ïðåâûøåíà äîïóñòèìàÿ äëèíà ìàðøðóòà ê ôàéëó"
# :!~ Restorer
msgid "E76: Too many ["
@@ -6003,7 +6015,7 @@ msgstr "E85: Óêàçàííûé áóôåð îòñóòñòâóåò â ñïèñêå áóôåðîâ"
# :!~ Restorer
#, c-format
msgid "E86: Buffer %ld does not exist"
-msgstr "E86: Áóôåð ïîä íîìåðîì %ld íå ñóùåñòâóåò"
+msgstr "E86: Íå ñóùåñòâóåò áóôåðà ïîä íîìåðîì %ld"
# :!~ Restorer
msgid "E87: Cannot go beyond last buffer"
@@ -6105,7 +6117,7 @@ msgstr "E108: Íå ñóùåñòâóåò ïåðåìåííîé \"%s\""
# :!~ Restorer
msgid "E109: Missing ':' after '?'"
msgstr ""
-"E109: Îòñóòñòâóåò ñèìâîë äâîåòî÷èÿ ':' â îïåðàòîðå ïðîâåðêè óñëîâèÿ '?'"
+"E109: Îòñóòñòâóåò ñèìâîë äâîåòî÷èÿ ':' â îïåðàòîðå ïðîâåðêè óñëîâèÿ `?`"
# :!~ Restorer
msgid "E110: Missing ')'"
@@ -6285,7 +6297,7 @@ msgstr "E144: Òðåáóåòñÿ óêàçàòü ÷èñëîâîé ïàðàìåòð äëÿ êîìàíäû :z"
msgid "E145: Shell commands and some functionality not allowed in rvim"
msgstr ""
"E145: Êîìàíäû êîìàíäíîé îáîëî÷êè è íåêîòîðàÿ ôóíêöèîíàëüíîñòü îòêëþ÷åíû â "
-"âàðèàíòå ïðîãðàììû rvim"
+"âàðèàíòå ïðîãðàììû rVim"
# :!~ Restorer
msgid "E146: Regular expressions can't be delimited by letters"
@@ -6485,7 +6497,7 @@ msgstr "E185: Íå íàéäåíà öâåòîâàÿ ñõåìà \"%s\""
# :!~ Restorer
msgid "E186: No previous directory"
-msgstr "E186: Ðàíåå èçìåíåíèé êàòàëîãà íå âûïîëíÿëîñü, îñòàëñÿ òåêóùèé êàòàëîã"
+msgstr "E186: Ïåðåõîäû â äðóãîé êàòàëîã ðàíåå íå âûïîëíÿëèñü"
# :!~ Restorer
msgid "E187: Directory unknown"
@@ -6506,7 +6518,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E190: Cannot open \"%s\" for writing"
-msgstr "E190: Íå óäàëîñü îòêðûòü íà çàïèñü ôàéëà \"%s\""
+msgstr "E190: Íå óäàëîñü îòêðûòü íà çàïèñü ôàéë \"%s\""
# :!~ Restorer
msgid "E191: Argument must be a letter or forward/backward quote"
@@ -6543,8 +6555,8 @@ msgid "E197: Cannot set language to \"%s\""
msgstr "E197: Íå óäàëîñü èçìåíèòü ðåãèîíàëüíûå íàñòðîéêè äëÿ \"%s\""
# :!~ Restorer
-msgid "E199: Active window or buffer deleted"
-msgstr "E199: Óäàëåíû àêòèâíîå îêíî èëè áóôåð"
+msgid "E199: Active window or buffer changed or deleted"
+msgstr "E199: Óäàëåíèå èëè èçìåíåíèå òåêóùåãî îêíà èëè áóôåðà"
# :!~ Restorer
msgid "E200: *ReadPre autocommands made the file unreadable"
@@ -6622,12 +6634,12 @@ msgstr "E214: Íó óäàëîñü íàéòè âðåìåííûé ôàéë äëÿ ïðîäîëæåíèÿ îïåðàöèè çàïèñè"
# :!~ Restorer
#, c-format
msgid "E215: Illegal character after *: %s"
-msgstr "E215: Òðåáóåòñÿ ïðîáåëüíûé ñèìâîë ïîñëå ñèìâîëà * â %s"
+msgstr "E215: Òðåáóåòñÿ ïðîáåëüíûé ñèìâîë ïîñëå ñèìâîëà '*' â %s"
# :!~ Restorer
#, c-format
msgid "E216: No such event: %s"
-msgstr "E216: Íå ñóùåñòâóåò ñîáûòèå %s"
+msgstr "E216: Íå ñóùåñòâóåò ñîáûòèÿ %s"
# :!~ Restorer
#, c-format
@@ -6662,12 +6674,12 @@ msgstr "E223: Ïðåâûøåíî êîëè÷åñòâî ïåðåíàçíà÷åíèé êëàâèàòóðíîé êîìàíäû"
# :!~ Restorer
#, c-format
msgid "E224: Global abbreviation already exists for %s"
-msgstr "E224: Îáíàðóæåíî ñóùåñòâóþùåå ãëîáàëüíîå ñîêðàùåíèå %s"
+msgstr "E224: Îáíàðóæåíî ñóùåñòâóþùåå îáùåå ñîêðàùåíèå %s"
# :!~ Restorer
#, c-format
msgid "E225: Global mapping already exists for %s"
-msgstr "E225: Îáíàðóæåíà ñóùåñòâóþùàÿ ãëîáàëüíàÿ êëàâèàòóðíàÿ êîìàíäà %s"
+msgstr "E225: Îáíàðóæåíà ñóùåñòâóþùàÿ îáùàÿ êëàâèàòóðíàÿ êîìàíäà %s"
# :!~ Restorer
#, c-format
@@ -6778,7 +6790,7 @@ msgstr "E249: Äåéñòâèÿ àâòîêîìàíä âûçâàëè èçìåíåíèå ðàñïîëîæåíèÿ îêîí"
# ~!: earlier
#, c-format
msgid "E250: Fonts for the following charsets are missing in fontset %s:"
-msgstr "E250: Â íàáîðå øðèôòîâ %s îòñóòñòâóþò øðèôòû äëÿ êîäèðîâîê:"
+msgstr "E250: Â íàáîðå øðèôòîâ %s îòñóòñòâóþò øðèôòû ñî ñëåäóþùèìè ñèìâîëàìè:"
# #Restorer: îòîáðàæàåòñÿ òîëüêî ïðè ñïåöèôè÷åñêèõ óñëîâèÿõ
# :!~ Restorer
@@ -6819,7 +6831,7 @@ msgstr "E258: Íå óäàëîñü îòïðàâèòü ñîîáùåíèå êëèåíòó"
msgid "E259: No matches found for cscope query %s of %s"
msgstr "E259: Â áàçàõ äàííûõ cscope ïî çàïðîñó %s íå íàéäåí %s"
-# #Restorer: âûâîäèòñÿ ïðè çíà÷åíèè 'verbose' > 0
+# #Restorer: âûâîäèòñÿ ïðè çíà÷åíèè 'verbose'>0
# :!~ Restorer
msgid "E260: Missing name after ->"
msgstr "E260: Íå óêàçàí âûçûâàåìûé ìåòîä â çàïèñè ->"
@@ -6887,7 +6899,7 @@ msgstr "E272: Íåîáðàáîòàííîå èñêëþ÷åíèå"
msgid "E273: Unknown longjmp status %d"
msgstr "E273: Íåîïðåäåë¸ííîå ñîñòîÿíèå %d"
-# #Restorer: âûâîäèòñÿ ïðè 'verbose' > 0
+# #Restorer: âûâîäèòñÿ ïðè 'verbose'>0
# :!~ Restorer
msgid "E274: No white space allowed before parenthesis"
msgstr "E274: Íå äîïóñêàåòñÿ ïðîáåëüíûé ñèìâîë ïåðåä êðóãëûìè ñêîáêàìè"
@@ -6900,7 +6912,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E276: Cannot use function as a method: %s"
-msgstr "E276: Íå äîïóñêàåòñÿ èñïîëüçîâàíèå ôóíêöèè êàê ìåòîä %s"
+msgstr "E276: Äàííàÿ ôóíêöèÿ íå ìîæåò áûòü èñïîëüçîâàíà êàê ìåòîä %s"
# :!~ Restorer
msgid "E277: Unable to read a server reply"
@@ -6908,8 +6920,7 @@ msgstr "E277: Íå óäàëîñü ñ÷èòàòü îòâåò ñåðâåðà"
# :!~ Restorer
msgid "E279: Sorry, ++shell is not supported on this system"
-msgstr ""
-"E279: Àðãóìåíò ++shell íå ïîääåðæèâàåòñÿ äëÿ äàííîé îïåðàöèîííîé ñèñòåìû"
+msgstr "E279: Àðãóìåíò ++shell íå ïîääåðæèâàåòñÿ â äàííîé îïåðàöèîííîé ñèñòåìå"
# :!~ Restorer
#, c-format
@@ -6920,7 +6931,7 @@ msgstr "E282: Íå óäàëîñü ñ÷èòàòü ôàéë \"%s\""
# :!~ Restorer
#, c-format
msgid "E283: No marks matching \"%s\""
-msgstr "E283: Îòñóòñòâóþò çàêëàäêè \"%s\""
+msgstr "E283: Îòñóòñòâóþò çàêëàäêè, ñîâïàäàþùèå ñ \"%s\""
# ~!: earlier
msgid "E284: Cannot set IC values"
@@ -7189,8 +7200,8 @@ msgstr ""
# :!~ Restorer
msgid "E352: Cannot erase folds with current 'foldmethod'"
msgstr ""
-"E352: Íå óäàëîñü îòìåíèòü îòîáðàæåíèå ñòðóêòóðû ïðè òåêóùåì çíà÷åíèè "
-"ïàðàìåòðà 'foldmethod'"
+"E352: Íå óäàëîñü óáðàòü îòîáðàæåíèå ñòðóêòóðû ïðè òåêóùåì çíà÷åíèè ïàðàìåòðà "
+"'foldmethod'"
# :!~ Restorer
#, c-format
@@ -7254,7 +7265,7 @@ msgstr "E366: Çàïðåù¸í ïåðåõîä âî âñïëûâàþùåå îêíî"
# :!~ Restorer
#, c-format
msgid "E367: No such group: \"%s\""
-msgstr "E367: Íå ñóùåñòâóåò ãðóïïà àâòîêîìàíä \"%s\""
+msgstr "E367: Íå ñóùåñòâóåò ãðóïïû àâòîêîìàíä \"%s\""
# :!~ Restorer
#, c-format
@@ -7266,6 +7277,7 @@ msgstr "E368: Ïîëó÷åííûé ÷åðåç ôóíêöèþ libcall() ñèãíàë SIG%s"
msgid "E369: Invalid item in %s%%[]"
msgstr "E369: Íåäîïóñòèìûé ìåòàñèìâîë â êëàññå ôàêóëüòàòèâíûõ ýëåìåíòîâ %s%%[]"
+# #Restorer: Check! Is error number duble!
# :!~ Restorer
#, c-format
msgid "E370: Could not load library %s: %s"
@@ -7278,12 +7290,12 @@ msgstr "E371: Íå íàéäåí ôàéë êîìàíäíîé îáîëî÷êè"
# :!~ Restorer
#, c-format
msgid "E372: Too many %%%c in format string"
-msgstr "E372:  ôîðìàòíîé ñòðîêå ïðåâûøåíî êîëè÷åñòâî %%%c"
+msgstr "E372:  ôîðìàòíîé ñòðîêå ïðåâûøåíî êîëè÷åñòâî ñïåöèôèêàòîðîâ %%%c"
# :!~ Restorer
#, c-format
msgid "E373: Unexpected %%%c in format string"
-msgstr "E373: Â ôîðìàòíîé ñòðîêå íåïðåäâèäåííîå ïîÿâëåíèå %%%c"
+msgstr "E373: Â ôîðìàòíîé ñòðîêå íåïðåäâèäåííîå ïîÿâëåíèå ñïåöèôèêàòîðà %%%c"
# :!~ Restorer
msgid "E374: Missing ] in format string"
@@ -7293,7 +7305,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E375: Unsupported %%%c in format string"
-msgstr "E375: Â ôîðìàòíîé ñòðîêå íå ïîääåðæèâàåòñÿ ýëåìåíò %%%c"
+msgstr "E375: Â ôîðìàòíîé ñòðîêå íå ïîääåðæèâàåòñÿ ñïåöèôèêàòîð %%%c"
# :!~ Restorer
#, c-format
@@ -7303,7 +7315,7 @@ msgstr "E376: Â ôîðìàòíîé ñòðîêå íåäîïóñòèìûé ñïåöèôèêàòîð %%%c"
# :!~ Restorer
#, c-format
msgid "E377: Invalid %%%c in format string"
-msgstr "E377: Â ôîðìàòíîé ñòðîêå íåäîïóñòèìûé ýëåìåíò %%%c"
+msgstr "E377: Â ôîðìàòíîé ñòðîêå íåäîïóñòèìûé ñïåöèôèêàòîð %%%c"
# :!~ Restorer
msgid "E378: 'errorformat' contains no pattern"
@@ -7393,7 +7405,7 @@ msgstr "E397: Òðåáóåòñÿ óêàçàòü íàèìåíîâàíèå ôàéëà"
# :!~ Restorer
#, c-format
msgid "E398: Missing '=': %s"
-msgstr "E398: Íå óêàçàí çíàê ðàâåíñòâà ó ïàðàìåòðîâ êîìàíäû :syntax region %s"
+msgstr "E398: Íå óêàçàí çíàê ðàâåíñòâà â ïàðàìåòðàõ êîìàíäû :syntax region %s"
# :!~ Restorer
#, c-format
@@ -7702,12 +7714,12 @@ msgstr ""
# #Restorer: ïîñëå ñîîáùåíèÿ äîïèñûâàåòñÿ ñèìâîë : è îøèáî÷íàÿ êîìàíäà
# :!~ Restorer
msgid "E464: Ambiguous use of user-defined command"
-msgstr "E464: Íåðàñïîçíàíà ñîçäàííàÿ ïîëüçîâàòåëåì êîìàíäà"
+msgstr "E464: Íå ðàñïîçíàíà ñîçäàííàÿ ïîëüçîâàòåëåì êîìàíäà"
# :!~ Restorer
#, c-format
msgid "E464: Ambiguous use of user-defined command: %s"
-msgstr "E464: Íåðàñïîçíàíà ñîçäàííàÿ ïîëüçîâàòåëåì êîìàíäà %s"
+msgstr "E464: Íå ðàñïîçíàíà ñîçäàííàÿ ïîëüçîâàòåëåì êîìàíäà %s"
# :!~ Restorer
msgid "E465: :winsize requires two number arguments"
@@ -7927,7 +7939,7 @@ msgstr "E503: Êîôå åù¸ íå ãîòîâ"
# :!~ Restorer
msgid "is read-only (cannot override: \"W\" in 'cpoptions')"
msgstr ""
-"ôàéë òîëüêî äëÿ ÷òåíèÿ (÷òîáû çàïèñàòü, óáåðèòå ôëàã \"W\" â 'cpoptions')"
+"ôàéë òîëüêî äëÿ ÷òåíèÿ (÷òîáû çàïèñàòü, óáåðèòå ôëàã 'W' â 'cpoptions')"
# #Restorer: îøèáêà E505:
# :!~ Restorer
@@ -7961,13 +7973,13 @@ msgstr ""
# :!~ Restorer
msgid "E509: Cannot create backup file (add ! to override)"
msgstr ""
-"E509: Íå óäàëîñü ñîçäàòü ðåçåðâíûé ôàéë (÷òîáû èãíîðèðîâàòü, óêàæèòå "
+"E509: Íå óäàëîñü ñîçäàòü ðåçåðâíûé ôàéë (÷òîáû çàïèñàòü, óêàæèòå "
"ìîäèôèêàòîð !)"
# :!~ Restorer
msgid "E510: Can't make backup file (add ! to write anyway)"
msgstr ""
-"E510: Íå óäàëîñü ñîçäàòü ðåçåðâíûé ôàéë (÷òîáû çàïèñàòü, óêàæèòå "
+"E510: Íå óäàëîñü ïîäãîòîâèòü ðåçåðâíûé ôàéë (÷òîáû çàïèñàòü, óêàæèòå "
"ìîäèôèêàòîð !)"
# :!~ Restorer
@@ -7981,8 +7993,8 @@ msgstr "E512: Îøèáêà çàêðûòèÿ ôàéëà ïîñëå îïåðàöèè çàïèñè"
# :!~ Restorer
msgid "E513: Write error, conversion failed (make 'fenc' empty to override)"
msgstr ""
-"E513: Îøèáêà çàïèñè. Ñáîé ïðè èçìåíåíèè êîäèðîâêè òåêñòà (÷òîáû "
-"èãíîðèðîâàòü, ñáðîñüòå ïàðàìåòð 'fenc')"
+"E513: Îøèáêà çàïèñè ïðè èçìåíåíèè êîäèðîâêè òåêñòà (÷òîáû èãíîðèðîâàòü, "
+"ñáðîñüòå ïàðàìåòð 'fenc')"
# :!~ Restorer
#, c-format
@@ -7990,7 +8002,7 @@ msgid ""
"E513: Write error, conversion failed in line %ld (make 'fenc' empty to "
"override)"
msgstr ""
-"E513: Îøèáêà çàïèñè. Ñáîé ïðè èçìåíåíèè êîäèðîâêè òåêñòà â ñòðîêå %ld (÷òîáû "
+"E513: Îøèáêà çàïèñè ïðè èçìåíåíèè êîäèðîâêè òåêñòà â ñòðîêå %ld (÷òîáû "
"èãíîðèðîâàòü, ñáðîñüòå ïàðàìåòð 'fenc')"
# :!~ Restorer
@@ -8281,15 +8293,15 @@ msgstr "E579: Ïðåâûøåíî êîëè÷åñòâî âëîæåíèé áëîêîâ êîìàíä"
# :!~ Restorer
msgid "E580: :endif without :if"
-msgstr "E580: Äëÿ êîìàíäû :endif íåò ñîîòâåòñòâóþùåé êîìàíäû :if"
+msgstr "E580: Äëÿ êîìàíäû :endif îòñóòñòâóåò ïàðíàÿ êîìàíäû :if"
# :!~ Restorer
msgid "E581: :else without :if"
-msgstr "E581: Äëÿ êîìàíäû :else íåò ñîîòâåòñòâóþùåé êîìàíäà :if"
+msgstr "E581: Äëÿ êîìàíäû :else îòñóòñòâóåò ïàðíàÿ êîìàíäà :if"
# :!~ Restorer
msgid "E582: :elseif without :if"
-msgstr "E582: Äëÿ êîìàíäû :elseif íåò ñîîòâåòñòâóþùåé êîìàíäû :if"
+msgstr "E582: Äëÿ êîìàíäû :elseif îòñóòñòâóåò ïàðíàÿ êîìàíäà :if"
# :!~ Restorer
msgid "E583: Multiple :else"
@@ -8313,11 +8325,11 @@ msgstr "E587: Êîìàíäà :break óêàçàíà âíå öèêëà :while èëè :for"
# :!~ Restorer
msgid "E588: :endwhile without :while"
-msgstr "E588: Äëÿ êîìàíäû :endwhile íåò êîìàíäû :while"
+msgstr "E588: Äëÿ êîìàíäû :endwhile îòñóòñòâóåò ïàðíàÿ êîìàíäà :while"
# :!~ Restorer
msgid "E588: :endfor without :for"
-msgstr "E588: Äëÿ êîìàíäû :endfor íåò êîìàíäû :for"
+msgstr "E588: Äëÿ êîìàíäû :endfor îòñóòñòâóåò ïàðíàÿ êîìàíäà :for"
# :!~ Restorer
msgid "E589: 'backupext' and 'patchmode' are equal"
@@ -8342,7 +8354,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E593: Need at least %d lines"
-msgstr "E593: Ìèíèìàëüíîå çíà÷åíèå êîëè÷åñòâà ñòðîê %d"
+msgstr "E593: Ìèíèìàëüíî âîçìîæíîå êîëè÷åñòâî ñòðîê %d"
# :!~ Restorer
#, c-format
@@ -8372,7 +8384,7 @@ msgstr "E599: Íåäîïóñòèìîå çíà÷åíèå ïàðàìåòðà 'imactivatekey'"
# :!~ Restorer
msgid "E600: Missing :endtry"
-msgstr "E600: Äëÿ êîìàíäû :try íå óêàçàíà êîìàíäà :endtry"
+msgstr "E600: Íå óêàçàíà êîìàíäà :endtry"
# :!~ Restorer
msgid "E601: :try nesting too deep"
@@ -8380,11 +8392,11 @@ msgstr "E601: Ïðåâûøåíî êîëè÷åñòâî âëîæåíèé êîìàíä :try"
# :!~ Restorer
msgid "E602: :endtry without :try"
-msgstr "E602: Äëÿ êîìàíäû :endtry íåò ñîîòâåòñòâóþùåé êîìàíäû :try"
+msgstr "E602: Äëÿ êîìàíäû :endtry îòñóòñòâóåò ïàðíàÿ êîìàíäà :try"
# :!~ Restorer
msgid "E603: :catch without :try"
-msgstr "E603: Äëÿ êîìàíäû :catch íå óêàçàíà êîìàíäà :try"
+msgstr "E603: Äëÿ êîìàíäû :catch îòñóòñòâóåò ïàðíàÿ êîìàíäà :try"
# :!~ Restorer
msgid "E604: :catch after :finally"
@@ -8397,7 +8409,7 @@ msgstr "E605: Íå îáðàáîòàííàÿ èñêëþ÷èòåëüíàÿ ñèòóàöèÿ %s"
# :!~ Restorer
msgid "E606: :finally without :try"
-msgstr "E606: Äëÿ êîìàíäû :finally íå óêàçàíà êîìàíäà :try"
+msgstr "E606: Äëÿ êîìàíäû :finally îòñóòñòâóåò ïàðíàÿ êîìàíäà :try"
# :!~ Restorer
msgid "E607: Multiple :finally"
@@ -8459,8 +8471,7 @@ msgstr "E619: Ôàéë íå ÿâëÿåòñÿ äîïóñòèìûì ôàéëîì îïèñàíèé PostScript \"%s\""
# :!~ Restorer
#, c-format
msgid "E620: Unable to convert to print encoding \"%s\""
-msgstr ""
-"E620: Ïðè âûâîäå íà ïå÷àòü íå óäàëîñü âûïîëíèòü èçìåíåíèå êîäèðîâêè íà \"%s\""
+msgstr "E620: Ïðè âûâîäå íà ïå÷àòü íå óäàëîñü ïðåîáðàçîâàòü â êîäèðîâêó \"%s\""
# :!~ Restorer
#, c-format
@@ -8498,7 +8509,7 @@ msgstr "E627: Îòñóòñòâóåò ñèìâîë äâîåòî÷èå â êîìàíäå %s"
#, c-format
msgid "E628: Missing ! or / in: %s"
-msgstr "E628: Îòñóòñòâóåò ñèìâîë ! èëè / â êîìàíäå %s"
+msgstr "E628: Îòñóòñòâóåò ñèìâîë '!' èëè '/' â êîìàíäå %s"
# :!~ Restorer
#, c-format
@@ -8663,7 +8674,7 @@ msgstr ""
# :!~ Restorer
msgid "E669: Unprintable character in group name"
-msgstr "E669: Íå ïå÷àòàåìûé ñèìâîë â íàèìåíîâàíèè ãðóïïû"
+msgstr "E669: Íåïå÷àòàåìûé ñèìâîë â íàèìåíîâàíèè ãðóïïû"
# :!~ Restorer
#, c-format
@@ -8802,7 +8813,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E697: Missing end of List ']': %s"
-msgstr "E697: Íå óêàçàíà çàêðûâàþùàÿ êâàäðàòíàÿ ñêîáêà â äàííûõ òèïà List %s"
+msgstr "E697: Íå óêàçàíà çàêðûâàþùàÿ êâàäðàòíàÿ ñêîáêà â äàííûõ òèï List %s"
# :!~ Restorer
msgid "E698: Variable nested too deep for making a copy"
@@ -8924,7 +8935,7 @@ msgstr ""
#, c-format
msgid "E723: Missing end of Dictionary '}': %s"
msgstr ""
-"E723: Äëÿ òèïà äàííûõ Dictionary íå óêàçàíà çàêðûâàþùàÿ ôèãóðíàÿ ñêîáêà %s"
+"E723: Â òèïå äàííûõ Dictionary íå óêàçàíà çàêðûâàþùàÿ ôèãóðíàÿ ñêîáêà %s"
# :!~ Restorer
msgid "E724: Variable nested too deep for displaying"
@@ -9134,11 +9145,11 @@ msgstr ""
# :!~ Restorer
msgid "E766: Insufficient arguments for printf()"
-msgstr "E766:  ôóíêöèè printf() íåäîñòàòî÷íîå êîëè÷åñòâî àðãóìåíòîâ"
+msgstr "E766: Íåäîñòàòî÷íîå êîëè÷åñòâî àðãóìåíòîâ â ôóíêöèè printf()"
# :!~ Restorer
msgid "E767: Too many arguments for printf()"
-msgstr "E767:  ôóíêöèè printf() ïðåâûøåíî êîëè÷åñòâî àðãóìåíòîâ"
+msgstr "E767: Ïðåâûøåíî êîëè÷åñòâî àðãóìåíòîâ â ôóíêöèè printf()"
# :!~ Restorer
#, c-format
@@ -9324,7 +9335,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E803: ID not found: %d"
-msgstr "E803: Íå íàéäåí èäåíòèôèêàöèîííûé íîìåð %d"
+msgstr "E803: Íå óäàëîñü íàéòè èäåíòèôèêàöèîííûé íîìåð %d"
# :!~ Restorer
#, no-c-format
@@ -9441,8 +9452,7 @@ msgstr "E826: Îøèáêà ïðè ðàñøèôðîâêå ôàéëà èçìåíåíèé %s"
# :!~ Restorer
#, c-format
msgid "E827: Undo file is encrypted: %s"
-msgstr ""
-"E827: Íå ïîääåðæèâàåìûé äàííîé ïðîãðàììîé Vim øèôðîâàííûé ôàéë èçìåíåíèé %s"
+msgstr "E827: Â äàííîé âåðñèè íå ïîääåðæèâàåòñÿ øèôðîâàííûé ôàéë èçìåíåíèé %s"
# :!~ Restorer
#, c-format
@@ -9470,8 +9480,8 @@ msgstr ""
msgid ""
"E833: %s is encrypted and this version of Vim does not support encryption"
msgstr ""
-"E833: Äàííàÿ âåðñèÿ ïðîãðàììû íå ïîääåðæèâàåò øèôðîâàíèå è îáíàðóæåí "
-"øèôðîâàííûé ôàéë %s"
+"E833: Â äàííîé âåðñèè íå ïîääåðæèâàåòñÿ øèôðîâàíèå è îáíàðóæåí øèôðîâàííûé "
+"ôàéë %s"
# :!~ Restorer
msgid "E834: Conflicts with value of 'listchars'"
@@ -9484,14 +9494,12 @@ msgstr "E835: Êîíôëèêò çíà÷åíèé ïàðàìåòðîâ 'ambiwidth' è 'fillchars'"
# :!~ Restorer
msgid "E836: This Vim cannot execute :python after using :py3"
msgstr ""
-"E836:  äàííîé âåðñèè ïðîãðàììû çàïðåù¸í âûçîâ êîìàíäû :python ïîñëå "
-"êîìàíäû :py3"
+"E836:  äàííîé âåðñèè çàïðåù¸í âûçîâ êîìàíäû :python ïîñëå êîìàíäû :py3"
# :!~ Restorer
msgid "E837: This Vim cannot execute :py3 after using :python"
msgstr ""
-"E837:  äàííîé âåðñèè ïðîãðàììû çàïðåù¸í âûçîâ êîìàíäû :py3 ïîñëå êîìàíäû :"
-"python"
+"E837:  äàííîé âåðñèè çàïðåù¸í âûçîâ êîìàíäû :py3 ïîñëå êîìàíäû :python"
# :!~ Restorer
msgid "E838: NetBeans is not supported with this GUI"
@@ -9601,8 +9609,8 @@ msgstr ""
# :!~ Restorer
msgid "E860: Need 'id' and 'type' or 'types' with 'both'"
msgstr ""
-"E860: Åñëè çàäàí êëþ÷ 'both', óêàæèòå çíà÷åíèå êëþ÷åé 'id' è 'type' èëè "
-"'types'"
+"E860: Åñëè çàäàí êëþ÷ \"both\", óêàæèòå çíà÷åíèå êëþ÷åé \"id\" è \"type\" "
+"èëè \"types\""
# :!~ Restorer
msgid "E861: Cannot open a second popup with a terminal"
@@ -9625,8 +9633,8 @@ msgid ""
"E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be "
"used"
msgstr ""
-"E864: Äëÿ ìåòàñèìâîëà \\%#= äîïóñòèìû 0, 1 èëè 2. Ìåõàíèçì ïîèñêà "
-"íàçíà÷àåòñÿ àâòîìàòè÷åñêè"
+"E864: Äëÿ ìåòàñèìâîëà \\%#= äîïóñòèìû 0, 1 èëè 2. Ìåõàíèçì ïîèñêà áûë "
+"íàçíà÷åí àâòîìàòè÷åñêè"
# :!~ Restorer
msgid "E865: (NFA) Regexp end encountered prematurely"
@@ -9719,7 +9727,7 @@ msgstr ""
#, c-format
msgid "E884: Function name cannot contain a colon: %s"
msgstr ""
-"E884: Íå äîïóñêàåòñÿ óêàçàíèå ñèìâîë äâîåòî÷èÿ â íàèìåíîâàíèè ôóíêöèè %s"
+"E884: Íå äîïóñêàåòñÿ óêàçàíèå ñèìâîëà äâîåòî÷èå â íàèìåíîâàíèè ôóíêöèè %s"
# :!~ Restorer
#, c-format
@@ -10112,7 +10120,8 @@ msgstr "E966: Íåäîïóñòèìûé íîìåð ñòðîêè %ld"
# :!~ Restorer
msgid "E968: Need at least one of 'id' or 'type'"
-msgstr "E968: Òðåáóåòñÿ óêàçàòü çíà÷åíèå êëþ÷à 'id' èëè çíà÷åíèå êëþ÷à 'type'"
+msgstr ""
+"E968: Òðåáóåòñÿ óêàçàòü çíà÷åíèå êëþ÷à \"id\" èëè çíà÷åíèå êëþ÷à \"type\""
# :!~ Restorer
#, c-format
@@ -10220,7 +10229,7 @@ msgstr "E990: Íå óêàçàí çàâåðøàþùèé ìàðêåð '%s'"
# :!~ Restorer
msgid "E991: Cannot use =<< here"
-msgstr "E991: Îïåðàòîð =<< íå ìîæåò áûòü ïðèìåí¸í"
+msgstr "E991: Îïåðàòîð `=<<` íå ìîæåò áûòü ïðèìåí¸í"
# :!~ Restorer
msgid "E992: Not allowed in a modeline when 'modelineexpr' is off"
@@ -10243,28 +10252,34 @@ msgstr "E995: Íå äîïóñêàåòñÿ èçìåíåíèå çíà÷åíèÿ ñóùåñòâóþùåé ïåðåìåííîé"
# :!~ Restorer
msgid "E996: Cannot lock a range"
-msgstr "E996: Íå äîïóñêàåòñÿ áëîêèðîâêà äëÿ çíà÷åíèé äèàïàçîíà"
+msgstr ""
+"E996: Äëÿ çíà÷åíèé äèàïàçîíà íå ìîæåò áûòü èçìåíåíî ñîñòîÿíèå áëîêèðîâêè"
# :!~ Restorer
msgid "E996: Cannot lock an option"
-msgstr "E996: Íå äîïóñêàåòñÿ áëîêèðîâêà äëÿ çíà÷åíèé ïàðàìåòðîâ"
+msgstr ""
+"E996: Äëÿ çíà÷åíèé ïàðàìåòðîâ íå ìîæåò áûòü èçìåíåíî ñîñòîÿíèå áëîêèðîâêè"
# :!~ Restorer
msgid "E996: Cannot lock a list or dict"
-msgstr "E996: Íå äîïóñêàåòñÿ áëîêèðîâêà äëÿ çíà÷åíèé ñïèñêà èëè ñëîâàðÿ"
+msgstr ""
+"E996: Äëÿ çíà÷åíèé ñïèñêà èëè ñëîâàðÿ íå ìîæåò áûòü èçìåíåíî ñîñòîÿíèå "
+"áëîêèðîâêè"
# :!~ Restorer
msgid "E996: Cannot lock an environment variable"
-msgstr "E996: Íå äîïóñêàåòñÿ áëîêèðîâêà äëÿ çíà÷åíèé ïåðåìåííûõ îêðóæåíèÿ"
+msgstr ""
+"E996: Äëÿ çíà÷åíèé ïåðåìåííûõ îêðóæåíèÿ íå ìîæåò áûòü èçìåíåíî ñîñòîÿíèå "
+"áëîêèðîâêè"
# :!~ Restorer
msgid "E996: Cannot lock a register"
-msgstr "E996: Íå äîïóñêàåòñÿ áëîêèðîâêà äëÿ äàííûõ ðåãèñòðà"
+msgstr "E996: Äëÿ äàííûõ ðåãèñòðà íå ìîæåò áûòü èçìåíåíî ñîñòîÿíèå áëîêèðîâêè"
# :!~ Restorer
#, c-format
msgid "E997: Tabpage not found: %d"
-msgstr "E997: Íå íàéäåíà âêëàäêà ïîä íîìåðîì %d"
+msgstr "E997: Íå óäàëîñü íàéòè âêëàäêó ïîä íîìåðîì %d"
# :!~ Restorer
#, c-format
@@ -10280,7 +10295,7 @@ msgstr "E999:  ïðîãðàììå íå ïîääåðæèâàåòñÿ îáðàáîò÷èê êîìàíä âåðñèè %d"
# :!~ Restorer
#, c-format
msgid "E1001: Variable not found: %s"
-msgstr "E1001: Íå íàéäåíà ïåðåìåííàÿ %s"
+msgstr "E1001: Íå óäàëîñü íàéòè ïåðåìåííóþ %s"
# :!~ Restorer
#, c-format
@@ -10308,7 +10323,8 @@ msgstr "E1006: Ïåðåìåííàÿ %s èñïîëüçóåòñÿ êàê àðãóìåíò ôóíêöèè"
# :!~ Restorer
msgid "E1007: Mandatory argument after optional argument"
msgstr ""
-"E1007: Îáÿçàòåëüíûå àðãóìåíòû óêàçûâàòüñÿ ïåðåä íåîáÿçàòåëüíûì àðãóìåíòîì"
+"E1007: Îáÿçàòåëüíûå àðãóìåíòû äîëæíû óêàçûâàòüñÿ ïåðåä íåîáÿçàòåëüíûì "
+"àðãóìåíòîì"
# :!~ Restorer
#, c-format
@@ -10462,7 +10478,7 @@ msgstr ""
#, c-format
msgid "E1036: %c requires number or float arguments"
msgstr ""
-"E1036: Òðåáóåòñÿ òèï îïåðàíäîâ Number èëè Float äëÿ âûïîëíåíèÿ îïåðàöèè %c"
+"E1036: Òèï îïåðàíäîâ äîëæåí áûòü Number èëè Float äëÿ âûïîëíåíèÿ îïåðàöèè %c"
# :!~ Restorer
#, c-format
@@ -10520,7 +10536,7 @@ msgstr "E1049: Êîìïîíåíò íå ÿâëÿåòñÿ ýêñïîðòèðóåìûì %s"
# :!~ Restorer
#, c-format
msgid "E1050: Colon required before a range: %s"
-msgstr "E1050: Òðåáóåòñÿ ñèìâîë äâîåòî÷èÿ ïåðåä çíà÷åíèåì äèàïàçîíà %s"
+msgstr "E1050: Òðåáóåòñÿ ñèìâîë äâîåòî÷èå ïåðåä çíà÷åíèåì äèàïàçîíà %s"
# :!~ Restorer
msgid "E1051: Wrong argument type for +"
@@ -10553,7 +10569,7 @@ msgstr "E1056: Îæèäàëñÿ òèï äàííûõ %s"
# :!~ Restorer
msgid "E1057: Missing :enddef"
-msgstr "E1057: Íå óêàçàíà êîìàíäà :enddef äëÿ êîìàíäû :def"
+msgstr "E1057: Íå óêàçàíà êîìàíäà :enddef"
# :!~ Restorer
msgid "E1058: Function nesting too deep"
@@ -10562,7 +10578,7 @@ msgstr "E1058: Ïðåâûøåíî êîëè÷åñòâî âëîæåííûõ ôóíêöèé"
# :!~ Restorer
#, c-format
msgid "E1059: No white space allowed before colon: %s"
-msgstr "E1059: Çàïðåù¸í ïðîáåëüíûé ñèìâîë ïåðåä ñèìâîëîì äâîåòî÷èÿ â %s"
+msgstr "E1059: Çàïðåù¸í ïðîáåëüíûé ñèìâîë ïåðåä ñèìâîëîì äâîåòî÷èå â %s"
# :!~ Restorer
#, c-format
@@ -10573,7 +10589,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E1061: Cannot find function %s"
-msgstr "E1061: Íå íàéäåíà ôóíêöèÿ %s"
+msgstr "E1061: Íå óäàëîñü íàéòè ôóíêöèþ %s"
# :!~ Restorer
msgid "E1062: Cannot index a Number"
@@ -10751,7 +10767,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E1102: Lambda function not found: %s"
-msgstr "E1102: Íå íàéäåíà ëÿìáäà-ôóíêöèÿ %s"
+msgstr "E1102: Íå óäàëîñü íàéòè ëÿáäà-ôóíêöèþ %s"
# :!~ Restorer
msgid "E1103: Dictionary not set"
@@ -10770,7 +10786,7 @@ msgstr "E1105: Íå äîïóñêàåòñÿ ïðåîáðàçîâàíèå ê ñòðîêîâîìó òèïó äëÿ %s"
#, c-format
msgid "E1106: One argument too many"
msgid_plural "E1106: %d arguments too many"
-msgstr[0] "E1106: Â ôóíêöèþ ïåðåäàíî íà îäèí àðãóìåíò áîëüøå"
+msgstr[0] "E1106: Â ôóíêöèþ ïåðåäàíî íà %d àðãóìåíò áîëüøå"
msgstr[1] "E1106: Â ôóíêöèþ ïåðåäàíî íà %d àðãóìåíòà áîëüøå"
msgstr[2] "E1106: Â ôóíêöèþ ïåðåäàíî íà %d àðãóìåíòîâ áîëüøå"
@@ -10860,7 +10876,7 @@ msgstr "E1124: Êîìàíäà \"%s\" äîïóñêàåòñÿ òîëüêî â êîìàíäíîì ôàéëå Vim9"
# :!~ Restorer
msgid "E1125: Final requires a value"
-msgstr "E1125: Òðåáóåòñÿ óêàçàòü çíà÷åíèå äëÿ êîìàíäû :final"
+msgstr "E1125: Òðåáóåòñÿ çàäàòü çíà÷åíèå äëÿ ôèíàëèçèðîâàííîé ïåðåìåííîé"
# :!~ Restorer
msgid "E1126: Cannot use :let in Vim9 script"
@@ -10911,7 +10927,7 @@ msgstr "E1135: Îæèäàëîñü ëîãè÷åñêîå çíà÷åíèå, à ïîëó÷åí String \"%s\""
# :!~ Restorer
msgid "E1136: <Cmd> mapping must end with <CR> before second <Cmd>"
msgstr ""
-"E1136: Íàçíà÷àåìàÿ ÷åðåç <Cmd> êîìàíäà íå çàâåðøàåòñÿ <CR> ïåðåä ñëåäóþùåé "
+"E1136: Íàçíà÷àåìàÿ êîìàíäà <Cmd> äîëæíà çàâåðøàåòñÿ <CR> ïåðåä ñëåäóþùåé "
"<Cmd>"
# :!~ Restorer
@@ -10993,8 +11009,7 @@ msgstr "E1154: Îáíàðóæåíà ïîïûòêà äåëåíèÿ íà íîëü"
# :!~ Restorer
msgid "E1155: Cannot define autocommands for ALL events"
-msgstr ""
-"E1155: Íå äîïóñêàåòñÿ îäíîâðåìåííî çàäàâàòü àâòîêîìàíäû äëÿ âñåõ ñîáûòèé"
+msgstr "E1155: Íå äîïóñêàåòñÿ îïðåäåëåíèå àâòîêîìàíä ñðàçó äëÿ âñåõ ñîáûòèé"
# :!~ Restorer
msgid "E1156: Cannot change the argument list recursively"
@@ -11069,7 +11084,7 @@ msgstr "E1168: Ýòîò àðãóìåíò óæå îáúÿâëåí â êîìàíäíîì ôàéëå %s"
# :!~ Restorer
#, c-format
msgid "E1169: Expression too recursive: %s"
-msgstr "E1169: Âûðàæåíèå ñëèøêîì ðåêóðñèâíî %s"
+msgstr "E1169: Áîëüøàÿ ðåêóðñèâíîñòü âûðàæåíèÿ %s"
# :!~ Restorer
msgid "E1170: Cannot use #{ to start a comment"
@@ -11120,8 +11135,8 @@ msgid ""
"E1179: Failed to extract PWD from %s, check your shell's config related to "
"OSC 7"
msgstr ""
-"Íå óäàëîñü èçâëå÷ü çíà÷åíèå òåêóùåãî ðàáî÷åãî êàòàëîãà èç %s. Ïðîâåðüòå "
-"íàñòðîéêè êîìàíäíîé îáîëî÷êè OSC 7"
+"Íå óäàëîñü èçâëå÷ü çíà÷åíèå ðàáî÷åãî êàòàëîãà èç %s. Ïðîâåðüòå íàñòðîéêè "
+"êîìàíäíîé îáîëî÷êè OSC 7"
# :!~ Restorer
#, c-format
@@ -11159,7 +11174,7 @@ msgstr "E1186: Âûðàæåíèå íå âîçâðàùàåò çíà÷åíèå %s"
# :!~ Restorer
msgid "E1187: Failed to source defaults.vim"
-msgstr "E1187: Îøèáêà ïðè îáðàáîòêå ôàéëà defaults.vim"
+msgstr "E1187: Ïðîèçîøëà îøèáêà ïðè îáðàáîòêå ôàéëà defaults.vim"
# :!~ Restorer
msgid "E1188: Cannot open a terminal from the command line window"
@@ -11175,7 +11190,7 @@ msgstr "E1189: Íå äîïóñêàåòñÿ óêàçàíèå ïîñëå êîìàíäû :legacy êîìàíäû %s"
#, c-format
msgid "E1190: One argument too few"
msgid_plural "E1190: %d arguments too few"
-msgstr[0] "E1190: Â ôóíêöèþ ïåðåäàíî íà îäèí àðãóìåíò ìåíüøå"
+msgstr[0] "E1190: Â ôóíêöèþ ïåðåäàíî íà %d àðãóìåíò ìåíüøå"
msgstr[1] "E1190: Â ôóíêöèþ ïåðåäàíî íà %d àðãóìåíòà ìåíüøå"
msgstr[2] "E1190: Â ôóíêöèþ ïåðåäàíî íà %d àðãóìåíòîâ ìåíüøå"
@@ -11238,7 +11253,7 @@ msgstr "E1203: Íå äîïóñêàåòñÿ ñèìâîë òî÷êè äëÿ òèïà äàííûõ %s â %s"
# :!~ Restorer
#, c-format
msgid "E1204: No Number allowed after .: '\\%%%c'"
-msgstr "E1204: Çàïðåùåíî óêàçàíèå ÷èñëà ïîñëå ñèìâîëà òî÷êè â '\\%%%c'"
+msgstr "E1204: Çàïðåùåíî óêàçàíèå ÷èñëà ïîñëå ñèìâîëà òî÷êè â \\%%%c"
# :!~ Restorer
msgid "E1205: No white space allowed between option and"
@@ -11404,7 +11419,7 @@ msgstr "E1236: Íå äîïóñêàåòñÿ îáðàùåíèå ê %s. Ýòî èìïîðòèðîâàííûé êîìïîíåíò"
# :!~ Restorer
#, c-format
msgid "E1237: No such user-defined command in current buffer: %s"
-msgstr "E1237: Äëÿ òåêóùåãî áóôåðà íå îáíàðóæåíà êîìàíäà ïîëüçîâàòåëÿ %s"
+msgstr "E1237: Äëÿ òåêóùåãî áóôåðà íå ñóùåñòâóåò êîìàíäû ïîëüçîâàòåëÿ %s"
# :!~ Restorer
#, c-format
@@ -11428,7 +11443,8 @@ msgstr "E1241: Â êîìàíäå óêàçàí íåäîïóñòèìûé ðàçäåëèòåëü ïàðàìåòðîâ %s"
# :!~ Restorer
#, c-format
msgid "E1242: No white space allowed before separator: %s"
-msgstr "E1242: Çàïðåù¸í ïðîáåë ïåðåä ðàçäåëèòåëåì ïàðàìåòðîâ â êîìàíäå %s"
+msgstr ""
+"E1242: Çàïðåù¸í ïðîáåëüíûé ñèìâîë ïåðåä ðàçäåëèòåëåì ïàðàìåòðîâ â êîìàíäå %s"
# :!~ Restorer
msgid "E1243: ASCII code not in 32-127 range"
@@ -11484,8 +11500,7 @@ msgstr ""
# :!~ Restorer
msgid "E1255: <Cmd> mapping must end with <CR>"
-msgstr ""
-"E1255: Íàçíà÷åííàÿ ÷åðåç <Cmd> êîìàíäà äîëæíà çàâåðøàòüñÿ ñèìâîëàìè <CR>"
+msgstr "E1255: Íàçíà÷åííàÿ êîìàíäà <Cmd> äîëæíà çàâåðøàòüñÿ ñèìâîëàìè <CR>"
# :!~ Restorer
#, c-format
@@ -11512,7 +11527,7 @@ msgstr "E1259: Íå óêàçàíî íàèìåíîâàíèå ïîñëå èìïîðòèðóåìîãî êîìïîíåíòà %s"
# :!~ Restorer
#, c-format
msgid "E1260: Cannot unlet an imported item: %s"
-msgstr "E1260: Íå äîïóñêàåòñÿ óäàëåíèå êîìïîíåíò â èìïîðòèðîâàííûõ äàííûõ %s"
+msgstr "E1260: Íå äîïóñêàåòñÿ óäàëåíèå êîìïîíåíòà â èìïîðòèðîâàííûõ äàííûõ %s"
# :!~ Restorer
msgid "E1261: Cannot import .vim without using \"as\""
@@ -11527,7 +11542,7 @@ msgstr "E1262: Íå äîïóñêàåòñÿ ïîâòîðíîå èìïîðòèðîâàíèå êîìàíäíîãî ôàéëà %s"
# :!~ Restorer
msgid "E1263: Cannot use name with # in Vim9 script, use export instead"
msgstr ""
-"E1263: Íå äîïóñêàþòñÿ íàèìåíîâàíèÿ ñ ñèìâîëîì #. Â êîìàíäíûõ ôàéëàõ Vim9 "
+"E1263: Íå äîïóñêàþòñÿ íàèìåíîâàíèÿ ñ ñèìâîëîì '#'. Â êîìàíäíûõ ôàéëàõ Vim9 "
"èñïîëüçóåòñÿ ýêñïîðò"
# :!~ Restorer
@@ -11754,8 +11769,7 @@ msgstr "E1306: Ïðåâûøåíî êîëè÷åñòâî âëîæåííûõ öèêëîâ"
#, c-format
msgid "E1307: Argument %d: Trying to modify a const %s"
msgstr ""
-"E1307: Îáíàðóæåíà ïîïûòêà èçìåíåíèÿ êîíñòàíòíîãî çíà÷åíèÿ %2$s ó àðãóìåíòà "
-"íîìåð %1$d"
+"E1307: Äëÿ àðãóìåíòà íîìåð %d ïîïûòêà èçìåíåíèÿ êîíñòàíòíîãî çíà÷åíèÿ %s"
# :!~ Restorer
msgid "E1308: Cannot resize a window in another tab page"
@@ -11841,12 +11855,12 @@ msgstr "E1325: Ó êëàññà \"%2$s\" îòñóòñòâóåò ìåòîä \"%1$s\""
# :!~ Restorer
#, c-format
msgid "E1326: Variable \"%s\" not found in object \"%s\""
-msgstr "E1326: Ó îáúåêòà \"%s\" îòñóòñòâóåò ïåðåìåííàÿ \"%s\""
+msgstr "E1326: Ó îáúåêòà \"%2$s\" îòñóòñòâóåò ïåðåìåííàÿ \"%1$s\""
# :!~ Restorer
#, c-format
msgid "E1327: Object required, found %s"
-msgstr "E1327: Îæèäàëñÿ Object, à ïîëó÷åí %s"
+msgstr "E1327: Îæèäàëñÿ òèï äàííûõ Object, à ïîëó÷åí %s"
# :!~ Restorer
#, c-format
@@ -11922,7 +11936,7 @@ msgstr "E1343: Íàèìåíîâàíèå èíòåðôåéñà äîëæíî íà÷èíàòüñÿ ñ ïðîïèñíîé áóêâû %s"
# :!~ Restorer
msgid "E1344: Cannot initialize a variable in an interface"
-msgstr "E1344: Íå äîïóñêàåòñÿ èíèöèàëèçèðîâàòü ïåðåìåííûå â èíòåðôåéñå"
+msgstr "E1344: Íå äîïóñêàåòñÿ èíèöèàëèçàöèÿ ïåðåìåííûõ â èíòåðôåéñå"
# :!~ Restorer
#, c-format
@@ -12100,7 +12114,7 @@ msgstr "E1380: Èíòåðôåéñû íå ïîääåðæèâàþò çàùèù¸ííûå ìåòîäû"
# :!~ Restorer
msgid "E1381: Interface cannot use \"implements\""
-msgstr "E1381: Äëÿ èíòåðôåéñà íåïðèìåíèìî êëþ÷åâîå ñëîâî \"implements\""
+msgstr "E1381: Ê èíòåðôåéñó íåïðèìåíèìî êëþ÷åâîå ñëîâî \"implements\""
# :!~ Restorer
#, c-format
@@ -12181,7 +12195,7 @@ msgstr "E1395: Íå äîïóñêàåòñÿ èçìåíåíèå ïñåâäîíèìà òèïà \"%s\""
# :!~ Restorer
#, c-format
msgid "E1396: Type alias \"%s\" already exists"
-msgstr "E1396: Ïñåâäîíèì òèïà óæå îïðåäåë¸í \"%s\""
+msgstr "E1396: Ïñåâäîíèì òèïà óæå ñóùåñòâóåò \"%s\""
# :!~ Restorer
msgid "E1397: Missing type alias name"
@@ -12246,7 +12260,7 @@ msgstr "E1408: Èíòåðôåéñû íå ïîääåðæèâàþò ôèíàëèçèðîâàííûå ïåðåìåííûå"
msgid "E1409: Cannot change read-only variable \"%s\" in class \"%s\""
msgstr ""
"E1409: Íå äîïóñêàåòñÿ èçìåíåíèå äîñòóïíîé òîëüêî äëÿ ÷òåíèÿ ïåðåìåííîé "
-"\"%s\" â êëàññå \"%s\""
+"\"%s\" êëàññà \"%s\""
# :!~ Restorer
msgid "E1410: Const variable not supported in an interface"
@@ -12316,6 +12330,16 @@ msgstr ""
msgid "E1510: Value too large: %s"
msgstr "E1510: Ïðåâûøåíà äîïóñòèìàÿ âåëè÷èíà â çíà÷åíèè %s"
+# :!~ Restorer
+#, c-format
+msgid "E1511: Wrong number of characters for field \"%s\""
+msgstr "E1511:  äàííîì ïîëå óêàçàíî íåäîïóñòèìîå êîëè÷åñòâî ñèìâîëîâ \"%s\""
+
+# :!~ Restorer
+#, c-format
+msgid "E1512: Wrong character width for field \"%s\""
+msgstr "E1512: Â äàííîì ïîëå íå ïîääåðæèâàþòñÿ ïîëíîøèðèííûå ñèìâîëû \"%s\""
+
# #Restorer: âûâîäèòñÿ, íàïðèìåð, ïî êîìàíäå `CTRL+g`, `g CTRL+g` è ò. ï.
# :!~ Restorer
msgid "--No lines in buffer--"
@@ -12366,6 +12390,7 @@ msgid "float"
msgstr "float"
# :!~ Restorer
+#.
msgid "search hit TOP, continuing at BOTTOM"
msgstr "Ïîèñê áóäåò ïðîäîëæåí îò ÍÈÆÍÅÉ ÃÐÀÍÈÖÛ äîêóìåíòà"
@@ -12405,7 +12430,8 @@ msgstr "íå óäàëîñü âûïîëíèòü äîáàâëåíèå â ñëîâàðü êëþ÷à %s"
#, c-format
msgid "index must be int or slice, not %s"
msgstr ""
-"èíäåêñ óêàçûâàåòñÿ öåëûì ÷èñëîì èëè êàê äèàïàçîí. Íåäîïóñòèìûé èíäåêñ %s"
+"èíäåêñ óêàçûâàåòñÿ êàê öåëîå ÷èñëî èëè êàê äèàïàçîí ÷èñåë. Íåäîïóñòèìûé "
+"èíäåêñ %s"
# :!~ Restorer
#, c-format
@@ -12456,7 +12482,7 @@ msgstr "çàäàíî íåäîïóñòèìîå ñâîéñòâî %s"
# :!~ Restorer
msgid "failed to change directory"
-msgstr "ñáîé ïðè ñìåíå êàòàëîãà"
+msgstr "ïðîèçîø¸ë ñáîé ïðè ñìåíå êàòàëîãà"
# :!~ Restorer
#, c-format
@@ -12514,8 +12540,8 @@ msgstr "èíäåêñ ñïèñêà âûõîäèò çà ãðàíèöû äèàïàçîíà"
#, c-format
msgid "internal error: failed to get Vim list item %d"
msgstr ""
-"âíóòðåííÿÿ îøèáêà. Íå óäàëîñü ïîëó÷èòü ó îáúåêòà Vim.List ýëåìåíò ñ èíäåêñîì "
-"%d"
+"âíóòðåííÿÿ îøèáêà. Íå óäàëîñü ïîëó÷èòü èç îáúåêòà Vim.List ýëåìåíò ñ "
+"èíäåêñîì %d"
# :!~ Restorer
msgid "slice step cannot be zero"
@@ -12593,8 +12619,8 @@ msgstr "íå äîïóñêàåòñÿ ñáðîñ ê íà÷àëüíûì çíà÷åíèÿì ó îáùåãî ïàðàìåòðà %s"
#, c-format
msgid "unable to unset option %s which does not have global value"
msgstr ""
-"íå äîïóñêàåòñÿ ñáðîñ ê íà÷àëüíûì çíà÷åíèÿì, åñëè íå óñòàíîâëåíî ãëîáàëüíîå "
-"çíà÷åíèå ó ïàðàìåòðà %s"
+"íå äîïóñêàåòñÿ ñáðîñ ê íà÷àëüíûì çíà÷åíèÿì, åñëè íå óñòàíîâëåíî çíà÷åíèå ó "
+"îáùåãî ïàðàìåòðà %s"
# :!~ Restorer
msgid "attempt to refer to deleted tab page"
@@ -12765,7 +12791,7 @@ msgstr ""
"Ôàéëû ðåäàêòîðà Vim (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n"
# #Restorer: èñïîëüçóåòñÿ äëÿ ôàéëà desktop
-# ~!: earlier
+# :!~ Restorer
msgid "GVim"
msgstr "gVim"
@@ -12791,15 +12817,15 @@ msgstr "Vim"
# :!~ Restorer
msgid "(local to window)"
-msgstr "(îáëàñòü äåéñòâèÿ: ëîêàëüíî äëÿ îêíà)"
+msgstr "(îáëàñòü äåéñòâèÿ: òîëüêî äëÿ îêíà)"
# :!~ Restorer
msgid "(local to buffer)"
-msgstr "(îáëàñòü äåéñòâèÿ: ëîêàëüíî äëÿ áóôåðà)"
+msgstr "(îáëàñòü äåéñòâèÿ: òîëüêî äëÿ áóôåðà)"
# :!~ Restorer
msgid "(global or local to buffer)"
-msgstr "(îáëàñòü äåéñòâèÿ: ãëîáàëüíàÿ èëè ëîêàëüíî äëÿ áóôåðà)"
+msgstr "(îáëàñòü äåéñòâèÿ: îáùèé èëè òîëüêî äëÿ áóôåðà)"
# :!~ Restorer
msgid ""
@@ -12898,7 +12924,7 @@ msgid ""
"many jump commands move the cursor to the first non-blank\n"
"character of a line"
msgstr ""
-"óñòàíîâêà êàðåòêè íà ïåðâûé íå ïðîáåëüíûé ñèìâîë â ñòðîêå\n"
+"óñòàíîâêà êàðåòêè íà ïåðâûé íåïðîáåëüíûé ñèìâîë â ñòðîêå\n"
"ïîñðåäñòâîì êîìàíä ïåðåìåùåíèÿ"
# :!~ Restorer
@@ -13119,7 +13145,7 @@ msgid ""
"include \"uhex\" to show unprintable characters as a hex number"
msgstr ""
"\"lastline\" — èíäèêàöèÿ, åñëè ñòðîêà ÷àñòè÷íî îòîáðàæåíà â îêíå\n"
-"\"uhex\" — ïîêàç íåïå÷àòàåìûõ ñèìâîëîâ êàê øåñòíàäöàòåðè÷íûå ÷èñëà"
+"\"uhex\" — ïîêàç íåïå÷àòàåìûõ ñèìâîëîâ êàê øåñòíàäöàòåðè÷íîå çíà÷åíèå"
# :!~ Restorer
msgid "characters to use for the status line, folds and filler lines"
@@ -13462,7 +13488,7 @@ msgstr "èñïîëüçóåìûé òåðìèíàëîì ïðîòîêîë îáìåíà äàííûõ ñ êëàâèàòóðîé"
# :!~ Restorer
msgid "recognize keys that start with <Esc> in Insert mode"
-msgstr "ðàñïîçíàâàòü â ðåæèìå âñòàâêè êîäû êëàâèø íà÷èíàþùèåñÿ ñ <ESC>"
+msgstr "ðàñïîçíàâàòü â ðåæèìå âñòàâêè êîäû êëàâèø íà÷èíàþùèåñÿ ñ <Esc>"
# :!~ Restorer
msgid "minimal number of lines to scroll at a time"
@@ -13600,7 +13626,7 @@ msgstr "îáëàñòü ýêðàíà, îñòàþùàÿñÿ íå çàíÿòîé îêíîì ïðîãðàììû (â ïèêñåëÿõ)"
# :!~ Restorer
msgid "list of ASCII characters that can be combined into complex shapes"
-msgstr "ïåðå÷åíü ñèìâîëîâ â êîäèðîâêå ASCII, èñïîëüçóåìûõ â ñîñòàâíûõ ñèìâîëàõ"
+msgstr "ïåðå÷åíü ñèìâîëîâ êîäèðîâêè ASCII, èñïîëüçóåìûõ â ñîñòàâíûõ ñèìâîëàõ"
# :!~ Restorer
msgid "options for text rendering"
@@ -13973,7 +13999,7 @@ msgstr ""
# :!~ Restorer
msgid "a <Tab> in an indent inserts 'shiftwidth' spaces"
msgstr ""
-"ïðè íàæàòèè êëàâèøè <TAB> â íà÷àëå ñòðîêè áóäåò âñòàâêà ïðîáåëîâ\n"
+"ïðè íàæàòèè êëàâèøè <TAB> , â íà÷àëå ñòðîêè áóäåò âñòàâêà ïðîáåëîâ\n"
"êàê çàäàíî â ïàðàìåòðå 'shiftwidth'"
# :!~ Restorer
@@ -14058,11 +14084,11 @@ msgstr "Ñòðóêòóðèðîâàíèå òåêñòà"
# :!~ Restorer
msgid "unset to display all folds open"
-msgstr "åñëè íå óñòàíîâëåíî, òî ðàçâåðíóòü âñå ñâ¸ðíóòûå ñòðîêè"
+msgstr "åñëè íå óñòàíîâëåíî, òî ðàçâåðíóòü âñå ñâ¸ðíóòûå áëîêè"
# :!~ Restorer
msgid "folds with a level higher than this number will be closed"
-msgstr "ñòðîêè ñòðóêòóðû ñ óðîâíåì âûøå óêàçàííîãî áóäóò ñâ¸ðíóòû"
+msgstr "ñòðîêè ñòðóêòóðû, ñ óðîâíåì âûøå óêàçàííîãî, áóäóò ñâ¸ðíóòû"
# :!~ Restorer
msgid "value for 'foldlevel' when starting to edit a file"
@@ -14225,7 +14251,7 @@ msgstr "ôîðìàòû ôàéëà, êîòîðûå ïðîâåðÿþòñÿ ïåðåä íà÷àëîì ðåäàêòèðîâàíèÿ"
# :!~ Restorer
msgid "obsolete, use 'fileformat'"
-msgstr "âûâåäåí èç óïîòðåáëåíèÿ, äåéñòâóåò ïàðàìåòð 'fileformat'"
+msgstr "áîëüøå íå ïðèìåíÿåòñÿ, èñïîëüçîâàòü ïàðàìåòð 'fileformat'"
# :!~ Restorer
msgid "obsolete, use 'fileformats'"
diff --git a/src/po/ru.po b/src/po/ru.po
index 9e2e3d8..d4b7d6b 100644
--- a/src/po/ru.po
+++ b/src/po/ru.po
@@ -21,10 +21,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: RuVim_0.9002185.251223\n"
+"Project-Id-Version: RuVim_0.9010059.260124\n"
"Report-Msgid-Bugs-To: The Vim Project, <vim-dev@vim.org>\n"
-"POT-Creation-Date: 2023-12-25 16:17+0300\n"
-"PO-Revision-Date: 2023-12-25 18:57+0300\n"
+"POT-Creation-Date: 2024-01-26 14:54+0300\n"
+"PO-Revision-Date: 2024-01-26 14:57+0300\n"
"Last-Translator: Restorer, <restorer@mail2k.ru>\n"
"Language-Team: RuVim, https://github.com/RestorerZ/RuVim\n"
"Language: ru_RU\n"
@@ -233,6 +233,7 @@ msgstr "Окончание"
msgid "Top"
msgstr "Ðачало"
+# #Restorer: локализуемое значение процента
# :!~ Restorer
#, c-format
msgid "%d%%"
@@ -266,6 +267,10 @@ msgstr " (файл %d из %d"
msgid " (file (%d) of %d)"
msgstr " (файл (%d) из %d"
+# :!~ Restorer
+msgid "[Command Line]"
+msgstr "[ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока]"
+
# #Restorer: в Ñтроке ÑоÑтоÑÐ½Ð¸Ñ Ð´Ð»Ñ Ð±ÑƒÑ„ÐµÑ€Ð° Ñ Ð¾ÐºÐ½Ð¾Ð¼ запроÑа и уведомлениÑ
# :!~ Restorer
msgid "[Prompt]"
@@ -551,7 +556,8 @@ msgstr "аргумента функции extend()"
#, c-format
msgid "Not enough memory to use internal diff for buffer \"%s\""
msgstr ""
-"Ð’Ñтроенному механизму ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтаточно памÑти на Ñчитывание буфера \"%s\""
+"Ð’Ñтроенному механизму ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтаточно памÑти на Ñчитывание буфера "
+"\"%s\""
# #Restorer: выводитÑÑ Ð² заголовке окна выбора файла
# :!~ Restorer
@@ -699,6 +705,7 @@ msgstr ""
# #Restorer: иÑпользуетÑÑ Ð² функции confirm() еÑли не заданы аргумент buttons
# #Restorer: иÑпользуетÑÑ ÐºÐ°Ðº кнопка по умолчанию в окнах Ñообщений ГИП
# :!~ Restorer
+#.
msgid "&Ok"
msgstr "&OK"
@@ -890,7 +897,8 @@ msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² \"%s\"?"
# :!~ Restorer
msgid "Warning: Entered other buffer unexpectedly (check autocommands)"
msgstr ""
-"Внимание! Ðепредвиденный переход в другой буфер (проверьте дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´)"
+"Внимание! Ðепредвиденный переход в другой буфер (проверьте дейÑÑ‚Ð²Ð¸Ñ "
+"автокоманд)"
# :!~ Restorer
#, c-format
@@ -1074,10 +1082,6 @@ msgstr "Ошибка"
msgid "Interrupt"
msgstr "Прерывание"
-# :!~ Restorer
-msgid "[Command Line]"
-msgstr "[ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока]"
-
# #Restorer: в UNIX-подобных ÑиÑтемах
# #Restorer: и ещё ошибка E502:
# ~!: earlier
@@ -1086,7 +1090,7 @@ msgstr "ÑвлÑетÑÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼"
# :!~ Restorer
msgid "Illegal file name"
-msgstr "ÐедопуÑтимые Ñимволы или превышена длина Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð°"
+msgstr "Обнаружены недопуÑтимые Ñимволы или превышена длина Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð°"
# #Restorer: в UNIX-подобных ÑиÑтемах
# ~!: earlier
@@ -1235,7 +1239,8 @@ msgstr "[нет Ñимвола Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñтроки]"
# :!~ Restorer
#, c-format
msgid ""
-"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well"
+"W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as "
+"well"
msgstr "W12: Внимание! Ðе ÑвÑзанные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñодержимого буфера и файла \"%s\""
# :!~ Restorer
@@ -1366,10 +1371,12 @@ msgstr ""
msgid "OK"
msgstr "OK"
+# #Restorer: наименование кнопки в диалоговом окне
# :!~ Restorer
msgid "Yes"
msgstr "Да"
+# #Restorer: наименование кнопки в диалоговом окне
# :!~ Restorer
msgid "No"
msgstr "Ðет"
@@ -1567,27 +1574,28 @@ msgstr "Directory\t*.nothing\n"
# :!~ Restorer
#, c-format
msgid "Font0: %s"
-msgstr "наименование шрифта font0 %s"
+msgstr "Шрифт font0 %s"
# :!~ Restorer
#, c-format
msgid "Font%d: %s"
-msgstr "наименование шрифта font%d %s"
+msgstr "Шрифт font%d %s"
# :!~ Restorer
#, c-format
msgid "Font%d width is not twice that of font0"
-msgstr "ширина Ñимволов font%d должна быть вдвое больше ширины Ñимволов font0"
+msgstr ""
+"ширина Ñимволов в font%d должна быть вдвое больше ширины Ñимволов в font0"
# :!~ Restorer
#, c-format
msgid "Font0 width: %d"
-msgstr "ширина Ñимволов font0 %d"
+msgstr "ширина Ñимволов в font0 %d"
# :!~ Restorer
#, c-format
msgid "Font%d width: %d"
-msgstr "ширина Ñимволов font%d %d"
+msgstr "ширина Ñимволов в font%d %d"
# #Restorer: выводитÑÑ Ð² информационном окне
# :!~ Restorer
@@ -1624,17 +1632,17 @@ msgstr "Показывать размер в пунктах"
msgid "Encoding:"
msgstr "Кодировка:"
-# #Restorer: наименование Ð¿Ð¾Ð»Ñ Ñо ÑпиÑком шрифтов в окне выбора шрифта
+# #Restorer: наименование Ð¿Ð¾Ð»Ñ Ñ Ð¿ÐµÑ€ÐµÑ‡Ð½ÐµÐ¼ шрифтов в окне выбора шрифта
# ~!: earlier
msgid "Font:"
msgstr "Шрифт:"
-# #Restorer: наименование Ð¿Ð¾Ð»Ñ Ñо ÑпиÑком начертаний в окне выбора шрифта
+# #Restorer: наименование Ð¿Ð¾Ð»Ñ Ñ Ð¿ÐµÑ€ÐµÑ‡Ð½ÐµÐ¼ начертаний в окне выбора шрифта
# :!~ Restorer
msgid "Style:"
msgstr "Ðачертание:"
-# #Restorer: наименование Ð¿Ð¾Ð»Ñ Ñо ÑпиÑком размеров в окне выбора шрифта
+# #Restorer: наименование Ð¿Ð¾Ð»Ñ Ñ Ð¿ÐµÑ€ÐµÑ‡Ð½ÐµÐ¼ размеров в окне выбора шрифта
# ~!: earlier
msgid "Size:"
msgstr "Размер:"
@@ -1888,6 +1896,7 @@ msgstr "номер Ñтроки выходит за пределы значенÐ
msgid "not allowed in the Vim sandbox"
msgstr "запрещено выполнение в изолированной Ñреде программы Vim"
+# #Restorer: Check! Is error number duble!
# :!~ Restorer
#, c-format
msgid "E370: Could not load library %s"
@@ -1945,16 +1954,18 @@ msgstr "выполнение прервано пользователем"
# :!~ Restorer
msgid "cannot create buffer/window command: object is being deleted"
msgstr ""
-"объект буфера или окна в процеÑÑе удалениÑ. Ðе удалоÑÑŒ Ñоздать Ð´Ð»Ñ Ð½Ð¸Ñ… команды"
+"объект буфера или окна в процеÑÑе удалениÑ. Ðе удалоÑÑŒ Ñоздать Ð´Ð»Ñ Ð½Ð¸Ñ… команду"
# :!~ Restorer
msgid "cannot register callback command: buffer/window is already being deleted"
msgstr ""
-"объект буфера или окна в процеÑÑе удалениÑ. Ðе удалоÑÑŒ зарегиÑтрировать команду"
+"объект буфера или окна в процеÑÑе удалениÑ. Ðе удалоÑÑŒ зарегиÑтрировать "
+"команду"
# :!~ Restorer
msgid "cannot register callback command: buffer/window reference not found"
-msgstr "не найдена ÑÑылка на буфер или окно. Ðе удалоÑÑŒ зарегиÑтрировать команду"
+msgstr ""
+"не найдена ÑÑылка на буфер или окно. Ðе удалоÑÑŒ зарегиÑтрировать команду"
# :!~ Restorer
msgid "cannot get line"
@@ -1968,7 +1979,7 @@ msgstr "Ðе удалоÑÑŒ зарегиÑтрировать наименоваÐ
# :!~ Restorer
#, c-format
msgid "%ld lines to indent... "
-msgstr "ВыполнÑетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ñтупа в %ld Ñтроках... "
+msgstr "ВыполнÑетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ отÑтупа в %ld Ñтроках... "
# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ значении 'report' < %ld
# :!~ Restorer
@@ -2084,7 +2095,7 @@ msgstr "Конец абзаца"
# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ автоподÑтановке
# :!~ Restorer
msgid "Pattern not found"
-msgstr "Ðе найдены варианты Ð´Ð»Ñ Ð¿Ð¾Ð´Ñтановки"
+msgstr "ОтÑутÑтвуют варианты Ð´Ð»Ñ Ð¿Ð¾Ð´Ñтановки"
# ~!: earlier
msgid "Back at original"
@@ -2140,6 +2151,11 @@ msgstr "аргумента функции filter()"
# #Restorer: допиÑываетÑÑ, например, к Ñообщению E741 или E742
# :!~ Restorer
+msgid "foreach() argument"
+msgstr "аргумента функции foreach()"
+
+# #Restorer: допиÑываетÑÑ, например, к Ñообщению E741 или E742
+# :!~ Restorer
msgid "extendnew() argument"
msgstr "аргумента функции extendnew()"
@@ -2167,7 +2183,7 @@ msgstr "Ðе раÑпознан аргумент командной Ñтроки
# :!~ Restorer
msgid "Too many edit arguments"
-msgstr "Превышено количеÑтво файлов передаваемых в программу Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²ÐºÐ¸"
+msgstr "Превышено количеÑтво файлов, передаваемых в программу Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²ÐºÐ¸"
# :!~ Restorer
msgid "Argument missing after"
@@ -2375,7 +2391,7 @@ msgstr "-R\t\t\tРабота в варианте только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ
# :!~ Restorer
msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tРабота в варианте Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñми (как \"rvim\")"
+msgstr "-Z\t\t\tРабота Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ð¾Ð¹ функциональноÑтью (как \"rvim\")"
# :!~ Restorer
msgid "-m\t\t\tModifications (writing files) not allowed"
@@ -2438,8 +2454,7 @@ msgstr "-f\t\t\tÐе иÑпользовать команду newcli Ð´Ð»Ñ Ð¾Ñ‚Ð
# #Restorer: убрал один \t, чтобы выглÑдело единообразно
# :!~ Restorer
msgid "-dev <device>\t\tUse <device> for I/O"
-msgstr ""
-"-dev <уÑтройÑтво>\tИÑпользовать Ð´Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¹ ввода-вывода данное <уÑтройÑтво>"
+msgstr "-dev <уÑтройÑтво>\tИÑпользовать Ð´Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¹ ввода-вывода <уÑтройÑтво>"
# :!~ Restorer
msgid "-A\t\t\tStart in Arabic mode"
@@ -2550,7 +2565,8 @@ msgstr "--remote-silent <файлы> То же, но не Ñообщать о
# #Restorer: добавил пару пробельных Ñимволов, дабы подравнÑÑ‚ÑŒ Ñообщение
# ~!: earlier
-msgid "--remote-wait <files> As --remote but wait for files to have been edited"
+msgid ""
+"--remote-wait <files> As --remote but wait for files to have been edited"
msgstr ""
"--remote-wait <файлы> То же, что и --remote, но Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸ÐµÐ¼ завершениÑ"
@@ -2579,13 +2595,13 @@ msgstr "--serverlist\t\tВывод доÑтупных Vim-Ñерверов и з
# :!~ Restorer
msgid "--servername <name>\tSend to/become the Vim server <name>"
-msgstr "--servername <назв>\tПодключение при наличии, либо Ñтать Ñервером <назв>"
+msgstr ""
+"--servername <назв>\tПодключение при наличии, либо Ñтать Ñервером <назв>"
# :!~ Restorer
msgid "--startuptime <file>\tWrite startup timing messages to <file>"
msgstr "--startuptime <файл>\tЗапиÑать хронометраж запуÑка программы в <файл>"
-# #Restorer: добавил один \t чтобы выглÑдело единообразно
# :!~ Restorer
msgid "--log <file>\t\tStart logging to <file> early"
msgstr "--log <файл>\t\tЗапиÑÑŒ протокола работы Ñ Ñтапа инициализации программы"
@@ -2595,7 +2611,6 @@ msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo"
msgstr "-i <файл>\t\tИÑпользование вмеÑто файла .viminfo указанного <файла>"
# \n\t\t.. Ð´Ð»Ñ ÑƒÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð² 80 Ñтолбцов (С. Ðлёшин)
-# #Restorer: убрал один \t и добавил пробелы, чтобы выглÑдело единообразно
# :!~ Restorer
msgid "--clean\t\t'nocompatible', Vim defaults, no plugins, no viminfo"
msgstr ""
@@ -2621,8 +2636,7 @@ msgstr ""
# :!~ Restorer
msgid "-display <display>\tRun Vim on <display>"
-msgstr ""
-"-display <X-Ñервер>\tЗапуÑк программы Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸ÐµÐ¼ к указанному X-Ñерверу"
+msgstr "-display <Ñервер>\tПодключение программы к X-Ñерверу <Ñервер>"
# :!~ Restorer
msgid "-iconic\t\tStart Vim iconified"
@@ -2639,7 +2653,8 @@ msgstr "-foreground <цвет>\tÐазначить указанный <цвет>
# #Restorer: убрал один \t, чтобы выглÑдело единообразно
# :!~ Restorer
msgid "-font <font>\t\tUse <font> for normal text (also: -fn)"
-msgstr "-font <шрифт>\tÐазначить указанный <шрифт> Ð´Ð»Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ð¾Ð³Ð¾ текÑта (или -fn)"
+msgstr ""
+"-font <шрифт>\tÐазначить указанный <шрифт> Ð´Ð»Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ð¾Ð³Ð¾ текÑта (или -fn)"
# :!~ Restorer
msgid "-boldfont <font>\tUse <font> for bold text"
@@ -2685,7 +2700,7 @@ msgstr ""
# :!~ Restorer
msgid "-display <display>\tRun Vim on <display> (also: --display)"
msgstr ""
-"-display <display>\tПодключение программы к X-Ñерверу <Ñервер> (--display)"
+"-display <Ñервер>\tПодключение программы к X-Ñерверу <Ñервер> (--display)"
# :!~ Restorer
msgid "--role <role>\tSet a unique role to identify the main window"
@@ -2746,12 +2761,12 @@ msgstr "СоÑтоÑние протокола «kitty» обмена данныÐ
# #Restorer: выводитÑÑ, например, по команде `:abbreviata`
# :!~ Restorer
msgid "No abbreviation found"
-msgstr "Ðе найдены ÑокращениÑ"
+msgstr "ОтÑутÑтвуют ÑокращениÑ"
# #Restorer: выводитÑÑ, например, по команде `:map`
# :!~ Restorer
msgid "No mapping found"
-msgstr "Ðе найдены клавиатурные команды"
+msgstr "ОтÑутÑтвуют клавиатурные команды"
# #Restorer: выводитÑÑ Ð¿Ð¾ команде `:marks`
# :!~ Restorer
@@ -2801,7 +2816,8 @@ msgid ""
"Maybe no changes were made or Vim did not update the swap file."
msgstr ""
"\n"
-"Возможно, не было изменений или программе Vim не удалоÑÑŒ обновить файл подкачки"
+"Возможно, не было изменений или программе Vim не удалоÑÑŒ обновить файл "
+"подкачки"
# :!~ Restorer
msgid " cannot be used with this version of Vim.\n"
@@ -2824,7 +2840,7 @@ msgid ""
",\n"
"or the file has been damaged."
msgstr ""
-", \n"
+",\n"
"либо он был повреждён"
# ~!: earlier
@@ -2852,7 +2868,7 @@ msgid ""
"If you entered a new crypt key but did not write the text file,"
msgstr ""
"\n"
-"ЕÑли поÑле Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ, текÑтовый файл не ÑохранÑли,"
+"ЕÑли поÑле Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ было Ñохранение текÑтового файла,"
# :!~ Restorer
msgid ""
@@ -2902,12 +2918,14 @@ msgstr "???БЛОК ПРОПУЩЕÐ"
# :!~ Restorer
msgid "??? from here until ???END lines may be messed up"
-msgstr "Строки, которые возможно иÑпорчены, помещены между метками ??? и ???END"
+msgstr ""
+"Строки, которые, возможно, иÑпорчены, помещены между метками ??? и ???END"
# :!~ Restorer
msgid "??? from here until ???END lines may have been inserted/deleted"
msgstr ""
-"Строки, которые были вÑтавлены или удалены, помещены между метками ??? и ???END"
+"Строки, которые были вÑтавлены или удалены, помещены между метками ??? и ???"
+"END"
# :!~ Restorer
msgid "??? lines may be missing"
@@ -3154,19 +3172,19 @@ msgstr ""
# #Restorer: Ñдвинут к границе Ñкрана
# :!~ Restorer
msgid " If this is the case, use \":recover\" or \"vim -r "
-msgstr "Ð’ Ñтом Ñлучае иÑпользуйте команду :recover или \"vim -r "
+msgstr "Ð’ Ñтом Ñлучае иÑпользуйте команду :recover или `vim -r "
# :!~ Restorer
msgid ""
"\"\n"
" to recover the changes (see \":help recovery\").\n"
msgstr ""
-"\",\n"
+"`,\n"
"чтобы выполнить воÑÑтановление данных (подробнее Ñм. `:help recovery`).\n"
# :!~ Restorer
msgid " If you did this already, delete the swap file \""
-msgstr "ЕÑли Ñто уже был Ñделано, то удалите файл подкачки \""
+msgstr "ЕÑли Ñто уже было Ñделано, то удалите файл подкачки \""
# :!~ Restorer
msgid ""
@@ -3207,7 +3225,7 @@ msgid ""
"&Quit\n"
"&Abort"
msgstr ""
-"Только чтение (&O)\n"
+"Открыть Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ (&O)\n"
"Редактировать (&E)\n"
"ВоÑÑтановить (&R)\n"
"Выход (&Q)\n"
@@ -3223,7 +3241,7 @@ msgid ""
"&Quit\n"
"&Abort"
msgstr ""
-"Только чтение (&O)\n"
+"Открыть Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ (&O)\n"
"Редактировать (&E)\n"
"ВоÑÑтановить (&R)\n"
"Удалить (&D)\n"
@@ -3371,7 +3389,7 @@ msgstr "Внимание! Ð”Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ терминал недоÑтуÐ
# :!~ Restorer
msgid "Type :qa! and press <Enter> to abandon all changes and exit Vim"
msgstr ""
-"Чтобы закрыть программу Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¾Ð¹ вÑех правок, наберите :qa! и нажмите "
+"Чтобы закрыть программу Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¾Ð¹ вÑех правок, наберите :qa! и нажмите "
"<ENTER>"
# :!~ Restorer
@@ -3445,8 +3463,8 @@ msgid ""
"Selected %s%ld of %ld Lines; %lld of %lld Words; %lld of %lld Chars; %lld of "
"%lld Bytes"
msgstr ""
-"Выделено: %sÑтрок %ld из %ld; Ñлов %lld из %lld; литер %lld из %lld; байт %lld "
-"из %lld"
+"Выделено: %sÑтрок %ld из %ld; Ñлов %lld из %lld; литер %lld из %lld; байт "
+"%lld из %lld"
# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸, например, иÑполнении оператора `g CTRL+g`
# :!~ Restorer
@@ -3459,8 +3477,8 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid ""
-"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte %lld "
-"of %lld"
+"Col %s of %s; Line %ld of %ld; Word %lld of %lld; Char %lld of %lld; Byte "
+"%lld of %lld"
msgstr ""
"Колонка %s из %s; Ñтрока %ld из %ld; Ñлово %lld из %lld; литера %lld из %lld; "
"байт %lld из %lld"
@@ -3592,6 +3610,10 @@ msgid "Printing '%s'"
msgstr "Печать '%s'"
# :!~ Restorer
+msgid "DefaultFontNameForWindows"
+msgstr "Consolas"
+
+# :!~ Restorer
#, c-format
msgid "Opening the X display took %ld msec"
msgstr "Подключение к X-Ñерверу занÑло %ld мÑ"
@@ -3721,7 +3743,8 @@ msgstr "Открыто Ñоединение по XSMP"
# :!~ Restorer
msgid "XSMP ICE connection watch failed"
-msgstr "Произошла ошибка при уÑтановке ÑÐ»ÐµÐ¶ÐµÐ½Ð¸Ñ Ð·Ð° подключением по протоколу ICE"
+msgstr ""
+"Произошла ошибка при уÑтановке ÑÐ»ÐµÐ¶ÐµÐ½Ð¸Ñ Ð·Ð° подключением по протоколу ICE"
# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ 'verbose'>0
# :!~ Restorer
@@ -3820,7 +3843,7 @@ msgid "cannot have both a list and a \"what\" argument"
msgstr ""
"в функции setqflist(). Должен быть указан либо первый, либо поÑледний аргумент"
-# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ 'verbose' > 0
+# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ 'verbose'>0
# :!~ Restorer
msgid "Switching to backtracking RE engine for pattern: "
msgstr "Переключение на механизм «поиÑк Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‚Ð¾Ð¼Â» Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñкового шаблона: "
@@ -3959,13 +3982,13 @@ msgid "recording"
msgstr "ЗÐПИСЬ Ð’ РЕГИСТР"
# #Restorer: при поиÑке файла в заданном каталоге, еÑли 'verbose'>10
-# ~!: earlier
+# :!~ Restorer
#, c-format
msgid "Searching for \"%s\" under \"%s\" in \"%s\""
msgstr "ПоиÑк \"%s\" в подкаталоге \"%s\" каталогов из \"%s\""
# #Restorer: при поиÑке файла в заданном каталоге, еÑли 'verbose'>10
-# ~!: earlier
+# :!~ Restorer
#, c-format
msgid "Searching for \"%s\" in \"%s\""
msgstr "ПоиÑк \"%s\" в каталогах из \"%s\""
@@ -4198,7 +4221,7 @@ msgstr "Ð’ файле %s на Ñтроке %d превышена длина на
# :!~ Restorer
msgid "Compressing word tree..."
-msgstr "Сжатие «дерева» Ñлов ..."
+msgstr "Сжатие «дерева» Ñлов..."
# :!~ Restorer
#, c-format
@@ -4213,12 +4236,13 @@ msgstr "Считывание файла аффикÑов %s..."
# :!~ Restorer
#, c-format
msgid "Conversion failure for word in %s line %d: %s"
-msgstr "Ð’ файле %s на Ñтроке %d произошёл Ñбой при изменении кодировки текÑÑ‚ %s"
+msgstr ""
+"Ð’ файле %s на Ñтроке %d произошёл Ñбой при изменении кодировки текÑта %s"
# :!~ Restorer
#, c-format
msgid "Conversion in %s not supported: from %s to %s"
-msgstr "Ð”Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° %s не поддерживаетÑÑ Ð¿ÐµÑ€ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ðµ из %s в %s"
+msgstr "Ð”Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° %s не поддерживаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ кодировки текÑта из %s в %s"
# :!~ Restorer
#, c-format
@@ -4228,19 +4252,22 @@ msgstr "Ð’ файле %s на Ñтроке %d недопуÑтимое значÐ
# :!~ Restorer
#, c-format
msgid "FLAG after using flags in %s line %d: %s"
-msgstr "Ð’ файле %s на Ñтроке %d поÑле значений флагов обнаружено правило FLAG %s"
+msgstr ""
+"Ð’ файле %s на Ñтроке %d поÑле значений флагов обнаружено правило FLAG %s"
# :!~ Restorer
#, c-format
msgid ""
-"Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"
+"Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line "
+"%d"
msgstr ""
"Ð’ файле %s на Ñтроке %d указан COMPOUNDFORBIDFLAG поÑле PFX, что нежелательно"
# :!~ Restorer
#, c-format
msgid ""
-"Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"
+"Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line "
+"%d"
msgstr ""
"Ð’ файле %s на Ñтроке %d указан COMPOUNDPERMITFLAG поÑле PFX, что нежелательно"
@@ -4252,7 +4279,8 @@ msgstr "Ð’ файле %s на Ñтроке %d недопуÑтимое значÐ
# :!~ Restorer
#, c-format
msgid "Wrong COMPOUNDWORDMAX value in %s line %d: %s"
-msgstr "Ð’ файле %s на Ñтроке %d недопуÑтимое значение правила COMPOUNDWORDMAX %s"
+msgstr ""
+"Ð’ файле %s на Ñтроке %d недопуÑтимое значение правила COMPOUNDWORDMAX %s"
# :!~ Restorer
#, c-format
@@ -4366,7 +4394,7 @@ msgstr "Ð’ файле %s на Ñтроке %d обнаружен недопуÑÑ
# :!~ Restorer
#, c-format
msgid "%s value differs from what is used in another .aff file"
-msgstr "Ð’ другом файле аффикÑов обнаружено отличающееÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ðµ Ð´Ð»Ñ %s"
+msgstr "Ð’ другом файле аффикÑов обнаружено неÑовпадающее значение Ð´Ð»Ñ %s"
# :!~ Restorer
#, c-format
@@ -4403,28 +4431,29 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "Reading word file %s..."
-msgstr "Считывание файла Ñо ÑпиÑком Ñлов %s..."
+msgstr "Считывание файла Ñ Ð¿ÐµÑ€ÐµÑ‡Ð½ÐµÐ¼ Ñлов %s..."
# :!~ Restorer
#, c-format
msgid "Conversion failure for word in %s line %ld: %s"
-msgstr "Ð’ файле %s на Ñтроке %ld произошёл Ñбой при изменении кодировки текÑÑ‚ %s"
+msgstr ""
+"Ð’ файле %s на Ñтроке %ld произошёл Ñбой при изменении кодировки текÑта %s"
# :!~ Restorer
#, c-format
msgid "Duplicate /encoding= line ignored in %s line %ld: %s"
-msgstr "Ð’ файле %s на Ñтроке %ld был проигнорирован повтор /encoding= %s"
+msgstr "Ð’ файле %s на Ñтроке %ld не обработан повтор /encoding= %s"
# :!~ Restorer
#, c-format
msgid "/encoding= line after word ignored in %s line %ld: %s"
msgstr ""
-"Ð’ файле %s на Ñтроке %ld проигнорирован указанный поÑле Ñлова /encoding= %s"
+"Ð’ файле %s на Ñтроке %ld не обработан указанный поÑле Ñлова /encoding= %s"
# :!~ Restorer
#, c-format
msgid "Duplicate /regions= line ignored in %s line %ld: %s"
-msgstr "Ð’ файле %s на Ñтроке %ld был проигнорирован повтор %s"
+msgstr "Ð’ файле %s на Ñтроке %ld не обработан повтор /regions= %s"
# :!~ Restorer
#, c-format
@@ -4434,7 +4463,8 @@ msgstr "Ð’ файле %s на Ñтроке %ld превышено количеÑ
# :!~ Restorer
#, c-format
msgid "/ line ignored in %s line %ld: %s"
-msgstr "Ð’ файле %s на Ñтроке %ld не обработан указанный поÑле Ñимвола / текÑÑ‚ %s"
+msgstr ""
+"Ð’ файле %s на Ñтроке %ld не обработан текÑÑ‚, указанный поÑле Ñимвола '/' %s"
# :!~ Restorer
#, c-format
@@ -4459,11 +4489,12 @@ msgstr "Сжато узлов %s: %ld из %ld. ОÑталоÑÑŒ %ld (%ld%%)"
# :!~ Restorer
msgid "Reading back spell file..."
-msgstr "Считывание запиÑанного файла правил напиÑÐ°Ð½Ð¸Ñ ..."
+msgstr "Считывание запиÑанного файла правил напиÑаниÑ..."
# :!~ Restorer
+#.
msgid "Performing soundfolding..."
-msgstr "ПоÑтроение префикÑного «дерева» омофонов ..."
+msgstr "ПоÑтроение префикÑного «дерева» омофонов..."
# :!~ Restorer
#, c-format
@@ -4789,7 +4820,8 @@ msgstr "Отмена изменений недоÑтупна. Продолжит
# :!~ Restorer
msgid "Cannot write undo file in any directory in 'undodir'"
msgstr ""
-"Ðе удалоÑÑŒ запиÑать файл изменений ни в один из каталогов из параметра 'udodir'"
+"Ðе удалоÑÑŒ запиÑать файл изменений ни в один из каталогов из параметра "
+"'udodir'"
# #Restorer: выводитÑÑ, например, Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ `:wundo` и `:rundo` при 'verbose'>0
# :!~ Restorer
@@ -4806,7 +4838,7 @@ msgstr "Ðе удалоÑÑŒ запиÑать файл. Файл не ÑвлÑеÑ
# #Restorer: выводитÑÑ, например, Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ `:wundo` и `:rundo` при 'verbose'>0
# :!~ Restorer
msgid "Skipping undo file write, nothing to undo"
-msgstr "ЗапиÑÑŒ файла изменений не выполнена. Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÑутÑтвуют."
+msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÑутÑтвуют. ЗапиÑÑŒ файла изменений не выполнена"
# #Restorer: выводитÑÑ, например, Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ `:wundo` и `:rundo` при 'verbose'>0
# :!~ Restorer
@@ -4928,7 +4960,7 @@ msgstr ""
# #Restorer: выводитÑÑ Ð¿Ð¾ команде `:command`
# :!~ Restorer
msgid "No user-defined commands found"
-msgstr "Ðе найдены Ñозданные пользователем команды"
+msgstr "Созданные пользователем команды не найдены"
# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ 'verbose'>0
# :!~ Restorer
@@ -4966,15 +4998,14 @@ msgstr "%s вернула %s"
# :!~ Restorer
#, c-format
-msgid "Function %s does not need compiling"
-msgstr "Ðе требуетÑÑ ÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑÑ†Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ %s"
+msgid "Function %s%s%s does not need compiling"
+msgstr "Ðе требуетÑÑ ÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑÑ†Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ %s%s%s"
# #Restorer: первый %s заменÑетÑÑ Ð½Ð° VIM_VERSION_LONG_ONLY (только наименование
# #Restorer: программы), второй %s - VIM_VERSION_DATE_ONLY (дата первого выпуÑка),
# #Restorer: третий %s - датой текущей Ñборки
# #Restorer: выводитÑÑ Ð¿Ð¾ команде vim.exe -h или `:version`
# :!~ Restorer
-# "%s (%s, Ñборано в %s)"
#, c-format
msgid "%s (%s, compiled %s)"
msgstr "%s (%s, Ñборка от %s)"
@@ -5155,59 +5186,59 @@ msgstr " Ð’ Ñтой верÑии включены (+) и отключены (-)
# ~!: earlier
msgid " system vimrc file: \""
-msgstr " общеÑиÑтемный файл vimrc: \""
+msgstr " общеÑиÑтемный файл vimrc: \""
# ~!: earlier
msgid " user vimrc file: \""
-msgstr " пользовательÑкий файл vimrc: \""
+msgstr " пользовательÑкий файл vimrc: \""
# ~!: earlier
msgid " 2nd user vimrc file: \""
-msgstr " второй пользовательÑкий файл vimrc: \""
+msgstr " второй пользовательÑкий файл vimrc: \""
# ~!: earlier
msgid " 3rd user vimrc file: \""
-msgstr " третий пользовательÑкий файл vimrc: \""
+msgstr " третий пользовательÑкий файл vimrc: \""
# ~!: earlier
msgid " user exrc file: \""
-msgstr " пользовательÑкий файл exrc: \""
+msgstr " пользовательÑкий файл exrc: \""
# ~!: earlier
msgid " 2nd user exrc file: \""
-msgstr " второй пользовательÑкий файл exrc: \""
+msgstr " второй пользовательÑкий файл exrc: \""
# ~!: earlier
msgid " system gvimrc file: \""
-msgstr " общеÑиÑтемный файл gvimrc: \""
+msgstr " общеÑиÑтемный файл gvimrc: \""
# ~!: earlier
msgid " user gvimrc file: \""
-msgstr " пользовательÑкий файл gvimrc: \""
+msgstr " пользовательÑкий файл gvimrc: \""
# ~!: earlier
msgid "2nd user gvimrc file: \""
-msgstr " второй пользовательÑкий файл gvimrc: \""
+msgstr "второй пользовательÑкий файл gvimrc: \""
# ~!: earlier
msgid "3rd user gvimrc file: \""
-msgstr " третий пользовательÑкий файл gvimrc: \""
+msgstr "третий пользовательÑкий файл gvimrc: \""
# :!~ Restorer
msgid " defaults file: \""
-msgstr " файл предуÑтановленных наÑтроек: \""
+msgstr " файл предуÑтановленных наÑтроек: \""
# ~!: earlier
msgid " system menu file: \""
-msgstr " общеÑиÑтемный файл меню: \""
+msgstr " общеÑиÑтемный файл меню: \""
# ~!: earlier
msgid " fall-back for $VIM: \""
-msgstr " значение $VIM по умолчанию: \""
+msgstr " значение $VIM по умолчанию: \""
# ~!: earlier
msgid " f-b for $VIMRUNTIME: \""
-msgstr " значение $VIMRUNTIME по умолчанию: \""
+msgstr " значение $VIMRUNTIME по умолчанию: \""
# :!~ Restorer
msgid "Compilation: "
@@ -5368,7 +5399,7 @@ msgstr ""
# #Restorer: E1016: Ð”Ð»Ñ Ð¾Ð±Ð»Ð°Ñти дейÑÑ‚Ð²Ð¸Ñ Â«Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ð°Ñ» не может быть объÑвлена Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ %s
# :!~ Restorer
msgid "global"
-msgstr "«глобальный»"
+msgstr "«общий»"
# #Restorer: подÑтавлÑетÑÑ Ð² «E1016: Cannot declare a %s variable: %s» как
# #Restorer: Ð¿ÐµÑ€Ð²Ð°Ñ %s. Может лучше не переводить? Пока Ñделал. ВыглÑдит так:
@@ -5403,7 +5434,7 @@ msgid ""
"# Buffer list:\n"
msgstr ""
"\n"
-"# СпиÑок буферов:\n"
+"# Перечень буферов:\n"
# #Restorer: запиÑÑŒ в viminfo-файл журнала (history) команд, поиÑка и проч.
# :!~ Restorer
@@ -5454,13 +5485,14 @@ msgstr ""
msgid "%sviminfo: %s in line: "
msgstr "%s%s в viminfo-файле на Ñтроке "
-# ~!: earlier
+# #Restorer: в viminfo-файле
+# :!~ Restorer
msgid ""
"\n"
"# global variables:\n"
msgstr ""
"\n"
-"# Глобальные переменные:\n"
+"# Общие переменные:\n"
# #Restorer: запиÑÑŒ в viminfo-файле
# :!~ Restorer
@@ -5589,7 +5621,7 @@ msgstr "Открыть файлы в отдельных вкладка&х про
# :!~ Restorer
msgid "Edit with single &Vim"
-msgstr "Открыть вÑе файлы в одной программе &Vim"
+msgstr "Открыть вÑе файлы в &одной программе Vim"
# :!~ Restorer
msgid "Diff with Vim"
@@ -5597,7 +5629,7 @@ msgstr "Сравнить файлы в программе Vim"
# :!~ Restorer
msgid "Edit with &Vim"
-msgstr "Открыть в программе &Vim"
+msgstr "Открыть в &программе Vim"
# :!~ Restorer
msgid "Edit with existing Vim"
@@ -5671,7 +5703,7 @@ msgstr "E18: ÐедопуÑтимые Ñимволы в приÑваиваемо
# :!~ Restorer
msgid "E19: Mark has invalid line number"
-msgstr "E19: Закладка указывает на не ÑущеÑтвующую Ñтроку"
+msgstr "E19: Закладка указывает на неÑущеÑтвующую Ñтроку"
# :!~ Restorer
msgid "E20: Mark not set"
@@ -5691,7 +5723,7 @@ msgstr "E23: ОтÑутÑтвуют ÑоÑедние файлы"
# :!~ Restorer
msgid "E24: No such abbreviation"
-msgstr "E24: ОтÑутÑтвует указанное Ñокращение"
+msgstr "E24: Ðе ÑущеÑтвует указанного ÑокращениÑ"
# :!~ Restorer
msgid "E25: GUI cannot be used: Not enabled at compile time"
@@ -5714,15 +5746,15 @@ msgstr "E28: Ðе ÑущеÑтвует группы подÑветки ÑинтÐ
# :!~ Restorer
msgid "E29: No inserted text yet"
-msgstr "E29: РегиÑÑ‚Ñ€ Ð´Ð»Ñ Ð¿Ð¾Ñледнего вÑтавленного текÑта пуÑÑ‚"
+msgstr "E29: РегиÑÑ‚Ñ€ поÑледнего набранного текÑта пуÑÑ‚"
# :!~ Restorer
msgid "E30: No previous command line"
-msgstr "E30: РегиÑÑ‚Ñ€ Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ режима командной Ñтроки пуÑÑ‚"
+msgstr "E30: РегиÑÑ‚Ñ€ поÑледней команды режима командной Ñтроки пуÑÑ‚"
# :!~ Restorer
msgid "E31: No such mapping"
-msgstr "E31: Ðе ÑущеÑтвует клавиатурной команды"
+msgstr "E31: Ðе ÑущеÑтвует указанной клавиатурной команды"
# :!~ Restorer
msgid "E32: No file name"
@@ -5783,7 +5815,8 @@ msgstr "E46: Ðе допуÑкаетÑÑ Ð¿Ñ€Ð¸Ñваивание значени
# :!~ Restorer
#, c-format
msgid "E46: Cannot change read-only variable \"%s\""
-msgstr "E46: Ðе допуÑкаетÑÑ Ð¿Ñ€Ð¸Ñваивание Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½Ñемой переменной \"%s\""
+msgstr ""
+"E46: Ðе допуÑкаетÑÑ Ð¿Ñ€Ð¸Ñваивание Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½Ñемой переменной \"%s\""
# :!~ Restorer
msgid "E47: Error while reading errorfile"
@@ -5900,7 +5933,7 @@ msgstr "E74: Превышена длина результата выполнен
# :!~ Restorer
msgid "E75: Name too long"
-msgstr "E75: Превышена длина маршрута к файлу"
+msgstr "E75: Превышена допуÑÑ‚Ð¸Ð¼Ð°Ñ Ð´Ð»Ð¸Ð½Ð° маршрута к файлу"
# :!~ Restorer
msgid "E76: Too many ["
@@ -5946,7 +5979,7 @@ msgstr "E85: Указанный буфер отÑутÑтвует в ÑпиÑкÐ
# :!~ Restorer
#, c-format
msgid "E86: Buffer %ld does not exist"
-msgstr "E86: Буфер под номером %ld не ÑущеÑтвует"
+msgstr "E86: Ðе ÑущеÑтвует буфера под номером %ld"
# :!~ Restorer
msgid "E87: Cannot go beyond last buffer"
@@ -6047,7 +6080,7 @@ msgstr "E108: Ðе ÑущеÑтвует переменной \"%s\""
# :!~ Restorer
msgid "E109: Missing ':' after '?'"
-msgstr "E109: ОтÑутÑтвует Ñимвол Ð´Ð²Ð¾ÐµÑ‚Ð¾Ñ‡Ð¸Ñ ':' в операторе проверки уÑÐ»Ð¾Ð²Ð¸Ñ '?'"
+msgstr "E109: ОтÑутÑтвует Ñимвол Ð´Ð²Ð¾ÐµÑ‚Ð¾Ñ‡Ð¸Ñ ':' в операторе проверки уÑÐ»Ð¾Ð²Ð¸Ñ `?`"
# :!~ Restorer
msgid "E110: Missing ')'"
@@ -6177,7 +6210,8 @@ msgstr ""
# :!~ Restorer
msgid "E135: *Filter* Autocommands must not change current buffer"
msgstr ""
-"E135: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ по ÑобытиÑм *Filter* не должны изменÑÑ‚ÑŒ текущий буфер"
+"E135: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ по ÑобытиÑм *Filter* не должны изменÑÑ‚ÑŒ текущий "
+"буфер"
# :!~ Restorer
msgid "E136: viminfo: Too many errors, skipping rest of file"
@@ -6224,7 +6258,7 @@ msgstr "E144: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ чиÑловой параметÑ
msgid "E145: Shell commands and some functionality not allowed in rvim"
msgstr ""
"E145: Команды командной оболочки и Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¾Ð½Ð°Ð»ÑŒÐ½Ð¾ÑÑ‚ÑŒ отключены в "
-"варианте программы rvim"
+"варианте программы rVim"
# :!~ Restorer
msgid "E146: Regular expressions can't be delimited by letters"
@@ -6424,7 +6458,7 @@ msgstr "E185: Ðе найдена Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ñхема \"%s\""
# :!~ Restorer
msgid "E186: No previous directory"
-msgstr "E186: Ранее изменений каталога не выполнÑлоÑÑŒ, оÑталÑÑ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¹ каталог"
+msgstr "E186: Переходы в другой каталог ранее не выполнÑлиÑÑŒ"
# :!~ Restorer
msgid "E187: Directory unknown"
@@ -6438,18 +6472,20 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E189: \"%s\" exists (add ! to override)"
-msgstr "E189: Файл \"%s\" уже ÑущеÑтвует (чтобы заменить, укажите модификатор !)"
+msgstr ""
+"E189: Файл \"%s\" уже ÑущеÑтвует (чтобы заменить, укажите модификатор !)"
# #Restorer: Ñм. E212
# :!~ Restorer
#, c-format
msgid "E190: Cannot open \"%s\" for writing"
-msgstr "E190: Ðе удалоÑÑŒ открыть на запиÑÑŒ файла \"%s\""
+msgstr "E190: Ðе удалоÑÑŒ открыть на запиÑÑŒ файл \"%s\""
# :!~ Restorer
msgid "E191: Argument must be a letter or forward/backward quote"
msgstr ""
-"E191: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ букву, прÑмую или обратную кавычку как параметр команды"
+"E191: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ букву, прÑмую или обратную кавычку как параметр "
+"команды"
# :!~ Restorer
msgid "E192: Recursive use of :normal too deep"
@@ -6480,8 +6516,8 @@ msgid "E197: Cannot set language to \"%s\""
msgstr "E197: Ðе удалоÑÑŒ изменить региональные наÑтройки Ð´Ð»Ñ \"%s\""
# :!~ Restorer
-msgid "E199: Active window or buffer deleted"
-msgstr "E199: Удалены активное окно или буфер"
+msgid "E199: Active window or buffer changed or deleted"
+msgstr "E199: Удаление или изменение текущего окна или буфера"
# :!~ Restorer
msgid "E200: *ReadPre autocommands made the file unreadable"
@@ -6491,7 +6527,8 @@ msgstr ""
# :!~ Restorer
msgid "E201: *ReadPre autocommands must not change current buffer"
msgstr ""
-"E201: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ по ÑобытиÑм *ReadPre не должны изменÑÑ‚ÑŒ текущий буфер"
+"E201: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ по ÑобытиÑм *ReadPre не должны изменÑÑ‚ÑŒ текущий "
+"буфер"
# :!~ Restorer
msgid "E202: Conversion made file unreadable!"
@@ -6509,7 +6546,8 @@ msgstr "E204: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ вызвали изменеÐ
# :!~ Restorer
msgid "E205: Patchmode: can't save original file"
msgstr ""
-"E205: Ðе удалоÑÑŒ Ñохранить иÑходный файл Ñ Ñ€Ð°Ñширением из параметра 'patchmode'"
+"E205: Ðе удалоÑÑŒ Ñохранить иÑходный файл Ñ Ñ€Ð°Ñширением из параметра "
+"'patchmode'"
# :!~ Restorer
msgid "E206: Patchmode: can't touch empty original file"
@@ -6556,12 +6594,12 @@ msgstr "E214: Ðу удалоÑÑŒ найти временный файл длÑ
# :!~ Restorer
#, c-format
msgid "E215: Illegal character after *: %s"
-msgstr "E215: ТребуетÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»ÑŒÐ½Ñ‹Ð¹ Ñимвол поÑле Ñимвола * в %s"
+msgstr "E215: ТребуетÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»ÑŒÐ½Ñ‹Ð¹ Ñимвол поÑле Ñимвола '*' в %s"
# :!~ Restorer
#, c-format
msgid "E216: No such event: %s"
-msgstr "E216: Ðе ÑущеÑтвует Ñобытие %s"
+msgstr "E216: Ðе ÑущеÑтвует ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ %s"
# :!~ Restorer
#, c-format
@@ -6596,12 +6634,12 @@ msgstr "E223: Превышено количеÑтво переназначени
# :!~ Restorer
#, c-format
msgid "E224: Global abbreviation already exists for %s"
-msgstr "E224: Обнаружено ÑущеÑтвующее глобальное Ñокращение %s"
+msgstr "E224: Обнаружено ÑущеÑтвующее общее Ñокращение %s"
# :!~ Restorer
#, c-format
msgid "E225: Global mapping already exists for %s"
-msgstr "E225: Обнаружена ÑущеÑÑ‚Ð²ÑƒÑŽÑ‰Ð°Ñ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ»Ð°Ð²Ð¸Ð°Ñ‚ÑƒÑ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° %s"
+msgstr "E225: Обнаружена ÑущеÑÑ‚Ð²ÑƒÑŽÑ‰Ð°Ñ Ð¾Ð±Ñ‰Ð°Ñ ÐºÐ»Ð°Ð²Ð¸Ð°Ñ‚ÑƒÑ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° %s"
# :!~ Restorer
#, c-format
@@ -6712,7 +6750,7 @@ msgstr "E249: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ вызвали изменеÐ
# ~!: earlier
#, c-format
msgid "E250: Fonts for the following charsets are missing in fontset %s:"
-msgstr "E250: Ð’ наборе шрифтов %s отÑутÑтвуют шрифты Ð´Ð»Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð¾Ðº:"
+msgstr "E250: Ð’ наборе шрифтов %s отÑутÑтвуют шрифты Ñо Ñледующими Ñимволами:"
# #Restorer: отображаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ при ÑпецифичеÑких уÑловиÑÑ…
# :!~ Restorer
@@ -6752,7 +6790,7 @@ msgstr "E258: Ðе удалоÑÑŒ отправить Ñообщение клие
msgid "E259: No matches found for cscope query %s of %s"
msgstr "E259: Ð’ базах данных cscope по запроÑу %s не найден %s"
-# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ значении 'verbose' > 0
+# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ значении 'verbose'>0
# :!~ Restorer
msgid "E260: Missing name after ->"
msgstr "E260: Ðе указан вызываемый метод в запиÑи ->"
@@ -6818,7 +6856,7 @@ msgstr "E272: Ðеобработанное иÑключение"
msgid "E273: Unknown longjmp status %d"
msgstr "E273: Ðеопределённое ÑоÑтоÑние %d"
-# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ 'verbose' > 0
+# #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ 'verbose'>0
# :!~ Restorer
msgid "E274: No white space allowed before parenthesis"
msgstr "E274: Ðе допуÑкаетÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»ÑŒÐ½Ñ‹Ð¹ Ñимвол перед круглыми Ñкобками"
@@ -6831,7 +6869,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E276: Cannot use function as a method: %s"
-msgstr "E276: Ðе допуÑкаетÑÑ Ð¸Ñпользование функции как метод %s"
+msgstr "E276: Ð”Ð°Ð½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ðµ может быть иÑпользована как метод %s"
# :!~ Restorer
msgid "E277: Unable to read a server reply"
@@ -6839,7 +6877,7 @@ msgstr "E277: Ðе удалоÑÑŒ Ñчитать ответ Ñервера"
# :!~ Restorer
msgid "E279: Sorry, ++shell is not supported on this system"
-msgstr "E279: Ðргумент ++shell не поддерживаетÑÑ Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ операционной ÑиÑтемы"
+msgstr "E279: Ðргумент ++shell не поддерживаетÑÑ Ð² данной операционной ÑиÑтеме"
# :!~ Restorer
#, c-format
@@ -6850,7 +6888,7 @@ msgstr "E282: Ðе удалоÑÑŒ Ñчитать файл \"%s\""
# :!~ Restorer
#, c-format
msgid "E283: No marks matching \"%s\""
-msgstr "E283: ОтÑутÑтвуют закладки \"%s\""
+msgstr "E283: ОтÑутÑтвуют закладки, Ñовпадающие Ñ \"%s\""
# ~!: earlier
msgid "E284: Cannot set IC values"
@@ -7016,7 +7054,8 @@ msgstr "E331: Ðе допуÑкаетÑÑ Ñ€Ð°Ð·Ð¼ÐµÑ‰Ð°Ñ‚ÑŒ иÑполнÑемÑ
# :!~ Restorer
msgid "E332: Separator cannot be part of a menu path"
msgstr ""
-"E332: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ разделитель как компонент в цепочке пунктов меню"
+"E332: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ разделитель как компонент в цепочке пунктов "
+"меню"
# :!~ Restorer
msgid "E333: Menu path must lead to a menu item"
@@ -7062,8 +7101,8 @@ msgstr "E342: ÐедоÑтаточно памÑти! (выделÑетÑÑ %lu Ð
# :!~ Restorer
#, c-format
msgid ""
-"E343: Invalid path: '**[number]' must be at the end of the path or be followed "
-"by '%s'."
+"E343: Invalid path: '**[number]' must be at the end of the path or be "
+"followed by '%s'."
msgstr ""
"E343: МаÑка вида '**[чиÑло]' указываетÑÑ Ð¿Ð¾Ñледней или поÑле неё должен быть "
"'%s'"
@@ -7112,7 +7151,7 @@ msgstr ""
# :!~ Restorer
msgid "E352: Cannot erase folds with current 'foldmethod'"
msgstr ""
-"E352: Ðе удалоÑÑŒ отменить отображение Ñтруктуры при текущем значении параметра "
+"E352: Ðе удалоÑÑŒ убрать отображение Ñтруктуры при текущем значении параметра "
"'foldmethod'"
# :!~ Restorer
@@ -7148,7 +7187,8 @@ msgstr "E359: УÑтановка режима Ñкрана не поддержи
# :!~ Restorer
msgid "E360: Cannot execute shell with -f option"
msgstr ""
-"E360: Ðе удалоÑÑŒ вызвать командную оболочку. Программа запущена Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð¼ -f"
+"E360: Ðе удалоÑÑŒ вызвать командную оболочку. Программа запущена Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð¼ -"
+"f"
# :!~ Restorer
msgid "E362: Using a boolean value as a Float"
@@ -7176,7 +7216,7 @@ msgstr "E366: Запрещён переход во вÑплывающее окн
# :!~ Restorer
#, c-format
msgid "E367: No such group: \"%s\""
-msgstr "E367: Ðе ÑущеÑтвует группа автокоманд \"%s\""
+msgstr "E367: Ðе ÑущеÑтвует группы автокоманд \"%s\""
# :!~ Restorer
#, c-format
@@ -7188,6 +7228,7 @@ msgstr "E368: Полученный через функцию libcall() ÑигнÐ
msgid "E369: Invalid item in %s%%[]"
msgstr "E369: ÐедопуÑтимый метаÑимвол в клаÑÑе факультативных Ñлементов %s%%[]"
+# #Restorer: Check! Is error number duble!
# :!~ Restorer
#, c-format
msgid "E370: Could not load library %s: %s"
@@ -7200,12 +7241,12 @@ msgstr "E371: Ðе найден файл командной оболочки"
# :!~ Restorer
#, c-format
msgid "E372: Too many %%%c in format string"
-msgstr "E372: Ð’ форматной Ñтроке превышено количеÑтво %%%c"
+msgstr "E372: Ð’ форматной Ñтроке превышено количеÑтво Ñпецификаторов %%%c"
# :!~ Restorer
#, c-format
msgid "E373: Unexpected %%%c in format string"
-msgstr "E373: Ð’ форматной Ñтроке непредвиденное поÑвление %%%c"
+msgstr "E373: Ð’ форматной Ñтроке непредвиденное поÑвление Ñпецификатора %%%c"
# :!~ Restorer
msgid "E374: Missing ] in format string"
@@ -7214,7 +7255,7 @@ msgstr "E374: Ðе указан Ñимвол закрывающей квадра
# :!~ Restorer
#, c-format
msgid "E375: Unsupported %%%c in format string"
-msgstr "E375: Ð’ форматной Ñтроке не поддерживаетÑÑ Ñлемент %%%c"
+msgstr "E375: Ð’ форматной Ñтроке не поддерживаетÑÑ Ñпецификатор %%%c"
# :!~ Restorer
#, c-format
@@ -7224,7 +7265,7 @@ msgstr "E376: Ð’ форматной Ñтроке недопуÑтимый Ñпе
# :!~ Restorer
#, c-format
msgid "E377: Invalid %%%c in format string"
-msgstr "E377: Ð’ форматной Ñтроке недопуÑтимый Ñлемент %%%c"
+msgstr "E377: Ð’ форматной Ñтроке недопуÑтимый Ñпецификатор %%%c"
# :!~ Restorer
msgid "E378: 'errorformat' contains no pattern"
@@ -7313,7 +7354,7 @@ msgstr "E397: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ наименование файÐ
# :!~ Restorer
#, c-format
msgid "E398: Missing '=': %s"
-msgstr "E398: Ðе указан знак равенÑтва у параметров команды :syntax region %s"
+msgstr "E398: Ðе указан знак равенÑтва в параметрах команды :syntax region %s"
# :!~ Restorer
#, c-format
@@ -7381,8 +7422,7 @@ msgstr "E411: Ðе найдена группу подÑветки %s"
# :!~ Restorer
#, c-format
msgid "E412: Not enough arguments: \":highlight link %s\""
-msgstr ""
-"E412: Указаны не вÑе требуемые параметры в команде `:highlight link %s`"
+msgstr "E412: Указаны не вÑе требуемые параметры в команде `:highlight link %s`"
# :!~ Restorer
#, c-format
@@ -7595,7 +7635,8 @@ msgstr ""
# :!~ Restorer
msgid "E459: Cannot go back to previous directory"
-msgstr "E459: У программы Vim отÑутÑтвуют права на иÑполнение в текущем каталоге"
+msgstr ""
+"E459: У программы Vim отÑутÑтвуют права на иÑполнение в текущем каталоге"
# :!~ Restorer
msgid "E460: Entries missing in mapset() dict argument"
@@ -7620,12 +7661,12 @@ msgstr ""
# #Restorer: поÑле ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¸ÑываетÑÑ Ñимвол : и Ð¾ÑˆÐ¸Ð±Ð¾Ñ‡Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°
# :!~ Restorer
msgid "E464: Ambiguous use of user-defined command"
-msgstr "E464: ÐераÑпознана ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼ команда"
+msgstr "E464: Ðе раÑпознана ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼ команда"
# :!~ Restorer
#, c-format
msgid "E464: Ambiguous use of user-defined command: %s"
-msgstr "E464: ÐераÑпознана ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼ команда %s"
+msgstr "E464: Ðе раÑпознана ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼ команда %s"
# :!~ Restorer
msgid "E465: :winsize requires two number arguments"
@@ -7844,8 +7885,7 @@ msgstr "E503: Кофе ещё не готов"
# #Restorer: ошибка E504:
# :!~ Restorer
msgid "is read-only (cannot override: \"W\" in 'cpoptions')"
-msgstr ""
-"файл только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ (чтобы запиÑать, уберите флаг \"W\" в 'cpoptions')"
+msgstr "файл только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ (чтобы запиÑать, уберите флаг 'W' в 'cpoptions')"
# #Restorer: ошибка E505:
# :!~ Restorer
@@ -7867,23 +7907,26 @@ msgstr ""
# :!~ Restorer
msgid "E507: Close error for backup file (add ! to write anyway)"
msgstr ""
-"E507: Ðе удалоÑÑŒ закрыть резервный файл (чтобы запиÑать, укажите модификатор !)"
+"E507: Ðе удалоÑÑŒ закрыть резервный файл (чтобы запиÑать, укажите "
+"модификатор !)"
# :!~ Restorer
msgid "E508: Can't read file for backup (add ! to write anyway)"
msgstr ""
-"E508: Ðе удалоÑÑŒ Ñчитать резервный файл (чтобы запиÑать, укажите модификатор !)"
+"E508: Ðе удалоÑÑŒ Ñчитать резервный файл (чтобы запиÑать, укажите "
+"модификатор !)"
# :!~ Restorer
msgid "E509: Cannot create backup file (add ! to override)"
msgstr ""
-"E509: Ðе удалоÑÑŒ Ñоздать резервный файл (чтобы игнорировать, укажите "
+"E509: Ðе удалоÑÑŒ Ñоздать резервный файл (чтобы запиÑать, укажите "
"модификатор !)"
# :!~ Restorer
msgid "E510: Can't make backup file (add ! to write anyway)"
msgstr ""
-"E510: Ðе удалоÑÑŒ Ñоздать резервный файл (чтобы запиÑать, укажите модификатор !)"
+"E510: Ðе удалоÑÑŒ подготовить резервный файл (чтобы запиÑать, укажите "
+"модификатор !)"
# :!~ Restorer
msgid "E511: NetBeans already connected"
@@ -7896,7 +7939,7 @@ msgstr "E512: Ошибка Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° поÑле операци
# :!~ Restorer
msgid "E513: Write error, conversion failed (make 'fenc' empty to override)"
msgstr ""
-"E513: Ошибка запиÑи. Сбой при изменении кодировки текÑта (чтобы игнорировать, "
+"E513: Ошибка запиÑи при изменении кодировки текÑта (чтобы игнорировать, "
"ÑброÑьте параметр 'fenc')"
# :!~ Restorer
@@ -7905,7 +7948,7 @@ msgid ""
"E513: Write error, conversion failed in line %ld (make 'fenc' empty to "
"override)"
msgstr ""
-"E513: Ошибка запиÑи. Сбой при изменении кодировки текÑта в Ñтроке %ld (чтобы "
+"E513: Ошибка запиÑи при изменении кодировки текÑта в Ñтроке %ld (чтобы "
"игнорировать, ÑброÑьте параметр 'fenc')"
# :!~ Restorer
@@ -8195,15 +8238,15 @@ msgstr "E579: Превышено количеÑтво вложений блокÐ
# :!~ Restorer
msgid "E580: :endif without :if"
-msgstr "E580: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endif нет ÑоответÑтвующей команды :if"
+msgstr "E580: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endif отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :if"
# :!~ Restorer
msgid "E581: :else without :if"
-msgstr "E581: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :else нет ÑоответÑтвующей команда :if"
+msgstr "E581: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :else отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :if"
# :!~ Restorer
msgid "E582: :elseif without :if"
-msgstr "E582: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :elseif нет ÑоответÑтвующей команды :if"
+msgstr "E582: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :elseif отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :if"
# :!~ Restorer
msgid "E583: Multiple :else"
@@ -8227,11 +8270,11 @@ msgstr "E587: Команда :break указана вне цикла :while ил
# :!~ Restorer
msgid "E588: :endwhile without :while"
-msgstr "E588: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endwhile нет команды :while"
+msgstr "E588: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endwhile отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :while"
# :!~ Restorer
msgid "E588: :endfor without :for"
-msgstr "E588: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endfor нет команды :for"
+msgstr "E588: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endfor отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :for"
# :!~ Restorer
msgid "E589: 'backupext' and 'patchmode' are equal"
@@ -8256,7 +8299,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E593: Need at least %d lines"
-msgstr "E593: Минимальное значение количеÑтва Ñтрок %d"
+msgstr "E593: Минимально возможное количеÑтво Ñтрок %d"
# :!~ Restorer
#, c-format
@@ -8286,7 +8329,7 @@ msgstr "E599: ÐедопуÑтимое значение параметра 'imac
# :!~ Restorer
msgid "E600: Missing :endtry"
-msgstr "E600: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :try не указана команда :endtry"
+msgstr "E600: Ðе указана команда :endtry"
# :!~ Restorer
msgid "E601: :try nesting too deep"
@@ -8294,11 +8337,11 @@ msgstr "E601: Превышено количеÑтво вложений комаÐ
# :!~ Restorer
msgid "E602: :endtry without :try"
-msgstr "E602: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endtry нет ÑоответÑтвующей команды :try"
+msgstr "E602: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :endtry отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :try"
# :!~ Restorer
msgid "E603: :catch without :try"
-msgstr "E603: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :catch не указана команда :try"
+msgstr "E603: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :catch отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :try"
# :!~ Restorer
msgid "E604: :catch after :finally"
@@ -8311,7 +8354,7 @@ msgstr "E605: Ðе Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚Ð°Ð½Ð½Ð°Ñ Ð¸ÑÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ ÑитÑ
# :!~ Restorer
msgid "E606: :finally without :try"
-msgstr "E606: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :finally не указана команда :try"
+msgstr "E606: Ð”Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :finally отÑутÑтвует Ð¿Ð°Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° :try"
# :!~ Restorer
msgid "E607: Multiple :finally"
@@ -8372,8 +8415,7 @@ msgstr "E619: Файл не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым файлом Ð
# :!~ Restorer
#, c-format
msgid "E620: Unable to convert to print encoding \"%s\""
-msgstr ""
-"E620: При выводе на печать не удалоÑÑŒ выполнить изменение кодировки на \"%s\""
+msgstr "E620: При выводе на печать не удалоÑÑŒ преобразовать в кодировку \"%s\""
# :!~ Restorer
#, c-format
@@ -8411,7 +8453,7 @@ msgstr "E627: ОтÑутÑтвует Ñимвол двоеточие в кома
#, c-format
msgid "E628: Missing ! or / in: %s"
-msgstr "E628: ОтÑутÑтвует Ñимвол ! или / в команде %s"
+msgstr "E628: ОтÑутÑтвует Ñимвол '!' или '/' в команде %s"
# :!~ Restorer
#, c-format
@@ -8575,7 +8617,7 @@ msgstr ""
# :!~ Restorer
msgid "E669: Unprintable character in group name"
-msgstr "E669: Ðе печатаемый Ñимвол в наименовании группы"
+msgstr "E669: Ðепечатаемый Ñимвол в наименовании группы"
# :!~ Restorer
#, c-format
@@ -8591,7 +8633,8 @@ msgstr "E671: Ðе найдено окно Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð¼ \"%s\""
# :!~ Restorer
msgid "E672: Unable to open window inside MDI application"
msgstr ""
-"E672: Ðе удалоÑÑŒ открыть окно редактора Vim в другой многодокументной программе"
+"E672: Ðе удалоÑÑŒ открыть окно редактора Vim в другой многодокументной "
+"программе"
# :!~ Restorer
msgid "E673: Incompatible multi-byte encoding and character set"
@@ -8600,7 +8643,8 @@ msgstr "E673: ÐеÑоответÑтвие между многобайтовой
# :!~ Restorer
msgid "E674: printmbcharset cannot be empty with multi-byte encoding."
msgstr ""
-"E674: Ðе задано значение параметра 'printmbcharset' Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð±Ð°Ð¹Ñ‚Ð¾Ð²Ð¾Ð¹ кодировки"
+"E674: Ðе задано значение параметра 'printmbcharset' Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ð±Ð°Ð¹Ñ‚Ð¾Ð²Ð¾Ð¹ "
+"кодировки"
# :!~ Restorer
msgid "E675: No default font specified for multi-byte printing."
@@ -8709,7 +8753,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E697: Missing end of List ']': %s"
-msgstr "E697: Ðе указана Ð·Ð°ÐºÑ€Ñ‹Ð²Ð°ÑŽÑ‰Ð°Ñ ÐºÐ²Ð°Ð´Ñ€Ð°Ñ‚Ð½Ð°Ñ Ñкобка в данных типа List %s"
+msgstr "E697: Ðе указана Ð·Ð°ÐºÑ€Ñ‹Ð²Ð°ÑŽÑ‰Ð°Ñ ÐºÐ²Ð°Ð´Ñ€Ð°Ñ‚Ð½Ð°Ñ Ñкобка в данных тип List %s"
# :!~ Restorer
msgid "E698: Variable nested too deep for making a copy"
@@ -8750,7 +8794,8 @@ msgstr "E705: ÐÐ°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ и функции Ñ
# :!~ Restorer
#, c-format
msgid "E706: Argument of %s must be a List, String or Dictionary"
-msgstr "E706: В функции %s тип аргумента должен быть List, String или Dictionary"
+msgstr ""
+"E706: В функции %s тип аргумента должен быть List, String или Dictionary"
# :!~ Restorer
#, c-format
@@ -8829,7 +8874,7 @@ msgstr ""
#, c-format
msgid "E723: Missing end of Dictionary '}': %s"
msgstr ""
-"E723: Ð”Ð»Ñ Ñ‚Ð¸Ð¿Ð° данных Dictionary не указана Ð·Ð°ÐºÑ€Ñ‹Ð²Ð°ÑŽÑ‰Ð°Ñ Ñ„Ð¸Ð³ÑƒÑ€Ð½Ð°Ñ Ñкобка %s"
+"E723: Ð’ типе данных Dictionary не указана Ð·Ð°ÐºÑ€Ñ‹Ð²Ð°ÑŽÑ‰Ð°Ñ Ñ„Ð¸Ð³ÑƒÑ€Ð½Ð°Ñ Ñкобка %s"
# :!~ Restorer
msgid "E724: Variable nested too deep for displaying"
@@ -8933,7 +8978,8 @@ msgstr ""
# :!~ Restorer
msgid "E744: NetBeans does not allow changes in read-only files"
msgstr ""
-"E744: Ð’ ИСР NetBeans не допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ файлов открытых только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
+"E744: Ð’ ИСР NetBeans не допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ файлов открытых только Ð´Ð»Ñ "
+"чтениÑ"
# :!~ Restorer
msgid "E745: Using a List as a Number"
@@ -8972,7 +9018,8 @@ msgstr ""
# :!~ Restorer
msgid "E752: No previous spell replacement"
msgstr ""
-"E752: Ð’ текущем ÑеанÑе работы подобное иÑправление напиÑÐ°Ð½Ð¸Ñ ÐµÑ‰Ñ‘ не выполнÑлаÑÑŒ"
+"E752: Ð’ текущем ÑеанÑе работы подобное иÑправление напиÑÐ°Ð½Ð¸Ñ ÐµÑ‰Ñ‘ не "
+"выполнÑлаÑÑŒ"
# :!~ Restorer
#, c-format
@@ -8999,7 +9046,8 @@ msgstr "E757: Ðекорректный заголовок в данном фай
# :!~ Restorer
msgid "E758: Truncated spell file"
-msgstr "E758: Размер файла не ÑоответÑтвует требуемому. Возможно, файл повреждён"
+msgstr ""
+"E758: Размер файла не ÑоответÑтвует требуемому. Возможно, файл повреждён"
# :!~ Restorer
msgid "E759: Format error in spell file"
@@ -9031,15 +9079,16 @@ msgstr "E764: Ðе задано значение параметра '%s'"
#, c-format
msgid "E765: 'spellfile' does not have %d entries"
msgstr ""
-"E765: Ð’ ÑпиÑке значений параметра 'spellfile' отÑутÑтвует запиÑÑŒ под номером %d"
+"E765: Ð’ ÑпиÑке значений параметра 'spellfile' отÑутÑтвует запиÑÑŒ под номером "
+"%d"
# :!~ Restorer
msgid "E766: Insufficient arguments for printf()"
-msgstr "E766: Ð’ функции printf() недоÑтаточное количеÑтво аргументов"
+msgstr "E766: ÐедоÑтаточное количеÑтво аргументов в функции printf()"
# :!~ Restorer
msgid "E767: Too many arguments for printf()"
-msgstr "E767: Ð’ функции printf() превышено количеÑтво аргументов"
+msgstr "E767: Превышено количеÑтво аргументов в функции printf()"
# :!~ Restorer
#, c-format
@@ -9121,7 +9170,8 @@ msgstr "E783: Обнаружен повтор Ñимвола в правиле M
# :!~ Restorer
msgid "E784: Cannot close last tab page"
msgstr ""
-"E784: Команда не выполнена. Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ программы требуетÑÑ Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одна вкладка"
+"E784: Команда не выполнена. Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ программы требуетÑÑ Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одна "
+"вкладка"
# :!~ Restorer
msgid "E785: complete() can only be used in Insert mode"
@@ -9153,7 +9203,8 @@ msgstr "E790: Запрещено применение команды :undojoin Ð
# :!~ Restorer
msgid "E791: Empty keymap entry"
msgstr ""
-"E791: Ð’ файле Ñ Ñ€Ð°Ñкладкой клавиатуры отÑутÑтвует запиÑÑŒ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñимвола"
+"E791: Ð’ файле Ñ Ñ€Ð°Ñкладкой клавиатуры отÑутÑтвует запиÑÑŒ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ "
+"Ñимвола"
# :!~ Restorer
msgid "E792: Empty menu name"
@@ -9222,7 +9273,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E803: ID not found: %d"
-msgstr "E803: Ðе найден идентификационный номер %d"
+msgstr "E803: Ðе удалоÑÑŒ найти идентификационный номер %d"
# :!~ Restorer
#, no-c-format
@@ -9261,7 +9312,8 @@ msgstr ""
# :!~ Restorer
msgid "E812: Autocommands changed buffer or buffer name"
msgstr ""
-"E812: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ вызвали изменение Ñодержимого или Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±ÑƒÑ„ÐµÑ€Ð°"
+"E812: ДейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´ вызвали изменение Ñодержимого или Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ "
+"буфера"
# :!~ Restorer
msgid "E813: Cannot close autocmd or popup window"
@@ -9336,8 +9388,7 @@ msgstr "E826: Ошибка при раÑшифровке файла измене
# :!~ Restorer
#, c-format
msgid "E827: Undo file is encrypted: %s"
-msgstr ""
-"E827: Ðе поддерживаемый данной программой Vim шифрованный файл изменений %s"
+msgstr "E827: Ð’ данной верÑии не поддерживаетÑÑ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ð¹ файл изменений %s"
# :!~ Restorer
#, c-format
@@ -9361,10 +9412,11 @@ msgstr "E832: Редактируемый файл не шифрован, но ш
# :!~ Restorer
#, c-format
-msgid "E833: %s is encrypted and this version of Vim does not support encryption"
+msgid ""
+"E833: %s is encrypted and this version of Vim does not support encryption"
msgstr ""
-"E833: Ð”Ð°Ð½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ не поддерживает шифрование и обнаружен "
-"шифрованный файл %s"
+"E833: Ð’ данной верÑии не поддерживаетÑÑ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ðµ и обнаружен шифрованный "
+"файл %s"
# :!~ Restorer
msgid "E834: Conflicts with value of 'listchars'"
@@ -9376,15 +9428,11 @@ msgstr "E835: Конфликт значений параметров 'ambiwidth'
# :!~ Restorer
msgid "E836: This Vim cannot execute :python after using :py3"
-msgstr ""
-"E836: Ð’ данной верÑии программы запрещён вызов команды :python поÑле команды :"
-"py3"
+msgstr "E836: Ð’ данной верÑии запрещён вызов команды :python поÑле команды :py3"
# :!~ Restorer
msgid "E837: This Vim cannot execute :py3 after using :python"
-msgstr ""
-"E837: Ð’ данной верÑии программы запрещён вызов команды :py3 поÑле команды :"
-"python"
+msgstr "E837: Ð’ данной верÑии запрещён вызов команды :py3 поÑле команды :python"
# :!~ Restorer
msgid "E838: NetBeans is not supported with this GUI"
@@ -9426,7 +9474,8 @@ msgstr "E846: Ðе указан код клавиши Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°"
# :!~ Restorer
msgid "E847: Too many syntax includes"
msgstr ""
-"E847: Превышено количеÑтво подключаемых файлов Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°Ð¼Ð¸ подÑветки ÑинтакÑиÑа"
+"E847: Превышено количеÑтво подключаемых файлов Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°Ð¼Ð¸ подÑветки "
+"ÑинтакÑиÑа"
# :!~ Restorer
msgid "E848: Too many syntax clusters"
@@ -9492,12 +9541,14 @@ msgstr ""
# :!~ Restorer
msgid "E860: Need 'id' and 'type' or 'types' with 'both'"
msgstr ""
-"E860: ЕÑли задан ключ 'both', укажите значение ключей 'id' и 'type' или 'types'"
+"E860: ЕÑли задан ключ \"both\", укажите значение ключей \"id\" и \"type\" или "
+"\"types\""
# :!~ Restorer
msgid "E861: Cannot open a second popup with a terminal"
msgstr ""
-"E861: Ðе допуÑкаетÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ðµ ещё одного вÑплывающего окна Ñодержащего терминал"
+"E861: Ðе допуÑкаетÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ðµ ещё одного вÑплывающего окна Ñодержащего "
+"терминал"
# :!~ Restorer
msgid "E862: Cannot use g: here"
@@ -9514,8 +9565,8 @@ msgid ""
"E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be "
"used"
msgstr ""
-"E864: Ð”Ð»Ñ Ð¼ÐµÑ‚Ð°Ñимвола \\%#= допуÑтимы 0, 1 или 2. Механизм поиÑка назначаетÑÑ "
-"автоматичеÑки"
+"E864: Ð”Ð»Ñ Ð¼ÐµÑ‚Ð°Ñимвола \\%#= допуÑтимы 0, 1 или 2. Механизм поиÑка был "
+"назначен автоматичеÑки"
# :!~ Restorer
msgid "E865: (NFA) Regexp end encountered prematurely"
@@ -9605,7 +9656,8 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E884: Function name cannot contain a colon: %s"
-msgstr "E884: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ Ñимвол Ð´Ð²Ð¾ÐµÑ‚Ð¾Ñ‡Ð¸Ñ Ð² наименовании функции %s"
+msgstr ""
+"E884: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ Ñимвола двоеточие в наименовании функции %s"
# :!~ Restorer
#, c-format
@@ -9621,7 +9673,8 @@ msgstr "E886: Ðе удалоÑÑŒ переименовать viminfo-файл в
msgid ""
"E887: Sorry, this command is disabled, the Python's site module could not be "
"loaded."
-msgstr "E887: Ðе подключен модуль site.py Ð´Ð»Ñ Ñзыка Python. Команда не выполнена"
+msgstr ""
+"E887: Ðе подключен модуль site.py Ð´Ð»Ñ Ñзыка Python. Команда не выполнена"
# :!~ Restorer
#, c-format
@@ -9655,8 +9708,8 @@ msgstr "E894: ОжидалÑÑ Ñ‚Ð¸Ð¿ данных Float, а получен Dict
# :!~ Restorer
msgid ""
-"E895: Sorry, this command is disabled, the MzScheme's racket/base module could "
-"not be loaded."
+"E895: Sorry, this command is disabled, the MzScheme's racket/base module "
+"could not be loaded."
msgstr ""
"E895: Ðе подключен модуль racket/base Ð´Ð»Ñ Ñзыка MzScheme. Команда не выполнена"
@@ -9749,7 +9802,8 @@ msgstr "E911: ОжидалÑÑ Ñ‚Ð¸Ð¿ данных Float, а получен Job"
# :!~ Restorer
msgid "E912: Cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel"
msgstr ""
-"E912: Функции ch_evalexpr() и ch_sendexpr() неприменимы к Ñоединению RAW или NL"
+"E912: Функции ch_evalexpr() и ch_sendexpr() неприменимы к Ñоединению RAW или "
+"NL"
# :!~ Restorer
msgid "E913: Using a Channel as a Number"
@@ -9993,7 +10047,8 @@ msgstr "E966: ÐедопуÑтимый номер Ñтроки %ld"
# :!~ Restorer
msgid "E968: Need at least one of 'id' or 'type'"
-msgstr "E968: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ значение ключа 'id' или значение ключа 'type'"
+msgstr ""
+"E968: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ значение ключа \"id\" или значение ключа \"type\""
# :!~ Restorer
#, c-format
@@ -10018,8 +10073,8 @@ msgstr ""
# :!~ Restorer
msgid "E973: Blob literal should have an even number of hex characters"
msgstr ""
-"E973: Данные Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ BLOB должны Ñодержать чётное количеÑтво шеÑтнадцатеричных "
-"цифр"
+"E973: Данные Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ BLOB должны Ñодержать чётное количеÑтво "
+"шеÑтнадцатеричных цифр"
# :!~ Restorer
msgid "E974: Using a Blob as a Number"
@@ -10075,7 +10130,8 @@ msgstr ""
# :!~ Restorer
msgid "E986: Cannot modify the tag stack within tagfunc"
msgstr ""
-"E986: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ Ñтека индекÑов через функцию параметра 'tagfunc'"
+"E986: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ Ñтека индекÑов через функцию параметра "
+"'tagfunc'"
# :!~ Restorer
msgid "E987: Invalid return value from tagfunc"
@@ -10090,7 +10146,8 @@ msgstr ""
# :!~ Restorer
msgid "E989: Non-default argument follows default argument"
msgstr ""
-"E989: ОбÑзательные аргументы должны указыватьÑÑ Ð¿ÐµÑ€ÐµÐ´ необÑзательным аргументом"
+"E989: ОбÑзательные аргументы должны указыватьÑÑ Ð¿ÐµÑ€ÐµÐ´ необÑзательным "
+"аргументом"
# :!~ Restorer
#, c-format
@@ -10099,7 +10156,7 @@ msgstr "E990: Ðе указан завершающий маркер '%s'"
# :!~ Restorer
msgid "E991: Cannot use =<< here"
-msgstr "E991: Оператор =<< не может быть применён"
+msgstr "E991: Оператор `=<<` не может быть применён"
# :!~ Restorer
msgid "E992: Not allowed in a modeline when 'modelineexpr' is off"
@@ -10122,28 +10179,34 @@ msgstr "E995: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ
# :!~ Restorer
msgid "E996: Cannot lock a range"
-msgstr "E996: Ðе допуÑкаетÑÑ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ° Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ диапазона"
+msgstr ""
+"E996: Ð”Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ диапазона не может быть изменено ÑоÑтоÑние блокировки"
# :!~ Restorer
msgid "E996: Cannot lock an option"
-msgstr "E996: Ðе допуÑкаетÑÑ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ° Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ параметров"
+msgstr ""
+"E996: Ð”Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ параметров не может быть изменено ÑоÑтоÑние блокировки"
# :!~ Restorer
msgid "E996: Cannot lock a list or dict"
-msgstr "E996: Ðе допуÑкаетÑÑ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ° Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ ÑпиÑка или ÑловарÑ"
+msgstr ""
+"E996: Ð”Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ ÑпиÑка или ÑÐ»Ð¾Ð²Ð°Ñ€Ñ Ð½Ðµ может быть изменено ÑоÑтоÑние "
+"блокировки"
# :!~ Restorer
msgid "E996: Cannot lock an environment variable"
-msgstr "E996: Ðе допуÑкаетÑÑ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ° Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ переменных окружениÑ"
+msgstr ""
+"E996: Ð”Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ переменных Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð½Ðµ может быть изменено ÑоÑтоÑние "
+"блокировки"
# :!~ Restorer
msgid "E996: Cannot lock a register"
-msgstr "E996: Ðе допуÑкаетÑÑ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ° Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… региÑтра"
+msgstr "E996: Ð”Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… региÑтра не может быть изменено ÑоÑтоÑние блокировки"
# :!~ Restorer
#, c-format
msgid "E997: Tabpage not found: %d"
-msgstr "E997: Ðе найдена вкладка под номером %d"
+msgstr "E997: Ðе удалоÑÑŒ найти вкладку под номером %d"
# :!~ Restorer
#, c-format
@@ -10158,7 +10221,7 @@ msgstr "E999: Ð’ программе не поддерживаетÑÑ Ð¾Ð±Ñ€Ð°Ð±
# :!~ Restorer
#, c-format
msgid "E1001: Variable not found: %s"
-msgstr "E1001: Ðе найдена Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ %s"
+msgstr "E1001: Ðе удалоÑÑŒ найти переменную %s"
# :!~ Restorer
#, c-format
@@ -10186,7 +10249,8 @@ msgstr "E1006: ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ %s иÑпользуетÑÑ ÐºÐ°Ðº аргуÐ
# :!~ Restorer
msgid "E1007: Mandatory argument after optional argument"
msgstr ""
-"E1007: ОбÑзательные аргументы указыватьÑÑ Ð¿ÐµÑ€ÐµÐ´ необÑзательным аргументом"
+"E1007: ОбÑзательные аргументы должны указыватьÑÑ Ð¿ÐµÑ€ÐµÐ´ необÑзательным "
+"аргументом"
# :!~ Restorer
#, c-format
@@ -10339,7 +10403,7 @@ msgstr "E1035: Ð”Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸ деление Ñ Ð¾Ñтатком тип
#, c-format
msgid "E1036: %c requires number or float arguments"
msgstr ""
-"E1036: ТребуетÑÑ Ñ‚Ð¸Ð¿ операндов Number или Float Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸ %c"
+"E1036: Тип операндов должен быть Number или Float Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸ %c"
# :!~ Restorer
#, c-format
@@ -10352,12 +10416,14 @@ msgstr "E1038: Команда :vim9script должна указыватьÑÑ Ñ‚
# :!~ Restorer
msgid "E1039: \"vim9script\" must be the first command in a script"
-msgstr "E1039: Команда :vim9script указываетÑÑ Ð¿ÐµÑ€Ð²Ð¾Ð¹ командой в командном файле"
+msgstr ""
+"E1039: Команда :vim9script указываетÑÑ Ð¿ÐµÑ€Ð²Ð¾Ð¹ командой в командном файле"
# :!~ Restorer
msgid "E1040: Cannot use :scriptversion after :vim9script"
msgstr ""
-"E1040: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ команды :scriptversion поÑле команды :vim9script"
+"E1040: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ команды :scriptversion поÑле команды :"
+"vim9script"
# :!~ Restorer
#, c-format
@@ -10366,7 +10432,8 @@ msgstr "E1041: Переопределение компонента командÐ
# :!~ Restorer
msgid "E1042: Export can only be used in vim9script"
-msgstr "E1042: Команда :export должна указыватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в командных файлах Vim9"
+msgstr ""
+"E1042: Команда :export должна указыватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в командных файлах Vim9"
# :!~ Restorer
msgid "E1043: Invalid command after :export"
@@ -10394,7 +10461,7 @@ msgstr "E1049: Компонент не ÑвлÑетÑÑ ÑкÑпортируем
# :!~ Restorer
#, c-format
msgid "E1050: Colon required before a range: %s"
-msgstr "E1050: ТребуетÑÑ Ñимвол Ð´Ð²Ð¾ÐµÑ‚Ð¾Ñ‡Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´ значением диапазона %s"
+msgstr "E1050: ТребуетÑÑ Ñимвол двоеточие перед значением диапазона %s"
# :!~ Restorer
msgid "E1051: Wrong argument type for +"
@@ -10427,7 +10494,7 @@ msgstr "E1056: ОжидалÑÑ Ñ‚Ð¸Ð¿ данных %s"
# :!~ Restorer
msgid "E1057: Missing :enddef"
-msgstr "E1057: Ðе указана команда :enddef Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :def"
+msgstr "E1057: Ðе указана команда :enddef"
# :!~ Restorer
msgid "E1058: Function nesting too deep"
@@ -10436,7 +10503,7 @@ msgstr "E1058: Превышено количеÑтво вложенных фун
# :!~ Restorer
#, c-format
msgid "E1059: No white space allowed before colon: %s"
-msgstr "E1059: Запрещён пробельный Ñимвол перед Ñимволом Ð´Ð²Ð¾ÐµÑ‚Ð¾Ñ‡Ð¸Ñ Ð² %s"
+msgstr "E1059: Запрещён пробельный Ñимвол перед Ñимволом двоеточие в %s"
# :!~ Restorer
#, c-format
@@ -10446,7 +10513,7 @@ msgstr "E1060: Ð’ команде :import отÑутÑтвует Ñимвол Ñ‚Ð
# :!~ Restorer
#, c-format
msgid "E1061: Cannot find function %s"
-msgstr "E1061: Ðе найдена Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ %s"
+msgstr "E1061: Ðе удалоÑÑŒ найти функцию %s"
# :!~ Restorer
msgid "E1062: Cannot index a Number"
@@ -10623,7 +10690,7 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid "E1102: Lambda function not found: %s"
-msgstr "E1102: Ðе найдена лÑмбда-Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ %s"
+msgstr "E1102: Ðе удалоÑÑŒ найти лÑбда-функцию %s"
# :!~ Restorer
msgid "E1103: Dictionary not set"
@@ -10642,7 +10709,7 @@ msgstr "E1105: Ðе допуÑкаетÑÑ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ðµ к ÑÑ‚Ñ
#, c-format
msgid "E1106: One argument too many"
msgid_plural "E1106: %d arguments too many"
-msgstr[0] "E1106: В функцию передано на один аргумент больше"
+msgstr[0] "E1106: В функцию передано на %d аргумент больше"
msgstr[1] "E1106: В функцию передано на %d аргумента больше"
msgstr[2] "E1106: В функцию передано на %d аргументов больше"
@@ -10729,7 +10796,7 @@ msgstr "E1124: Команда \"%s\" допуÑкаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в ко
# :!~ Restorer
msgid "E1125: Final requires a value"
-msgstr "E1125: ТребуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ значение Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ :final"
+msgstr "E1125: ТребуетÑÑ Ð·Ð°Ð´Ð°Ñ‚ÑŒ значение Ð´Ð»Ñ Ñ„Ð¸Ð½Ð°Ð»Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð¹ переменной"
# :!~ Restorer
msgid "E1126: Cannot use :let in Vim9 script"
@@ -10780,8 +10847,7 @@ msgstr "E1135: ОжидалоÑÑŒ логичеÑкое значение, а по
# :!~ Restorer
msgid "E1136: <Cmd> mapping must end with <CR> before second <Cmd>"
msgstr ""
-"E1136: ÐÐ°Ð·Ð½Ð°Ñ‡Ð°ÐµÐ¼Ð°Ñ Ñ‡ÐµÑ€ÐµÐ· <Cmd> команда не завершаетÑÑ <CR> перед Ñледующей "
-"<Cmd>"
+"E1136: ÐÐ°Ð·Ð½Ð°Ñ‡Ð°ÐµÐ¼Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° <Cmd> должна завершаетÑÑ <CR> перед Ñледующей <Cmd>"
# :!~ Restorer
msgid "E1138: Using a Bool as a Number"
@@ -10862,7 +10928,7 @@ msgstr "E1154: Обнаружена попытка Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° ноль"
# :!~ Restorer
msgid "E1155: Cannot define autocommands for ALL events"
-msgstr "E1155: Ðе допуÑкаетÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾ задавать автокоманды Ð´Ð»Ñ Ð²Ñех Ñобытий"
+msgstr "E1155: Ðе допуÑкаетÑÑ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ðµ автокоманд Ñразу Ð´Ð»Ñ Ð²Ñех Ñобытий"
# :!~ Restorer
msgid "E1156: Cannot change the argument list recursively"
@@ -10907,8 +10973,8 @@ msgstr ""
#, c-format
msgid "E1163: Variable %d: type mismatch, expected %s but got %s in %s"
msgstr ""
-"E1163: ÐеÑоответÑтвующий тип данных переменной %d. ОжидалÑÑ %s, а получен %s в "
-"%s"
+"E1163: ÐеÑоответÑтвующий тип данных переменной %d. ОжидалÑÑ %s, а получен %s "
+"в %s"
# :!~ Restorer
msgid "E1164: vim9cmd must be followed by a command"
@@ -10936,7 +11002,7 @@ msgstr "E1168: Этот аргумент уже объÑвлен в команд
# :!~ Restorer
#, c-format
msgid "E1169: Expression too recursive: %s"
-msgstr "E1169: Выражение Ñлишком рекурÑивно %s"
+msgstr "E1169: Ð‘Ð¾Ð»ÑŒÑˆÐ°Ñ Ñ€ÐµÐºÑƒÑ€ÑивноÑÑ‚ÑŒ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ %s"
# :!~ Restorer
msgid "E1170: Cannot use #{ to start a comment"
@@ -10984,11 +11050,11 @@ msgstr ""
# :!~ Restorer
#, c-format
msgid ""
-"E1179: Failed to extract PWD from %s, check your shell's config related to OSC "
-"7"
+"E1179: Failed to extract PWD from %s, check your shell's config related to "
+"OSC 7"
msgstr ""
-"Ðе удалоÑÑŒ извлечь значение текущего рабочего каталога из %s. Проверьте "
-"наÑтройки командной оболочки OSC 7"
+"Ðе удалоÑÑŒ извлечь значение рабочего каталога из %s. Проверьте наÑтройки "
+"командной оболочки OSC 7"
# :!~ Restorer
#, c-format
@@ -11026,7 +11092,7 @@ msgstr "E1186: Выражение не возвращает значение %s"
# :!~ Restorer
msgid "E1187: Failed to source defaults.vim"
-msgstr "E1187: Ошибка при обработке файла defaults.vim"
+msgstr "E1187: Произошла ошибка при обработке файла defaults.vim"
# :!~ Restorer
msgid "E1188: Cannot open a terminal from the command line window"
@@ -11041,7 +11107,7 @@ msgstr "E1189: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ поÑле комаÐ
#, c-format
msgid "E1190: One argument too few"
msgid_plural "E1190: %d arguments too few"
-msgstr[0] "E1190: В функцию передано на один аргумент меньше"
+msgstr[0] "E1190: В функцию передано на %d аргумент меньше"
msgstr[1] "E1190: В функцию передано на %d аргумента меньше"
msgstr[2] "E1190: В функцию передано на %d аргументов меньше"
@@ -11104,7 +11170,7 @@ msgstr "E1203: Ðе допуÑкаетÑÑ Ñимвол точки Ð´Ð»Ñ Ñ‚Ð¸Ð¿
# :!~ Restorer
#, c-format
msgid "E1204: No Number allowed after .: '\\%%%c'"
-msgstr "E1204: Запрещено указание чиÑла поÑле Ñимвола точки в '\\%%%c'"
+msgstr "E1204: Запрещено указание чиÑла поÑле Ñимвола точки в \\%%%c"
# :!~ Restorer
msgid "E1205: No white space allowed between option and"
@@ -11203,7 +11269,8 @@ msgstr "E1223: Тип данных аргумента номер %d должен
# :!~ Restorer
#, c-format
msgid "E1224: String, Number or List required for argument %d"
-msgstr "E1224: Тип данных аргумента номер %d должен быть String, Number или List"
+msgstr ""
+"E1224: Тип данных аргумента номер %d должен быть String, Number или List"
# :!~ Restorer
#, c-format
@@ -11266,7 +11333,7 @@ msgstr "E1236: Ðе допуÑкаетÑÑ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ðµ к %s. Это им
# :!~ Restorer
#, c-format
msgid "E1237: No such user-defined command in current buffer: %s"
-msgstr "E1237: Ð”Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ буфера не обнаружена команда Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %s"
+msgstr "E1237: Ð”Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ буфера не ÑущеÑтвует команды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %s"
# :!~ Restorer
#, c-format
@@ -11290,7 +11357,8 @@ msgstr "E1241: Ð’ команде указан недопуÑтимый раздÐ
# :!~ Restorer
#, c-format
msgid "E1242: No white space allowed before separator: %s"
-msgstr "E1242: Запрещён пробел перед разделителем параметров в команде %s"
+msgstr ""
+"E1242: Запрещён пробельный Ñимвол перед разделителем параметров в команде %s"
# :!~ Restorer
msgid "E1243: ASCII code not in 32-127 range"
@@ -11341,11 +11409,12 @@ msgstr "E1252: Тип данных аргумента номер %d должен
# :!~ Restorer
msgid "E1254: Cannot use script variable in for loop"
-msgstr "E1254: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ локальных переменных в команде цикла :for"
+msgstr ""
+"E1254: Ðе допуÑкаетÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ðµ локальных переменных в команде цикла :for"
# :!~ Restorer
msgid "E1255: <Cmd> mapping must end with <CR>"
-msgstr "E1255: ÐÐ°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ð°Ñ Ñ‡ÐµÑ€ÐµÐ· <Cmd> команда должна завершатьÑÑ Ñимволами <CR>"
+msgstr "E1255: ÐÐ°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° <Cmd> должна завершатьÑÑ Ñимволами <CR>"
# :!~ Restorer
#, c-format
@@ -11355,7 +11424,8 @@ msgstr "E1256: Тип данных аргумента номер %d должен
# :!~ Restorer
#, c-format
msgid "E1257: Imported script must use \"as\" or end in .vim: %s"
-msgstr "E1257: Ðе указано ключевое Ñлово \"as\" или раÑширение файла .vim Ð´Ð»Ñ %s"
+msgstr ""
+"E1257: Ðе указано ключевое Ñлово \"as\" или раÑширение файла .vim Ð´Ð»Ñ %s"
# :!~ Restorer
#, c-format
@@ -11371,7 +11441,7 @@ msgstr "E1259: Ðе указано наименование поÑле импоÑ
# :!~ Restorer
#, c-format
msgid "E1260: Cannot unlet an imported item: %s"
-msgstr "E1260: Ðе допуÑкаетÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ компонент в импортированных данных %s"
+msgstr "E1260: Ðе допуÑкаетÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ компонента в импортированных данных %s"
# :!~ Restorer
msgid "E1261: Cannot import .vim without using \"as\""
@@ -11386,7 +11456,7 @@ msgstr "E1262: Ðе допуÑкаетÑÑ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ðµ импортиро
# :!~ Restorer
msgid "E1263: Cannot use name with # in Vim9 script, use export instead"
msgstr ""
-"E1263: Ðе допуÑкаютÑÑ Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ñимволом #. Ð’ командных файлах Vim9 "
+"E1263: Ðе допуÑкаютÑÑ Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ñимволом '#'. Ð’ командных файлах Vim9 "
"иÑпользуетÑÑ ÑкÑпорт"
# :!~ Restorer
@@ -11431,7 +11501,8 @@ msgstr "E1270: Ðе допуÑкаетÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° вида :s\\/sub/ в
# :!~ Restorer
#, c-format
msgid "E1271: Compiling closure without context: %s"
-msgstr "E1271: КомпилÑÑ†Ð¸Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ функции вне контекÑта вышеÑтоÑщей функции %s"
+msgstr ""
+"E1271: КомпилÑÑ†Ð¸Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ функции вне контекÑта вышеÑтоÑщей функции %s"
# :!~ Restorer
#, c-format
@@ -11492,7 +11563,8 @@ msgstr "E1283: Величина битового Ñдвига должна быÑ
#, c-format
msgid "E1284: Argument 1, list item %d: Dictionary required"
msgstr ""
-"E1284: Тип данных в %d Ñлементе ÑпиÑка аргумента номер 1 должен быть Dictionary"
+"E1284: Тип данных в %d Ñлементе ÑпиÑка аргумента номер 1 должен быть "
+"Dictionary"
# :!~ Restorer
#, c-format
@@ -11535,20 +11607,24 @@ msgstr "E1292: Окно командной Ñтроки уже ÑущеÑтвуÐ
# :!~ Restorer
msgid "E1293: Cannot use a negative id after adding a textprop with text"
msgstr ""
-"E1293: Запрещено отрицательное значение ИД поÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ текÑта"
+"E1293: Запрещено отрицательное значение ИД поÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ "
+"текÑта"
# :!~ Restorer
msgid "E1294: Can only use text_align when column is zero"
-msgstr "E1294: Ключ \"text_align\" допуÑтим при нулевом значении позиции колонки"
+msgstr ""
+"E1294: Ключ \"text_align\" допуÑтим при нулевом значении позиции колонки"
# :!~ Restorer
msgid "E1295: Cannot specify both 'type' and 'types'"
-msgstr "E1295: Ðе допуÑкаетÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ðµ указание ключей \"type\" и \"types\""
+msgstr ""
+"E1295: Ðе допуÑкаетÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ðµ указание ключей \"type\" и \"types\""
# :!~ Restorer
msgid "E1296: Can only use left padding when column is zero"
msgstr ""
-"E1296: Ключ \"text_padding_left\" допуÑтим при нулевом значении позиции колонки"
+"E1296: Ключ \"text_padding_left\" допуÑтим при нулевом значении позиции "
+"колонки"
# :!~ Restorer
#, c-format
@@ -11605,8 +11681,7 @@ msgstr "E1306: Превышено количеÑтво вложенных цик
#, c-format
msgid "E1307: Argument %d: Trying to modify a const %s"
msgstr ""
-"E1307: Обнаружена попытка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð½Ñтантного Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ %2$s у аргумента "
-"номер %1$d"
+"E1307: Ð”Ð»Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð° номер %d попытка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð½Ñтантного Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ %s"
# :!~ Restorer
msgid "E1308: Cannot resize a window in another tab page"
@@ -11692,12 +11767,12 @@ msgstr "E1325: У клаÑÑа \"%2$s\" отÑутÑтвует метод \"%1$s
# :!~ Restorer
#, c-format
msgid "E1326: Variable \"%s\" not found in object \"%s\""
-msgstr "E1326: У объекта \"%s\" отÑутÑтвует Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ \"%s\""
+msgstr "E1326: У объекта \"%2$s\" отÑутÑтвует Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ \"%1$s\""
# :!~ Restorer
#, c-format
msgid "E1327: Object required, found %s"
-msgstr "E1327: ОжидалÑÑ Object, а получен %s"
+msgstr "E1327: ОжидалÑÑ Ñ‚Ð¸Ð¿ данных Object, а получен %s"
# :!~ Restorer
#, c-format
@@ -11763,7 +11838,8 @@ msgstr "E1341: Обнаружено повторное объÑвление пе
# :!~ Restorer
msgid "E1342: Interface can only be defined in Vim9 script"
-msgstr "E1342: Тип Interface может быть определён только в командных файлах Vim9"
+msgstr ""
+"E1342: Тип Interface может быть определён только в командных файлах Vim9"
# :!~ Restorer
#, c-format
@@ -11772,7 +11848,7 @@ msgstr "E1343: Ðаименование интерфейÑа должно нач
# :!~ Restorer
msgid "E1344: Cannot initialize a variable in an interface"
-msgstr "E1344: Ðе допуÑкаетÑÑ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ переменные в интерфейÑе"
+msgstr "E1344: Ðе допуÑкаетÑÑ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ… в интерфейÑе"
# :!~ Restorer
#, c-format
@@ -11948,7 +12024,7 @@ msgstr "E1380: ИнтерфейÑÑ‹ не поддерживают защищён
# :!~ Restorer
msgid "E1381: Interface cannot use \"implements\""
-msgstr "E1381: Ð”Ð»Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа неприменимо ключевое Ñлово \"implements\""
+msgstr "E1381: К интерфейÑу неприменимо ключевое Ñлово \"implements\""
# :!~ Restorer
#, c-format
@@ -11992,9 +12068,11 @@ msgstr "E1389: Ðе указано наименование поÑле ключÐ
# :!~ Restorer
#, c-format
msgid ""
-"E1390: Cannot use an object variable \"this.%s\" except with the \"new\" method"
+"E1390: Cannot use an object variable \"this.%s\" except with the \"new\" "
+"method"
msgstr ""
-"E1390: ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° \"this.%s\" может указыватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в методе \"new\""
+"E1390: ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° \"this.%s\" может указыватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в методе "
+"\"new\""
# :!~ Restorer
#, c-format
@@ -12027,7 +12105,7 @@ msgstr "E1395: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ пÑевдоним
# :!~ Restorer
#, c-format
msgid "E1396: Type alias \"%s\" already exists"
-msgstr "E1396: ПÑевдоним типа уже определён \"%s\""
+msgstr "E1396: ПÑевдоним типа уже ÑущеÑтвует \"%s\""
# :!~ Restorer
msgid "E1397: Missing type alias name"
@@ -12092,7 +12170,7 @@ msgstr "E1408: ИнтерфейÑÑ‹ не поддерживают финализ
msgid "E1409: Cannot change read-only variable \"%s\" in class \"%s\""
msgstr ""
"E1409: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ доÑтупной только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ \"%s\" "
-"в клаÑÑе \"%s\""
+"клаÑÑа \"%s\""
# :!~ Restorer
msgid "E1410: Const variable not supported in an interface"
@@ -12116,8 +12194,8 @@ msgstr "E1501: Ðргумент номер %d не указан в позициÐ
# :!~ Restorer
#, c-format
msgid ""
-"E1502: Positional argument %d used as field width reused as different type: %s/"
-"%s"
+"E1502: Positional argument %d used as field width reused as different type: "
+"%s/%s"
msgstr ""
"E1502: Ð”Ð»Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð° номер %d в Ñпецификации позиции указан тип %s, а в "
"Ñпецификации ширины — тип %s"
@@ -12141,7 +12219,8 @@ msgstr "E1505: ÐедопуÑтимые Ñпецификаторы форматÐ
# :!~ Restorer
msgid "E1506: Buffer too small to copy xattr value or key"
-msgstr "E1506: ÐедоÑтаточный размер буфера Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ€Ð°Ñширенного атрибута"
+msgstr ""
+"E1506: ÐедоÑтаточный размер буфера Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ€Ð°Ñширенного атрибута"
# :!~ Restorer
msgid ""
@@ -12159,6 +12238,16 @@ msgstr "E1509: Произошла ошибка при Ñчитывании илÐ
msgid "E1510: Value too large: %s"
msgstr "E1510: Превышена допуÑÑ‚Ð¸Ð¼Ð°Ñ Ð²ÐµÐ»Ð¸Ñ‡Ð¸Ð½Ð° в значении %s"
+# :!~ Restorer
+#, c-format
+msgid "E1511: Wrong number of characters for field \"%s\""
+msgstr "E1511: Ð’ данном поле указано недопуÑтимое количеÑтво Ñимволов \"%s\""
+
+# :!~ Restorer
+#, c-format
+msgid "E1512: Wrong character width for field \"%s\""
+msgstr "E1512: Ð’ данном поле не поддерживаютÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑˆÐ¸Ñ€Ð¸Ð½Ð½Ñ‹Ðµ Ñимволы \"%s\""
+
# #Restorer: выводитÑÑ, например, по команде `CTRL+g`, `g CTRL+g` и Ñ‚. п.
# :!~ Restorer
msgid "--No lines in buffer--"
@@ -12209,6 +12298,7 @@ msgid "float"
msgstr "float"
# :!~ Restorer
+#.
msgid "search hit TOP, continuing at BOTTOM"
msgstr "ПоиÑк будет продолжен от ÐИЖÐЕЙ ГРÐÐИЦЫ документа"
@@ -12247,7 +12337,9 @@ msgstr "не удалоÑÑŒ выполнить добавление в ÑловÐ
# :!~ Restorer
#, c-format
msgid "index must be int or slice, not %s"
-msgstr "Ð¸Ð½Ð´ÐµÐºÑ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ÑÑ Ñ†ÐµÐ»Ñ‹Ð¼ чиÑлом или как диапазон. ÐедопуÑтимый Ð¸Ð½Ð´ÐµÐºÑ %s"
+msgstr ""
+"Ð¸Ð½Ð´ÐµÐºÑ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ÑÑ ÐºÐ°Ðº целое чиÑло или как диапазон чиÑел. ÐедопуÑтимый "
+"Ð¸Ð½Ð´ÐµÐºÑ %s"
# :!~ Restorer
#, c-format
@@ -12298,7 +12390,7 @@ msgstr "задано недопуÑтимое ÑвойÑтво %s"
# :!~ Restorer
msgid "failed to change directory"
-msgstr "Ñбой при Ñмене каталога"
+msgstr "произошёл Ñбой при Ñмене каталога"
# :!~ Restorer
#, c-format
@@ -12317,8 +12409,8 @@ msgstr ""
# :!~ Restorer
msgid "internal error: imp.find_module returned tuple with NULL"
msgstr ""
-"внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Результат функции imp.find_module() неизменÑемый ÑпиÑок без "
-"Ñлементов"
+"внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Результат функции imp.find_module() неизменÑемый ÑпиÑок "
+"без Ñлементов"
# :!~ Restorer
msgid "cannot delete vim.Dictionary attributes"
@@ -12345,7 +12437,8 @@ msgstr "ожидалаÑÑŒ поÑледовательноÑÑ‚ÑŒ из двух Ñ
# :!~ Restorer
msgid "list constructor does not accept keyword arguments"
msgstr ""
-"не допуÑкаетÑÑ Ð¸Ñпользовать в конÑтрукторе объекта List зарезервированные Ñлова"
+"не допуÑкаетÑÑ Ð¸Ñпользовать в конÑтрукторе объекта List зарезервированные "
+"Ñлова"
# :!~ Restorer
msgid "list index out of range"
@@ -12355,7 +12448,8 @@ msgstr "Ð¸Ð½Ð´ÐµÐºÑ ÑпиÑка выходит за границы диапаÐ
#, c-format
msgid "internal error: failed to get Vim list item %d"
msgstr ""
-"внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Ðе удалоÑÑŒ получить у объекта Vim.List Ñлемент Ñ Ð¸Ð½Ð´ÐµÐºÑом %d"
+"внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Ðе удалоÑÑŒ получить из объекта Vim.List Ñлемент Ñ Ð¸Ð½Ð´ÐµÐºÑом "
+"%d"
# :!~ Restorer
msgid "slice step cannot be zero"
@@ -12433,8 +12527,8 @@ msgstr "не допуÑкаетÑÑ ÑÐ±Ñ€Ð¾Ñ Ðº начальным значеÐ
#, c-format
msgid "unable to unset option %s which does not have global value"
msgstr ""
-"не допуÑкаетÑÑ ÑÐ±Ñ€Ð¾Ñ Ðº начальным значениÑм, еÑли не уÑтановлено глобальное "
-"значение у параметра %s"
+"не допуÑкаетÑÑ ÑÐ±Ñ€Ð¾Ñ Ðº начальным значениÑм, еÑли не уÑтановлено значение у "
+"общего параметра %s"
# :!~ Restorer
msgid "attempt to refer to deleted tab page"
@@ -12523,7 +12617,8 @@ msgstr "не удалоÑÑŒ преобразовать в тип List прогр
# :!~ Restorer
#, c-format
msgid "unable to convert %s to a Vim structure"
-msgstr "не удалоÑÑŒ преобразовать в тип данных программы Vim переданный объект %s"
+msgstr ""
+"не удалоÑÑŒ преобразовать в тип данных программы Vim переданный объект %s"
# :!~ Restorer
msgid "internal error: NULL reference passed"
@@ -12604,7 +12699,7 @@ msgstr ""
"Файлы редактора Vim (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n"
# #Restorer: иÑпользуетÑÑ Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° desktop
-# ~!: earlier
+# :!~ Restorer
msgid "GVim"
msgstr "gVim"
@@ -12630,25 +12725,27 @@ msgstr "Vim"
# :!~ Restorer
msgid "(local to window)"
-msgstr "(облаÑÑ‚ÑŒ дейÑтвиÑ: локально Ð´Ð»Ñ Ð¾ÐºÐ½Ð°)"
+msgstr "(облаÑÑ‚ÑŒ дейÑтвиÑ: только Ð´Ð»Ñ Ð¾ÐºÐ½Ð°)"
# :!~ Restorer
msgid "(local to buffer)"
-msgstr "(облаÑÑ‚ÑŒ дейÑтвиÑ: локально Ð´Ð»Ñ Ð±ÑƒÑ„ÐµÑ€Ð°)"
+msgstr "(облаÑÑ‚ÑŒ дейÑтвиÑ: только Ð´Ð»Ñ Ð±ÑƒÑ„ÐµÑ€Ð°)"
# :!~ Restorer
msgid "(global or local to buffer)"
-msgstr "(облаÑÑ‚ÑŒ дейÑтвиÑ: Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ð°Ñ Ð¸Ð»Ð¸ локально Ð´Ð»Ñ Ð±ÑƒÑ„ÐµÑ€Ð°)"
+msgstr "(облаÑÑ‚ÑŒ дейÑтвиÑ: общий или только Ð´Ð»Ñ Ð±ÑƒÑ„ÐµÑ€Ð°)"
# :!~ Restorer
msgid "\" Each \"set\" line shows the current value of an option (on the left)."
msgstr ""
-"\" Ð’ Ñтроках, начинающихÑÑ Ñо Ñлова «set», показано текущее значение параметров"
+"\" Ð’ Ñтроках, начинающихÑÑ Ñо Ñлова «set», показано текущее значение "
+"параметров"
# :!~ Restorer
msgid "\" Hit <Enter> on a \"set\" line to execute it."
msgstr ""
-"\" Чтобы применить параметр, нажмите клавишу <ENTER> на Ñтроке Ñо Ñловом «set»:"
+"\" Чтобы применить параметр, нажмите клавишу <ENTER> на Ñтроке Ñо Ñловом "
+"«set»:"
# :!~ Restorer
msgid "\" A boolean option will be toggled."
@@ -12664,7 +12761,8 @@ msgstr ""
# :!~ Restorer
msgid "\" Hit <Enter> on a help line to open a help window on this option."
msgstr ""
-"\" Чтобы получить Ñправку по параметру, нажмите клавишу <ENTER> на его опиÑании"
+"\" Чтобы получить Ñправку по параметру, нажмите клавишу <ENTER> на его "
+"опиÑании"
# :!~ Restorer
msgid "\" Hit <Enter> on an index line to jump there."
@@ -12674,7 +12772,8 @@ msgstr ""
# :!~ Restorer
msgid "\" Hit <Space> on a \"set\" line to refresh it."
msgstr ""
-"\" Чтобы обновить значение параметра, нажмите клавишу <SPACE> на Ñтроке Ñ Â«set»"
+"\" Чтобы обновить значение параметра, нажмите клавишу <SPACE> на Ñтроке Ñ "
+"«set»"
# :!~ Restorer
msgid "important"
@@ -12729,7 +12828,7 @@ msgid ""
"many jump commands move the cursor to the first non-blank\n"
"character of a line"
msgstr ""
-"уÑтановка каретки на первый не пробельный Ñимвол в Ñтроке\n"
+"уÑтановка каретки на первый непробельный Ñимвол в Ñтроке\n"
"поÑредÑтвом команд перемещениÑ"
# :!~ Restorer
@@ -12950,7 +13049,7 @@ msgid ""
"include \"uhex\" to show unprintable characters as a hex number"
msgstr ""
"\"lastline\" — индикациÑ, еÑли Ñтрока чаÑтично отображена в окне\n"
-"\"uhex\" — показ непечатаемых Ñимволов как шеÑтнадцатеричные чиÑла"
+"\"uhex\" — показ непечатаемых Ñимволов как шеÑтнадцатеричное значение"
# :!~ Restorer
msgid "characters to use for the status line, folds and filler lines"
@@ -13020,7 +13119,8 @@ msgstr "режимы, в которых текÑÑ‚ под кареткой моÐ
# :!~ Restorer
msgid "syntax, highlighting and spelling"
-msgstr "РаÑпознавание ÑинтакÑиÑа файлов, подÑветка текÑта, проверка правопиÑаниÑ"
+msgstr ""
+"РаÑпознавание ÑинтакÑиÑа файлов, подÑветка текÑта, проверка правопиÑаниÑ"
# :!~ Restorer
msgid "\"dark\" or \"light\"; the background color brightness"
@@ -13292,7 +13392,7 @@ msgstr "иÑпользуемый терминалом протокол обмеÐ
# :!~ Restorer
msgid "recognize keys that start with <Esc> in Insert mode"
-msgstr "раÑпознавать в режиме вÑтавки коды клавиш начинающиеÑÑ Ñ <ESC>"
+msgstr "раÑпознавать в режиме вÑтавки коды клавиш начинающиеÑÑ Ñ <Esc>"
# :!~ Restorer
msgid "minimal number of lines to scroll at a time"
@@ -13430,8 +13530,7 @@ msgstr "облаÑÑ‚ÑŒ Ñкрана, оÑтающаÑÑÑ Ð½Ðµ занÑтой о
# :!~ Restorer
msgid "list of ASCII characters that can be combined into complex shapes"
-msgstr ""
-"перечень Ñимволов в кодировке ASCII, иÑпользуемых в ÑоÑтавных Ñимволах"
+msgstr "перечень Ñимволов кодировки ASCII, иÑпользуемых в ÑоÑтавных Ñимволах"
# :!~ Restorer
msgid "options for text rendering"
@@ -13803,7 +13902,7 @@ msgstr ""
# :!~ Restorer
msgid "a <Tab> in an indent inserts 'shiftwidth' spaces"
msgstr ""
-"при нажатии клавиши <TAB> в начале Ñтроки будет вÑтавка пробелов\n"
+"при нажатии клавиши <TAB> , в начале Ñтроки будет вÑтавка пробелов\n"
"как задано в параметре 'shiftwidth'"
# :!~ Restorer
@@ -13888,11 +13987,11 @@ msgstr "Структурирование текÑта"
# :!~ Restorer
msgid "unset to display all folds open"
-msgstr "еÑли не уÑтановлено, то развернуть вÑе Ñвёрнутые Ñтроки"
+msgstr "еÑли не уÑтановлено, то развернуть вÑе Ñвёрнутые блоки"
# :!~ Restorer
msgid "folds with a level higher than this number will be closed"
-msgstr "Ñтроки Ñтруктуры Ñ ÑƒÑ€Ð¾Ð²Ð½ÐµÐ¼ выше указанного будут Ñвёрнуты"
+msgstr "Ñтроки Ñтруктуры, Ñ ÑƒÑ€Ð¾Ð²Ð½ÐµÐ¼ выше указанного, будут Ñвёрнуты"
# :!~ Restorer
msgid "value for 'foldlevel' when starting to edit a file"
@@ -14055,7 +14154,7 @@ msgstr "форматы файла, которые проверÑÑŽÑ‚ÑÑ Ð¿ÐµÑ€Ð
# :!~ Restorer
msgid "obsolete, use 'fileformat'"
-msgstr "выведен из употреблениÑ, дейÑтвует параметр 'fileformat'"
+msgstr "больше не применÑетÑÑ, иÑпользовать параметр 'fileformat'"
# :!~ Restorer
msgid "obsolete, use 'fileformats'"
diff --git a/src/po/sr.po b/src/po/sr.po
index 413a4cc..2f5113c 100644
--- a/src/po/sr.po
+++ b/src/po/sr.po
@@ -2,7 +2,7 @@
#
# Do ":help uganda" in Vim to read copying and usage conditions.
# Do ":help credits" in Vim to see a list of people who contributed.
-# Copyright (C) 2023
+# Copyright (C) 2024
# This file is distributed under the same license as the Vim package.
# FIRST AUTHOR Ivan Pešić <ivan.pesic@gmail.com>, 2017.
#
@@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Vim(Serbian)\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-12-20 12:15+0400\n"
-"PO-Revision-Date: 2023-12-20 12:17+0400\n"
+"POT-Creation-Date: 2024-03-04 14:05+0400\n"
+"PO-Revision-Date: 2024-03-04 14:10+0400\n"
"Last-Translator: Ivan Pešić <ivan.pesic@gmail.com>\n"
"Language-Team: Serbian\n"
"Language: sr\n"
@@ -180,6 +180,9 @@ msgstr " (фајл %d од %d)"
msgid " (file (%d) of %d)"
msgstr " (фајл (%d) од %d)"
+msgid "[Command Line]"
+msgstr "[Командна линија]"
+
msgid "[Prompt]"
msgstr "[Одзив]"
@@ -705,9 +708,6 @@ msgstr "Грешка"
msgid "Interrupt"
msgstr "Прекид"
-msgid "[Command Line]"
-msgstr "[Командна линија]"
-
msgid "is a directory"
msgstr "је директоријум"
@@ -1451,6 +1451,9 @@ msgstr "mapnew() аргумент"
msgid "filter() argument"
msgstr "filter() аргумент"
+msgid "foreach() argument"
+msgstr "foreach() аргумент"
+
msgid "extendnew() argument"
msgstr "extendnew() аргумент"
@@ -2508,6 +2511,9 @@ msgstr "у %s на %s"
msgid "Printing '%s'"
msgstr "Штампа Ñе ’%s’"
+msgid "DefaultFontNameForWindows"
+msgstr "Consolas"
+
#, c-format
msgid "Opening the X display took %ld msec"
msgstr "Отварање X приказа је трајало %ld мÑек"
@@ -3456,8 +3462,8 @@ msgid "%s returning %s"
msgstr "%s враћа %s"
#, c-format
-msgid "Function %s does not need compiling"
-msgstr "Ðије потребно да Ñе функција %s компајлира"
+msgid "Function %s%s%s does not need compiling"
+msgstr "Ðије потребно да Ñе функција %s%s%s компајлира"
#, c-format
msgid "%s (%s, compiled %s)"
@@ -4214,6 +4220,10 @@ msgid "E105: Using :loadkeymap not in a sourced file"
msgstr "E105: Коришћење :loadkeymap ван фајла који Ñе учитава као Ñкрипта"
#, c-format
+msgid "E106: Unsupported diff output format: %s"
+msgstr "E106: Ðије подржан diff излазни формат: %s"
+
+#, c-format
msgid "E107: Missing parentheses: %s"
msgstr "E107: ÐедоÑтају заграде: %s"
@@ -4543,8 +4553,8 @@ msgstr "E196: У овој верзији нема диграфа"
msgid "E197: Cannot set language to \"%s\""
msgstr "E197: Језик не може да Ñе поÑтави на „%sâ€"
-msgid "E199: Active window or buffer deleted"
-msgstr "E199: Active window or buffer deleted"
+msgid "E199: Active window or buffer changed or deleted"
+msgstr "E199: Ðктивни прозор или бафер је измењен или обриÑан"
msgid "E200: *ReadPre autocommands made the file unreadable"
msgstr "E200: *ReadPre аутокоманде Ñу учиниле фајл нечитљивим"
@@ -8747,6 +8757,13 @@ msgid "E1411: Missing dot after object \"%s\""
msgstr "E1411: ÐедоÑтаје тачка након објекта „%sâ€"
#, c-format
+msgid "E1412: Builtin object method \"%s\" not supported"
+msgstr "E1412: Ðије подржана уграђена метода објекта „%sâ€"
+
+msgid "E1413: Builtin class method not supported"
+msgstr "E1413: Ðије подржана уграђена метода клаÑе"
+
+#, c-format
msgid "E1500: Cannot mix positional and non-positional arguments: %s"
msgstr "E1500: Ðе могу да Ñе мешају позициони и непозициони аргументи: %s"
@@ -8792,6 +8809,17 @@ msgstr ""
msgid "E1510: Value too large: %s"
msgstr "E1510: ВредноÑÑ‚ је превелика: %s"
+#, c-format
+msgid "E1511: Wrong number of characters for field \"%s\""
+msgstr "E1511: Погрешан број карактера за поље „%sâ€"
+
+#, c-format
+msgid "E1512: Wrong character width for field \"%s\""
+msgstr "E1512: Погрешна ширина карактера за поље „%sâ€"
+
+msgid "E1513: Cannot edit buffer. 'winfixbuf' is enabled"
+msgstr "E1513: Ðе може да Ñе уређује бафер. Укључена је опција 'winfixbuf'"
+
msgid "--No lines in buffer--"
msgstr "--У баферу нема линија--"
@@ -9525,6 +9553,9 @@ msgstr "минимални број линија који Ñе кориÑти з
msgid "minimal number of lines used for any window"
msgstr "минимални број линија који Ñе кориÑти за било који прозор"
+msgid "keep window focused on a single buffer"
+msgstr "одржава Ñ„Ð¾ÐºÑƒÑ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð° на одређени бафер"
+
msgid "keep the height of the window"
msgstr "задржава Ñе виÑина прозора"
diff --git a/src/popupwin.c b/src/popupwin.c
index 64bb0b5..bdf4ac7 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -3899,8 +3899,8 @@ may_update_popup_mask(int type)
// The screen position "line" / "col" needs to be
// redrawn. Figure out what window that is and update
- // w_redraw_top and w_redr_bot. Only needs to be done
- // once for each window line.
+ // w_redraw_top and w_redraw_bot. Only needs to be
+ // done once for each window line.
wp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP);
if (wp != NULL)
{
diff --git a/src/profiler.c b/src/profiler.c
index 780b958..504d713 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -287,11 +287,13 @@ profile_equal(proftime_T *tm1, proftime_T *tm2)
profile_cmp(const proftime_T *tm1, const proftime_T *tm2)
{
# ifdef MSWIN
- return (int)(tm2->QuadPart - tm1->QuadPart);
+ return tm2->QuadPart == tm1->QuadPart ? 0 :
+ tm2->QuadPart > tm1->QuadPart ? 1 : -1;
# else
if (tm1->tv_sec == tm2->tv_sec)
- return tm2->tv_fsec - tm1->tv_fsec;
- return tm2->tv_sec - tm1->tv_sec;
+ return tm2->tv_fsec == tm1->tv_fsec ? 0 :
+ tm2->tv_fsec > tm1->tv_fsec ? 1 : -1;
+ return tm2->tv_sec > tm1->tv_sec ? 1 : -1;
# endif
}
diff --git a/src/proto/diff.pro b/src/proto/diff.pro
index d14907e..9c34dcf 100644
--- a/src/proto/diff.pro
+++ b/src/proto/diff.pro
@@ -30,4 +30,5 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1);
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp);
void f_diff_filler(typval_T *argvars, typval_T *rettv);
void f_diff_hlID(typval_T *argvars, typval_T *rettv);
+void f_diff(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */
diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro
index 9879a40..ea14fe5 100644
--- a/src/proto/evalvars.pro
+++ b/src/proto/evalvars.pro
@@ -77,7 +77,7 @@ void vars_clear_ext(hashtab_T *ht, int free_val);
void delete_var(hashtab_T *ht, hashitem_T *hi);
int before_set_vvar(char_u *varname, dictitem_T *di, typval_T *tv, int copy, int *type_error);
void set_var(char_u *name, typval_T *tv, int copy);
-void set_var_const(char_u *name, scid_T sid, type_T *type_arg, typval_T *tv_arg, int copy, int flags_arg, int var_idx);
+int set_var_const(char_u *name, scid_T sid, type_T *type_arg, typval_T *tv_arg, int copy, int flags_arg, int var_idx);
int var_check_permission(dictitem_T *di, char_u *name);
int var_check_ro(int flags, char_u *name, int use_gettext);
int var_check_lock(int flags, char_u *name, int use_gettext);
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index b122a14..1473879 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -30,7 +30,7 @@ int typebuf_changed(int tb_change_cnt);
int typebuf_typed(void);
int typebuf_maplen(void);
void del_typebuf(int len, int offset);
-void gotchars_nop(void);
+void gotchars_ignore(void);
void ungetchars(int len);
int save_typebuf(void);
void save_typeahead(tasave_T *tp);
diff --git a/src/proto/gui_gtk_x11.pro b/src/proto/gui_gtk_x11.pro
index e85cf20..d019cf0 100644
--- a/src/proto/gui_gtk_x11.pro
+++ b/src/proto/gui_gtk_x11.pro
@@ -13,7 +13,7 @@ void gui_mch_show_tabline(int showit);
int gui_mch_showing_tabline(void);
void gui_mch_update_tabline(void);
void gui_mch_set_curtab(int nr);
-void gui_gtk_set_selection_targets(void);
+void gui_gtk_set_selection_targets(GdkAtom);
void gui_gtk_set_dnd_targets(void);
int gui_mch_init(void);
void gui_mch_forked(void);
diff --git a/src/proto/indent.pro b/src/proto/indent.pro
index 5ab338d..bafcefc 100644
--- a/src/proto/indent.pro
+++ b/src/proto/indent.pro
@@ -14,8 +14,8 @@ long get_sts_value(void);
int get_indent(void);
int get_indent_lnum(linenr_T lnum);
int get_indent_buf(buf_T *buf, linenr_T lnum);
-int get_indent_str(char_u *ptr, int ts, int list);
-int get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list);
+int get_indent_str(char_u *ptr, int ts, int no_ts);
+int get_indent_str_vtab(char_u *ptr, int ts, int *vts, int no_ts);
int set_indent(int size, int flags);
int get_number_indent(linenr_T lnum);
int briopt_check(win_T *wp);
diff --git a/src/proto/list.pro b/src/proto/list.pro
index 5abe03c..0b58c69 100644
--- a/src/proto/list.pro
+++ b/src/proto/list.pro
@@ -56,6 +56,7 @@ int filter_map_one(typval_T *tv, typval_T *expr, filtermap_T filtermap, funccall
void f_filter(typval_T *argvars, typval_T *rettv);
void f_map(typval_T *argvars, typval_T *rettv);
void f_mapnew(typval_T *argvars, typval_T *rettv);
+void f_foreach(typval_T *argvars, typval_T *rettv);
void f_add(typval_T *argvars, typval_T *rettv);
void f_count(typval_T *argvars, typval_T *rettv);
void f_extend(typval_T *argvars, typval_T *rettv);
diff --git a/src/proto/memline.pro b/src/proto/memline.pro
index 3fa8707..c5d9b5d 100644
--- a/src/proto/memline.pro
+++ b/src/proto/memline.pro
@@ -19,6 +19,11 @@ char_u *ml_get(linenr_T lnum);
char_u *ml_get_pos(pos_T *pos);
char_u *ml_get_curline(void);
char_u *ml_get_cursor(void);
+colnr_T ml_get_len(linenr_T lnum);
+colnr_T ml_get_pos_len(pos_T *pos);
+colnr_T ml_get_curline_len(void);
+colnr_T ml_get_cursor_len(void);
+colnr_T ml_get_buf_len(buf_T *buf, linenr_T lnum);
char_u *ml_get_buf(buf_T *buf, linenr_T lnum, int will_change);
int ml_line_alloced(void);
int ml_append(linenr_T lnum, char_u *line, colnr_T len, int newfile);
diff --git a/src/proto/move.pro b/src/proto/move.pro
index b96b86d..bc9c025 100644
--- a/src/proto/move.pro
+++ b/src/proto/move.pro
@@ -1,6 +1,5 @@
/* move.c */
int adjust_plines_for_skipcol(win_T *wp);
-void redraw_for_cursorline(win_T *wp);
int sms_marker_overlap(win_T *wp, int extra2);
void update_topline_redraw(void);
void update_topline(void);
diff --git a/src/proto/ops.pro b/src/proto/ops.pro
index 193e894..bebe635 100644
--- a/src/proto/ops.pro
+++ b/src/proto/ops.pro
@@ -14,6 +14,7 @@ void adjust_cursor_eol(void);
char_u *skip_comment(char_u *line, int process, int include_space, int *is_comment);
int do_join(long count, int insert_space, int save_undo, int use_formatoptions, int setmark);
void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int is_del);
+void charwise_block_prep(pos_T start, pos_T end, struct block_def *bdp, linenr_T lnum, int inclusive);
void op_addsub(oparg_T *oap, linenr_T Prenum1, int g_cmd);
void clear_oparg(oparg_T *oap);
void cursor_pos_info(dict_T *dict);
diff --git a/src/proto/option.pro b/src/proto/option.pro
index effa813..be7ee95 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -29,7 +29,6 @@ char *did_set_autochdir(optset_T *args);
char *did_set_ballooneval(optset_T *args);
char *did_set_balloonevalterm(optset_T *args);
char *did_set_binary(optset_T *args);
-char *did_set_breakat(optset_T *args);
char *did_set_buflisted(optset_T *args);
char *did_set_cmdheight(optset_T *args);
char *did_set_compatible(optset_T *args);
diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro
index cfd1982..340ffc4 100644
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -20,6 +20,7 @@ int expand_set_backupcopy(optexpand_T *args, int *numMatches, char_u ***matches)
char *did_set_backupext_or_patchmode(optset_T *args);
char *did_set_belloff(optset_T *args);
int expand_set_belloff(optexpand_T *args, int *numMatches, char_u ***matches);
+char *did_set_breakat(optset_T *args);
char *did_set_breakindentopt(optset_T *args);
int expand_set_breakindentopt(optexpand_T *args, int *numMatches, char_u ***matches);
char *did_set_browsedir(optset_T *args);
diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro
index 17a9ba2..4731010 100644
--- a/src/proto/os_mswin.pro
+++ b/src/proto/os_mswin.pro
@@ -51,6 +51,7 @@ void serverProcessPendingMessages(void);
char *charset_id2name(int id);
char *quality_id2name(DWORD id);
void gui_mch_expand_font(optexpand_T *args, void *param, int (*add_match)(char_u *val));
+UINT WINAPI vimGetDpiForSystem(void);
int get_logfont(LOGFONTW *lf, char_u *name, HDC printer_dc, int verbose);
void channel_init_winsock(void);
/* vim: set ft=c : */
diff --git a/src/proto/screen.pro b/src/proto/screen.pro
index b4f54a2..cf7cd95 100644
--- a/src/proto/screen.pro
+++ b/src/proto/screen.pro
@@ -7,7 +7,7 @@ int compute_foldcolumn(win_T *wp, int col);
size_t fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum);
int screen_get_current_line_off(void);
void reset_screen_attr(void);
-void screen_line(win_T *wp, int row, int coloff, int endcol, int clear_width, int flags);
+void screen_line(win_T *wp, int row, int coloff, int endcol, int clear_width, colnr_T last_vcol, int flags);
void rl_mirror(char_u *str);
void draw_vsep_win(win_T *wp, int row);
int stl_connected(win_T *wp);
@@ -55,8 +55,8 @@ void comp_col(void);
int number_width(win_T *wp);
int screen_screencol(void);
int screen_screenrow(void);
-char *set_fillchars_option(win_T *wp, char_u *val, int apply);
-char *set_listchars_option(win_T *wp, char_u *val, int apply);
+char *set_fillchars_option(win_T *wp, char_u *val, int apply, char *errbuf, size_t errbuflen);
+char *set_listchars_option(win_T *wp, char_u *val, int apply, char *errbuf, size_t errbuflen);
char_u *get_fillchars_name(expand_T *xp, int idx);
char_u *get_listchars_name(expand_T *xp, int idx);
char *check_chars_options(void);
diff --git a/src/proto/search.pro b/src/proto/search.pro
index 99e279d..5b2b889 100644
--- a/src/proto/search.pro
+++ b/src/proto/search.pro
@@ -32,7 +32,7 @@ int check_linecomment(char_u *line);
void showmatch(int c);
int current_search(long count, int forward);
int linewhite(linenr_T lnum);
-void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum);
+void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum, int forceit);
spat_T *get_spat(int idx);
int get_spat_last_idx(void);
void f_searchcount(typval_T *argvars, typval_T *rettv);
diff --git a/src/proto/term.pro b/src/proto/term.pro
index b83df86..d82f906 100644
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -33,6 +33,7 @@ void term_set_winsize(int height, int width);
void term_fg_color(int n);
void term_bg_color(int n);
void term_ul_color(int n);
+void term_font(int n);
char_u *term_bg_default(void);
void term_fg_rgb_color(guicolor_T rgb);
void term_bg_rgb_color(guicolor_T rgb);
diff --git a/src/proto/typval.pro b/src/proto/typval.pro
index c9845e0..b6ea131 100644
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -26,6 +26,7 @@ int check_for_opt_list_arg(typval_T *args, int idx);
int check_for_dict_arg(typval_T *args, int idx);
int check_for_nonnull_dict_arg(typval_T *args, int idx);
int check_for_opt_dict_arg(typval_T *args, int idx);
+int check_for_opt_nonnull_dict_arg(typval_T *args, int idx);
int check_for_chan_or_job_arg(typval_T *args, int idx);
int check_for_opt_chan_or_job_arg(typval_T *args, int idx);
int check_for_job_arg(typval_T *args, int idx);
diff --git a/src/proto/undo.pro b/src/proto/undo.pro
index 851d281..619ad70 100644
--- a/src/proto/undo.pro
+++ b/src/proto/undo.pro
@@ -18,10 +18,9 @@ void ex_undojoin(exarg_T *eap);
void u_unchanged(buf_T *buf);
void u_find_first_changed(void);
void u_update_save_nr(buf_T *buf);
-void u_clearall(buf_T *buf);
void u_clearline(void);
void u_undoline(void);
-void u_blockfree(buf_T *buf);
+void u_clearallandblockfree(buf_T *buf);
int bufIsChanged(buf_T *buf);
int anyBufIsChanged(void);
int bufIsChangedNotTerm(buf_T *buf);
diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro
index e393c04..9bb4616 100644
--- a/src/proto/userfunc.pro
+++ b/src/proto/userfunc.pro
@@ -50,6 +50,7 @@ void list_functions(regmatch_T *regmatch);
ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free, int class_flags, ocmember_T *obj_members, int obj_member_count);
void ex_function(exarg_T *eap);
ufunc_T *find_func_by_name(char_u *name, compiletype_T *compile_type);
+void defcompile_function(ufunc_T *ufunc, class_T *cl);
void ex_defcompile(exarg_T *eap);
int eval_fname_script(char_u *p);
int translated_function_exists(char_u *name, int is_global);
diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro
index f1b6360..1ed175e 100644
--- a/src/proto/vim9class.pro
+++ b/src/proto/vim9class.pro
@@ -1,5 +1,7 @@
/* vim9class.c */
int object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl);
+int is_valid_builtin_obj_methodname(char_u *funcname);
+ufunc_T *class_get_builtin_method(class_T *cl, class_builtin_T builtin_method, int *method_idx);
void ex_class(exarg_T *eap);
type_T *oc_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx);
type_T *oc_member_type_by_idx(class_T *cl, int is_object, int member_idx);
@@ -31,6 +33,13 @@ void object_free_items(int copyID);
void emsg_var_cl_define(char *msg, char_u *name, size_t len, class_T *cl);
void method_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len);
void member_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len);
+void defcompile_class(class_T *cl);
+void defcompile_classes_in_script(void);
+int is_class_name(char_u *name, typval_T *rettv);
+void protected_method_access_errmsg(char_u *method_name);
+int object_empty(object_T *obj);
+int object_len(object_T *obj);
+char_u *object_string(object_T *obj, char_u *numbuf, int copyID, int echo_style, int restore_copyID, int composite_val);
int class_instance_of(class_T *cl, class_T *other_cl);
void f_instanceof(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */
diff --git a/src/proto/window.pro b/src/proto/window.pro
index cfb771d..9e66db5 100644
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -1,11 +1,15 @@
/* window.c */
+int check_can_set_curbuf_disabled(void);
+int check_can_set_curbuf_forceit(int forceit);
int window_layout_locked(enum CMD_index cmd);
win_T *prevwin_curwin(void);
win_T *swbuf_goto_win_with_buf(buf_T *buf);
void do_window(int nchar, long Prenum, int xchar);
void get_wincmd_addr_type(char_u *arg, exarg_T *eap);
+int check_split_disallowed(win_T *wp);
int win_split(int size, int flags);
-int win_split_ins(int size, int flags, win_T *new_wp, int dir);
+int win_splitmove(win_T *wp, int size, int flags);
+int win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_flatten);
int win_valid_popup(win_T *win);
int win_valid(win_T *win);
win_T *win_find_by_id(int id);
@@ -18,6 +22,7 @@ void leaving_window(win_T *win);
void entering_window(win_T *win);
void curwin_init(void);
void close_windows(buf_T *buf, int keep_curwin);
+int last_window(void);
int one_window(void);
int win_close(win_T *win, int free_buf);
void snapshot_windows_scroll_size(void);
@@ -25,7 +30,7 @@ void may_make_initial_scroll_size_snapshot(void);
void may_trigger_win_scrolled_resized(void);
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp);
void win_free_all(void);
-win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp);
+win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp, frame_T **unflat_altfr);
void close_others(int message, int forceit);
void unuse_tabpage(tabpage_T *tp);
void use_tabpage(tabpage_T *tp);
@@ -87,10 +92,11 @@ int only_one_window(void);
void check_lnums(int do_curwin);
void check_lnums_nested(int do_curwin);
void reset_lnums(void);
-void make_snapshot(int idx);
+int make_snapshot(int idx);
void restore_snapshot(int idx, int close_curwin);
int win_hasvertsplit(void);
int get_win_number(win_T *wp, win_T *first_win);
int get_tab_number(tabpage_T *tp);
char *check_colorcolumn(win_T *wp);
+int get_last_winid(void);
/* vim: set ft=c : */
diff --git a/src/quickfix.c b/src/quickfix.c
index dd681ca..0bf4cfe 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -780,9 +780,9 @@ qf_get_next_buf_line(qfstate_T *state)
return QF_END_OF_INPUT;
p_buf = ml_get_buf(state->buf, state->buflnum, FALSE);
+ len = ml_get_buf_len(state->buf, state->buflnum);
state->buflnum += 1;
- len = (int)STRLEN(p_buf);
if (len > IOSIZE - 2)
{
state->linebuf = qf_grow_linebuf(state, len);
@@ -3146,7 +3146,8 @@ qf_goto_win_with_qfl_file(int qf_fnum)
// Didn't find it, go to the window before the quickfix
// window, unless 'switchbuf' contains 'uselast': in this case we
// try to jump to the previously used window first.
- if ((swb_flags & SWB_USELAST) && win_valid(prevwin))
+ if ((swb_flags & SWB_USELAST) && win_valid(prevwin) &&
+ !prevwin->w_p_wfb)
win = prevwin;
else if (altwin != NULL)
win = altwin;
@@ -3158,7 +3159,8 @@ qf_goto_win_with_qfl_file(int qf_fnum)
}
// Remember a usable window.
- if (altwin == NULL && !win->w_p_pvw && bt_normal(win->w_buffer))
+ if (altwin == NULL && !win->w_p_pvw && !win->w_p_wfb &&
+ bt_normal(win->w_buffer))
altwin = win;
}
@@ -3261,8 +3263,51 @@ qf_jump_edit_buffer(
prev_winid == curwin->w_id ? curwin : NULL);
}
else
- retval = buflist_getfile(qf_ptr->qf_fnum,
- (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
+ {
+ int fnum = qf_ptr->qf_fnum;
+
+ if (!forceit && curwin->w_p_wfb && curbuf->b_fnum != fnum)
+ {
+ if (qi->qfl_type == QFLT_LOCATION)
+ {
+ // Location lists cannot split or reassign their window
+ // so 'winfixbuf' windows must fail
+ emsg(_(e_winfixbuf_cannot_go_to_buffer));
+ return FAIL;
+ }
+
+ if (win_valid(prevwin) && !prevwin->w_p_wfb &&
+ !bt_quickfix(prevwin->w_buffer))
+ {
+ // 'winfixbuf' is set; attempt to change to a window without it
+ // that isn't a quickfix/location list window.
+ win_goto(prevwin);
+ }
+ if (curwin->w_p_wfb)
+ {
+ // Split the window, which will be 'nowinfixbuf', and set curwin
+ // to that
+ if (win_split(0, 0) == OK)
+ *opened_window = TRUE;
+
+ if (curwin->w_p_wfb)
+ {
+ // Autocommands set 'winfixbuf' or sent us to another window
+ // with it set, or we failed to split the window. Give up,
+ // but don't return immediately, as they may have messed
+ // with the list.
+ emsg(_(e_winfixbuf_cannot_go_to_buffer));
+ retval = FAIL;
+ }
+ }
+ }
+
+ if (retval == OK)
+ {
+ retval = buflist_getfile(fnum,
+ (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
+ }
+ }
// If a location list, check whether the associated window is still
// present.
@@ -4829,8 +4874,17 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
}
// delete all existing lines
+ //
+ // Note: we cannot store undo information, because
+ // qf buffer is usually not allowed to be modified.
+ //
+ // So we need to clean up undo information
+ // otherwise autocommands may invalidate the undo stack
while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0)
(void)ml_delete((linenr_T)1);
+
+ // Remove all undo information
+ u_clearallandblockfree(curbuf);
}
// Check if there is anything to display
@@ -4982,6 +5036,11 @@ qf_jump_first(qf_info_T *qi, int_u save_qfid, int forceit)
if (qf_restore_list(qi, save_qfid) == FAIL)
return;
+
+ if (!check_can_set_curbuf_forceit(forceit))
+ return;
+
+
// Autocommands might have cleared the list, check for that.
if (!qf_list_empty(qf_get_curlist(qi)))
qf_jump(qi, 0, 0, forceit);
@@ -5898,7 +5957,7 @@ ex_cfile(exarg_T *eap)
// This function is used by the :cfile, :cgetfile and :caddfile
// commands.
- // :cfile always creates a new quickfix list and jumps to the
+ // :cfile always creates a new quickfix list and may jump to the
// first error.
// :cgetfile creates a new quickfix list but doesn't jump to the
// first error.
@@ -6137,13 +6196,14 @@ vgr_match_buflines(
break;
col = regmatch->endpos[0].col
+ (col == regmatch->endpos[0].col);
- if (col > (colnr_T)STRLEN(ml_get_buf(buf, lnum, FALSE)))
+ if (col > ml_get_buf_len(buf, lnum))
break;
}
}
else
{
char_u *str = ml_get_buf(buf, lnum, FALSE);
+ colnr_T linelen = ml_get_buf_len(buf, lnum);
int score;
int_u matches[MAX_FUZZY_MATCHES];
int_u sz = ARRAY_LENGTH(matches);
@@ -6182,7 +6242,7 @@ vgr_match_buflines(
if ((flags & VGR_GLOBAL) == 0)
break;
col = matches[pat_len - 1] + col + 1;
- if (col > (colnr_T)STRLEN(str))
+ if (col > linelen)
break;
}
}
@@ -6488,6 +6548,9 @@ ex_vimgrep(exarg_T *eap)
char_u *au_name = NULL;
int status;
+ if (!check_can_set_curbuf_forceit(eap->forceit))
+ return;
+
au_name = vgr_get_auname(eap->cmdidx);
if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
curbuf->b_fname, TRUE, curbuf))
diff --git a/src/regexp.c b/src/regexp.c
index c3bc496..4373ae0 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -1318,6 +1318,9 @@ reg_match_visual(void)
top = curbuf->b_visual.vi_end;
bot = curbuf->b_visual.vi_start;
}
+ // a substitute command may have removed some lines
+ if (bot.lnum > curbuf->b_ml.ml_line_count)
+ bot.lnum = curbuf->b_ml.ml_line_count;
mode = curbuf->b_visual.vi_mode;
curswant = curbuf->b_visual.vi_curswant;
}
diff --git a/src/register.c b/src/register.c
index f381e30..47ed218 100644
--- a/src/register.c
+++ b/src/register.c
@@ -832,8 +832,9 @@ insert_reg(
if ((State & REPLACE_FLAG) != 0)
{
pos_T curpos;
- u_save_cursor();
- del_bytes((long)STRLEN(y_current->y_array[0]), TRUE, FALSE);
+ if (u_save_cursor() == FAIL)
+ return FAIL;
+ del_chars((long)mb_charlen(y_current->y_array[0]), TRUE);
curpos = curwin->w_cursor;
if (oneright() == FAIL)
// hit end of line, need to put forward (after the current position)
@@ -1147,7 +1148,6 @@ op_yank(oparg_T *oap, int deleting, int mess)
int yanktype = oap->motion_type;
long yanklines = oap->line_count;
linenr_T yankendlnum = oap->end.lnum;
- char_u *p;
char_u *pnew;
struct block_def bd;
#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
@@ -1239,70 +1239,7 @@ op_yank(oparg_T *oap, int deleting, int mess)
case MCHAR:
{
- colnr_T startcol = 0, endcol = MAXCOL;
- int is_oneChar = FALSE;
- colnr_T cs, ce;
-
- p = ml_get(lnum);
- bd.startspaces = 0;
- bd.endspaces = 0;
-
- if (lnum == oap->start.lnum)
- {
- startcol = oap->start.col;
- if (virtual_op)
- {
- getvcol(curwin, &oap->start, &cs, NULL, &ce);
- if (ce != cs && oap->start.coladd > 0)
- {
- // Part of a tab selected -- but don't
- // double-count it.
- bd.startspaces = (ce - cs + 1)
- - oap->start.coladd;
- if (bd.startspaces < 0)
- bd.startspaces = 0;
- startcol++;
- }
- }
- }
-
- if (lnum == oap->end.lnum)
- {
- endcol = oap->end.col;
- if (virtual_op)
- {
- getvcol(curwin, &oap->end, &cs, NULL, &ce);
- if (p[endcol] == NUL || (cs + oap->end.coladd < ce
- // Don't add space for double-wide
- // char; endcol will be on last byte
- // of multi-byte char.
- && (*mb_head_off)(p, p + endcol) == 0))
- {
- if (oap->start.lnum == oap->end.lnum
- && oap->start.col == oap->end.col)
- {
- // Special case: inside a single char
- is_oneChar = TRUE;
- bd.startspaces = oap->end.coladd
- - oap->start.coladd + oap->inclusive;
- endcol = startcol;
- }
- else
- {
- bd.endspaces = oap->end.coladd
- + oap->inclusive;
- endcol -= oap->inclusive;
- }
- }
- }
- }
- if (endcol == MAXCOL)
- endcol = (colnr_T)STRLEN(p);
- if (startcol > endcol || is_oneChar)
- bd.textlen = 0;
- else
- bd.textlen = endcol - startcol + oap->inclusive;
- bd.textstart = p + startcol;
+ charwise_block_prep(oap->start, oap->end, &bd, lnum, oap->inclusive);
if (yank_copy_line(&bd, y_idx, FALSE) == FAIL)
goto fail;
break;
@@ -1856,7 +1793,7 @@ do_put(
}
// get the old line and advance to the position to insert at
oldp = ml_get_curline();
- oldlen = (int)STRLEN(oldp);
+ oldlen = ml_get_curline_len();
init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0,
oldp, oldp);
@@ -1902,10 +1839,10 @@ do_put(
spaces = y_width + 1;
init_chartabsize_arg(&cts, curwin, 0, 0,
y_array[i], y_array[i]);
- for (j = 0; j < yanklen; j++)
+
+ while (*cts.cts_ptr != NUL)
{
- spaces -= lbr_chartabsize(&cts);
- ++cts.cts_ptr;
+ spaces -= lbr_chartabsize_adv(&cts);
cts.cts_vcol = 0;
}
clear_chartabsize_arg(&cts);
@@ -1987,7 +1924,7 @@ do_put(
curwin->w_cursor.col++;
// in Insert mode we might be after the NUL, correct for that
- len = (colnr_T)STRLEN(ml_get_curline());
+ len = ml_get_curline_len();
if (curwin->w_cursor.col > len)
curwin->w_cursor.col = len;
}
@@ -2071,7 +2008,7 @@ do_put(
totlen = count * yanklen;
do {
oldp = ml_get(lnum);
- oldlen = (int)STRLEN(oldp);
+ oldlen = ml_get_len(lnum);
if (lnum > start_lnum)
{
pos_T pos;
@@ -2151,7 +2088,7 @@ do_put(
lnum = new_cursor.lnum;
ptr = ml_get(lnum) + col;
totlen = (int)STRLEN(y_array[y_size - 1]);
- newp = alloc(STRLEN(ptr) + totlen + 1);
+ newp = alloc(ml_get_len(lnum) - col + totlen + 1);
if (newp == NULL)
goto error;
STRCPY(newp, y_array[y_size - 1]);
@@ -2192,7 +2129,7 @@ do_put(
curwin->w_cursor.lnum = lnum;
ptr = ml_get(lnum);
if (cnt == count && i == y_size - 1)
- lendiff = (int)STRLEN(ptr);
+ lendiff = ml_get_len(lnum);
if (*ptr == '#' && preprocs_left())
indent = 0; // Leave # lines at start
else
@@ -2210,7 +2147,7 @@ do_put(
curwin->w_cursor = old_pos;
// remember how many chars were removed
if (cnt == count && i == y_size - 1)
- lendiff -= (int)STRLEN(ml_get(lnum));
+ lendiff -= ml_get_len(lnum);
}
}
if (cnt == 1)
@@ -2302,7 +2239,7 @@ error:
curwin->w_set_curswant = TRUE;
// Make sure the cursor is not after the NUL.
- int len = (int)STRLEN(ml_get_curline());
+ int len = ml_get_curline_len();
if (curwin->w_cursor.col > len)
{
if (cur_ve_flags == VE_ALL)
diff --git a/src/screen.c b/src/screen.c
index ac24a16..71ddbca 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -18,8 +18,7 @@
* displayed (excluding text written by external commands).
* ScreenAttrs[off] Contains the associated attributes.
* ScreenCols[off] Contains the virtual columns in the line. -1 means not
- * available or before buffer text, MAXCOL means after the
- * end of the line.
+ * available or before buffer text.
*
* LineOffset[row] Contains the offset into ScreenLines*[], ScreenAttrs[]
* and ScreenCols[] for each line.
@@ -452,6 +451,10 @@ skip_for_popup(int row, int col)
* SLF_RIGHTLEFT rightleft window:
* When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
* When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
+ * SLF_INC_VCOL:
+ * When FALSE, use "last_vcol" for ScreenCols[] of the columns to clear.
+ * When TRUE, use an increasing sequence starting from "last_vcol + 1" for
+ * ScreenCols[] of the columns to clear.
*/
void
screen_line(
@@ -460,6 +463,7 @@ screen_line(
int coloff,
int endcol,
int clear_width,
+ colnr_T last_vcol,
int flags UNUSED)
{
unsigned off_from;
@@ -504,6 +508,8 @@ screen_line(
// Clear rest first, because it's left of the text.
if (clear_width > 0)
{
+ int clear_start = col;
+
while (col <= endcol && ScreenLines[off_to] == ' '
&& ScreenAttrs[off_to] == 0
&& (!enc_utf8 || ScreenLinesUC[off_to] == 0))
@@ -514,6 +520,10 @@ screen_line(
if (col <= endcol)
screen_fill(row, row + 1, col + coloff,
endcol + coloff + 1, ' ', ' ', 0);
+
+ for (int i = endcol; i >= clear_start; i--)
+ ScreenCols[off_to + (i - col)] =
+ (flags & SLF_INC_VCOL) ? ++last_vcol : last_vcol;
}
col = endcol + 1;
off_to = LineOffset[row] + col + coloff;
@@ -775,7 +785,8 @@ screen_line(
&& ScreenAttrs[off_to] == 0
&& (!enc_utf8 || ScreenLinesUC[off_to] == 0))
{
- ScreenCols[off_to] = MAXCOL;
+ ScreenCols[off_to] =
+ (flags & SLF_INC_VCOL) ? ++last_vcol : last_vcol;
++off_to;
++col;
}
@@ -830,7 +841,8 @@ screen_line(
' ', ' ', 0);
while (col < clear_width)
{
- ScreenCols[off_to++] = MAXCOL;
+ ScreenCols[off_to++]
+ = (flags & SLF_INC_VCOL) ? ++last_vcol : last_vcol;
++col;
}
}
@@ -1667,6 +1679,8 @@ screen_start_highlight(int attr)
*/
if (aep != NULL)
{
+ if (aep->ae_u.cterm.font > 0 && aep->ae_u.cterm.font < 12)
+ term_font(aep->ae_u.cterm.font);
#ifdef FEAT_TERMGUICOLORS
// When 'termguicolors' is set but fg or bg is unset,
// fall back to the cterm colors. This helps for SpellBad,
@@ -2567,6 +2581,25 @@ give_up:
new_LineOffset[new_row] = new_row * Columns;
new_LineWraps[new_row] = FALSE;
+ (void)vim_memset(new_ScreenLines + new_row * Columns,
+ ' ', (size_t)Columns * sizeof(schar_T));
+ if (enc_utf8)
+ {
+ (void)vim_memset(new_ScreenLinesUC + new_row * Columns,
+ 0, (size_t)Columns * sizeof(u8char_T));
+ for (int i = 0; i < p_mco; ++i)
+ (void)vim_memset(new_ScreenLinesC[i]
+ + new_row * Columns,
+ 0, (size_t)Columns * sizeof(u8char_T));
+ }
+ if (enc_dbcs == DBCS_JPNU)
+ (void)vim_memset(new_ScreenLines2 + new_row * Columns,
+ 0, (size_t)Columns * sizeof(schar_T));
+ (void)vim_memset(new_ScreenAttrs + new_row * Columns,
+ 0, (size_t)Columns * sizeof(sattr_T));
+ (void)vim_memset(new_ScreenCols + new_row * Columns,
+ 0, (size_t)Columns * sizeof(colnr_T));
+
/*
* If the screen is not going to be cleared, copy as much as
* possible from the old screen to the new one and clear the rest
@@ -2575,24 +2608,6 @@ give_up:
*/
if (!doclear)
{
- (void)vim_memset(new_ScreenLines + new_row * Columns,
- ' ', (size_t)Columns * sizeof(schar_T));
- if (enc_utf8)
- {
- (void)vim_memset(new_ScreenLinesUC + new_row * Columns,
- 0, (size_t)Columns * sizeof(u8char_T));
- for (int i = 0; i < p_mco; ++i)
- (void)vim_memset(new_ScreenLinesC[i]
- + new_row * Columns,
- 0, (size_t)Columns * sizeof(u8char_T));
- }
- if (enc_dbcs == DBCS_JPNU)
- (void)vim_memset(new_ScreenLines2 + new_row * Columns,
- 0, (size_t)Columns * sizeof(schar_T));
- (void)vim_memset(new_ScreenAttrs + new_row * Columns,
- 0, (size_t)Columns * sizeof(sattr_T));
- (void)vim_memset(new_ScreenCols + new_row * Columns,
- 0, (size_t)Columns * sizeof(colnr_T));
old_row = new_row + (screen_Rows - Rows);
if (old_row >= 0 && ScreenLines != NULL)
{
@@ -4533,7 +4548,7 @@ comp_col(void)
if (!last_has_status)
sc_col = ru_col;
}
- if (p_sc)
+ if (p_sc && *p_sloc == 'l')
{
sc_col += SHOWCMD_COLS;
if (!p_ru || last_has_status) // no need for separating space
@@ -4688,6 +4703,15 @@ static struct charstab lcstab[] =
{NULL, "leadmultispace"},
};
+ static char *
+field_value_err(char *errbuf, size_t errbuflen, char *fmt, char *field)
+{
+ if (errbuf == NULL)
+ return "";
+ vim_snprintf(errbuf, errbuflen, _(fmt), field);
+ return errbuf;
+}
+
/*
* Handle setting 'listchars' or 'fillchars'.
* "value" points to either the global or the window-local value.
@@ -4697,7 +4721,8 @@ static struct charstab lcstab[] =
* Returns error message, NULL if it's OK.
*/
static char *
-set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
+set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply,
+ char *errbuf, size_t errbuflen)
{
int round, i, len, entries;
char_u *p, *s;
@@ -4777,9 +4802,7 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
for (i = 0; i < entries; ++i)
{
len = (int)STRLEN(tab[i].name);
- if (!(STRNCMP(p, tab[i].name, len) == 0
- && p[len] == ':'
- && p[len + 1] != NUL))
+ if (!(STRNCMP(p, tab[i].name, len) == 0 && p[len] == ':'))
continue;
if (is_listchars && strcmp(tab[i].name, "multispace") == 0)
@@ -4794,12 +4817,16 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
{
c1 = get_encoded_char_adv(&s);
if (char2cells(c1) > 1)
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
++multispace_len;
}
if (multispace_len == 0)
// lcs-multispace cannot be an empty string
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
p = s;
}
else
@@ -4830,12 +4857,16 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
{
c1 = get_encoded_char_adv(&s);
if (char2cells(c1) > 1)
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
++lead_multispace_len;
}
if (lead_multispace_len == 0)
// lcs-leadmultispace cannot be an empty string
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
p = s;
}
else
@@ -4855,21 +4886,33 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
c2 = c3 = 0;
s = p + len + 1;
+ if (*s == NUL)
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
c1 = get_encoded_char_adv(&s);
if (char2cells(c1) > 1)
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
if (tab[i].cp == &lcs_chars.tab2)
{
if (*s == NUL)
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
c2 = get_encoded_char_adv(&s);
if (char2cells(c2) > 1)
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
if (!(*s == ',' || *s == NUL))
{
c3 = get_encoded_char_adv(&s);
if (char2cells(c3) > 1)
- return e_invalid_argument;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
}
}
@@ -4890,6 +4933,10 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
p = s;
break;
}
+ else
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
}
if (i == entries)
@@ -4921,18 +4968,20 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply)
* Handle the new value of 'fillchars'.
*/
char *
-set_fillchars_option(win_T *wp, char_u *val, int apply)
+set_fillchars_option(win_T *wp, char_u *val, int apply, char *errbuf,
+ size_t errbuflen)
{
- return set_chars_option(wp, val, FALSE, apply);
+ return set_chars_option(wp, val, FALSE, apply, errbuf, errbuflen);
}
/*
* Handle the new value of 'listchars'.
*/
char *
-set_listchars_option(win_T *wp, char_u *val, int apply)
+set_listchars_option(win_T *wp, char_u *val, int apply, char *errbuf,
+ size_t errbuflen)
{
- return set_chars_option(wp, val, TRUE, apply);
+ return set_chars_option(wp, val, TRUE, apply, errbuf, errbuflen);
}
/*
@@ -4972,15 +5021,15 @@ check_chars_options(void)
tabpage_T *tp;
win_T *wp;
- if (set_listchars_option(curwin, p_lcs, FALSE) != NULL)
+ if (set_listchars_option(curwin, p_lcs, FALSE, NULL, 0) != NULL)
return e_conflicts_with_value_of_listchars;
- if (set_fillchars_option(curwin, p_fcs, FALSE) != NULL)
+ if (set_fillchars_option(curwin, p_fcs, FALSE, NULL, 0) != NULL)
return e_conflicts_with_value_of_fillchars;
FOR_ALL_TAB_WINDOWS(tp, wp)
{
- if (set_listchars_option(wp, wp->w_p_lcs, FALSE) != NULL)
+ if (set_listchars_option(wp, wp->w_p_lcs, FALSE, NULL, 0) != NULL)
return e_conflicts_with_value_of_listchars;
- if (set_fillchars_option(wp, wp->w_p_fcs, FALSE) != NULL)
+ if (set_fillchars_option(wp, wp->w_p_fcs, FALSE, NULL, 0) != NULL)
return e_conflicts_with_value_of_fillchars;
}
return NULL;
diff --git a/src/scriptfile.c b/src/scriptfile.c
index 69016bf..6dc5557 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1690,6 +1690,8 @@ do_source_ext(
// reset version, "vim9script" may have been added or removed.
si->sn_version = 1;
}
+ if (ret_sid != NULL)
+ *ret_sid = sid;
}
else
{
diff --git a/src/search.c b/src/search.c
index d4baa91..166ef4a 100644
--- a/src/search.c
+++ b/src/search.c
@@ -660,7 +660,7 @@ searchit(
&& pos->col < MAXCOL - 2)
{
ptr = ml_get_buf(buf, pos->lnum, FALSE);
- if ((int)STRLEN(ptr) <= pos->col)
+ if (ml_get_buf_len(buf, pos->lnum) <= pos->col)
start_char_len = 1;
else
start_char_len = (*mb_ptr2len)(ptr + pos->col);
@@ -966,8 +966,7 @@ searchit(
if (pos->lnum > 1) // just in case
{
--pos->lnum;
- pos->col = (colnr_T)STRLEN(ml_get_buf(buf,
- pos->lnum, FALSE));
+ pos->col = ml_get_buf_len(buf, pos->lnum);
}
}
else
@@ -1102,7 +1101,7 @@ searchit(
if (pos->lnum > buf->b_ml.ml_line_count)
{
pos->lnum = buf->b_ml.ml_line_count;
- pos->col = (int)STRLEN(ml_get_buf(buf, pos->lnum, FALSE));
+ pos->col = ml_get_buf_len(buf, pos->lnum);
if (pos->col > 0)
--pos->col;
}
@@ -1772,7 +1771,7 @@ searchc(cmdarg_T *cap, int t_cmd)
p = ml_get_curline();
col = curwin->w_cursor.col;
- len = (int)STRLEN(p);
+ len = ml_get_curline_len();
while (count--)
{
@@ -2315,7 +2314,7 @@ findmatchlimit(
break;
linep = ml_get(pos.lnum);
- pos.col = (colnr_T)STRLEN(linep); // pos.col on trailing NUL
+ pos.col = ml_get_len(pos.lnum); // pos.col on trailing NUL
do_quotes = -1;
line_breakcheck();
@@ -2492,7 +2491,7 @@ findmatchlimit(
if (pos.lnum > 1)
{
ptr = ml_get(pos.lnum - 1);
- if (*ptr && *(ptr + STRLEN(ptr) - 1) == '\\')
+ if (*ptr && *(ptr + ml_get_len(pos.lnum - 1) - 1) == '\\')
{
do_quotes = 1;
if (start_in_quotes == MAYBE)
@@ -2986,8 +2985,7 @@ current_search(
// try again from end of buffer
// searching backwards, so set pos to last line and col
pos.lnum = curwin->w_buffer->b_ml.ml_line_count;
- pos.col = (colnr_T)STRLEN(
- ml_get(curwin->w_buffer->b_ml.ml_line_count));
+ pos.col = ml_get_len(curwin->w_buffer->b_ml.ml_line_count);
}
}
}
@@ -3292,7 +3290,8 @@ find_pattern_in_path(
long count,
int action, // What to do when we find it
linenr_T start_lnum, // first line to start searching
- linenr_T end_lnum) // last line for searching
+ linenr_T end_lnum, // last line for searching
+ int forceit) // If true, always switch to the found path
{
SearchedFile *files; // Stack of included files
SearchedFile *bigger; // When we need more space
@@ -3829,7 +3828,7 @@ search_line:
break;
if (!GETFILE_SUCCESS(getfile(
curwin_save->w_buffer->b_fnum, NULL,
- NULL, TRUE, lnum, FALSE)))
+ NULL, TRUE, lnum, forceit)))
break; // failed to jump to file
}
else
@@ -3842,7 +3841,7 @@ search_line:
{
if (!GETFILE_SUCCESS(getfile(
0, files[depth].name, NULL, TRUE,
- files[depth].lnum, FALSE)))
+ files[depth].lnum, forceit)))
break; // failed to jump to file
// autocommands may have changed the lnum, we don't
// want that here
@@ -4561,7 +4560,10 @@ fuzzy_match_item_compare(const void *s1, const void *s2)
int idx1 = ((fuzzyItem_T *)s1)->idx;
int idx2 = ((fuzzyItem_T *)s2)->idx;
- return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+ if (v1 == v2)
+ return idx1 == idx2 ? 0 : idx1 > idx2 ? 1 : -1;
+ else
+ return v1 > v2 ? -1 : 1;
}
/*
@@ -4908,7 +4910,10 @@ fuzzy_match_str_compare(const void *s1, const void *s2)
int idx1 = ((fuzmatch_str_T *)s1)->idx;
int idx2 = ((fuzmatch_str_T *)s2)->idx;
- return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+ if (v1 == v2)
+ return idx1 == idx2 ? 0 : idx1 > idx2 ? 1 : -1;
+ else
+ return v1 > v2 ? -1 : 1;
}
/*
@@ -4936,9 +4941,14 @@ fuzzy_match_func_compare(const void *s1, const void *s2)
char_u *str1 = ((fuzmatch_str_T *)s1)->str;
char_u *str2 = ((fuzmatch_str_T *)s2)->str;
- if (*str1 != '<' && *str2 == '<') return -1;
- if (*str1 == '<' && *str2 != '<') return 1;
- return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+ if (*str1 != '<' && *str2 == '<')
+ return -1;
+ if (*str1 == '<' && *str2 != '<')
+ return 1;
+ if (v1 == v2)
+ return idx1 == idx2 ? 0 : idx1 > idx2 ? 1 : -1;
+ else
+ return v1 > v2 ? -1 : 1;
}
/*
diff --git a/src/spell.c b/src/spell.c
index da8ece0..43c521d 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -1384,7 +1384,7 @@ spell_move_to(
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
- len = (int)STRLEN(line);
+ len = ml_get_buf_len(wp->w_buffer, lnum);
if (buflen < len + MAXWLEN + 2)
{
vim_free(buf);
@@ -2988,7 +2988,7 @@ ex_spellrepall(exarg_T *eap UNUSED)
if (addlen <= 0 || STRNCMP(line + curwin->w_cursor.col,
repl_to, repl_to_len) != 0)
{
- p = alloc(STRLEN(line) + addlen + 1);
+ p = alloc(ml_get_curline_len() + addlen + 1);
if (p == NULL)
break;
mch_memmove(p, line, curwin->w_cursor.col);
diff --git a/src/spellfile.c b/src/spellfile.c
index 24df042..51261ab 100644
--- a/src/spellfile.c
+++ b/src/spellfile.c
@@ -5877,7 +5877,7 @@ sug_write(spellinfo_T *spin, char_u *fname)
{
// <sugline>: <sugnr> ... NUL
line = ml_get_buf(spin->si_spellbuf, lnum, FALSE);
- len = (int)STRLEN(line) + 1;
+ len = ml_get_buf_len(spin->si_spellbuf, lnum) + 1;
if (fwrite(line, (size_t)len, (size_t)1, fd) == 0)
{
emsg(_(e_error_while_writing));
diff --git a/src/spellsuggest.c b/src/spellsuggest.c
index ecc0a74..c6e6183 100644
--- a/src/spellsuggest.c
+++ b/src/spellsuggest.c
@@ -508,9 +508,8 @@ spell_suggest(int count)
++badlen;
end_visual_mode();
// make sure we don't include the NUL at the end of the line
- line = ml_get_curline();
- if (badlen > (int)STRLEN(line) - (int)curwin->w_cursor.col)
- badlen = (int)STRLEN(line) - (int)curwin->w_cursor.col;
+ if (badlen > ml_get_curline_len() - (int)curwin->w_cursor.col)
+ badlen = ml_get_curline_len() - (int)curwin->w_cursor.col;
}
// Find the start of the badly spelled word.
else if (spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL) == 0
@@ -543,7 +542,7 @@ spell_suggest(int count)
curwin->w_cursor.col);
// Make a copy of current line since autocommands may free the line.
- line = vim_strsave(ml_get_curline());
+ line = vim_strnsave(ml_get_curline(), ml_get_curline_len());
if (line == NULL)
goto skip;
@@ -3763,11 +3762,16 @@ sug_compare(const void *s1, const void *s2)
{
suggest_T *p1 = (suggest_T *)s1;
suggest_T *p2 = (suggest_T *)s2;
- int n = p1->st_score - p2->st_score;
+ int n;
+
+ n = p1->st_score == p2->st_score ? 0 :
+ p1->st_score > p2->st_score ? 1 : -1;
if (n == 0)
{
- n = p1->st_altscore - p2->st_altscore;
+ n = p1->st_altscore == p2->st_altscore ? 0 :
+ p1->st_altscore > p2->st_altscore ? 1 : -1;
+
if (n == 0)
n = STRICMP(p1->st_word, p2->st_word);
}
diff --git a/src/strings.c b/src/strings.c
index 0aeea4b..33de175 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -942,7 +942,6 @@ string_filter_map(
break;
len = (int)STRLEN(tv.vval.v_string);
- newtv.v_type = VAR_UNKNOWN;
set_vim_var_nr(VV_KEY, idx);
if (filter_map_one(&tv, expr, filtermap, fc, &newtv, &rem) == FAIL
|| did_emsg)
@@ -951,7 +950,7 @@ string_filter_map(
clear_tv(&tv);
break;
}
- else if (filtermap != FILTERMAP_FILTER)
+ if (filtermap == FILTERMAP_MAP || filtermap == FILTERMAP_MAPNEW)
{
if (newtv.v_type != VAR_STRING)
{
@@ -963,7 +962,7 @@ string_filter_map(
else
ga_concat(&ga, newtv.vval.v_string);
}
- else if (!rem)
+ else if (filtermap == FILTERMAP_FOREACH || !rem)
ga_concat(&ga, tv.vval.v_string);
clear_tv(&newtv);
@@ -2469,6 +2468,55 @@ adjust_types(
return OK;
}
+ static void
+format_overflow_error(const char *pstart)
+{
+ size_t arglen = 0;
+ char *argcopy = NULL;
+ const char *p = pstart;
+
+ while (VIM_ISDIGIT((int)(*p)))
+ ++p;
+
+ arglen = p - pstart;
+ argcopy = ALLOC_CLEAR_MULT(char, arglen + 1);
+ if (argcopy != NULL)
+ {
+ strncpy(argcopy, pstart, arglen);
+ semsg(_( e_val_too_large), argcopy);
+ free(argcopy);
+ }
+ else
+ semsg(_(e_out_of_memory_allocating_nr_bytes), arglen);
+}
+
+#define MAX_ALLOWED_STRING_WIDTH 6400
+
+ static int
+get_unsigned_int(
+ const char *pstart,
+ const char **p,
+ unsigned int *uj)
+{
+ *uj = **p - '0';
+ ++*p;
+
+ while (VIM_ISDIGIT((int)(**p)) && *uj < MAX_ALLOWED_STRING_WIDTH)
+ {
+ *uj = 10 * *uj + (unsigned int)(**p - '0');
+ ++*p;
+ }
+
+ if (*uj > MAX_ALLOWED_STRING_WIDTH)
+ {
+ format_overflow_error(pstart);
+ return FAIL;
+ }
+
+ return OK;
+}
+
+
static int
parse_fmt_types(
const char ***ap_types,
@@ -2512,6 +2560,7 @@ parse_fmt_types(
// variable for positional arg
int pos_arg = -1;
const char *ptype = NULL;
+ const char *pstart = p+1;
p++; // skip '%'
@@ -2532,10 +2581,11 @@ parse_fmt_types(
}
// Positional argument
- unsigned int uj = *p++ - '0';
+ unsigned int uj;
+
+ if (get_unsigned_int(pstart, &p, &uj) == FAIL)
+ goto error;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
pos_arg = uj;
any_pos = 1;
@@ -2572,10 +2622,10 @@ parse_fmt_types(
if (VIM_ISDIGIT((int)(*p)))
{
// Positional argument field width
- unsigned int uj = *p++ - '0';
+ unsigned int uj;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
+ if (get_unsigned_int(arg + 1, &p, &uj) == FAIL)
+ goto error;
if (*p != '$')
{
@@ -2602,10 +2652,11 @@ parse_fmt_types(
{
// size_t could be wider than unsigned int; make sure we treat
// argument like common implementations do
- unsigned int uj = *p++ - '0';
+ const char *digstart = p;
+ unsigned int uj;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
if (*p == '$')
{
@@ -2626,10 +2677,10 @@ parse_fmt_types(
if (VIM_ISDIGIT((int)(*p)))
{
// Parse precision
- unsigned int uj = *p++ - '0';
+ unsigned int uj;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
+ if (get_unsigned_int(arg + 1, &p, &uj) == FAIL)
+ goto error;
if (*p == '$')
{
@@ -2657,10 +2708,11 @@ parse_fmt_types(
{
// size_t could be wider than unsigned int; make sure we
// treat argument like common implementations do
- unsigned int uj = *p++ - '0';
+ const char *digstart = p;
+ unsigned int uj;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
if (*p == '$')
{
@@ -2969,10 +3021,12 @@ vim_vsnprintf_typval(
if (*ptype == '$')
{
// Positional argument
- unsigned int uj = *p++ - '0';
+ const char *digstart = p;
+ unsigned int uj;
+
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
pos_arg = uj;
++p;
@@ -3003,16 +3057,18 @@ vim_vsnprintf_typval(
if (*p == '*')
{
int j;
+ const char *digstart = p + 1;
p++;
if (VIM_ISDIGIT((int)(*p)))
{
// Positional argument field width
- unsigned int uj = *p++ - '0';
+ unsigned int uj;
+
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
arg_idx = uj;
++p;
@@ -3026,6 +3082,12 @@ vim_vsnprintf_typval(
&arg_cur, fmt),
va_arg(ap, int));
+ if (j > MAX_ALLOWED_STRING_WIDTH)
+ {
+ format_overflow_error(digstart);
+ goto error;
+ }
+
if (j >= 0)
min_field_width = j;
else
@@ -3038,10 +3100,18 @@ vim_vsnprintf_typval(
{
// size_t could be wider than unsigned int; make sure we treat
// argument like common implementations do
- unsigned int uj = *p++ - '0';
+ const char *digstart = p;
+ unsigned int uj;
+
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
+
+ if (uj > MAX_ALLOWED_STRING_WIDTH)
+ {
+ format_overflow_error(digstart);
+ goto error;
+ }
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
min_field_width = uj;
}
@@ -3055,25 +3125,35 @@ vim_vsnprintf_typval(
{
// size_t could be wider than unsigned int; make sure we
// treat argument like common implementations do
- unsigned int uj = *p++ - '0';
+ const char *digstart = p;
+ unsigned int uj;
+
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
+
+ if (uj > MAX_ALLOWED_STRING_WIDTH)
+ {
+ format_overflow_error(digstart);
+ goto error;
+ }
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
precision = uj;
}
else if (*p == '*')
{
int j;
+ const char *digstart = p;
p++;
if (VIM_ISDIGIT((int)(*p)))
{
// positional argument
- unsigned int uj = *p++ - '0';
+ unsigned int uj;
+
+ if (get_unsigned_int(digstart, &p, &uj) == FAIL)
+ goto error;
- while (VIM_ISDIGIT((int)(*p)))
- uj = 10 * uj + (unsigned int)(*p++ - '0');
arg_idx = uj;
++p;
@@ -3087,6 +3167,12 @@ vim_vsnprintf_typval(
&arg_cur, fmt),
va_arg(ap, int));
+ if (j > MAX_ALLOWED_STRING_WIDTH)
+ {
+ format_overflow_error(digstart);
+ goto error;
+ }
+
if (j >= 0)
precision = j;
else
@@ -3874,6 +3960,7 @@ vim_vsnprintf_typval(
if (tvs != NULL && tvs[num_posarg != 0 ? num_posarg : arg_idx - 1].v_type != VAR_UNKNOWN)
emsg(_(e_too_many_arguments_to_printf));
+error:
vim_free((char*)ap_types);
va_end(ap);
diff --git a/src/structs.h b/src/structs.h
index 3b51e0c..47a0050 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -246,6 +246,8 @@ typedef struct
long wo_nuw;
# define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth'
#endif
+ int wo_wfb;
+#define w_p_wfb w_onebuf_opt.wo_wfb // 'winfixbuf'
int wo_wfh;
# define w_p_wfh w_onebuf_opt.wo_wfh // 'winfixheight'
int wo_wfw;
@@ -800,7 +802,8 @@ typedef struct memline
#define ML_ALLOCATED 0x10 // ml_line_ptr is an allocated copy
int ml_flags;
- colnr_T ml_line_len; // length of the cached line, including NUL
+ colnr_T ml_line_len; // length of the cached line + NUL + text properties
+ colnr_T ml_line_textlen;// length of the cached line + NUL, 0 if not known yet
linenr_T ml_line_lnum; // line number of cached line, 0 if not valid
char_u *ml_line_ptr; // pointer to cached line
@@ -1186,6 +1189,7 @@ typedef struct attr_entry
short_u fg_color; // foreground color number
short_u bg_color; // background color number
short_u ul_color; // underline color number
+ short_u font; // font number
# ifdef FEAT_TERMGUICOLORS
guicolor_T fg_rgb; // foreground color RGB
guicolor_T bg_rgb; // background color RGB
@@ -1528,6 +1532,17 @@ typedef enum {
#define OCMFLAG_CONST 0x04 // "const" object/class member
/*
+ * Object methods called by builtin functions (e.g. string(), empty(), etc.)
+ */
+typedef enum {
+ CLASS_BUILTIN_INVALID,
+ CLASS_BUILTIN_STRING,
+ CLASS_BUILTIN_EMPTY,
+ CLASS_BUILTIN_LEN,
+ CLASS_BUILTIN_MAX
+} class_builtin_T;
+
+/*
* Entry for an object or class member variable.
*/
typedef struct {
@@ -1590,6 +1605,9 @@ struct class_S
int class_obj_method_count_child; // count without "extends"
ufunc_T **class_obj_methods; // allocated
+ // index of builtin methods
+ int class_builtin_methods[CLASS_BUILTIN_MAX];
+
garray_T class_type_list; // used for type pointers
type_T class_type; // type used for the class
type_T class_object_type; // same as class_type but VAR_OBJECT
@@ -4333,7 +4351,7 @@ struct VimMenu
HMENU submenu_id; // If this is submenu, add children here
HWND tearoff_handle; // hWnd of tearoff if created
#endif
-#if FEAT_GUI_HAIKU
+#ifdef FEAT_GUI_HAIKU
BMenuItem *id; // Id of menu item
BMenu *submenu_id; // If this is submenu, add children here
# ifdef FEAT_TOOLBAR
@@ -4357,7 +4375,6 @@ typedef int vimmenu_T;
*/
typedef struct
{
- buf_T *save_curbuf; // saved curbuf
int use_aucmd_win_idx; // index in aucmd_win[] if >= 0
int save_curwin_id; // ID of saved curwin
int new_curwin_id; // ID of new curwin
@@ -4366,6 +4383,9 @@ typedef struct
char_u *globaldir; // saved value of globaldir
int save_VIsual_active; // saved VIsual_active
int save_State; // saved State
+#ifdef FEAT_JOB_CHANNEL
+ int save_prompt_insert; // saved b_prompt_insert
+#endif
} aco_save_T;
/*
@@ -4879,11 +4899,12 @@ typedef struct {
hashtab_T sve_hashtab;
} save_v_event_T;
-// Enum used by filter(), map() and mapnew()
+// Enum used by filter(), map(), mapnew() and foreach()
typedef enum {
FILTERMAP_FILTER,
FILTERMAP_MAP,
- FILTERMAP_MAPNEW
+ FILTERMAP_MAPNEW,
+ FILTERMAP_FOREACH
} filtermap_T;
// Structure used by switch_win() to pass values to restore_win()
@@ -4907,6 +4928,10 @@ typedef struct {
win_T *cts_win;
char_u *cts_line; // start of the line
char_u *cts_ptr; // current position in line
+#ifdef FEAT_LINEBREAK
+ int cts_bri_size; // cached size of 'breakindent', or -1
+ // if not computed yet
+#endif
#ifdef FEAT_PROP_POPUP
int cts_text_prop_count; // number of text props; when zero
// cts_text_props is not used
diff --git a/src/syntax.c b/src/syntax.c
index 4e35956..48e7152 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -593,7 +593,6 @@ syn_sync(
int had_sync_point;
stateitem_T *cur_si;
synpat_T *spp;
- char_u *line;
int found_flags = 0;
int found_match_idx = 0;
linenr_T found_current_lnum = 0;
@@ -651,8 +650,9 @@ syn_sync(
*/
for ( ; start_lnum > 1; --start_lnum)
{
- line = ml_get(start_lnum - 1);
- if (*line == NUL || *(line + STRLEN(line) - 1) != '\\')
+ char_u *l = ml_get(start_lnum - 1);
+
+ if (*l == NUL || *(l + ml_get_len(start_lnum - 1) - 1) != '\\')
break;
}
current_lnum = start_lnum;
@@ -2775,7 +2775,6 @@ find_endpos(
regmmatch_T regmatch;
regmmatch_T best_regmatch; // startpos/endpos of best match
lpos_T pos;
- char_u *line;
int had_match = FALSE;
char_u buf_chartab[32]; // chartab array for syn option iskyeyword
@@ -2899,8 +2898,7 @@ find_endpos(
if (pos.lnum > startpos->lnum)
break;
- line = ml_get_buf(syn_buf, startpos->lnum, FALSE);
- line_len = (int)STRLEN(line);
+ line_len = ml_get_buf_len(syn_buf, startpos->lnum);
// take care of an empty match or negative offset
if (pos.col <= matchcol)
@@ -3101,7 +3099,7 @@ syn_add_start_off(
{
// a "\n" at the end of the pattern may take us below the last line
result->lnum = syn_buf->b_ml.ml_line_count;
- col = (int)STRLEN(ml_get_buf(syn_buf, result->lnum, FALSE));
+ col = ml_get_buf_len(syn_buf, result->lnum);
}
if (off != 0)
{
diff --git a/src/tag.c b/src/tag.c
index 893415f..2ac0da2 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -289,6 +289,9 @@ do_tag(
static char_u **matches = NULL;
static int flags;
+ if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit))
+ return FALSE;
+
#ifdef FEAT_EVAL
if (tfu_in_use)
{
@@ -395,7 +398,7 @@ do_tag(
tagstack_clear_entry(&tagstack[0]);
for (i = 1; i < tagstacklen; ++i)
tagstack[i - 1] = tagstack[i];
- --tagstackidx;
+ tagstack[--tagstackidx].user_data = NULL;
}
/*
@@ -3705,6 +3708,9 @@ jumpto_tag(
size_t len;
char_u *lbuf;
+ if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit))
+ return FAIL;
+
// Make a copy of the line, it can become invalid when an autocommand calls
// back here recursively.
len = matching_line_len(lbuf_arg) + 1;
diff --git a/src/term.c b/src/term.c
index dd59fdf..8aa86ce 100644
--- a/src/term.c
+++ b/src/term.c
@@ -625,7 +625,7 @@ static tcap_entry_T builtin_kitty[] = {
#ifdef FEAT_TERMGUICOLORS
/*
- * Additions for using the RGB colors
+ * Additions for using the RGB colors and terminal font
*/
static tcap_entry_T builtin_rgb[] = {
// These are printf strings, not terminal codes.
@@ -637,6 +637,14 @@ static tcap_entry_T builtin_rgb[] = {
};
#endif
+#ifdef HAVE_TGETENT
+static tcap_entry_T special_term[] = {
+ // These are printf strings, not terminal codes.
+ {(int)KS_CF, "\033[%dm"},
+ {(int)KS_NAME, NULL} // end marker
+};
+#endif
+
/*
* iris-ansi for Silicon Graphics machines.
*/
@@ -1235,6 +1243,7 @@ static tcap_entry_T builtin_debug[] = {
{(int)KS_U7, "[U7]"},
{(int)KS_RFG, "[RFG]"},
{(int)KS_RBG, "[RBG]"},
+ {(int)KS_CF, "[CF%d]"},
{K_UP, "[KU]"},
{K_DOWN, "[KD]"},
{K_LEFT, "[KL]"},
@@ -1754,6 +1763,7 @@ get_term_entries(int *height, int *width)
{KS_CBE, "BE"}, {KS_CBD, "BD"},
{KS_CST, "ST"}, {KS_CRT, "RT"},
{KS_SSI, "Si"}, {KS_SRI, "Ri"},
+ {KS_CF, "CF"},
{(enum SpecialKey)0, NULL}
};
int i;
@@ -2113,6 +2123,10 @@ set_termname(char_u *term)
&& term_strings_not_set(KS_8U))
apply_builtin_tcap(term, builtin_rgb, TRUE);
#endif
+#ifdef HAVE_TGETENT
+ if (term_strings_not_set(KS_CF))
+ apply_builtin_tcap(term, special_term, TRUE);
+#endif
}
/*
@@ -3116,6 +3130,17 @@ term_set_winsize(int height, int width)
}
#endif
+ void
+term_font(int n)
+{
+ if (*T_CFO)
+ {
+ char buf[20];
+ sprintf(buf, (char *)T_CFO, 9 + n);
+ OUT_STR(buf);
+ }
+}
+
static void
term_color(char_u *s, int n)
{
@@ -4986,6 +5011,8 @@ handle_u7_response(int *arg, char_u *tp UNUSED, int csi_len UNUSED)
#ifdef FEAT_EVAL
set_vim_var_string(VV_TERMU7RESP, tp, csi_len);
#endif
+ apply_autocmds(EVENT_TERMRESPONSEALL,
+ (char_u *)"ambiguouswidth", NULL, FALSE, curbuf);
}
}
else if (arg[0] == 3)
@@ -5595,6 +5622,8 @@ handle_csi(
#endif
apply_autocmds(EVENT_TERMRESPONSE,
NULL, NULL, FALSE, curbuf);
+ apply_autocmds(EVENT_TERMRESPONSEALL,
+ (char_u *)"version", NULL, FALSE, curbuf);
key_name[0] = (int)KS_EXTRA;
key_name[1] = (int)KE_IGNORE;
}
@@ -5621,6 +5650,8 @@ handle_csi(
# ifdef FEAT_EVAL
set_vim_var_string(VV_TERMBLINKRESP, tp, *slen);
# endif
+ apply_autocmds(EVENT_TERMRESPONSEALL,
+ (char_u *)"cursorblink", NULL, FALSE, curbuf);
}
#endif
@@ -5737,8 +5768,8 @@ handle_osc(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen)
int rval, gval, bval;
rval = hexhex2nr(tp_r);
- gval = hexhex2nr(tp_b);
- bval = hexhex2nr(tp_g);
+ gval = hexhex2nr(tp_g);
+ bval = hexhex2nr(tp_b);
#endif
if (is_bg)
{
@@ -5784,6 +5815,8 @@ handle_osc(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen)
set_vim_var_string(is_bg ? VV_TERMRBGRESP
: VV_TERMRFGRESP, tp, *slen);
#endif
+ apply_autocmds(EVENT_TERMRESPONSEALL,
+ is_bg ? (char_u *)"background" : (char_u *)"foreground", NULL, FALSE, curbuf);
break;
}
if (i == len)
@@ -5882,6 +5915,8 @@ handle_dcs(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen)
#ifdef FEAT_EVAL
set_vim_var_string(VV_TERMSTYLERESP, tp, *slen);
#endif
+ apply_autocmds(EVENT_TERMRESPONSEALL,
+ (char_u *)"cursorshape", NULL, FALSE, curbuf);
break;
}
}
diff --git a/src/termdefs.h b/src/termdefs.h
index 9f72dc1..f28fd19 100644
--- a/src/termdefs.h
+++ b/src/termdefs.h
@@ -114,10 +114,11 @@ enum SpecialKey
KS_SSI, // save icon text
KS_SRI, // restore icon text
KS_FD, // disable focus event tracking
- KS_FE // enable focus event tracking
+ KS_FE, // enable focus event tracking
+ KS_CF // set terminal alternate font
};
-#define KS_LAST KS_FE
+#define KS_LAST KS_CF
/*
* the terminal capabilities are stored in this array
@@ -191,6 +192,7 @@ extern char_u *(term_strings[]); // current terminal strings
#define T_CAF (TERM_STR(KS_CAF)) // set foreground color (ANSI)
#define T_CAB (TERM_STR(KS_CAB)) // set background color (ANSI)
#define T_CAU (TERM_STR(KS_CAU)) // set underline color (ANSI)
+#define T_CFO (TERM_STR(KS_CF)) // set alternate font
#define T_LE (TERM_STR(KS_LE)) // cursor left
#define T_ND (TERM_STR(KS_ND)) // cursor right
#define T_CIS (TERM_STR(KS_CIS)) // set icon text start
diff --git a/src/terminal.c b/src/terminal.c
index a641a85..25a6a5d 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -3965,7 +3965,8 @@ update_system_term(term_T *term)
else
pos.col = 0;
- screen_line(curwin, term->tl_toprow + pos.row, 0, pos.col, Columns, 0);
+ screen_line(curwin, term->tl_toprow + pos.row, 0, pos.col, Columns, -1,
+ 0);
}
term->tl_dirty_row_start = MAX_ROW;
@@ -4088,7 +4089,7 @@ term_update_window(win_T *wp)
#ifdef FEAT_MENU
+ winbar_height(wp)
#endif
- , wp->w_wincol, pos.col, wp->w_width,
+ , wp->w_wincol, pos.col, wp->w_width, -1,
#ifdef FEAT_PROP_POPUP
popup_is_popup(wp) ? SLF_POPUP :
#endif
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 1614cf0..c4403e6 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -248,6 +248,7 @@ NEW_TESTS = \
test_regexp_utf8 \
test_registers \
test_reltime \
+ test_remote \
test_rename \
test_restricted \
test_retab \
@@ -324,6 +325,7 @@ NEW_TESTS = \
test_window_cmd \
test_window_id \
test_windows_home \
+ test_winfixbuf \
test_wnext \
test_wordcount \
test_writefile \
@@ -492,6 +494,7 @@ NEW_TESTS_RES = \
test_recover.res \
test_regex_char_classes.res \
test_registers.res \
+ test_remote.res \
test_rename.res \
test_restricted.res \
test_retab.res \
@@ -555,6 +558,7 @@ NEW_TESTS_RES = \
test_window_cmd.res \
test_window_id.res \
test_windows_home.res \
+ test_winfixbuf.res \
test_wordcount.res \
test_writefile.res \
test_xxd.res \
diff --git a/src/testdir/check.vim b/src/testdir/check.vim
index 82abb64..e67d39a 100644
--- a/src/testdir/check.vim
+++ b/src/testdir/check.vim
@@ -160,6 +160,14 @@ func CheckEnv(name)
endif
endfunc
+" Command to Check for pure X11 (no Wayland)
+command -nargs=0 CheckX11 call CheckX11()
+func CheckX11()
+ if !empty($WAYLAND_DISPLAY) || empty($DISPLAY)
+ throw 'Skipped: not pure X11 environment'
+ endif
+endfunc
+
" Command to check that we are using the GUI
command CheckGui call CheckGui()
func CheckGui()
diff --git a/src/testdir/dumps/Test_balloon_eval_term_02.dump b/src/testdir/dumps/Test_balloon_eval_term_02.dump
index 51c5e32..f3bd633 100644
--- a/src/testdir/dumps/Test_balloon_eval_term_02.dump
+++ b/src/testdir/dumps/Test_balloon_eval_term_02.dump
@@ -1,6 +1,6 @@
|o+0&#ffffff0|n|e| |o|n|e| |o|n|e| @38
|t|w|o| |t|X|o| |t|w|o| @38
-|t|h|r|e|e+0&#e0e0e08| |t|h>r+0&#ffffff0|e@1| |t|h|r|e@1| @32
+|t|h|r|e|e+0#0000001#a8a8a8255| |t|h>r+0#0000000#ffffff0|e@1| |t|h|r|e@1| @32
|~+0#4040ff13&| @2| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@27
|~| @2| +0#0000001#ffd7ff255|l|i|n|e| |3| |c|o|l|u|m|n| |5|:| | +0#4040ff13#ffffff0@27
|~| @2| +0#0000001#ffd7ff255|e| |t|h|r|<| @10| +0#4040ff13#ffffff0@27
diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_01.dump b/src/testdir/dumps/Test_conceal_cul_wcr_01.dump
new file mode 100644
index 0000000..9cb27c8
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_cul_wcr_01.dump
@@ -0,0 +1,4 @@
+|o+8&#ffffff0|n|e| |o|n|e| |o|n|e| @1|o|n|e| |o|n|e| |o|n|e| |o|n|e| |o|n>e| @7
+@1|o|n|e| |o|n|e| |o|n|e| @27
+|~+0#4040ff13&| @38
+| +0#0000000&@21|1|,|4|0| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_02.dump b/src/testdir/dumps/Test_conceal_cul_wcr_02.dump
new file mode 100644
index 0000000..668e1af
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_cul_wcr_02.dump
@@ -0,0 +1,4 @@
+|o+8#ffffff16#e000002|n|e| |o|n|e| |o|n|e| @1|o|n|e| |o|n|e| |o|n|e| |o|n|e| |o|n>e| @7
+@1|o|n|e| |o|n|e| |o|n|e| @27
+|~+0#4040ff13&| @38
+|:+0#0000000#ffffff0|s|e|t| |w|i|n|c|o|l|o|r|=|E|r@1|o|r|M|s|g|1|,|4|0| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_03.dump b/src/testdir/dumps/Test_conceal_cul_wcr_03.dump
new file mode 100644
index 0000000..965e9f5
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_cul_wcr_03.dump
@@ -0,0 +1,4 @@
+|o+0#ffffff16#e000002|n|e| |o|n|e| |o|n|e| @1|o|n|e| |o|n|e| |o|n|e| |o|n|e| |o|n>e| @7
+@1|o|n|e| |o|n|e| |o|n|e| @27
+|~+0#4040ff13&| @38
+|:+0#0000000#ffffff0|s|e|t| |n|o|c|u|r|s|o|r|l|i|n|e| @4|1|,|4|0| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump b/src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump
new file mode 100644
index 0000000..d1a31a6
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump
@@ -0,0 +1,4 @@
+| +8&#ffffff0@7>e|n|o| |e|n|o| |e|n|o| |e|n|o| |e|n|o| @1|e|n|o| |e|n|o| |e|n|o
+| @27|e|n|o| |e|n|o| |e|n|o|
+| +0#4040ff13&@38|~
+| +0#0000000&@21|1|,|4|0| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump b/src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump
new file mode 100644
index 0000000..21809e9
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump
@@ -0,0 +1,4 @@
+| +8#ffffff16#e000002@7>e|n|o| |e|n|o| |e|n|o| |e|n|o| |e|n|o| @1|e|n|o| |e|n|o| |e|n|o
+| @27|e|n|o| |e|n|o| |e|n|o|
+| +0#4040ff13&@38|~
+|:+0#0000000#ffffff0|s|e|t| |w|i|n|c|o|l|o|r|=|E|r@1|o|r|M|s|g|1|,|4|0| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump b/src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump
new file mode 100644
index 0000000..0eeb739
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump
@@ -0,0 +1,4 @@
+| +0#ffffff16#e000002@7>e|n|o| |e|n|o| |e|n|o| |e|n|o| |e|n|o| @1|e|n|o| |e|n|o| |e|n|o
+| @27|e|n|o| |e|n|o| |e|n|o|
+| +0#4040ff13&@38|~
+|:+0#0000000#ffffff0|s|e|t| |n|o|c|u|r|s|o|r|l|i|n|e| @4|1|,|4|0| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_double_width_1.dump b/src/testdir/dumps/Test_conceal_double_width_1.dump
new file mode 100644
index 0000000..57353bb
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_1.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@4|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@4|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@3>c| @11| +0&#ffd7d7255| +0&#ffffff0@44
+|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|2|9|-|2|5| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_double_width_2.dump b/src/testdir/dumps/Test_conceal_double_width_2.dump
new file mode 100644
index 0000000..782db47
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_2.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@4|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@1>b@2|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@4| @11| +0&#ffd7d7255| +0&#ffffff0@44
+|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|1|5|-|1|3| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_double_width_3.dump b/src/testdir/dumps/Test_conceal_double_width_3.dump
new file mode 100644
index 0000000..5102c7b
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_3.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@4|b@1>b@2|c@4| @13| +0&#ffd7d7255| +0&#ffffff0@44
+|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44
+|~+0#4040ff13&| @73
+|:+0#0000000&|s|e|t| |c|o|n|c|e|a|l@1|e|v|e|l|=|3| @37|1|,|1|5|-|1|3| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_double_width_4.dump b/src/testdir/dumps/Test_conceal_double_width_4.dump
new file mode 100644
index 0000000..8ef8b96
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_4.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@4|b@4|c@3>c| @13| +0&#ffd7d7255| +0&#ffffff0@44
+|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44
+|~+0#4040ff13&| @73
+|:+0#0000000&|s|e|t| |c|o|n|c|e|a|l@1|e|v|e|l|=|3| @37|1|,|2|9|-|2|5| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_1.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_1.dump
new file mode 100644
index 0000000..e794b7c
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_wrap_1.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@9|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@4| @3
+|b@4|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@8>c| @3
+|~+0#4040ff13&| @18
+| +0#0000000&@9|1|,|4@1|-|4|0| @2
diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_2.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_2.dump
new file mode 100644
index 0000000..36e64fc
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_wrap_2.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@9|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@4| @3
+>b@4|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@9| @3
+|~+0#4040ff13&| @18
+| +0#0000000&@9|1|,|2|3|-|2|1| @2
diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_3.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_3.dump
new file mode 100644
index 0000000..ba6c835
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_wrap_3.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@9|b@4| @4
+>b@4|c@9| @4
+|~+0#4040ff13&| @18
+|:+0#0000000&|s|e|t| |c|o|n|c|e|1|,|2|3|-|2|1| @2
diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_4.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_4.dump
new file mode 100644
index 0000000..8997e98
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_double_width_wrap_4.dump
@@ -0,0 +1,4 @@
+|a+0&#ffffff0@9|b@4| @4
+|b@4|c@8>c| @4
+|~+0#4040ff13&| @18
+|:+0#0000000&| @8|1|,|4@1|-|4|0| @2
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_1.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_1.dump
new file mode 100644
index 0000000..635c6db
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_1.dump
@@ -0,0 +1,3 @@
+|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o>p| @57
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|2|5| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_2.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_2.dump
new file mode 100644
index 0000000..ecdc5a3
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_2.dump
@@ -0,0 +1,3 @@
+|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p> @57
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|2|6| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_3.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_3.dump
new file mode 100644
index 0000000..5eff9fa
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_3.dump
@@ -0,0 +1,3 @@
+|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p| > @56
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|2|6|-|2|7| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_4.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_4.dump
new file mode 100644
index 0000000..0b2120a
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_4.dump
@@ -0,0 +1,3 @@
+|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p| @1> @55
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|2|6|-|2|8| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_5.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_5.dump
new file mode 100644
index 0000000..2aa8644
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_5.dump
@@ -0,0 +1,3 @@
+|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p| @1>r| @54
+|~+0#4040ff13&| @73
+| +0#0000000&@56|1|,|2|8| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump
new file mode 100644
index 0000000..840e19b
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump
@@ -0,0 +1,3 @@
+| +0&#ffffff0@57>p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a
+| +0#4040ff13&@73|~
+| +0#0000000&@56|1|,|2|5| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump
new file mode 100644
index 0000000..c4b0190
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump
@@ -0,0 +1,3 @@
+| +0&#ffffff0@56> |p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a
+| +0#4040ff13&@73|~
+| +0#0000000&@56|1|,|2|6| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump
new file mode 100644
index 0000000..e4a05f7
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump
@@ -0,0 +1,3 @@
+| +0&#ffffff0@55> @1|p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a
+| +0#4040ff13&@73|~
+| +0#0000000&@56|1|,|2|6|-|2|7| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump
new file mode 100644
index 0000000..9f21657
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump
@@ -0,0 +1,3 @@
+| +0&#ffffff0@54> @2|p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a
+| +0#4040ff13&@73|~
+| +0#0000000&@56|1|,|2|6|-|2|8| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump
new file mode 100644
index 0000000..7d2dad6
--- /dev/null
+++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump
@@ -0,0 +1,3 @@
+| +0&#ffffff0@54>r| @1|p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a
+| +0#4040ff13&@73|~
+| +0#0000000&@56|1|,|2|8| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump b/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump
index b6e20b7..326abac 100644
--- a/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump
+++ b/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump
@@ -1,9 +1,9 @@
-|a+0&#e0e0e08|b|c| | +0&#ffffff0@70
-|a+0&#e0e0e08|b|c| | +0&#ffffff0@70
-|a+0&#e0e0e08|b|c| | +0&#ffffff0@70
-|a+0&#e0e0e08|b|c| | +0&#ffffff0@70
-|a+0&#e0e0e08|b|c| | +0&#ffffff0@70
->a|b+0&#e0e0e08|c| | +0&#ffffff0@70
+|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70
+|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70
+|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70
+|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70
+|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70
+>a|b+0#0000001#a8a8a8255|c| | +0#0000000#ffffff0@70
|a|b|c| @71
|a|b|c| @71
|a|b|c| @71
diff --git a/src/testdir/dumps/Test_difffunc_diffexpr_1.dump b/src/testdir/dumps/Test_difffunc_diffexpr_1.dump
new file mode 100644
index 0000000..b103cc8
--- /dev/null
+++ b/src/testdir/dumps/Test_difffunc_diffexpr_1.dump
@@ -0,0 +1,12 @@
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|z+0#0000000#5fd7ff255|e|r|o| @30
+| +0#0000e05#a8a8a8255@1>o+0#0000000#ffffff0|n|e| @31||+1&&| +0#0000e05#a8a8a8255@1|o+0#0000000#ffffff0|n|e| @31
+| +0#0000e05#a8a8a8255@1|t+0#0000000#ffd7ff255|w|o|x+2&#ff404010| +0&#ffd7ff255@30||+1&#ffffff0| +0#0000e05#a8a8a8255@1|t+0#0000000#ffd7ff255|w|o| @31
+| +0#0000e05#a8a8a8255@1|t+0#0000000#ffffff0|h|r|e@1| @29||+1&&| +0#0000e05#a8a8a8255@1|t+0#0000000#ffffff0|h|r|e@1| @29
+| +0#0000e05#a8a8a8255@1|f+0#0000000#5fd7ff255|o|u|r| @30||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f@2|u|n|c|2|.|t|x|t| @4|1|,|1| @11|A|l@1| |X+1&&|d|i|f@2|u|n|c|1|.|t|x|t| @4|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f@2|u|n|c|2|.|t|x|t|"| |4|L|,| |2|0|B| @50
diff --git a/src/testdir/dumps/Test_display_scroll_update_visual.dump b/src/testdir/dumps/Test_display_scroll_update_visual.dump
index c174390..4b17a3b 100644
--- a/src/testdir/dumps/Test_display_scroll_update_visual.dump
+++ b/src/testdir/dumps/Test_display_scroll_update_visual.dump
@@ -1,4 +1,4 @@
-| +0#0000e05#a8a8a8255@1>f+0#0000000#ffffff0|o+0&#e0e0e08@1| | +0&#ffffff0@53
+| +0#0000e05#a8a8a8255@1>f+0#0000000#ffffff0|o+0#0000001#a8a8a8255@1| | +0#0000000#ffffff0@53
| +0#0000e05#a8a8a8255@1|f+0#0000000#ffffff0|o@1| @54
| +0#0000e05#a8a8a8255@1|f+0#0000000#ffffff0|o@1| @54
| +0#0000e05#a8a8a8255@1|f+0#0000000#ffffff0|o@1| @54
diff --git a/src/testdir/dumps/Test_drop_modified_1.dump b/src/testdir/dumps/Test_drop_modified_1.dump
new file mode 100644
index 0000000..bbd60c0
--- /dev/null
+++ b/src/testdir/dumps/Test_drop_modified_1.dump
@@ -0,0 +1,10 @@
+>T+0&#ffffff0|h|e| |q|u|i|c|k| |b|r|o|w|n| |f|o|x| |j|u|m|p|e|d| |o|v|e|r| |t|h|e| |l|a|z|y| |d|o|g|s| @29
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|d|r|o|p| |X|d|r|o|p|_|m|o|d|i|f|i|e|d|.|t|x|t| @32|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_echowin_showmode.dump b/src/testdir/dumps/Test_echowin_showmode.dump
index 24eb4d0..9a73bbf 100644
--- a/src/testdir/dumps/Test_echowin_showmode.dump
+++ b/src/testdir/dumps/Test_echowin_showmode.dump
@@ -1,4 +1,4 @@
->o+0&#ffffff0|n+0&#e0e0e08|e| | +0&#ffffff0@70
+>o+0&#ffffff0|n+0#0000001#a8a8a8255|e| | +0#0000000#ffffff0@70
|t|w|o| @71
|~+0#4040ff13&| @73
|~| @73
diff --git a/src/testdir/dumps/Test_hlsearch_visual_1.dump b/src/testdir/dumps/Test_hlsearch_visual_1.dump
index 99150db..e65d567 100644
--- a/src/testdir/dumps/Test_hlsearch_visual_1.dump
+++ b/src/testdir/dumps/Test_hlsearch_visual_1.dump
@@ -1,6 +1,6 @@
-|x+0&#ffffff0@2| |y+2&#ffff4012|y+2&#e0e0e08@1| +0&&|z@2| | +0&#ffffff0@27
-|x+0&#e0e0e08@2| |y+2&&@2| +0&&|z@2| | +0&#ffffff0@27
-|x+0&#e0e0e08@2| |y+2&&>y+2&#ffff4012@1| +0&#ffffff0|z@2| @28
+|x+0&#ffffff0@2| |y+2&#ffff4012|y+2#0000001#a8a8a8255@1| +0&&|z@2| | +0#0000000#ffffff0@27
+|x+0#0000001#a8a8a8255@2| |y+2&&@2| +0&&|z@2| | +0#0000000#ffffff0@27
+|x+0#0000001#a8a8a8255@2| |y+2&&>y+2#0000000#ffff4012@1| +0&#ffffff0|z@2| @28
|~+0#4040ff13&| @38
|~| @38
|-+2#0000000&@1| |V|I|S|U|A|L| |-@1|3+0&&| @8|3|,|6| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_matchparen_win_execute_1.dump b/src/testdir/dumps/Test_matchparen_win_execute_1.dump
new file mode 100644
index 0000000..75ab210
--- /dev/null
+++ b/src/testdir/dumps/Test_matchparen_win_execute_1.dump
@@ -0,0 +1,5 @@
+>{+0&#40ffff15|}| +0&#ffffff0@72
+|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|A|l@1
+|{+0&&|}| @72
+|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|A|l@1
+| +0&&@74
diff --git a/src/testdir/dumps/Test_number_insert_delete_lines_1.dump b/src/testdir/dumps/Test_number_insert_delete_lines_1.dump
new file mode 100644
index 0000000..5aecb46
--- /dev/null
+++ b/src/testdir/dumps/Test_number_insert_delete_lines_1.dump
@@ -0,0 +1,8 @@
+| +0#af5f00255#ffffff0@1|1| |1+0#0000000&| @69
+| +0#af5f00255&@1|2| >2+0#0000000&| @69
+| +0#af5f00255&@1|3| |3+0#0000000&| @69
+| +0#af5f00255&@1|4| |4+0#0000000&| @69
+| +0#af5f00255&@1|5| |5+0#0000000&| @69
+| +0#af5f00255&@1|6| |6+0#0000000&| @69
+| +0#af5f00255&@1|7| |7+0#0000000&| @69
+@57|2|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_number_insert_delete_lines_2.dump b/src/testdir/dumps/Test_number_insert_delete_lines_2.dump
new file mode 100644
index 0000000..dea68e8
--- /dev/null
+++ b/src/testdir/dumps/Test_number_insert_delete_lines_2.dump
@@ -0,0 +1,8 @@
+| +0#af5f00255#ffffff0@1|1| |1+0#0000000&| @69
+| +0#af5f00255&@1|2| >3+0#0000000&| @69
+| +0#af5f00255&@1|3| |4+0#0000000&| @69
+| +0#af5f00255&@1|4| |5+0#0000000&| @69
+| +0#af5f00255&@1|5| |6+0#0000000&| @69
+| +0#af5f00255&@1|6| |7+0#0000000&| @69
+|~+0#4040ff13&| @73
+| +0#0000000&@56|2|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_number_insert_delete_lines_3.dump b/src/testdir/dumps/Test_number_insert_delete_lines_3.dump
new file mode 100644
index 0000000..fff3297
--- /dev/null
+++ b/src/testdir/dumps/Test_number_insert_delete_lines_3.dump
@@ -0,0 +1,8 @@
+| +0#af5f00255#ffffff0@1|1| |1+0#0000000&| @69
+| +0#af5f00255&@1|2| >4+0#0000000&| @69
+| +0#af5f00255&@1|3| |5+0#0000000&| @69
+| +0#af5f00255&@1|4| |6+0#0000000&| @69
+| +0#af5f00255&@1|5| |7+0#0000000&| @69
+|~+0#4040ff13&| @73
+|~| @73
+| +0#0000000&@56|2|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_popup_command_03.dump b/src/testdir/dumps/Test_popup_command_03.dump
index fa2ac70..2a0c5af 100644
--- a/src/testdir/dumps/Test_popup_command_03.dump
+++ b/src/testdir/dumps/Test_popup_command_03.dump
@@ -1,5 +1,5 @@
|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @51
-|a|n|d| |o|n|e| |t|w|o| |X+0&#e0e0e08|t|h|r|e@1> +0&#ffffff0|f|o|u|r| |f|i|v|e| @46
+|a|n|d| |o|n|e| |t|w|o| |X+0#0000001#a8a8a8255|t|h|r|e@1> +0#0000000#ffffff0|f|o|u|r| |f|i|v|e| @46
|o|n|e| |m|o|r|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @46
|~+0#4040ff13&| @73
|~| @73
diff --git a/src/testdir/dumps/Test_prop_above_below_empty_1.dump b/src/testdir/dumps/Test_prop_above_below_empty_1.dump
index f470016..1cc6d01 100644
--- a/src/testdir/dumps/Test_prop_above_below_empty_1.dump
+++ b/src/testdir/dumps/Test_prop_above_below_empty_1.dump
@@ -1,16 +1,16 @@
-| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|1| |1+0#0000000&@7| @47
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|2| | +0#0000000&@55
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|3| |3+0#0000000&@8| @46
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|4| | +0#0000000&@55
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|5| >5+0#0000000&@10| @44
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
@42|5|,|1|-|5|7| @7|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_above_below_empty_2.dump b/src/testdir/dumps/Test_prop_above_below_empty_2.dump
index 3954a4b..db11724 100644
--- a/src/testdir/dumps/Test_prop_above_below_empty_2.dump
+++ b/src/testdir/dumps/Test_prop_above_below_empty_2.dump
@@ -1,16 +1,16 @@
-| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|1| |1+0#0000000&@7|$+0#4040ff13&| +0#0000000&@46
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|2| |$+0#4040ff13&| +0#0000000&@54
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|3| |3+0#0000000&@8|$+0#4040ff13&| +0#0000000&@45
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|4| |$+0#4040ff13&| +0#0000000&@54
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|5| >5+0#0000000&@10|$+0#4040ff13&| +0#0000000&@43
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
|:|s|e|t| |l|i|s|t| @32|5|,|1|-|5|7| @7|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_above_below_empty_3.dump b/src/testdir/dumps/Test_prop_above_below_empty_3.dump
index 27f9eec..78f30b7 100644
--- a/src/testdir/dumps/Test_prop_above_below_empty_3.dump
+++ b/src/testdir/dumps/Test_prop_above_below_empty_3.dump
@@ -1,16 +1,16 @@
-| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|1| |1+0#0000000&@7| | +0&#ffd7d7255| +0&#ffffff0@45
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|2| | +0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|3| |3+0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|4| | +0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|5| >5+0#0000000&@8|5+0&#ffd7d7255|5+0&#ffffff0| @44
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
|:| @40|5|,|1|-|5|7| @7|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_above_below_empty_4.dump b/src/testdir/dumps/Test_prop_above_below_empty_4.dump
index cc3c27d..2c7bf4d 100644
--- a/src/testdir/dumps/Test_prop_above_below_empty_4.dump
+++ b/src/testdir/dumps/Test_prop_above_below_empty_4.dump
@@ -1,16 +1,16 @@
-| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|4| |1+0#0000000&@7| @47
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|3| | +0#0000000&@55
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|2| |3+0#0000000&@8| @46
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|1| | +0#0000000&@55
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
|5+0#af5f00255&| @2>5+0#0000000&@10| @44
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
|:| @40|5|,|1|-|5|7| @7|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_above_below_empty_5.dump b/src/testdir/dumps/Test_prop_above_below_empty_5.dump
index 5ee4d80..1928ea2 100644
--- a/src/testdir/dumps/Test_prop_above_below_empty_5.dump
+++ b/src/testdir/dumps/Test_prop_above_below_empty_5.dump
@@ -1,16 +1,16 @@
-| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|2| |1+0#0000000&@7| @47
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|1| | +0#0000000&@55
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
|3+0#af5f00255&| @2>3+0#0000000&@8| @46
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|1| | +0#0000000&@55
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
-| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
| +0#af5f00255&@1|2| |5+0#0000000&@10| @44
-| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
|:| @40|3|,|1|-|5|7| @7|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_above_below_empty_6.dump b/src/testdir/dumps/Test_prop_above_below_empty_6.dump
new file mode 100644
index 0000000..5013643
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_above_below_empty_6.dump
@@ -0,0 +1,16 @@
+| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@1|1| |1+0#0000000&@7| @47
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
+|2+0#af5f00255&| @2> +0#0000000&@55
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@1|1| |3+0#0000000&@8| @46
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@1|2| | +0#0000000&@55
+| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54
+| +0#af5f00255&@3|!+0#0000001#ffff4012| +0#0000000#ffffff0@54
+|@+0#4040ff13&@2| @56
+|:+0#0000000&|c|a|l@1| |A|d@1|M|o|r|e|(|)| @26|2|,|0|-|5|7| @7|T|o|p|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_1.dump b/src/testdir/dumps/Test_prop_inserts_text_1.dump
index 7d1b102..7a51c12 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_1.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_1.dump
@@ -1,6 +1,6 @@
|i+0&#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| |s|o
|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0&#5fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n>g| @27
-|p|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @40
+|p|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @40
|F|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @34
|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@49
|l|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @42
diff --git a/src/testdir/dumps/Test_prop_inserts_text_2.dump b/src/testdir/dumps/Test_prop_inserts_text_2.dump
index 2a5b2f3..c9c325f 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_2.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_2.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d|
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0&#5fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n>g| @23
-| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38
+| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38
| +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32
| +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47
| +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40
diff --git a/src/testdir/dumps/Test_prop_inserts_text_3.dump b/src/testdir/dumps/Test_prop_inserts_text_3.dump
index 36a4b8c..2b93554 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_3.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_3.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d|
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0&#5fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23
-| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s>t| @38
+| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s>t| @38
| +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32
| +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47
| +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40
diff --git a/src/testdir/dumps/Test_prop_inserts_text_4.dump b/src/testdir/dumps/Test_prop_inserts_text_4.dump
index 8bb637a..83e656a 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_4.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_4.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d|
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0&#5fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23
-| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38
+| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38
| +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=>1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32
| +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47
| +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40
diff --git a/src/testdir/dumps/Test_prop_inserts_text_5.dump b/src/testdir/dumps/Test_prop_inserts_text_5.dump
index 75194f6..2885d4d 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_5.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_5.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d|
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0&#5fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23
-| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38
+| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38
| +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=>2+0#0000000&| |}|;| @32
| +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47
| +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40
diff --git a/src/testdir/dumps/Test_prop_inserts_text_6.dump b/src/testdir/dumps/Test_prop_inserts_text_6.dump
index fb25ddf..5aeddb4 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_6.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_6.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d|
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0&#5fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23
-| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38
+| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38
| +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32
| +0#0000e05#a8a8a8255@1>e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47
| +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40
diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump
index 2383b4a..48d8ebc 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump
@@ -1,6 +1,6 @@
-|1+0&#e0e0e08|2|3+0&#ffffff0|4|5|6|7|8|9| @50
-|1+0&#e0e0e08|-+0#e000e06#ffffff0|å£*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46
-|1+0&#e0e0e08|2|å£*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48
-|1+0&#e0e0e08>2+0&#ffffff0|3|4|5|6|7|8|9| @50
+|1+0#0000001#a8a8a8255|2|3+0#0000000#ffffff0|4|5|6|7|8|9| @50
+|1+0#0000001#a8a8a8255|-+0#e000e06#ffffff0|å£*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46
+|1+0#0000001#a8a8a8255|2|å£*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48
+|1+0#0000001#a8a8a8255>2+0#0000000#ffffff0|3|4|5|6|7|8|9| @50
|~+0#4040ff13&| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|2| @6|4|,|2| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump
index 920cb1d..0234ba4 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump
@@ -1,6 +1,6 @@
-|1+0&#e0e0e08|2|3|4+0&#ffffff0|5|6|7|8|9| @50
-|1+0&#e0e0e08|-+0#e000e06#ffffff0|å£*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46
-|1+0&#e0e0e08|2|å£*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48
-|1+0&#e0e0e08|2>3+0&#ffffff0|4|5|6|7|8|9| @50
+|1+0#0000001#a8a8a8255|2|3|4+0#0000000#ffffff0|5|6|7|8|9| @50
+|1+0#0000001#a8a8a8255|-+0#e000e06#ffffff0|å£*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46
+|1+0#0000001#a8a8a8255|2|å£*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48
+|1+0#0000001#a8a8a8255|2>3+0#0000000#ffffff0|4|5|6|7|8|9| @50
|~+0#4040ff13&| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|3| @6|4|,|3| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump
index 0017f02..ff5af3a 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump
@@ -1,6 +1,6 @@
-|1+0&#e0e0e08|2|3|4|5|6|7|8+0&#ffffff0|9| @50
-|1+0&#e0e0e08|-+0#e000e06#ffffff0|å£*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46
-|1+0&#e0e0e08|2|å£*0#e000e06#ffffff0|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48
-|1+0&#e0e0e08|2|3|4|5|6>7+0&#ffffff0|8|9| @50
+|1+0#0000001#a8a8a8255|2|3|4|5|6|7|8+0#0000000#ffffff0|9| @50
+|1+0#0000001#a8a8a8255|-+0#e000e06#ffffff0|å£*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46
+|1+0#0000001#a8a8a8255|2|å£*0#e000e06#ffffff0|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48
+|1+0#0000001#a8a8a8255|2|3|4|5|6>7+0#0000000#ffffff0|8|9| @50
|~+0#4040ff13&| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|7| @6|4|,|7| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump
index cb7e0c9..496eee9 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump
@@ -1,6 +1,6 @@
-|1+0&#ffffff0|2+0&#e0e0e08|3|4|5|6|7|8+0&#ffffff0|9| @50
-|1|-+0#e000e06&|å£*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46
-|1|2+0&#e0e0e08|å£*0#e000e06#ffffff0|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48
-|1>2|3+0&#e0e0e08|4|5|6|7|8+0&#ffffff0|9| @50
+|1+0&#ffffff0|2+0#0000001#a8a8a8255|3|4|5|6|7|8+0#0000000#ffffff0|9| @50
+|1|-+0#e000e06&|å£*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46
+|1|2+0#0000001#a8a8a8255|å£*0#e000e06#ffffff0|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48
+|1>2|3+0#0000001#a8a8a8255|4|5|6|7|8+0#0000000#ffffff0|9| @50
|~+0#4040ff13&| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|6| @6|4|,|2| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump
index c4be65f..8630777 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump
@@ -1,6 +1,6 @@
-|1+0&#ffffff0|2|3+0&#e0e0e08|4|5|6|7|8+0&#ffffff0|9| @50
-|1|-+0#e000e06&|å£*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46
-|1|2|å£*0#e000e06&|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48
-|1|2>3|4+0&#e0e0e08|5|6|7|8+0&#ffffff0|9| @50
+|1+0&#ffffff0|2|3+0#0000001#a8a8a8255|4|5|6|7|8+0#0000000#ffffff0|9| @50
+|1|-+0#e000e06&|å£*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46
+|1|2|å£*0#e000e06&|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48
+|1|2>3|4+0#0000001#a8a8a8255|5|6|7|8+0#0000000#ffffff0|9| @50
|~+0#4040ff13&| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|5| @6|4|,|3| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump
index 54c7fde..bcc9101 100644
--- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump
+++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump
@@ -1,6 +1,6 @@
-|1+0&#ffffff0|2|3|4+0&#e0e0e08|5|6|7|8+0&#ffffff0|9| @50
-|1|-+0#e000e06&|å£*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46
-|1|2|å£*0#e000e06&|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48
-|1|2|3>4|5+0&#e0e0e08|6|7|8+0&#ffffff0|9| @50
+|1+0&#ffffff0|2|3|4+0#0000001#a8a8a8255|5|6|7|8+0#0000000#ffffff0|9| @50
+|1|-+0#e000e06&|å£*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46
+|1|2|å£*0#e000e06&|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48
+|1|2|3>4|5+0#0000001#a8a8a8255|6|7|8+0#0000000#ffffff0|9| @50
|~+0#4040ff13&| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|4| @6|4|,|4| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_1.dump b/src/testdir/dumps/Test_prop_wincolor_1.dump
new file mode 100644
index 0000000..d8a6226
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_1.dump
@@ -0,0 +1,8 @@
+>s+0&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @45
+@3|B+0&#5fd7ff255|E|L|O|W| +0&#ffd7ff255@51
+|s|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @33
+|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@37
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_2.dump b/src/testdir/dumps/Test_prop_wincolor_2.dump
new file mode 100644
index 0000000..6e5126c
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_2.dump
@@ -0,0 +1,8 @@
+>s+8&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @45
+@3|B+8&#5fd7ff255|E|L|O|W| +8&#ffd7ff255@51
+|s+0&&|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @33
+|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@37
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_3.dump b/src/testdir/dumps/Test_prop_wincolor_3.dump
new file mode 100644
index 0000000..f77c274
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_3.dump
@@ -0,0 +1,8 @@
+>s+8&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @14| +8&#ffd7d7255| +8&#ffd7ff255@29
+@3|B+8&#5fd7ff255|E|L|O|W| +8&#ffd7ff255@51
+|s+0&&|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @2| +0&#ffd7d7255| +0&#ffd7ff255@29
+|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@6| +0&#ffd7d7255| +0&#ffd7ff255@29
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_4.dump b/src/testdir/dumps/Test_prop_wincolor_4.dump
new file mode 100644
index 0000000..06d6b0f
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_4.dump
@@ -0,0 +1,8 @@
+>s+8&#af5f00255|o|m|e| |t|e|x|t| |h|e|r|e| @14| +8&#ffd7d7255| +8&#af5f00255@29
+@3|B+8&#5fd7ff255|E|L|O|W| +8&#af5f00255@51
+|s+0&#ffd7ff255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @2| +0&#ffd7d7255| +0&#ffd7ff255@29
+|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@6| +0&#ffd7d7255| +0&#ffd7ff255@29
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_5.dump b/src/testdir/dumps/Test_prop_wincolor_5.dump
new file mode 100644
index 0000000..0c062b4
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_5.dump
@@ -0,0 +1,8 @@
+|s+8&#af5f00255|o|m|e| |t|e|x|t| |h|e|r>e| @14| +8&#ffd7d7255| +8&#af5f00255@29
+@3|B+8&#5fd7ff255|E|L|O|W| +8&#af5f00255@51
+|s+0&#ffd7ff255|o|m|e| |m|u|c|h| |l|o|n|g+0&#e0e0e08|e+0&#ffd7ff255|r| |t|e|x|t| |h|e|r|e| @2| +0&#ffd7d7255| +0&#ffd7ff255@29
+|m|o|r|e| |t|e|x|t| |h|e|r|e+0&#e0e0e08| +0&#ffd7ff255@2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@6| +0&#ffd7d7255| +0&#ffd7ff255@29
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|1|,|1|4| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_6.dump b/src/testdir/dumps/Test_prop_wincolor_6.dump
new file mode 100644
index 0000000..e07b3e6
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_6.dump
@@ -0,0 +1,8 @@
+|s+0&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @10| +0&#e0e0e08| +0&#ffd7ff255@2| +0&#ffd7d7255| +0&#ffd7ff255@29
+@3|B+0&#5fd7ff255|E|L|O|W| +0&#ffd7ff255@51
+|s+8&#af5f00255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r>e| @2| +8&#ffd7d7255| +8&#af5f00255@29
+|m+0&#ffd7ff255|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@2| +0&#e0e0e08| +0&#ffd7ff255@2| +0&#ffd7d7255| +0&#ffd7ff255@29
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|2|,|2|6| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_7.dump b/src/testdir/dumps/Test_prop_wincolor_7.dump
new file mode 100644
index 0000000..9412811
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_7.dump
@@ -0,0 +1,8 @@
+|s+0&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @11| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29
+@3|B+0&#5fd7ff255|E|L|O|W| +0&#ffd7ff255@51
+|s+8&#af5f00255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e> @2| +8&#ffd7d7255| +8&#af5f00255@29
+|m+0&#ffd7ff255|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@3| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|2|,|2|7| @9|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_8.dump b/src/testdir/dumps/Test_prop_wincolor_8.dump
new file mode 100644
index 0000000..9df69ec
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_8.dump
@@ -0,0 +1,8 @@
+|s+8&#af5f00255|o|m|e| |t|e|x|t| |h|e|r|e| @11> @2| +8&#ffd7d7255| +8&#af5f00255@29
+@3|B+8&#5fd7ff255|E|L|O|W| +8&#af5f00255@51
+|s+0&#ffd7ff255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29
+|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@3| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29
+|~+0#4040ff13&| @58
+|~| @58
+|~| @58
+|:+0#0000000#ffffff0| @40|1|,|1|5|-|2|7| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_wincolor_9.dump b/src/testdir/dumps/Test_prop_wincolor_9.dump
new file mode 100644
index 0000000..7b26974
--- /dev/null
+++ b/src/testdir/dumps/Test_prop_wincolor_9.dump
@@ -0,0 +1,8 @@
+| +8&#af5f00255@29| +8&#ffd7d7255| +8&#af5f00255@1> @12|e|r|e|h| |t|x|e|t| |e|m|o|s
+| @51|W+8&#5fd7ff255|O|L|E|B| +8&#af5f00255@2
+| +0&#ffd7ff255@29| +0&#ffd7d7255| +0&#ffd7ff255@1| +0&#e0e0e08|e+0&#ffd7ff255|r|e|h| |t|x|e|t| |r|e|g|n|o|l| |h|c|u|m| |e|m|o|s
+| @29| +0&#ffd7d7255| +0&#ffd7ff255@1| +0&#e0e0e08| +0&#ffd7ff255@3|R+0&#ffff4012|E|T|F|A| +0&#ffd7ff255@2|e|r|e|h| |t|x|e|t| |e|r|o|m
+| +0#4040ff13&@58|~
+| @58|~
+| @58|~
+|:+0#0000000#ffffff0| @40|1|,|1|5|-|2|7| @6|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_with_text_above_6.dump b/src/testdir/dumps/Test_prop_with_text_above_6.dump
index da28228..0aa04b5 100644
--- a/src/testdir/dumps/Test_prop_with_text_above_6.dump
+++ b/src/testdir/dumps/Test_prop_with_text_above_6.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|f+0#0000000#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@36
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|s+0#0000000#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@35
-| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000000#e0e0e08|n|s|e|r|t|e>d+0&#ffffff0| |o|n|e| |t|w|o| @37
+| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000001#a8a8a8255|n|s|e|r|t|e>d+0#0000000#ffffff0| |o|n|e| |t|w|o| @37
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|b+0#0000000#5fd7ff255|e|l|o|w| +0&#ffffff0@48
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|2| |t+0#0000000&|h|r|e@1| |f|o|u|r| @43
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3| +0#0000000&@2|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| +0&#ffffff0@37
diff --git a/src/testdir/dumps/Test_prop_with_text_above_7.dump b/src/testdir/dumps/Test_prop_with_text_above_7.dump
index c50749b..b675ed9 100644
--- a/src/testdir/dumps/Test_prop_with_text_above_7.dump
+++ b/src/testdir/dumps/Test_prop_with_text_above_7.dump
@@ -1,6 +1,6 @@
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|f+0#0000000#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@36
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|s+0#0000000#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@35
-| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000000#e0e0e08|n|s|e|r|t|e>d+0&#ffffff0| +0&#e0e0e08|o|n|e| |t|w|o| +0&#ffffff0@37
+| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000001#a8a8a8255|n|s|e|r|t|e>d+0#0000000#ffffff0| +0#0000001#a8a8a8255|o|n|e| |t|w|o| +0#0000000#ffffff0@37
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|b+0#0000000#5fd7ff255|e|l|o|w| +0#4040ff13#ffffff0| +0#0000000&@47
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|2| |t+0#0000000&|h|r|e@1| |f|o|u|r| @43
| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3| +0#0000000&@2|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| +0&#ffffff0@37
diff --git a/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump b/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump
index 1bc9903..d9a055e 100644
--- a/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump
+++ b/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump
@@ -1,8 +1,8 @@
|X+0&#ffff4012@59
-|a+0&#e0e0e08@1>a+0&#ffffff0| @56
+|a+0#0000001#a8a8a8255@1>a+0#0000000#ffffff0| @56
|X+0&#ffff4012@59
@1| +0&#ffffff0@58
-|b+0&#e0e0e08@2|b+0&#ffffff0@2| @53
+|b+0#0000001#a8a8a8255@2|b+0#0000000#ffffff0@2| @53
|~+0#4040ff13&| @58
|~| @58
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|3|x|3| @6|2|,|3| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_prop_with_text_override_2.dump b/src/testdir/dumps/Test_prop_with_text_override_2.dump
index 334929e..5311cd7 100644
--- a/src/testdir/dumps/Test_prop_with_text_override_2.dump
+++ b/src/testdir/dumps/Test_prop_with_text_override_2.dump
@@ -1,4 +1,4 @@
-|s+0&#ffffff0|o|m+0&#e0e0e08|e| | +0#4040ff13#40ffff15|i|n|s|e|r|t|e|d| |t+0#0000000#e0e0e08|e|x|t| |h|e>r+0&#ffffff0|e| @35
+|s+0&#ffffff0|o|m+0#0000001#a8a8a8255|e| | +0#4040ff13#40ffff15|i|n|s|e|r|t|e|d| |t+0#0000001#a8a8a8255|e|x|t| |h|e>r+0#0000000#ffffff0|e| @35
|~+0#4040ff13&| @58
|~| @58
|~| @58
diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_1.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_1.dump
new file mode 100644
index 0000000..a0a269f
--- /dev/null
+++ b/src/testdir/dumps/Test_relnr_colors_wrapped_1.dump
@@ -0,0 +1,20 @@
+| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0
+| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17
+| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0
+| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17
+|1+0#0000001#ff404010@2| >1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1
+| +0#0000001#ff404010@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1
+| +0#0000001#ff404010@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17
+| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@45
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@45
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@27| @17
+| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1
+| +0#0000001#40ff4011@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17
+| +0#0000001#40ff4011@1|3| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1
+| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17
+| +0#0000001#40ff4011@1|4| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2
+| +0#0000000&@31|1@2|,|1| @8|5@1|%|
diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_2.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_2.dump
new file mode 100644
index 0000000..1f2df5e
--- /dev/null
+++ b/src/testdir/dumps/Test_relnr_colors_wrapped_2.dump
@@ -0,0 +1,20 @@
+| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0
+| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17
+|1+0#0000001#ff404010@1|0| >1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1
+| +0#0000001#ff404010@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0
+| +0#0000001#ff404010@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17
+| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1
+| +0#0000001#40ff4011@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17
+| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@45
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@45
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@27| @17
+| +0#0000001#40ff4011@1|3| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1
+| +0#0000001#40ff4011@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17
+| +0#0000001#40ff4011@1|4| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1
+| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17
+| +0#0000001#40ff4011@1|5| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2
+| +0#0000000&@31|1@1|0|,|1| @8|5@1|%|
diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_3.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_3.dump
new file mode 100644
index 0000000..b6f6c60
--- /dev/null
+++ b/src/testdir/dumps/Test_relnr_colors_wrapped_3.dump
@@ -0,0 +1,20 @@
+| +0#0000001#4040ff13@1|3| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0
+| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17
+| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0
+| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17
+| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17
+|1+0#0000001#ff404010@1|2| >1+0#0000000#ffffff0@45
+| +0#0000001#ff404010@3|1+0#0000000#ffffff0@45
+| +0#0000001#ff404010@3|1+0#0000000#ffffff0@27| @17
+| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1
+| +0#0000001#40ff4011@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17
+| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1
+| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17
+| +0#0000001#40ff4011@1|3| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2
+| +0#0000000&@31|1@1|2|,|1| @8|5@1|%|
diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_4.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_4.dump
new file mode 100644
index 0000000..b838950
--- /dev/null
+++ b/src/testdir/dumps/Test_relnr_colors_wrapped_4.dump
@@ -0,0 +1,20 @@
+| +0#0000001#4040ff13@1|5| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0
+| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17
+| +0#0000001#4040ff13@1|4| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0
+| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17
+| +0#0000001#4040ff13@1|3| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17
+| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0@45
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@45
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@27| @17
+| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1
+| +0#0000001#4040ff13@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17
+|1+0#0000001#ff404010@1|4| >1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1
+| +0#0000001#ff404010@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1
+| +0#0000001#ff404010@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17
+| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2
+| +0#0000000&@31|1@1|4|,|1| @8|5@1|%|
diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_5.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_5.dump
new file mode 100644
index 0000000..549275a
--- /dev/null
+++ b/src/testdir/dumps/Test_relnr_colors_wrapped_5.dump
@@ -0,0 +1,20 @@
+| +0#0000001#4040ff13@1|4| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0
+| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17
+| +0#0000001#4040ff13@1|3| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0
+| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17
+| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1
+| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17
+| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0@45
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@45
+| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@27| @17
+|1+0#0000001#ff404010@1|3| >1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1
+| +0#0000001#ff404010@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1
+| +0#0000001#ff404010@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17
+| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1
+| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1
+| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17
+| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2
+| +0#0000000&@31|1@1|3|,|1| @8|5@1|%|
diff --git a/src/testdir/dumps/Test_statusline_showcmd_3.dump b/src/testdir/dumps/Test_statusline_showcmd_3.dump
index 049e0f7..d2b2158 100644
--- a/src/testdir/dumps/Test_statusline_showcmd_3.dump
+++ b/src/testdir/dumps/Test_statusline_showcmd_3.dump
@@ -1,6 +1,6 @@
-|a+0&#e0e0e08| +0&#ffffff0@73
-|b+0&#e0e0e08| +0&#ffffff0@73
-|c+0&#e0e0e08> +0&#ffffff0@73
+|a+0#0000001#a8a8a8255| +0#0000000#ffffff0@73
+|b+0#0000001#a8a8a8255| +0#0000000#ffffff0@73
+|c+0#0000001#a8a8a8255> +0#0000000#ffffff0@73
|~+0#4040ff13&| @73
|3+3#0000000&|x|2| @71
|-+2&&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@56
diff --git a/src/testdir/dumps/Test_syntax_c_01.dump b/src/testdir/dumps/Test_syntax_c_01.dump
index 7224216..bd2ec04 100644
--- a/src/testdir/dumps/Test_syntax_c_01.dump
+++ b/src/testdir/dumps/Test_syntax_c_01.dump
@@ -4,8 +4,8 @@
| +0#0000e05&@2|i|n|t| @2|n|o|t|_|u|s|e|d|;| +0#0000000&@56
|#+0#e000e06&|e|l|s|e| +0#0000000&@69
@3|i+0#00e0003&|n|t| +0#0000000&@2|u|s|e|d|;| @60
-|#+0#e000e06&|e+0&#e0e0e08|n|d|i|f| +0#0000000&| +0&#ffffff0@67
-| +0&#e0e0e08@2|p|r|i|n|t|f|(|"+0#e000002&|J|u|s|t| |a|n| |e|x|a|m|p|l|e| |p|i|e|c|e| |o|f| >C+0&#ffffff0| |c|o|d|e|\+0#e000e06&|n|"+0#e000002&|)+0#0000000&|;| @27
+|#+0#e000e06&|e+0#0000001#a8a8a8255|n|d|i|f| | +0#0000000#ffffff0@67
+| +0#0000001#a8a8a8255@2|p|r|i|n|t|f|(|"|J|u|s|t| |a|n| |e|x|a|m|p|l|e| |p|i|e|c|e| |o|f| >C+0#e000002#ffffff0| |c|o|d|e|\+0#e000e06&|n|"+0#e000002&|)+0#0000000&|;| @27
@3|r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|x|0|f@1|;+0#0000000&| @58
|}| @73
| +0#ffffff16#ff404010@16| +0#0000000#ffffff0@57
diff --git a/src/testdir/dumps/Test_tabline_showcmd_3.dump b/src/testdir/dumps/Test_tabline_showcmd_3.dump
index 3e29cda..21a66a3 100644
--- a/src/testdir/dumps/Test_tabline_showcmd_3.dump
+++ b/src/testdir/dumps/Test_tabline_showcmd_3.dump
@@ -1,6 +1,6 @@
|3+1&#ffffff0|x|2| @71
-|a+0&#e0e0e08| +0&#ffffff0@73
-|b+0&#e0e0e08| +0&#ffffff0@73
-|c+0&#e0e0e08> +0&#ffffff0@73
+|a+0#0000001#a8a8a8255| +0#0000000#ffffff0@73
+|b+0#0000001#a8a8a8255| +0#0000000#ffffff0@73
+|c+0#0000001#a8a8a8255> +0#0000000#ffffff0@73
|~+0#4040ff13&| @73
|-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@38|3|,|2| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_terminal_popup_7.dump b/src/testdir/dumps/Test_terminal_popup_7.dump
index e7e5aae..0b14d27 100644
--- a/src/testdir/dumps/Test_terminal_popup_7.dump
+++ b/src/testdir/dumps/Test_terminal_popup_7.dump
@@ -4,7 +4,7 @@
|3| @12|â•”+0#0000001#ffd7ff255|â•@44|â•—| +0#0000000#ffffff0@13
|4| @12|â•‘+0#0000001#ffd7ff255|s|o|m|e| |t|e|x|t| @35|â•‘| +0#0000000#ffffff0@13
|5| @12|â•‘+0#0000001#ffd7ff255|t|o| |e+0&#ffff4012|d|i|t| +0&#ffd7ff255@37|â•‘| +0#0000000#ffffff0@13
-|6| @12|â•‘+0#0000001#ffd7ff255|i+0&#e0e0e08|n| |a| >p+0&#ffd7ff255|o|p|u|p| |w|i|n|d|o|w| @27|â•‘| +0#0000000#ffffff0@13
+|6| @12|â•‘+0#0000001#ffd7ff255|i+0&#a8a8a8255|n| |a| >p+0&#ffd7ff255|o|p|u|p| |w|i|n|d|o|w| @27|â•‘| +0#0000000#ffffff0@13
|7| @12|â•‘+0#0000001#ffd7ff255|~+0#4040ff13&| @43|â•‘+0#0000001&| +0#0000000#ffffff0@13
|8| @12|â•‘+0#0000001#ffd7ff255|~+0#4040ff13&| @43|â•‘+0#0000001&| +0#0000000#ffffff0@13
|9| @12|â•‘+0#0000001#ffd7ff255|~+0#4040ff13&| @43|â•‘+0#0000001&| +0#0000000#ffffff0@13
diff --git a/src/testdir/dumps/Test_textprop_hl_override_2.dump b/src/testdir/dumps/Test_textprop_hl_override_2.dump
index 187233d..9e677f8 100644
--- a/src/testdir/dumps/Test_textprop_hl_override_2.dump
+++ b/src/testdir/dumps/Test_textprop_hl_override_2.dump
@@ -1,6 +1,6 @@
|O+0&#ffffff0|n|e| |o+0#4040ff13#ffff4012|n|e| |o+0#0000000#ffffff0|n|e| |o+0#4040ff13#ffff4012|n|e| |o+0#0000000#ffffff0|n|e| @55
|T|w|o| |t+0#4040ff13#ffff4012|w|o| |t+0#0000000#ffffff0|w|o| |t+0#4040ff13#ffff4012|w|o| |t+0#0000000#ffffff0|w|o| @55
-|T|h|r+0&#e0e0e08|e|e+0#4040ff13&| |t|h|r+0#0000000&|e@1| |t+0#4040ff13#ffff4012|h|r|e|e+0#0000000#e0e0e08| |t|h|r>e+0&#ffffff0@1| @51
+|T|h|r+0#0000001#a8a8a8255|e@1| |t|h|r|e@1| |t+0#4040ff13#ffff4012|h|r|e|e+0#0000001#a8a8a8255| |t|h|r>e+0#0000000#ffffff0@1| @51
|~+0#4040ff13&| @73
|~| @73
|~| @73
diff --git a/src/testdir/dumps/Test_vim9_no_redraw.dump b/src/testdir/dumps/Test_vim9_no_redraw.dump
index 1d77a08..2f02082 100644
--- a/src/testdir/dumps/Test_vim9_no_redraw.dump
+++ b/src/testdir/dumps/Test_vim9_no_redraw.dump
@@ -1,4 +1,4 @@
-|s+0&#ffffff0|o+0&#e0e0e08|m|e| |t|e|x|t| | +0&#ffffff0@64
+|s+0&#ffffff0|o+0#0000001#a8a8a8255|m|e| |t|e|x|t| | +0#0000000#ffffff0@64
|~+0#4040ff13&| @73
|~| @73
|~| @73
diff --git a/src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump b/src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump
new file mode 100644
index 0000000..d81456f
--- /dev/null
+++ b/src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump
@@ -0,0 +1,8 @@
+| +0#af5f00255#ffffff0@1|1| |o+0#0000000&|n|e| @52
+| +0#af5f00255&@1|2| |t+0#0000000&|w|o| @52
+| +0#af5f00255&@3|s+0#ffffff16#ff404010|y|n|t|a|x| |e|r@1|o|r| +0#0000000#ffffff0@43
+| +0#af5f00255&@1|3| >t+0#0000000&|h|r|e@1| @50
+| +0#af5f00255&@1|4| |f+0#0000000&|o|u|r+0#e000002&| +0#0000000&@40|o+0#ffffff16#ff404010|t|h|e|r| |e|r@1|o|r
+| +0#af5f00255#ffffff0@1|5| |f+0#e000002&|i+0#0000000&|v|e| @51
+|~+0#4040ff13&| @58
+| +0#0000000&@41|3|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_visual_block_with_virtualedit.dump b/src/testdir/dumps/Test_visual_block_with_virtualedit.dump
index 2991a63..7a24250 100644
--- a/src/testdir/dumps/Test_visual_block_with_virtualedit.dump
+++ b/src/testdir/dumps/Test_visual_block_with_virtualedit.dump
@@ -1,6 +1,6 @@
-|a+0&#e0e0e08@5> +0&#ffffff0@43
-|b+0&#e0e0e08@3| @2| +0&#ffffff0@42
-|c+0&#e0e0e08@1| @4| +0&#ffffff0@42
+|a+0#0000001#a8a8a8255@5> +0#0000000#ffffff0@43
+|b+0#0000001#a8a8a8255@3| @2| +0#0000000#ffffff0@42
+|c+0#0000001#a8a8a8255@1| @4| +0#0000000#ffffff0@42
|~+0#4040ff13&| @48
|~| @48
|~| @48
diff --git a/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump b/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump
index 3c62156..e68df74 100644
--- a/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump
+++ b/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump
@@ -1,6 +1,6 @@
-|a+0&#e0e0e08@5| | +0&#ffffff0@42
-|b+0&#e0e0e08@3| @2| +0&#ffffff0@42
-|c+0&#e0e0e08@1> +0&#ffffff0| +0&#e0e0e08@3| +0&#ffffff0@42
+|a+0#0000001#a8a8a8255@5| | +0#0000000#ffffff0@42
+|b+0#0000001#a8a8a8255@3| @2| +0#0000000#ffffff0@42
+|c+0#0000001#a8a8a8255@1> +0#0000000#ffffff0| +0#0000001#a8a8a8255@3| +0#0000000#ffffff0@42
|~+0#4040ff13&| @48
|~| @48
|~| @48
diff --git a/src/testdir/dumps/Test_visual_ends_before_showbreak.dump b/src/testdir/dumps/Test_visual_ends_before_showbreak.dump
new file mode 100644
index 0000000..ee809ba
--- /dev/null
+++ b/src/testdir/dumps/Test_visual_ends_before_showbreak.dump
@@ -0,0 +1,6 @@
+|x+0&#ffffff0@4| @69
+|↪+0#4040ff13&| |y+0#0000001#a8a8a8255@68> +0#0000000#ffffff0| +0#0000001#a8a8a8255@2
+|↪+0#4040ff13#ffffff0| |z+0#0000000&@3| @68
+|~+0#4040ff13&| @73
+|~| @73
+|-+2#0000000&@1| |V|I|S|U|A|L| |-@1| +0&&@34|7|0| @7|1|,|7|6|-|1|4|7| @5|A|l@1|
diff --git a/src/testdir/dumps/Test_visual_hl_with_showbreak.dump b/src/testdir/dumps/Test_visual_hl_with_showbreak.dump
index fa0b2dc..0bd83b0 100644
--- a/src/testdir/dumps/Test_visual_hl_with_showbreak.dump
+++ b/src/testdir/dumps/Test_visual_hl_with_showbreak.dump
@@ -1,5 +1,5 @@
|a+0&#ffffff0@48>a
-|++0#4040ff13&|a+0#0000000#e0e0e08@3|a+0&#ffffff0@5| @38
+|++0#4040ff13&|a+0#0000001#a8a8a8255@3|a+0#0000000#ffffff0@5| @38
|~+0#4040ff13&| @48
|~| @48
|~| @48
diff --git a/src/testdir/dumps/Test_visual_sbr_1.dump b/src/testdir/dumps/Test_visual_sbr_1.dump
index 0a9511d..3c167ec 100644
--- a/src/testdir/dumps/Test_visual_sbr_1.dump
+++ b/src/testdir/dumps/Test_visual_sbr_1.dump
@@ -1,4 +1,4 @@
-|>+0#4040ff13#ffffff0| +0#0000000#e0e0e08|k|a|s|d| |g|u|b|e|r|g|r|e|n|,| |n|o| |s|e|a| |t|a|k|i|m|a|t|a| |s|a|n|c|t|u|s| |e|s|t| |L|o|r|e|m| |i|p|s|u|m| |d|o|l|o|r| |s|i|t| |a|m|e|t|.> +0&#ffffff0@1
+|>+0#4040ff13#ffffff0| +0#0000001#a8a8a8255|k|a|s|d| |g|u|b|e|r|g|r|e|n|,| |n|o| |s|e|a| |t|a|k|i|m|a|t|a| |s|a|n|c|t|u|s| |e|s|t| |L|o|r|e|m| |i|p|s|u|m| |d|o|l|o|r| |s|i|t| |a|m|e|t|.> +0#0000000#ffffff0@1
@75
@75
@75
diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump
index f61440a..4cbf8d0 100644
--- a/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump
+++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump
@@ -1,4 +1,4 @@
-|<+0#4040ff13#ffffff0@2| +0#0000000&@4| +0&#e0e0e08|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0&#ffffff0@45
+|<+0#4040ff13#ffffff0@2| +0#0000000&@4| +0#0000001#a8a8a8255|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0#0000000#ffffff0@45
|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3@1|0| @5|A|l@1
| +0&&@74
|~+0#4040ff13&| @73
diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump
index 1f10940..a6df79e 100644
--- a/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump
+++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump
@@ -1,4 +1,4 @@
-| +0&#ffffff0@7|++0#4040ff13&@2| +0#0000000#e0e0e08|9|0| |9|1| |9|2| |9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0&#ffffff0@33
+| +0&#ffffff0@7|++0#4040ff13&@2| +0#0000001#a8a8a8255|9|0| |9|1| |9|2| |9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0#0000000#ffffff0@33
|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3|4|2| @5|A|l@1
| +0&&@74
|~+0#4040ff13&| @73
diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump
index d36d675..77ef541 100644
--- a/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump
+++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump
@@ -1,4 +1,4 @@
-|++0#4040ff13#ffffff0@2| +0#0000000&@4| +0&#e0e0e08|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0&#ffffff0@45
+|++0#4040ff13#ffffff0@2| +0#0000000&@4| +0#0000001#a8a8a8255|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0#0000000#ffffff0@45
|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3@1|0| @5|A|l@1
| +0&&@74
|~+0#4040ff13&| @73
diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump
index 101352e..0abcc3c 100644
--- a/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump
+++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump
@@ -1,4 +1,4 @@
-|++0#4040ff13#ffffff0@2| +0#0000000#e0e0e08|9|8| |9@1> +0&#ffffff0@65
+|++0#4040ff13#ffffff0@2| +0#0000001#a8a8a8255|9|8| |9@1> +0#0000000#ffffff0@65
|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3|1|0| @5|A|l@1
| +0&&@74
|~+0#4040ff13&| @73
diff --git a/src/testdir/dumps/Test_win_gotoid_2.dump b/src/testdir/dumps/Test_win_gotoid_2.dump
index 7a778f5..8573fbe 100644
--- a/src/testdir/dumps/Test_win_gotoid_2.dump
+++ b/src/testdir/dumps/Test_win_gotoid_2.dump
@@ -6,7 +6,7 @@
|[+1&&|N|o| |N|a|m|e|]| @47|1|,|1| @11|T|o|p
|2+0&&|1| @72
|2@1| @72
-|2+0&#e0e0e08>3+0&#ffffff0| @72
+|2+0#0000001#a8a8a8255>3+0#0000000#ffffff0| @72
|2|4| @72
|2|5| @72
|2|6| @72
diff --git a/src/testdir/dumps/Test_wincolor_01.dump b/src/testdir/dumps/Test_wincolor_01.dump
index 5a5ccf5..c8578b2 100644
--- a/src/testdir/dumps/Test_wincolor_01.dump
+++ b/src/testdir/dumps/Test_wincolor_01.dump
@@ -1,6 +1,6 @@
| +0#af5f00255#ffd7ff255@1|2| | +0#0000001&@4| +0&#e0e0e08| +0&#ffd7ff255@64
-| +0#af5f00255&@1|1| |1+0#0000001&@4|1+0&#e0e0e08@4| | +0&#ffd7ff255@59
-| +8#af5f00255&@1|0| |2+0#0000001#e0e0e08@4>2+0&#ffd7ff255@5| +8&&@59
+| +0#af5f00255&@1|1| |1+0#0000001&@4|1+0&#a8a8a8255@4| | +0&#ffd7ff255@59
+| +8#af5f00255&@1|0| |2+0#0000001#a8a8a8255@4>2+0&#ffd7ff255@5| +8&&@59
| +0#af5f00255&@1|1| |3+0#0000001&| |h|e|r|e+0&#e0e0e08| +0&#ffd7ff255|3| @62
| +0#af5f00255&@1|2| | +0#0000001&@4| +0&#e0e0e08| +0&#ffd7ff255@64
| +0#af5f00255&@1|3| |t+0#40ff4011&|h|e| |c|a+0&#e0e0e08|t+0&#ffd7ff255| |i|s| |o+1&&|u|t| +0&&|o|f| |t|h|e| |b|a|g| +0#0000001&@45
diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim
index 4d008a0..dd2f012 100644
--- a/src/testdir/shared.vim
+++ b/src/testdir/shared.vim
@@ -300,7 +300,8 @@ func GetVimCommand(...)
endif
let cmd .= ' --not-a-term'
let cmd .= ' --gui-dialog-file guidialogfile'
- let cmd = substitute(cmd, 'VIMRUNTIME=\S\+', '', '')
+ " remove any environment variables
+ let cmd = substitute(cmd, '[A-Z_]\+=\S\+ *', '', 'g')
" If using valgrind, make sure every run uses a different log file.
if cmd =~ 'valgrind.*--log-file='
@@ -363,7 +364,7 @@ func RunVimPiped(before, after, arguments, pipecmd)
" Optionally run Vim under valgrind
" let cmd = 'valgrind --tool=memcheck --leak-check=yes --num-callers=25 --log-file=valgrind ' . cmd
- exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments
+ exe "silent !" .. a:pipecmd .. ' ' .. cmd .. args .. ' ' .. a:arguments
if len(a:before) > 0
call delete('Xbefore.vim')
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index cecb55a..564d568 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -270,6 +270,7 @@ func Test_win_tab_autocmd()
let g:record = []
augroup testing
+ au WinNewPre * call add(g:record, 'WinNewPre')
au WinNew * call add(g:record, 'WinNew')
au WinClosed * call add(g:record, 'WinClosed')
au WinEnter * call add(g:record, 'WinEnter')
@@ -286,8 +287,8 @@ func Test_win_tab_autocmd()
close
call assert_equal([
- \ 'WinLeave', 'WinNew', 'WinEnter',
- \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
+ \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
+ \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
\ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
\ 'WinLeave', 'WinClosed', 'WinEnter'
\ ], g:record)
@@ -298,17 +299,96 @@ func Test_win_tab_autocmd()
bwipe somefile
call assert_equal([
- \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
+ \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
\ 'WinClosed', 'TabClosed'
\ ], g:record)
+ let g:record = []
+ copen
+ help
+ tabnext
+ vnew
+
+ call assert_equal([
+ \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
+ \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
+ \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter'
+ \ ], g:record)
+
augroup testing
au!
augroup END
unlet g:record
endfunc
+func Test_WinNewPre()
+ " Test that the old window layout can be accessed before a new window is created.
+ let g:layouts_pre = []
+ let g:layouts_post = []
+ augroup testing
+ au WinNewPre * call add(g:layouts_pre, winlayout())
+ au WinNew * call add(g:layouts_post, winlayout())
+ augroup END
+ split
+ call assert_notequal(g:layouts_pre[0], g:layouts_post[0])
+ split
+ call assert_equal(g:layouts_pre[1], g:layouts_post[0])
+ call assert_notequal(g:layouts_pre[1], g:layouts_post[1])
+ tabnew
+ call assert_notequal(g:layouts_pre[2], g:layouts_post[1])
+ call assert_notequal(g:layouts_pre[2], g:layouts_post[2])
+ augroup testing
+ au!
+ augroup END
+ unlet g:layouts_pre
+ unlet g:layouts_post
+
+ " Test modifying window layout during WinNewPre throws.
+ let g:caught = 0
+ augroup testing
+ au!
+ au WinNewPre * split
+ augroup END
+ try
+ vnew
+ catch
+ let g:caught += 1
+ endtry
+ augroup testing
+ au!
+ au WinNewPre * tabnew
+ augroup END
+ try
+ vnew
+ catch
+ let g:caught += 1
+ endtry
+ augroup testing
+ au!
+ au WinNewPre * close
+ augroup END
+ try
+ vnew
+ catch
+ let g:caught += 1
+ endtry
+ augroup testing
+ au!
+ au WinNewPre * tabclose
+ augroup END
+ try
+ vnew
+ catch
+ let g:caught += 1
+ endtry
+ call assert_equal(4, g:caught)
+ augroup testing
+ au!
+ augroup END
+ unlet g:caught
+endfunc
+
func Test_WinResized()
CheckRunVimInTerminal
@@ -739,6 +819,27 @@ func Test_WinClosed_switch_tab()
%bwipe!
endfunc
+" This used to trigger WinClosed twice for the same window, and the window's
+" buffer was NULL in the second autocommand.
+func Test_WinClosed_BufUnload_close_other()
+ tabnew
+ let g:tab = tabpagenr()
+ let g:buf = bufnr()
+ new
+ setlocal bufhidden=wipe
+ augroup test-WinClosed
+ autocmd BufUnload * ++once exe g:buf .. 'bwipe!'
+ autocmd WinClosed * call tabpagebuflist(g:tab)
+ augroup END
+ close
+
+ unlet g:tab
+ unlet g:buf
+ autocmd! test-WinClosed
+ augroup! test-WinClosed
+ %bwipe!
+endfunc
+
func s:AddAnAutocmd()
augroup vimBarTest
au BufReadCmd * echo 'hello'
@@ -2626,6 +2727,24 @@ func Test_TextChangedI_with_setline()
bwipe!
endfunc
+func Test_TextChanged_with_norm()
+ " For unknown reason this fails on MS-Windows
+ CheckNotMSWindows
+ CheckFeature terminal
+ let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
+ call assert_equal('running', term_getstatus(buf))
+ call term_sendkeys(buf, ":let g:a=0\<cr>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":au! TextChanged * :let g:a+=1\<cr>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":norm! ia\<cr>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":echo g:a\<cr>")
+ call term_wait(buf, 50)
+ call WaitForAssert({-> assert_match('^1.*$', term_getline(buf, 3))})
+ bwipe!
+endfunc
+
func Test_Changed_FirstTime()
CheckFeature terminal
CheckNotGui
@@ -4315,4 +4434,44 @@ func Test_autocmd_shortmess()
delfunc SetupVimTest_shm
endfunc
+func Test_autocmd_invalidates_undo_on_textchanged()
+ CheckRunVimInTerminal
+ let script =<< trim END
+ set hidden
+ " create quickfix list (at least 2 lines to move line)
+ vimgrep /u/j %
+
+ " enter quickfix window
+ cwindow
+
+ " set modifiable
+ setlocal modifiable
+
+ " set autocmd to clear quickfix list
+
+ autocmd! TextChanged <buffer> call setqflist([])
+ " move line
+ move+1
+ END
+ call writefile(script, 'XTest_autocmd_invalidates_undo_on_textchanged', 'D')
+ let buf = RunVimInTerminal('XTest_autocmd_invalidates_undo_on_textchanged', {'rows': 20})
+ call term_sendkeys(buf, ":so %\<cr>")
+ call term_sendkeys(buf, "G")
+ call WaitForAssert({-> assert_match('^XTest_autocmd_invalidates_undo_on_textchanged\s*$', term_getline(buf, 20))}, 1000)
+
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_autocmd_creates_new_buffer_on_bufleave()
+ e a.txt
+ e b.txt
+ setlocal bufhidden=wipe
+ autocmd BufLeave <buffer> diffsplit c.txt
+ bn
+ call assert_equal(1, winnr('$'))
+ call assert_equal('a.txt', bufname('%'))
+ bw a.txt
+ bw c.txt
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_breakindent.vim b/src/testdir/test_breakindent.vim
index ee05548..96d91c9 100644
--- a/src/testdir/test_breakindent.vim
+++ b/src/testdir/test_breakindent.vim
@@ -424,7 +424,7 @@ func Test_breakindent12()
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
- call s:close_windows('set nuw=4 listchars=')
+ call s:close_windows('set nuw=4 listchars&')
endfunc
func Test_breakindent12_vartabs()
@@ -439,7 +439,7 @@ func Test_breakindent12_vartabs()
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
- call s:close_windows('set nuw=4 listchars= vts&')
+ call s:close_windows('set nuw=4 listchars& vts&')
endfunc
func Test_breakindent13()
@@ -733,7 +733,7 @@ func Test_breakindent20_list()
\ "shall make no law ",
\ ]
call s:compare_lines(expect, lines)
- " set minimum indent
+ " set minimum text width
setl briopt=min:5
redraw!
let lines = s:screen_lines2(1, 6, 20)
@@ -1086,5 +1086,83 @@ func Test_linebreak_list()
bwipe!
endfunc
+func Test_breakindent_change_display_uhex()
+ call s:test_windows('setl briopt=min:0 list listchars=eol:$')
+ redraw!
+ let lines = s:screen_lines(line('.'), 20)
+ let expect = [
+ \ "^Iabcdefghijklmnopqr",
+ \ " stuvwxyzABCDEFGHIJ",
+ \ " KLMNOP$ "
+ \ ]
+ call s:compare_lines(expect, lines)
+ set display+=uhex
+ redraw!
+ let lines = s:screen_lines(line('.'), 20)
+ let expect = [
+ \ "<09>abcdefghijklmnop",
+ \ " qrstuvwxyzABCDEF",
+ \ " GHIJKLMNOP$ "
+ \ ]
+ call s:compare_lines(expect, lines)
+ set display&
+
+ call s:close_windows()
+endfunc
+
+func Test_breakindent_list_split()
+ 10new
+ 61vsplit
+ setlocal tabstop=8 breakindent list listchars=tab:<->,eol:$
+ put =s:input
+ 30vsplit
+ setlocal listchars=eol:$
+ let expect = [
+ \ "^IabcdefghijklmnopqrstuvwxyzAB|<------>abcdefghijklmnopqrstuv",
+ \ " CDEFGHIJKLMNOP$ | wxyzABCDEFGHIJKLMNOP$ ",
+ \ "~ |~ "
+ \ ]
+ redraw!
+ let lines = s:screen_lines(line('.'), 61)
+ call s:compare_lines(expect, lines)
+ wincmd p
+ redraw!
+ let lines = s:screen_lines(line('.'), 61)
+ call s:compare_lines(expect, lines)
+
+ bwipe!
+endfunc
+
+func Test_breakindent_min_with_signcol()
+ call s:test_windows('setl briopt=min:15 signcolumn=yes')
+ redraw!
+ let expect = [
+ \ " abcdefghijklmn",
+ \ " opqrstuvwxyzABC",
+ \ " DEFGHIJKLMNOP "
+ \ ]
+ let lines = s:screen_lines(line('.'), 20)
+ call s:compare_lines(expect, lines)
+ setl briopt=min:17
+ redraw!
+ let expect = [
+ \ " abcdefghijklmn",
+ \ " opqrstuvwxyzABCDE",
+ \ " FGHIJKLMNOP "
+ \ ]
+ let lines = s:screen_lines(line('.'), 20)
+ call s:compare_lines(expect, lines)
+ setl briopt=min:19
+ redraw!
+ let expect = [
+ \ " abcdefghijklmn",
+ \ " opqrstuvwxyzABCDEF",
+ \ " GHIJKLMNOP "
+ \ ]
+ let lines = s:screen_lines(line('.'), 20)
+ call s:compare_lines(expect, lines)
+
+ call s:close_windows()
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim
index 53947f4..8be521b 100644
--- a/src/testdir/test_clientserver.vim
+++ b/src/testdir/test_clientserver.vim
@@ -13,7 +13,7 @@ source shared.vim
func Check_X11_Connection()
if has('x11')
- CheckEnv DISPLAY
+ CheckX11
try
call remote_send('xxx', '')
catch
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 4554712..7c86bcd 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -691,7 +691,7 @@ func Test_getcompletion()
bw Xtest\
endif
- call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:')
+ call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E866:')
call assert_fails('call getcompletion("", "burp")', 'E475:')
call assert_fails('call getcompletion("abc", [])', 'E1174:')
endfunc
@@ -917,6 +917,26 @@ func Test_cmdline_remove_char()
let &encoding = encoding_save
endfunc
+func Test_cmdline_del_utf8()
+ let @s = '⒌'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+
+ let @s = 'a̳'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+
+ let @s = 'β̳'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+
+ if has('arabic')
+ let @s = 'لا'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+ endif
+endfunc
+
func Test_cmdline_keymap_ctrl_hat()
CheckFeature keymap
@@ -3742,4 +3762,34 @@ func Test_custom_completion_with_glob()
delfunc TestGlobComplete
endfunc
+func Test_window_size_stays_same_after_changing_cmdheight()
+ set laststatus=2
+ let expected = winheight(0)
+ function! Function_name() abort
+ call feedkeys(":"..repeat('x', &columns), 'x')
+ let &cmdheight=2
+ let &cmdheight=1
+ redraw
+ endfunction
+ call Function_name()
+ call assert_equal(expected, winheight(0))
+endfunc
+
+" verify that buffer-completion finds all buffer names matching a pattern
+func Test_buffer_completion()
+ " should return empty list
+ call assert_equal([], getcompletion('', 'buffer'))
+
+ call mkdir('Xbuf_complete', 'R')
+ e Xbuf_complete/Foobar.c
+ e Xbuf_complete/MyFoobar.c
+ e AFoobar.h
+ let expected = ["Xbuf_complete/Foobar.c", "Xbuf_complete/MyFoobar.c", "AFoobar.h"]
+
+ call assert_equal(3, len(getcompletion('Foo', 'buffer')))
+ call assert_equal(expected, getcompletion('Foo', 'buffer'))
+ call feedkeys(":b Foo\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
index 5ba16db..33a2662 100644
--- a/src/testdir/test_cmdwin.vim
+++ b/src/testdir/test_cmdwin.vim
@@ -188,7 +188,7 @@ func Test_cmdwin_tabpage()
tabclose!
endfunc
-func Test_cmdwin_interrupted()
+func Test_cmdwin_interrupted_more_prompt()
CheckScreendump
" aborting the :smile output caused the cmdline window to use the current
@@ -470,4 +470,117 @@ func Test_cmdwin_restore_heights()
set cmdheight& showtabline& laststatus&
endfunc
+func Test_cmdwin_temp_curwin()
+ func CheckWraps(expect_wrap)
+ setlocal textwidth=0 wrapmargin=1
+
+ call deletebufline('', 1, '$')
+ let as = repeat('a', winwidth(0) - 2 - &wrapmargin)
+ call setline(1, as .. ' b')
+ normal! gww
+
+ setlocal textwidth& wrapmargin&
+ call assert_equal(a:expect_wrap ? [as, 'b'] : [as .. ' b'], getline(1, '$'))
+ endfunc
+
+ func CheckCmdWin()
+ call assert_equal('command', win_gettype())
+ " textoff and &wrapmargin formatting considers the cmdwin_type char.
+ call assert_equal(1, getwininfo(win_getid())[0].textoff)
+ call CheckWraps(1)
+ endfunc
+
+ func CheckOtherWin()
+ call assert_equal('', win_gettype())
+ call assert_equal(0, getwininfo(win_getid())[0].textoff)
+ call CheckWraps(0)
+ endfunc
+
+ call feedkeys("q::call CheckCmdWin()\<CR>:call win_execute(win_getid(winnr('#')), 'call CheckOtherWin()')\<CR>:q<CR>", 'ntx')
+
+ %bwipe!
+ delfunc CheckWraps
+ delfunc CheckCmdWin
+ delfunc CheckOtherWin
+endfunc
+
+func Test_cmdwin_interrupted()
+ func CheckInterrupted()
+ call feedkeys("q::call assert_equal('', getcmdwintype())\<CR>:call assert_equal('', getcmdtype())\<CR>:q<CR>", 'ntx')
+ endfunc
+
+ augroup CmdWin
+
+ " While opening the cmdwin's split:
+ " Close the cmdwin's window.
+ au WinEnter * ++once quit
+ call CheckInterrupted()
+
+ " Close the old window.
+ au WinEnter * ++once execute winnr('#') 'quit'
+ call CheckInterrupted()
+
+ " Switch back to the old window.
+ au WinEnter * ++once wincmd p
+ call CheckInterrupted()
+
+ " Change the old window's buffer.
+ au WinEnter * ++once call win_execute(win_getid(winnr('#')), 'enew')
+ call CheckInterrupted()
+
+ " Using BufLeave autocmds as cmdwin restrictions do not apply to them when
+ " fired from opening the cmdwin...
+ " After opening the cmdwin's split, while creating the cmdwin's buffer:
+ " Delete the cmdwin's buffer.
+ au BufLeave * ++once bwipe
+ call CheckInterrupted()
+
+ " Close the cmdwin's window.
+ au BufLeave * ++once quit
+ call CheckInterrupted()
+
+ " Close the old window.
+ au BufLeave * ++once execute winnr('#') 'quit'
+ call CheckInterrupted()
+
+ " Switch to a different window.
+ au BufLeave * ++once split
+ call CheckInterrupted()
+
+ " Change the old window's buffer.
+ au BufLeave * ++once call win_execute(win_getid(winnr('#')), 'enew')
+ call CheckInterrupted()
+
+ " However, changing the current buffer is OK and does not interrupt.
+ au BufLeave * ++once edit other
+ call feedkeys("q::let t=getcmdwintype()\<CR>:let b=bufnr()\<CR>:clo<CR>", 'ntx')
+ call assert_equal(':', t)
+ call assert_equal(1, bufloaded('other'))
+ call assert_notequal(b, bufnr('other'))
+
+ augroup END
+
+ " No autocmds should remain, but clear the augroup to be sure.
+ augroup CmdWin
+ au!
+ augroup END
+
+ %bwipe!
+ delfunc CheckInterrupted
+endfunc
+
+func Test_cmdwin_existing_bufname()
+ func CheckName()
+ call assert_equal(1, getbufinfo('')[0].command)
+ call assert_equal(0, getbufinfo('[Command Line]')[0].command)
+ call assert_match('#a\s*"\[Command Line\]"', execute('ls'))
+ call assert_match('%a\s*"\[Command Line\]"', execute('ls'))
+ endfunc
+
+ file [Command Line]
+ call feedkeys("q::call CheckName()\<CR>:q\<CR>", 'ntx')
+ 0file
+ delfunc CheckName
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_comments.vim b/src/testdir/test_comments.vim
index c34b85c..67454f4 100644
--- a/src/testdir/test_comments.vim
+++ b/src/testdir/test_comments.vim
@@ -237,6 +237,12 @@ func Test_comment_autoformat()
call feedkeys("aone\ntwo\n", 'xt')
call assert_equal(['one', 'two', ''], getline(1, '$'))
+ set backspace=indent,eol,start
+ %d
+ call feedkeys("aone \n\<BS>", 'xt')
+ call assert_equal(['one'], getline(1, '$'))
+ set backspace&
+
close!
endfunc
diff --git a/src/testdir/test_conceal.vim b/src/testdir/test_conceal.vim
index e977921..355817d 100644
--- a/src/testdir/test_conceal.vim
+++ b/src/testdir/test_conceal.vim
@@ -171,6 +171,57 @@ func Test_conceal_with_cursorcolumn()
call StopVimInTerminal(buf)
endfunc
+" Check that 'cursorline' and 'wincolor' apply to the whole line in presence
+" of wrapped lines containing concealed text.
+func Test_conceal_wrapped_cursorline_wincolor()
+ CheckScreendump
+
+ let code =<< trim [CODE]
+ call setline(1, 'one one one |hidden| one one one one one one one one')
+ syntax match test /|hidden|/ conceal
+ set conceallevel=2 concealcursor=n cursorline
+ normal! g$
+ [CODE]
+
+ call writefile(code, 'XTest_conceal_cul_wcr', 'D')
+ let buf = RunVimInTerminal('-S XTest_conceal_cul_wcr', {'rows': 4, 'cols': 40})
+ call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_01', {})
+
+ call term_sendkeys(buf, ":set wincolor=ErrorMsg\n")
+ call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_02', {})
+
+ call term_sendkeys(buf, ":set nocursorline\n")
+ call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_03', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+" Same as Test_conceal_wrapped_cursorline_wincolor(), but with 'rightleft'.
+func Test_conceal_wrapped_cursorline_wincolor_rightleft()
+ CheckScreendump
+
+ let code =<< trim [CODE]
+ call setline(1, 'one one one |hidden| one one one one one one one one')
+ syntax match test /|hidden|/ conceal
+ set conceallevel=2 concealcursor=n cursorline rightleft
+ normal! g$
+ [CODE]
+
+ call writefile(code, 'XTest_conceal_cul_wcr_rl', 'D')
+ let buf = RunVimInTerminal('-S XTest_conceal_cul_wcr_rl', {'rows': 4, 'cols': 40})
+ call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_01', {})
+
+ call term_sendkeys(buf, ":set wincolor=ErrorMsg\n")
+ call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_02', {})
+
+ call term_sendkeys(buf, ":set nocursorline\n")
+ call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_03', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_conceal_resize_term()
CheckScreendump
@@ -338,77 +389,290 @@ func Test_conceal_eol()
endfunc
func Test_conceal_mouse_click()
- enew!
+ call NewWindow(10, 40)
set mouse=a
setlocal conceallevel=2 concealcursor=nc
syn match Concealed "this" conceal
hi link Concealed Search
- call setline(1, 'conceal this click here')
- redraw
- call assert_equal(['conceal click here '], ScreenLines(1, 20))
-
- " click on the space between "this" and "click" puts cursor there
- call test_setmouse(1, 9)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 13, 0, 13], getcurpos())
- " click on 'h' of "here" puts cursor there
- call test_setmouse(1, 16)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 20, 0, 20], getcurpos())
- " click on 'e' of "here" puts cursor there
- call test_setmouse(1, 19)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 23], getcurpos())
- " click after end of line puts cursor on 'e' without 'virtualedit'
- call test_setmouse(1, 20)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 24], getcurpos())
- call test_setmouse(1, 21)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 25], getcurpos())
- call test_setmouse(1, 22)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 26], getcurpos())
- call test_setmouse(1, 31)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 35], getcurpos())
- call test_setmouse(1, 32)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 36], getcurpos())
-
- set virtualedit=all
- redraw
- " click on the space between "this" and "click" puts cursor there
- call test_setmouse(1, 9)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 13, 0, 13], getcurpos())
- " click on 'h' of "here" puts cursor there
- call test_setmouse(1, 16)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 20, 0, 20], getcurpos())
- " click on 'e' of "here" puts cursor there
- call test_setmouse(1, 19)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 23, 0, 23], getcurpos())
- " click after end of line puts cursor there without 'virtualedit'
- call test_setmouse(1, 20)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 24, 0, 24], getcurpos())
- call test_setmouse(1, 21)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 24, 1, 25], getcurpos())
- call test_setmouse(1, 22)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 24, 2, 26], getcurpos())
- call test_setmouse(1, 31)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 24, 11, 35], getcurpos())
- call test_setmouse(1, 32)
- call feedkeys("\<LeftMouse>", "tx")
- call assert_equal([0, 1, 24, 12, 36], getcurpos())
-
- bwipe!
- set mouse& virtualedit&
+
+ " Test with both 'nocursorline' and 'cursorline', as they use two different
+ " code paths to set virtual columns for the cells to clear.
+ for cul in [v:false, v:true]
+ let &l:cursorline = cul
+
+ call setline(1, 'conceal this click here')
+ call assert_equal([
+ \ 'conceal click here ',
+ \ ], ScreenLines(1, 40))
+
+ " Click on the space between "this" and "click" puts cursor there.
+ call test_setmouse(1, 9)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 13, 0, 13], getcurpos())
+ " Click on 'h' of "here" puts cursor there.
+ call test_setmouse(1, 16)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 20, 0, 20], getcurpos())
+ " Click on 'e' of "here" puts cursor there.
+ call test_setmouse(1, 19)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 23], getcurpos())
+ " Click after end of line puts cursor on 'e' without 'virtualedit'.
+ call test_setmouse(1, 20)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 24], getcurpos())
+ call test_setmouse(1, 21)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 25], getcurpos())
+ call test_setmouse(1, 22)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 26], getcurpos())
+ call test_setmouse(1, 31)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 35], getcurpos())
+ call test_setmouse(1, 32)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 36], getcurpos())
+
+ set virtualedit=all
+ redraw
+ " Click on the space between "this" and "click" puts cursor there.
+ call test_setmouse(1, 9)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 13, 0, 13], getcurpos())
+ " Click on 'h' of "here" puts cursor there.
+ call test_setmouse(1, 16)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 20, 0, 20], getcurpos())
+ " Click on 'e' of "here" puts cursor there.
+ call test_setmouse(1, 19)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 23], getcurpos())
+ " Click after end of line puts cursor there with 'virtualedit'.
+ call test_setmouse(1, 20)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 0, 24], getcurpos())
+ call test_setmouse(1, 21)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 1, 25], getcurpos())
+ call test_setmouse(1, 22)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 2, 26], getcurpos())
+ call test_setmouse(1, 31)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 11, 35], getcurpos())
+ call test_setmouse(1, 32)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 12, 36], getcurpos())
+ " Behavior should also be the same with 'colorcolumn'.
+ setlocal colorcolumn=30
+ redraw
+ call test_setmouse(1, 31)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 11, 35], getcurpos())
+ call test_setmouse(1, 32)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 12, 36], getcurpos())
+ setlocal colorcolumn&
+
+ if has('rightleft')
+ setlocal rightleft
+ call assert_equal([
+ \ ' ereh kcilc laecnoc',
+ \ ], ScreenLines(1, 40))
+ " Click on the space between "this" and "click" puts cursor there.
+ call test_setmouse(1, 41 - 9)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 13, 0, 13], getcurpos())
+ " Click on 'h' of "here" puts cursor there.
+ call test_setmouse(1, 41 - 16)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 20, 0, 20], getcurpos())
+ " Click on 'e' of "here" puts cursor there.
+ call test_setmouse(1, 41 - 19)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 23, 0, 23], getcurpos())
+ " Click after end of line puts cursor there with 'virtualedit'.
+ call test_setmouse(1, 41 - 20)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 0, 24], getcurpos())
+ call test_setmouse(1, 41 - 21)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 1, 25], getcurpos())
+ call test_setmouse(1, 41 - 22)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 2, 26], getcurpos())
+ call test_setmouse(1, 41 - 31)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 11, 35], getcurpos())
+ call test_setmouse(1, 41 - 32)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 24, 12, 36], getcurpos())
+ setlocal rightleft&
+ endif
+
+ set virtualedit&
+
+ " Test with a wrapped line.
+ call setline(1, ['conceal this click here']->repeat(3)->join())
+ call assert_equal([
+ \ 'conceal click here conceal cli ',
+ \ 'ck here conceal click here ',
+ \ ], ScreenLines([1, 2], 40))
+ " Click on boguscols puts cursor on the last char of a screen line.
+ for col in range(33, 40)
+ call test_setmouse(1, col)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 40, 0, 40], getcurpos())
+ endfor
+
+ " Also test with the last char of a screen line concealed.
+ setlocal number signcolumn=yes
+ call assert_equal([
+ \ ' 1 conceal click here conceal ',
+ \ ' click here conceal click h ',
+ \ ' ere ',
+ \ ], ScreenLines([1, 3], 40))
+ call test_setmouse(1, 34)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 32, 0, 32], getcurpos())
+ call test_setmouse(2, 7)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 37, 0, 37], getcurpos())
+ " Click on boguscols puts cursor on the last char of a screen line.
+ for col in range(35, 40)
+ call test_setmouse(1, col)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 34, 0, 34], getcurpos())
+ call test_setmouse(2, col)
+ call feedkeys("\<LeftMouse>", "tx")
+ call assert_equal([0, 1, 68, 0, 68], getcurpos())
+ endfor
+ setlocal number& signcolumn&
+ endfor
+
+ call CloseWindow()
+ set mouse&
+endfunc
+
+" Test that cursor is drawn at the correct column when it is after end of the
+" line with 'virtualedit' and concealing.
+func Run_test_conceal_virtualedit_after_eol(wrap)
+ let code =<< trim eval [CODE]
+ let &wrap = {a:wrap}
+ call setline(1, 'abcdefgh|hidden|ijklmnpop')
+ syntax match test /|hidden|/ conceal
+ set conceallevel=2 concealcursor=n virtualedit=all
+ normal! $
+ [CODE]
+ call writefile(code, 'XTest_conceal_ve_after_eol', 'D')
+ let buf = RunVimInTerminal('-S XTest_conceal_ve_after_eol', {'rows': 3})
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_1', {})
+ call term_sendkeys(buf, "l")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_2', {})
+ call term_sendkeys(buf, "l")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_3', {})
+ call term_sendkeys(buf, "l")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_4', {})
+ call term_sendkeys(buf, "rr")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_5', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_conceal_virtualedit_after_eol()
+ CheckScreendump
+
+ call Run_test_conceal_virtualedit_after_eol(1)
+ call Run_test_conceal_virtualedit_after_eol(0)
+endfunc
+
+" Same as Run_test_conceal_virtualedit_after_eol(), but with 'rightleft'.
+func Run_test_conceal_virtualedit_after_eol_rightleft(wrap)
+ let code =<< trim eval [CODE]
+ let &wrap = {a:wrap}
+ call setline(1, 'abcdefgh|hidden|ijklmnpop')
+ syntax match test /|hidden|/ conceal
+ set conceallevel=2 concealcursor=n virtualedit=all rightleft
+ normal! $
+ [CODE]
+ call writefile(code, 'XTest_conceal_ve_after_eol_rl', 'D')
+ let buf = RunVimInTerminal('-S XTest_conceal_ve_after_eol_rl', {'rows': 3})
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_1', {})
+ call term_sendkeys(buf, "h")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_2', {})
+ call term_sendkeys(buf, "h")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_3', {})
+ call term_sendkeys(buf, "h")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_4', {})
+ call term_sendkeys(buf, "rr")
+ call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_5', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_conceal_virtualedit_after_eol_rightleft()
+ CheckFeature rightleft
+ CheckScreendump
+
+ call Run_test_conceal_virtualedit_after_eol_rightleft(1)
+ call Run_test_conceal_virtualedit_after_eol_rightleft(0)
+endfunc
+
+" Test that cursor position is correct when double-width chars are concealed.
+func Run_test_conceal_double_width(wrap)
+ let code =<< trim eval [CODE]
+ let &wrap = {a:wrap}
+ call setline(1, ['aaaaaå£=å£bbbbbå£=å£ccccc', 'foobar'])
+ syntax match test /å£=å£/ conceal cchar=β
+ set conceallevel=2 concealcursor=n colorcolumn=30
+ normal! $
+ [CODE]
+ call writefile(code, 'XTest_conceal_double_width', 'D')
+ let buf = RunVimInTerminal('-S XTest_conceal_double_width', {'rows': 4})
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_1', {})
+ call term_sendkeys(buf, "gM")
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_2', {})
+ call term_sendkeys(buf, ":set conceallevel=3\<CR>")
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_3', {})
+ call term_sendkeys(buf, "$")
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_4', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_conceal_double_width()
+ CheckScreendump
+
+ call Run_test_conceal_double_width(1)
+ call Run_test_conceal_double_width(0)
+endfunc
+
+" Test that line wrapping is correct when double-width chars are concealed.
+func Test_conceal_double_width_wrap()
+ CheckScreendump
+
+ let code =<< trim [CODE]
+ call setline(1, 'aaaaaaaaaaå£=å£bbbbbbbbbbå£=å£cccccccccc')
+ syntax match test /å£=å£/ conceal cchar=β
+ set conceallevel=2 concealcursor=n
+ normal! $
+ [CODE]
+ call writefile(code, 'XTest_conceal_double_width_wrap', 'D')
+ let buf = RunVimInTerminal('-S XTest_conceal_double_width_wrap', {'rows': 4, 'cols': 20})
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_1', {})
+ call term_sendkeys(buf, "gM")
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_2', {})
+ call term_sendkeys(buf, ":set conceallevel=3\<CR>")
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_3', {})
+ call term_sendkeys(buf, "$")
+ call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_4', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim
index 930fd7b..7602bd3 100644
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
@@ -3,6 +3,7 @@
source shared.vim
source screendump.vim
source check.vim
+source view_util.vim
func Test_diff_fold_sync()
enew!
@@ -871,6 +872,10 @@ func VerifyInternal(buf, dumpfile, extra)
endfunc
func Test_diff_screen()
+ if has('osxdarwin') && system('diff --version') =~ '^Apple diff'
+ throw 'Skipped: unified diff does not work properly on this macOS version'
+ endif
+
let g:test_is_flaky = 1
CheckScreendump
CheckFeature menu
@@ -1129,7 +1134,7 @@ func Test_diff_breakindent_after_filler()
CheckScreendump
let lines =<< trim END
- set laststatus=0 diffopt+=followwrap breakindent
+ set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
call setline(1, ['a', ' ' .. repeat('c', 50)])
vnew
call setline(1, ['a', 'b', ' ' .. repeat('c', 50)])
@@ -1712,5 +1717,307 @@ func Test_diff_put_and_undo()
set nodiff
endfunc
+" Test for the diff() function
+def Test_diff_func()
+ # string is added/removed/modified at the beginning
+ assert_equal("@@ -0,0 +1 @@\n+abc\n",
+ diff(['def'], ['abc', 'def'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 1}],
+ diff(['def'], ['abc', 'def'], {output: 'indices'}))
+ assert_equal("@@ -1 +0,0 @@\n-abc\n",
+ diff(['abc', 'def'], ['def'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 0}],
+ diff(['abc', 'def'], ['def'], {output: 'indices'}))
+ assert_equal("@@ -1 +1 @@\n-abc\n+abx\n",
+ diff(['abc', 'def'], ['abx', 'def'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff(['abc', 'def'], ['abx', 'def'], {output: 'indices'}))
+
+ # string is added/removed/modified at the end
+ assert_equal("@@ -1,0 +2 @@\n+def\n",
+ diff(['abc'], ['abc', 'def'], {output: 'unified'}))
+ assert_equal([{from_idx: 1, from_count: 0, to_idx: 1, to_count: 1}],
+ diff(['abc'], ['abc', 'def'], {output: 'indices'}))
+ assert_equal("@@ -2 +1,0 @@\n-def\n",
+ diff(['abc', 'def'], ['abc'], {output: 'unified'}))
+ assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 0}],
+ diff(['abc', 'def'], ['abc'], {output: 'indices'}))
+ assert_equal("@@ -2 +2 @@\n-def\n+xef\n",
+ diff(['abc', 'def'], ['abc', 'xef'], {output: 'unified'}))
+ assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 1}],
+ diff(['abc', 'def'], ['abc', 'xef'], {output: 'indices'}))
+
+ # string is added/removed/modified in the middle
+ assert_equal("@@ -2,0 +3 @@\n+xxx\n",
+ diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'unified'}))
+ assert_equal([{from_idx: 2, from_count: 0, to_idx: 2, to_count: 1}],
+ diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'indices'}))
+ assert_equal("@@ -3 +2,0 @@\n-333\n",
+ diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'unified'}))
+ assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 0}],
+ diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'indices'}))
+ assert_equal("@@ -3 +3 @@\n-333\n+xxx\n",
+ diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'unified'}))
+ assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}],
+ diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'indices'}))
+
+ # new strings are added to an empty List
+ assert_equal("@@ -0,0 +1,2 @@\n+abc\n+def\n",
+ diff([], ['abc', 'def'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 2}],
+ diff([], ['abc', 'def'], {output: 'indices'}))
+
+ # all the strings are removed from a List
+ assert_equal("@@ -1,2 +0,0 @@\n-abc\n-def\n",
+ diff(['abc', 'def'], [], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 2, to_idx: 0, to_count: 0}],
+ diff(['abc', 'def'], [], {output: 'indices'}))
+
+ # First character is added/removed/different
+ assert_equal("@@ -1 +1 @@\n-abc\n+bc\n",
+ diff(['abc'], ['bc'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff(['abc'], ['bc'], {output: 'indices'}))
+ assert_equal("@@ -1 +1 @@\n-bc\n+abc\n",
+ diff(['bc'], ['abc'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff(['bc'], ['abc'], {output: 'indices'}))
+ assert_equal("@@ -1 +1 @@\n-abc\n+xbc\n",
+ diff(['abc'], ['xbc'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff(['abc'], ['xbc'], {output: 'indices'}))
+
+ # Last character is added/removed/different
+ assert_equal("@@ -1 +1 @@\n-abc\n+abcd\n",
+ diff(['abc'], ['abcd'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff(['abc'], ['abcd'], {output: 'indices'}))
+ assert_equal("@@ -1 +1 @@\n-abcd\n+abc\n",
+ diff(['abcd'], ['abc'], {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff(['abcd'], ['abc'], {output: 'indices'}))
+ var diff_unified: string = diff(['abc'], ['abx'], {output: 'unified'})
+ assert_equal("@@ -1 +1 @@\n-abc\n+abx\n", diff_unified)
+ var diff_indices: list<dict<number>> =
+ diff(['abc'], ['abx'], {output: 'indices'})
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff_indices)
+
+ # partial string modification at the start and at the end.
+ var fromlist =<< trim END
+ one two
+ three four
+ five six
+ END
+ var tolist =<< trim END
+ one
+ six
+ END
+ assert_equal("@@ -1,3 +1,2 @@\n-one two\n-three four\n-five six\n+one\n+six\n", diff(fromlist, tolist, {output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 3, to_idx: 0, to_count: 2}],
+ diff(fromlist, tolist, {output: 'indices'}))
+
+ # non-contiguous modifications
+ fromlist =<< trim END
+ one two
+ three four
+ five abc six
+ END
+ tolist =<< trim END
+ one abc two
+ three four
+ five six
+ END
+ assert_equal("@@ -1 +1 @@\n-one two\n+one abc two\n@@ -3 +3 @@\n-five abc six\n+five six\n",
+ diff(fromlist, tolist, {output: 'unified'}))
+ assert_equal([{'from_count': 1, 'to_idx': 0, 'to_count': 1, 'from_idx': 0},
+ {'from_count': 1, 'to_idx': 2, 'to_count': 1, 'from_idx': 2}],
+ diff(fromlist, tolist, {output: 'indices'}))
+
+ # add/remove blank lines
+ assert_equal("@@ -2,2 +1,0 @@\n-\n-\n",
+ diff(['one', '', '', 'two'], ['one', 'two'], {output: 'unified'}))
+ assert_equal([{from_idx: 1, from_count: 2, to_idx: 1, to_count: 0}],
+ diff(['one', '', '', 'two'], ['one', 'two'], {output: 'indices'}))
+ assert_equal("@@ -1,0 +2,2 @@\n+\n+\n",
+ diff(['one', 'two'], ['one', '', '', 'two'], {output: 'unified'}))
+ assert_equal([{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}],
+ diff(['one', 'two'], ['one', '', '', 'two'], {output: 'indices'}))
+
+ # diff ignoring case
+ assert_equal('', diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'unified'}))
+ assert_equal([], diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'indices'}))
+
+ # diff ignoring all whitespace changes except leading whitespace changes
+ assert_equal('', diff(['abc def'], ['abc def '], {iwhite: true}))
+ assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:true}))
+ assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:false}))
+ assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:true}))
+ assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:false}))
+
+ # diff ignoring all whitespace changes
+ assert_equal('', diff(['abc def'], [' abc def '], {iwhiteall: true}))
+ assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:true}))
+ assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:false}))
+
+ # diff ignoring trailing whitespace changes
+ assert_equal('', diff(['abc'], ['abc '], {iwhiteeol: true}))
+
+ # diff ignoring blank lines
+ assert_equal('', diff(['one', '', '', 'two'], ['one', 'two'], {iblank: true}))
+ assert_equal('', diff(['one', 'two'], ['one', '', '', 'two'], {iblank: true}))
+
+ # same string
+ assert_equal('', diff(['abc', 'def', 'ghi'], ['abc', 'def', 'ghi']))
+ assert_equal('', diff([''], ['']))
+ assert_equal('', diff([], []))
+
+ # different xdiff algorithms
+ for algo in ['myers', 'minimal', 'patience', 'histogram']
+ assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
+ diff([' abc '], [' xxx '], {algorithm: algo, output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff([' abc '], [' xxx '], {algorithm: algo, output: 'indices'}))
+ endfor
+ assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
+ diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'unified'}))
+ assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
+ diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'indices'}))
+
+ # identical strings
+ assert_equal('', diff(['111', '222'], ['111', '222'], {output: 'unified'}))
+ assert_equal([], diff(['111', '222'], ['111', '222'], {output: 'indices'}))
+ assert_equal('', diff([], [], {output: 'unified'}))
+ assert_equal([], diff([], [], {output: 'indices'}))
+
+ # If 'diffexpr' is set, it should not be used for diff()
+ def MyDiffExpr()
+ enddef
+ var save_diffexpr = &diffexpr
+ :set diffexpr=MyDiffExpr()
+ assert_equal("@@ -1 +1 @@\n-abc\n+\n",
+ diff(['abc'], [''], {output: 'unified'}))
+ assert_equal([{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1}],
+ diff(['abc'], [''], {output: 'indices'}))
+ assert_equal('MyDiffExpr()', &diffexpr)
+ &diffexpr = save_diffexpr
+
+ # try different values for unified diff 'context'
+ assert_equal("@@ -0,0 +1 @@\n+x\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c']))
+ assert_equal("@@ -0,0 +1 @@\n+x\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 0}))
+ assert_equal("@@ -1 +1,2 @@\n+x\n a\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 1}))
+ assert_equal("@@ -1,2 +1,3 @@\n+x\n a\n b\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 2}))
+ assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 3}))
+ assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 4}))
+ assert_equal("@@ -0,0 +1 @@\n+x\n",
+ diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: -1}))
+
+ # Error cases
+ assert_fails('call diff({}, ["a"])', 'E1211:')
+ assert_fails('call diff(["a"], {})', 'E1211:')
+ assert_fails('call diff(["a"], ["a"], [])', 'E1206:')
+ assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz')
+ assert_fails('call diff(["a"], ["a"], {context: []})', 'E745: Using a List as a Number')
+enddef
+
+" Test for using the diff() function with 'diffexpr'
+func Test_diffexpr_with_diff_func()
+ CheckScreendump
+
+ let lines =<< trim END
+ def DiffFuncExpr()
+ var in: list<string> = readfile(v:fname_in)
+ var new: list<string> = readfile(v:fname_new)
+ var out: string = diff(in, new)
+ writefile(split(out, "\n"), v:fname_out)
+ enddef
+ set diffexpr=DiffFuncExpr()
+
+ edit Xdifffunc1.txt
+ diffthis
+ vert split Xdifffunc2.txt
+ diffthis
+ END
+ call writefile(lines, 'XsetupDiffFunc.vim', 'D')
+
+ call writefile(['zero', 'one', 'two', 'three'], 'Xdifffunc1.txt', 'D')
+ call writefile(['one', 'twox', 'three', 'four'], 'Xdifffunc2.txt', 'D')
+
+ let buf = RunVimInTerminal('-S XsetupDiffFunc.vim', {'rows': 12})
+ call VerifyScreenDump(buf, 'Test_difffunc_diffexpr_1', {})
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_diff_toggle_wrap_skipcol_leftcol()
+ 61vnew
+ call setline(1, 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.')
+ 30vnew
+ call setline(1, 'ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.')
+ let win1 = win_getid()
+ setlocal smoothscroll
+ exe "normal! $\<C-E>"
+ wincmd l
+ let win2 = win_getid()
+ setlocal smoothscroll
+ exe "normal! $\<C-E>"
+ call assert_equal([
+ \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|',
+ \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
+ \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
+ \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
+ \ '~ |ptua. |',
+ \ ], ScreenLines([1, 5], 62))
+ call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29},
+ \ screenpos(win1, line('.', win1), col('.', win1)))
+ call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36},
+ \ screenpos(win2, line('.', win2), col('.', win2)))
+
+ wincmd h
+ diffthis
+ wincmd l
+ diffthis
+ normal! 0
+ call assert_equal([
+ \ ' ipsum dolor sit amet, conset| Lorem ipsum dolor sit amet, |',
+ \ '~ |~ |',
+ \ ], ScreenLines([1, 2], 62))
+ call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3},
+ \ screenpos(win1, line('.', win1), col('.', win1)))
+ call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34},
+ \ screenpos(win2, line('.', win2), col('.', win2)))
+
+ normal! $
+ call assert_equal([
+ \ ' voluptua. | diam voluptua. |',
+ \ '~ |~ |',
+ \ ], ScreenLines([1, 2], 62))
+ call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11},
+ \ screenpos(win1, line('.', win1), col('.', win1)))
+ call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48},
+ \ screenpos(win2, line('.', win2), col('.', win2)))
+
+ diffoff!
+ call assert_equal([
+ \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|',
+ \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|',
+ \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|',
+ \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|',
+ \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|',
+ \ '~ |ptua. |',
+ \ ], ScreenLines([1, 6], 62))
+ call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29},
+ \ screenpos(win1, line('.', win1), col('.', win1)))
+ call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36},
+ \ screenpos(win2, line('.', win2), col('.', win2)))
+
+ bwipe!
+ bwipe!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_display.vim b/src/testdir/test_display.vim
index 5e0f86a..86e400e 100644
--- a/src/testdir/test_display.vim
+++ b/src/testdir/test_display.vim
@@ -252,12 +252,12 @@ func Test_eob_fillchars()
" default value
call assert_match('eob:\~', &fillchars)
" invalid values
- call assert_fails(':set fillchars=eob:', 'E474:')
- call assert_fails(':set fillchars=eob:xy', 'E474:')
- call assert_fails(':set fillchars=eob:\255', 'E474:')
- call assert_fails(':set fillchars=eob:<ff>', 'E474:')
- call assert_fails(":set fillchars=eob:\x01", 'E474:')
- call assert_fails(':set fillchars=eob:\\x01', 'E474:')
+ call assert_fails(':set fillchars=eob:', 'E1511:')
+ call assert_fails(':set fillchars=eob:xy', 'E1511:')
+ call assert_fails(':set fillchars=eob:\255', 'E1511:')
+ call assert_fails(':set fillchars=eob:<ff>', 'E1511:')
+ call assert_fails(":set fillchars=eob:\x01", 'E1512:')
+ call assert_fails(':set fillchars=eob:\\x01', 'E1512:')
" default is ~
new
redraw
@@ -411,14 +411,16 @@ func Run_Test_display_lastline(euro)
call StopVimInTerminal(buf)
endfunc
-func Test_display_lastline()
+func Test_display_lastline_dump()
CheckScreendump
call Run_Test_display_lastline('')
call Run_Test_display_lastline('euro_')
+endfunc
- call assert_fails(':set fillchars=lastline:', 'E474:')
- call assert_fails(':set fillchars=lastline:〇', 'E474:')
+func Test_display_lastline_fails()
+ call assert_fails(':set fillchars=lastline:', 'E1511:')
+ call assert_fails(':set fillchars=lastline:〇', 'E1512:')
endfunc
func Test_display_long_lastline()
diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim
index d662f4a..36e0525 100644
--- a/src/testdir/test_edit.vim
+++ b/src/testdir/test_edit.vim
@@ -2123,4 +2123,39 @@ func Test_edit_shift_bs()
call StopVimInTerminal(buf)
endfunc
+func Test_edit_Ctrl_RSB()
+ new
+ let g:triggered = []
+ autocmd InsertCharPre <buffer> let g:triggered += [v:char]
+
+ " i_CTRL-] should not trigger InsertCharPre
+ exe "normal! A\<C-]>"
+ call assert_equal([], g:triggered)
+
+ " i_CTRL-] should expand abbreviations but not trigger InsertCharPre
+ inoreabbr <buffer> f foo
+ exe "normal! Af\<C-]>a"
+ call assert_equal(['f', 'f', 'o', 'o', 'a'], g:triggered)
+ call assert_equal('fooa', getline(1))
+
+ " CTRL-] followed by i_CTRL-V should not expand abbreviations
+ " i_CTRL-V doesn't trigger InsertCharPre
+ call setline(1, '')
+ exe "normal! Af\<C-V>\<C-]>"
+ call assert_equal("f\<C-]>", getline(1))
+
+ let g:triggered = []
+ call setline(1, '')
+
+ " Also test assigning to v:char
+ autocmd InsertCharPre <buffer> let v:char = 'f'
+ exe "normal! Ag\<C-]>h"
+ call assert_equal(['g', 'f', 'o', 'o', 'h'], g:triggered)
+ call assert_equal('ffff', getline(1))
+
+ autocmd! InsertCharPre
+ unlet g:triggered
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim
index 47fc267..221ceb0 100644
--- a/src/testdir/test_excmd.vim
+++ b/src/testdir/test_excmd.vim
@@ -3,6 +3,7 @@
source check.vim
source shared.vim
source term_util.vim
+source screendump.vim
func Test_ex_delete()
new
@@ -84,18 +85,27 @@ endfunc
" Test for the :drop command
func Test_drop_cmd()
call writefile(['L1', 'L2'], 'Xdropfile', 'D')
+ " Test for reusing the current buffer
enew | only
+ let expected_nr = bufnr()
drop Xdropfile
+ call assert_equal(expected_nr, bufnr())
call assert_equal('L2', getline(2))
" Test for switching to an existing window
below new
drop Xdropfile
call assert_equal(1, winnr())
- " Test for splitting the current window
+ " Test for splitting the current window (set nohidden)
enew | only
set modified
drop Xdropfile
call assert_equal(2, winnr('$'))
+ " Not splitting the current window even if modified (set hidden)
+ set hidden
+ enew | only
+ set modified
+ drop Xdropfile
+ call assert_equal(1, winnr('$'))
" Check for setting the argument list
call assert_equal(['Xdropfile'], argv())
enew | only!
@@ -729,4 +739,19 @@ func Test_ex_address_range_overflow()
call assert_fails(':--+foobar', 'E492:')
endfunc
+func Test_drop_modified_file()
+ CheckScreendump
+ let lines =<< trim END
+ call setline(1, 'The quick brown fox jumped over the lazy dogs')
+ END
+ call writefile([''], 'Xdrop_modified.txt', 'D')
+ call writefile(lines, 'Xtest_drop_modified', 'D')
+ let buf = RunVimInTerminal('-S Xtest_drop_modified Xdrop_modified.txt', {'rows': 10,'columns': 40})
+ call term_sendkeys(buf, ":drop Xdrop_modified.txt\<CR>")
+ call VerifyScreenDump(buf, 'Test_drop_modified_1', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_execute_func.vim b/src/testdir/test_execute_func.vim
index 09b976b..faaace0 100644
--- a/src/testdir/test_execute_func.vim
+++ b/src/testdir/test_execute_func.vim
@@ -204,4 +204,28 @@ func Test_execute_func_with_null()
endif
endfunc
+func Test_win_execute_tabpagewinnr()
+ belowright split
+ tab split
+ belowright split
+ call assert_equal(2, tabpagewinnr(1))
+
+ tabprevious
+ wincmd p
+ call assert_equal(1, tabpagenr())
+ call assert_equal(1, tabpagewinnr(1))
+ call assert_equal(2, tabpagewinnr(2))
+
+ call win_execute(win_getid(1, 2),
+ \ 'call assert_equal(2, tabpagenr())'
+ \ .. '| call assert_equal(1, tabpagewinnr(1))'
+ \ .. '| call assert_equal(1, tabpagewinnr(2))')
+
+ call assert_equal(1, tabpagenr())
+ call assert_equal(1, tabpagewinnr(1))
+ call assert_equal(2, tabpagewinnr(2))
+
+ %bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_exists.vim b/src/testdir/test_exists.vim
index a735a7d..9cdb3fb 100644
--- a/src/testdir/test_exists.vim
+++ b/src/testdir/test_exists.vim
@@ -1,5 +1,7 @@
" Tests for the exists() function
+import './vim9.vim' as v9
+
func Test_exists()
augroup myagroup
autocmd! BufEnter *.my echo "myfile edited"
@@ -334,4 +336,51 @@ func Test_exists_funcarg()
call FuncArg_Tests("arg1", "arg2")
endfunc
+" Test for using exists() with class and object variables and methods.
+func Test_exists_class_object()
+ let lines =<< trim END
+ vim9script
+ class A
+ var var1: number = 10
+ static var var2: number = 10
+ static def Foo()
+ enddef
+ def Bar()
+ enddef
+ endclass
+
+ assert_equal(1, exists("A"))
+ var a = A.new()
+ assert_equal(1, exists("a"))
+
+ assert_equal(1, exists("a.var1"))
+ assert_fails('exists("a.var2")', 'E1375: Class variable "var2" accessible only using class "A"')
+ assert_fails('exists("a.var3")', 'E1326: Variable "var3" not found in object "A"')
+ assert_equal(1, exists("A.var2"))
+ assert_fails('exists("A.var1")', 'E1376: Object variable "var1" accessible only using class "A" object')
+ assert_fails('exists("A.var3")', 'E1337: Class variable "var3" not found in class "A"')
+
+ assert_equal(1, exists("a.Bar"))
+ assert_fails('exists("a.Barz")', 'E1326: Variable "Barz" not found in object "A"')
+ assert_fails('exists("a.Foo")', 'E1326: Variable "Foo" not found in object "A"')
+ assert_equal(1, exists("A.Foo"))
+ assert_fails('exists("A.Bar")', 'E1337: Class variable "Bar" not found in class "A"')
+ assert_fails('exists("A.Barz")', 'E1337: Class variable "Barz" not found in class "A"')
+
+ def Baz()
+ assert_equal(1, exists("A"))
+ var aa = A.new()
+ assert_equal(1, exists("A.var2"))
+ assert_fails('exists("A.var1")', 'E1376: Object variable "var1" accessible only using class "A" object')
+ assert_fails('exists("A.var3")', 'E1337: Class variable "var3" not found in class "A"')
+
+ assert_equal(1, exists("A.Foo"))
+ assert_fails('exists("A.Bar")', 'E1337: Class variable "Bar" not found in class "A"')
+ assert_fails('exists("A.Barz")', 'E1337: Class variable "Barz" not found in class "A"')
+ enddef
+ Baz()
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_expand.vim b/src/testdir/test_expand.vim
index d7c393a..bebe138 100644
--- a/src/testdir/test_expand.vim
+++ b/src/testdir/test_expand.vim
@@ -51,6 +51,19 @@ func Test_expand_tilde_filename()
bwipe!
endfunc
+func Test_expand_env_pathsep()
+ let $FOO = './foo'
+ call assert_equal('./foo/bar', expand('$FOO/bar'))
+ let $FOO = './foo/'
+ call assert_equal('./foo/bar', expand('$FOO/bar'))
+ let $FOO = 'C:'
+ call assert_equal('C:/bar', expand('$FOO/bar'))
+ let $FOO = 'C:/'
+ call assert_equal('C:/bar', expand('$FOO/bar'))
+
+ unlet $FOO
+endfunc
+
func Test_expandcmd()
let $FOO = 'Test'
call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y'))
diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim
index 6913eec..d77e5e0 100644
--- a/src/testdir/test_filetype.vim
+++ b/src/testdir/test_filetype.vim
@@ -150,6 +150,7 @@ def s:GetFilenameChecks(): dict<list<string>>
chatito: ['file.chatito'],
chill: ['file..ch'],
chordpro: ['file.chopro', 'file.crd', 'file.cho', 'file.crdpro', 'file.chordpro'],
+ chuck: ['file.ck'],
cl: ['file.eni'],
clean: ['file.dcl', 'file.icl'],
clojure: ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'],
@@ -188,6 +189,7 @@ def s:GetFilenameChecks(): dict<list<string>>
cynpp: ['file.cyn'],
cypher: ['file.cypher'],
d: ['file.d'],
+ dafny: ['file.dfy'],
dart: ['file.dart', 'file.drt'],
datascript: ['file.ds'],
dcd: ['file.dcd'],
@@ -213,7 +215,7 @@ def s:GetFilenameChecks(): dict<list<string>>
dracula: ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'],
dtd: ['file.dtd'],
dtrace: ['/usr/lib/dtrace/io.d'],
- dts: ['file.dts', 'file.dtsi'],
+ dts: ['file.dts', 'file.dtsi', 'file.dtso', 'file.its'],
dune: ['jbuild', 'dune', 'dune-project', 'dune-workspace'],
dylan: ['file.dylan'],
dylanintr: ['file.intr'],
@@ -281,7 +283,7 @@ def s:GetFilenameChecks(): dict<list<string>>
glsl: ['file.glsl'],
gn: ['file.gn', 'file.gni'],
gnash: ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'],
- gnuplot: ['file.gpi', '.gnuplot'],
+ gnuplot: ['file.gpi', '.gnuplot', 'file.gnuplot'],
go: ['file.go'],
gomod: ['go.mod'],
gosum: ['go.sum', 'go.work.sum'],
@@ -350,13 +352,13 @@ def s:GetFilenameChecks(): dict<list<string>>
jproperties: ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'],
json: ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'],
json5: ['file.json5'],
- jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json'],
+ jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'],
jsonl: ['file.jsonl'],
jsonnet: ['file.jsonnet', 'file.libsonnet'],
jsp: ['file.jsp'],
julia: ['file.jl'],
just: ['justfile', 'Justfile', '.justfile', 'config.just'],
- kconfig: ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
+ kconfig: ['Kconfig', 'Kconfig.debug', 'Kconfig.file', 'Config.in', 'Config.in.host'],
kdl: ['file.kdl'],
kivy: ['file.kv'],
kix: ['file.kix'],
@@ -620,7 +622,7 @@ def s:GetFilenameChecks(): dict<list<string>>
services: ['/etc/services', 'any/etc/services'],
setserial: ['/etc/serial.conf', 'any/etc/serial.conf'],
sexplib: ['file.sexp'],
- sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf'],
+ sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats'],
sieve: ['file.siv', 'file.sieve'],
sil: ['file.sil'],
simula: ['file.sim'],
@@ -777,6 +779,7 @@ def s:GetFilenameChecks(): dict<list<string>>
vdmpp: ['file.vpp', 'file.vdmpp'],
vdmrt: ['file.vdmrt'],
vdmsl: ['file.vdm', 'file.vdmsl'],
+ vento: ['file.vto'],
vera: ['file.vr', 'file.vri', 'file.vrh'],
verilogams: ['file.va', 'file.vams'],
vgrindefs: ['vgrindefs'],
@@ -1602,82 +1605,89 @@ func Test_mod_file()
filetype on
" *.mod defaults to Modsim III
- call writefile(['locks like Modsim III'], 'modfile.mod')
- split modfile.mod
+ call writefile(['locks like Modsim III'], 'Xfile.mod', 'D')
+ split Xfile.mod
call assert_equal('modsim3', &filetype)
bwipe!
" Users preference set by g:filetype_mod
let g:filetype_mod = 'lprolog'
- split modfile.mod
+ split Xfile.mod
call assert_equal('lprolog', &filetype)
unlet g:filetype_mod
bwipe!
+ " LambdaProlog module
+ call writefile(['module lpromod.'], 'Xfile.mod')
+ split Xfile.mod
+ call assert_equal('lprolog', &filetype)
+ bwipe!
+
+ " LambdaProlog with comment and empty lines prior module
+ call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'Xfile.mod')
+ split Xfile.mod
+ call assert_equal('lprolog', &filetype)
+ bwipe!
+
" RAPID header start with a line containing only "%%%",
" but is not always present.
- call writefile(['%%%'], 'modfile.mod')
- split modfile.mod
+ call writefile(['%%%'], 'Xfile.mod')
+ split Xfile.mod
call assert_equal('rapid', &filetype)
bwipe!
- call delete('modfile.mod')
" RAPID supports umlauts in module names, leading spaces,
" the .mod extension is not case sensitive.
- call writefile([' module ÃœmlautModule'], 'modfile.Mod')
- split modfile.Mod
+ call writefile([' module ÃœmlautModule'], 'Xfile.Mod', 'D')
+ split Xfile.Mod
call assert_equal('rapid', &filetype)
bwipe!
- call delete('modfile.Mod')
" RAPID is not case sensitive, embedded spaces, sysmodule,
" file starts with empty line(s).
- call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'modfile.MOD')
- split modfile.MOD
+ call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'Xfile.MOD', 'D')
+ split Xfile.MOD
call assert_equal('rapid', &filetype)
bwipe!
" Modula-2 MODULE not start of line
- call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'modfile.MOD')
- split modfile.MOD
+ call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'Xfile.mod')
+ split Xfile.mod
call assert_equal('modula2', &filetype)
call assert_equal('pim', b:modula2.dialect)
bwipe!
" Modula-2 with comment and empty lines prior MODULE
- call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'modfile.MOD')
- split modfile.MOD
+ call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'Xfile.mod')
+ split Xfile.mod
call assert_equal('modula2', &filetype)
call assert_equal('pim', b:modula2.dialect)
bwipe!
- call delete('modfile.MOD')
-
- " LambdaProlog module
- call writefile(['module lpromod.'], 'modfile.mod')
- split modfile.mod
- call assert_equal('lprolog', &filetype)
+ " Modula-2 program MODULE with priorty (and uppercase extension)
+ call writefile(['MODULE Module2Mod [42];'], 'Xfile.MOD')
+ split Xfile.MOD
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
bwipe!
- " LambdaProlog with comment and empty lines prior module
- call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'modfile.mod')
- split modfile.mod
- call assert_equal('lprolog', &filetype)
+ " Modula-2 implementation MODULE with priorty (and uppercase extension)
+ call writefile(['IMPLEMENTATION MODULE Module2Mod [42];'], 'Xfile.MOD')
+ split Xfile.MOD
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
bwipe!
- call delete('modfile.mod')
" go.mod
- call writefile(['module example.com/M'], 'go.mod')
+ call writefile(['module example.com/M'], 'go.mod', 'D')
split go.mod
call assert_equal('gomod', &filetype)
bwipe!
- call delete('go.mod')
call writefile(['module M'], 'go.mod')
split go.mod
call assert_equal('gomod', &filetype)
bwipe!
- call delete('go.mod')
filetype off
endfunc
diff --git a/src/testdir/test_filter_map.vim b/src/testdir/test_filter_map.vim
index 6a07bec..37ebe84 100644
--- a/src/testdir/test_filter_map.vim
+++ b/src/testdir/test_filter_map.vim
@@ -14,6 +14,18 @@ func Test_filter_map_list_expr_string()
call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2'))
call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9))
call assert_equal([7, 7, 7], map([1, 2, 3], ' 7 '))
+
+ " foreach()
+ let list01 = [1, 2, 3, 4]
+ let list02 = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, v:val * 2)'))
+ call assert_equal([2, 4, 6, 8], list02)
+ let list02 = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, v:key * 2)'))
+ call assert_equal([0, 2, 4, 6], list02)
+ let list02 = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, 9)'))
+ call assert_equal([9, 9, 9, 9], list02)
endfunc
" dict with expression string
@@ -29,6 +41,14 @@ func Test_filter_map_dict_expr_string()
call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2'))
call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]'))
call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9))
+
+ " foreach()
+ let dict01 = {}
+ call assert_equal(dict, foreach(copy(dict), 'let dict01[v:key] = v:val * 2'))
+ call assert_equal({"foo": 2, "bar": 4, "baz": 6}, dict01)
+ let dict01 = {}
+ call assert_equal(dict, foreach(copy(dict), 'let dict01[v:key] = v:key[0]'))
+ call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, dict01)
endfunc
" list with funcref
@@ -54,6 +74,16 @@ func Test_filter_map_list_expr_funcref()
return a:index * 2
endfunc
call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4')))
+
+ " foreach()
+ func! s:foreach1(index, val) abort
+ call add(g:test_variable, a:val + 1)
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = []
+ call assert_equal([0, 1, 2, 3, 4], foreach(range(5), function('s:foreach1')))
+ call assert_equal([1, 2, 3, 4, 5], g:test_variable)
+ call remove(g:, 'test_variable')
endfunc
func Test_filter_map_nested()
@@ -90,11 +120,46 @@ func Test_filter_map_dict_expr_funcref()
return a:key[0]
endfunc
call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), function('s:filter4')))
+
+ " foreach()
+ func! s:foreach1(key, val) abort
+ call extend(g:test_variable, {a:key: a:val * 2})
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = {}
+ call assert_equal(dict, foreach(copy(dict), function('s:foreach1')))
+ call assert_equal({"foo": 2, "bar": 4, "baz": 6}, g:test_variable)
+ call remove(g:, 'test_variable')
+endfunc
+
+func Test_map_filter_locked()
+ let list01 = [1, 2, 3, 4]
+ lockvar 1 list01
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ call assert_equal([2, 4, 6, 8], map(list01, 'v:val * 2'))
+ call assert_equal([1, 2, 3, 4], map(list01, 'v:val / 2'))
+ call assert_equal([2, 4, 6, 8], mapnew(list01, 'v:val * 2'))
+ let g:test_variable = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(g:test_variable, v:val * 2)'))
+ call remove(g:, 'test_variable')
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ unlockvar 1 list01
+ lockvar! list01
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ call assert_fails('call map(list01, "v:val * 2")', 'E741:')
+ call assert_equal([2, 4, 6, 8], mapnew(list01, 'v:val * 2'))
+ let g:test_variable = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(g:test_variable, v:val * 2)'))
+ call assert_fails('call foreach(list01, "let list01[0] = -1")', 'E741:')
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ call remove(g:, 'test_variable')
+ unlockvar! list01
endfunc
func Test_map_filter_fails()
call assert_fails('call map([1], "42 +")', 'E15:')
call assert_fails('call filter([1], "42 +")', 'E15:')
+ call assert_fails('call foreach([1], "let a = }")', 'E15:')
call assert_fails("let l = filter([1, 2, 3], '{}')", 'E728:')
call assert_fails("let l = filter({'k' : 10}, '{}')", 'E728:')
call assert_fails("let l = filter([1, 2], {})", 'E731:')
@@ -106,6 +171,8 @@ func Test_map_filter_fails()
call assert_fails("let l = filter([1, 2], function('min'))", 'E118:')
call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_partial()))
call assert_fails("let l = filter([1, 2], {a, b, c -> 1})", 'E119:')
+ call assert_fails('call foreach([1], "xyzzy")', 'E492:')
+ call assert_fails('call foreach([1], "let a = foo")', 'E121:')
endfunc
func Test_map_and_modify()
@@ -123,7 +190,7 @@ endfunc
func Test_filter_and_modify()
let l = [0]
- " cannot change the list halfway a map()
+ " cannot change the list halfway thru filter()
call assert_fails('call filter(l, "remove(l, 0)")', 'E741:')
let d = #{a: 0, b: 0, c: 0}
@@ -133,6 +200,18 @@ func Test_filter_and_modify()
call assert_fails('call filter(b, "remove(b, 0)")', 'E741:')
endfunc
+func Test_foreach_and_modify()
+ let l = [0]
+ " cannot change the list halfway thru foreach()
+ call assert_fails('call foreach(l, "let a = remove(l, 0)")', 'E741:')
+
+ let d = #{a: 0, b: 0, c: 0}
+ call assert_fails('call foreach(d, "let a = remove(d, v:key)")', 'E741:')
+
+ let b = 0z1234
+ call assert_fails('call foreach(b, "let a = remove(b, 0)")', 'E741:')
+endfunc
+
func Test_mapnew_dict()
let din = #{one: 1, two: 2}
let dout = mapnew(din, {k, v -> string(v)})
@@ -160,6 +239,36 @@ func Test_mapnew_blob()
call assert_equal(0z129956, bout)
endfunc
+func Test_foreach_blob()
+ let lines =<< trim END
+ LET g:test_variable = []
+ call assert_equal(0z0001020304, foreach(0z0001020304, 'call add(g:test_variable, v:val)'))
+ call assert_equal([0, 1, 2, 3, 4], g:test_variable)
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+
+ func! s:foreach1(index, val) abort
+ call add(g:test_variable, a:val)
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = []
+ call assert_equal(0z0001020304, foreach(0z0001020304, function('s:foreach1')))
+ call assert_equal([0, 1, 2, 3, 4], g:test_variable)
+
+ let lines =<< trim END
+ def Foreach1(_, val: any): list<number>
+ add(g:test_variable, val)
+ return [ 11, 12, 13, 14 ]
+ enddef
+ g:test_variable = []
+ assert_equal(0z0001020304, foreach(0z0001020304, Foreach1))
+ assert_equal([0, 1, 2, 3, 4], g:test_variable)
+ END
+ call v9.CheckDefSuccess(lines)
+
+ call remove(g:, 'test_variable')
+endfunc
+
" Test for using map(), filter() and mapnew() with a string
func Test_filter_map_string()
" filter()
@@ -219,6 +328,37 @@ func Test_filter_map_string()
END
call v9.CheckLegacyAndVim9Success(lines)
+ " foreach()
+ let lines =<< trim END
+ VAR s = "abc"
+ LET g:test_variable = []
+ call assert_equal(s, foreach(s, 'call add(g:test_variable, v:val)'))
+ call assert_equal(['a', 'b', 'c'], g:test_variable)
+ LET g:test_variable = []
+ LET s = 'ã‚iã†ãˆãŠ'
+ call assert_equal(s, foreach(s, 'call add(g:test_variable, v:val)'))
+ call assert_equal(['ã‚', 'i', 'ã†', 'ãˆ', 'ãŠ'], g:test_variable)
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+ func! s:foreach1(index, val) abort
+ call add(g:test_variable, a:val)
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = []
+ call assert_equal('abcd', foreach('abcd', function('s:foreach1')))
+ call assert_equal(['a', 'b', 'c', 'd'], g:test_variable)
+ let lines =<< trim END
+ def Foreach1(_, val: string): list<number>
+ add(g:test_variable, val)
+ return [ 11, 12, 13, 14 ]
+ enddef
+ g:test_variable = []
+ assert_equal('abcd', foreach('abcd', Foreach1))
+ assert_equal(['a', 'b', 'c', 'd'], g:test_variable)
+ END
+ call v9.CheckDefSuccess(lines)
+ call remove(g:, 'test_variable')
+
let lines =<< trim END
#" map() and filter()
call assert_equal('[ã‚][âˆ][a][😊][â‰][💕][💕][b][💕]', map(filter('ã‚xâˆax😊xâ‰ðŸ’•ðŸ’•b💕x', '"x" != v:val'), '"[" .. v:val .. "]"'))
diff --git a/src/testdir/test_format.vim b/src/testdir/test_format.vim
index af364c2..785348b 100644
--- a/src/testdir/test_format.vim
+++ b/src/testdir/test_format.vim
@@ -105,67 +105,6 @@ func Test_printf_pos_misc()
END
call v9.CheckLegacyAndVim9Success(lines)
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:")
-
- call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:")
-
- call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:")
-
- call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:")
-
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:")
-
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:")
-
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:")
- call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:")
endfunc
func Test_printf_pos_float()
@@ -287,8 +226,6 @@ func Test_printf_pos_float()
call assert_equal('nan', printf('%1$S', -0.0 / 0.0))
END
call v9.CheckLegacyAndVim9Success(lines)
-
- call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:')
endfunc
func Test_printf_pos_errors()
@@ -299,6 +236,111 @@ func Test_printf_pos_errors()
call v9.CheckLegacyAndVim9Failure(['echo printf("%1$s")'], 'E1503:')
call v9.CheckLegacyAndVim9Failure(['echo printf("%1$d", 1.2)'], 'E805:')
call v9.CheckLegacyAndVim9Failure(['echo printf("%1$f")'], 'E1503:')
+
+ call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:')
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789d', 5)"], "E1510:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.5d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.5d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.123456789d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.5d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.987654321d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.987654321d', 5)"], "E1510:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.5d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.5d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.123456789d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.5d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.987654321d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.987654321d', 5)"], "E1510:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.*1$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.*1$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.*123456789$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.*1$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.*987654321$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.*987654321$d', 5)"], "E1510:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*1$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*1$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*123456789d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.*1$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*987654321$d', 5)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*987654321$d', 5)"], "E1510:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$.*1$d', 5, 9999)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*2$d', 5, 9999)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$*3$.*1$d', 5, 9123, 9321)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$.*3$d', 5, 9123, 9321)"], "E1510:")
+ call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$.*3$d', 5, 9123, 9312)"], "E1510:")
+
+ call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$d', 5, 9999)"], "E1510:")
endfunc
func Test_printf_pos_64bit()
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 85ccc78..fecebc4 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -3953,4 +3953,55 @@ func Test_glob_extended_mswin()
call delete('Xtestglob', 'rf')
endfunc
+" Tests for the slice() function.
+func Test_slice()
+ let lines =<< trim END
+ call assert_equal([1, 2, 3, 4, 5], slice(range(6), 1))
+ call assert_equal([2, 3, 4, 5], slice(range(6), 2))
+ call assert_equal([2, 3], slice(range(6), 2, 4))
+ call assert_equal([0, 1, 2, 3], slice(range(6), 0, 4))
+ call assert_equal([1, 2, 3], slice(range(6), 1, 4))
+ call assert_equal([1, 2, 3, 4], slice(range(6), 1, -1))
+ call assert_equal([1, 2], slice(range(6), 1, -3))
+ call assert_equal([1], slice(range(6), 1, -4))
+ call assert_equal([], slice(range(6), 1, -5))
+ call assert_equal([], slice(range(6), 1, -6))
+
+ call assert_equal(0z1122334455, slice(0z001122334455, 1))
+ call assert_equal(0z22334455, slice(0z001122334455, 2))
+ call assert_equal(0z2233, slice(0z001122334455, 2, 4))
+ call assert_equal(0z00112233, slice(0z001122334455, 0, 4))
+ call assert_equal(0z112233, slice(0z001122334455, 1, 4))
+ call assert_equal(0z11223344, slice(0z001122334455, 1, -1))
+ call assert_equal(0z1122, slice(0z001122334455, 1, -3))
+ call assert_equal(0z11, slice(0z001122334455, 1, -4))
+ call assert_equal(0z, slice(0z001122334455, 1, -5))
+ call assert_equal(0z, slice(0z001122334455, 1, -6))
+
+ call assert_equal('12345', slice('012345', 1))
+ call assert_equal('2345', slice('012345', 2))
+ call assert_equal('23', slice('012345', 2, 4))
+ call assert_equal('0123', slice('012345', 0, 4))
+ call assert_equal('123', slice('012345', 1, 4))
+ call assert_equal('1234', slice('012345', 1, -1))
+ call assert_equal('12', slice('012345', 1, -3))
+ call assert_equal('1', slice('012345', 1, -4))
+ call assert_equal('', slice('012345', 1, -5))
+ call assert_equal('', slice('012345', 1, -6))
+
+ #" Composing chars are treated as a part of the preceding base char.
+ call assert_equal('βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1))
+ call assert_equal('γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2))
+ call assert_equal('γ̳̂δ̳̃', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2, 4))
+ call assert_equal('ὰ̳βÌ̳γ̳̂δ̳̃', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(0, 4))
+ call assert_equal('βÌ̳γ̳̂δ̳̃', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, 4))
+ call assert_equal('βÌ̳γ̳̂δ̳̃ε̳̄', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -1))
+ call assert_equal('βÌ̳γ̳̂', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -3))
+ call assert_equal('βÌ̳', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -4))
+ call assert_equal('', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -5))
+ call assert_equal('', 'ὰ̳βÌ̳γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -6))
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_goto.vim b/src/testdir/test_goto.vim
index 85c156a..357a8d2 100644
--- a/src/testdir/test_goto.vim
+++ b/src/testdir/test_goto.vim
@@ -312,18 +312,23 @@ func Test_gd_string_only()
call XTest_goto_decl('gd', lines, 5, 10)
endfunc
-" Check that setting 'cursorline' does not change curswant
-func Test_cursorline_keep_col()
+" Check that setting some options does not change curswant
+func Test_set_options_keep_col()
new
call setline(1, ['long long long line', 'short line'])
normal ggfi
let pos = getcurpos()
normal j
- set cursorline
+ set invhlsearch spell spelllang=en,cjk spelloptions=camel textwidth=80
+ set cursorline cursorcolumn cursorlineopt=line colorcolumn=+1
+ set background=dark
+ set background=light
normal k
call assert_equal(pos, getcurpos())
bwipe!
- set nocursorline
+ set hlsearch& spell& spelllang& spelloptions& textwidth&
+ set cursorline& cursorcolumn& cursorlineopt& colorcolumn&
+ set background&
endfunc
func Test_gd_local_block()
diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim
index e7f7c6d..2ff8d34 100644
--- a/src/testdir/test_gui.vim
+++ b/src/testdir/test_gui.vim
@@ -111,6 +111,8 @@ func Test_getfontname_without_arg()
endfunc
func Test_getwinpos()
+ CheckX11
+
call assert_match('Window position: X \d\+, Y \d\+', execute('winpos'))
call assert_true(getwinposx() >= 0)
call assert_true(getwinposy() >= 0)
@@ -633,7 +635,7 @@ endfunc
func Test_set_guiligatures()
CheckX11BasedGui
- if has('gui_gtk') || has('gui_gtk2') || has('gui_gnome') || has('gui_gtk3')
+ if has('gui_gtk') || has('gui_gtk2') || has('gui_gnome') || has('gui_gtk3') || has('win32')
" Try correct value
set guiligatures=<>=ab
call assert_equal("<>=ab", &guiligatures)
@@ -897,7 +899,7 @@ func Test_set_term()
endfunc
func Test_windowid_variable()
- if g:x11_based_gui || has('win32')
+ if (g:x11_based_gui && empty($WAYLAND_DISPLAY)) || has('win32')
call assert_true(v:windowid > 0)
else
call assert_equal(0, v:windowid)
@@ -1708,7 +1710,11 @@ func Test_gui_lowlevel_keyevent()
" Test for <Ctrl-A> to <Ctrl-Z> keys
for kc in range(65, 90)
call SendKeys([0x11, kc])
- let ch = getcharstr()
+ try
+ let ch = getcharstr()
+ catch /^Vim:Interrupt$/
+ let ch = "\<c-c>"
+ endtry
call assert_equal(nr2char(kc - 64), ch)
endfor
diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim
index af60503..d6c9f50 100644
--- a/src/testdir/test_highlight.vim
+++ b/src/testdir/test_highlight.vim
@@ -557,22 +557,23 @@ func Test_cursorline_after_yank()
call StopVimInTerminal(buf)
endfunc
-" test for issue #4862
+" Test for issue #4862: pasting above 'cursorline' redraws properly.
func Test_put_before_cursorline()
new
only!
- call setline(1, 'A')
+ call setline(1, ['A', 'B', 'C'])
+ call cursor(2, 1)
redraw
- let std_attr = screenattr(1, 1)
+ let std_attr = screenattr(2, 1)
set cursorline
redraw
- let cul_attr = screenattr(1, 1)
+ let cul_attr = screenattr(2, 1)
normal yyP
redraw
- " Line 1 has cursor so it should be highlighted with CursorLine.
- call assert_equal(cul_attr, screenattr(1, 1))
- " And CursorLine highlighting from the second line should be gone.
- call assert_equal(std_attr, screenattr(2, 1))
+ " Line 2 has cursor so it should be highlighted with CursorLine.
+ call assert_equal(cul_attr, screenattr(2, 1))
+ " And CursorLine highlighting from line 3 should be gone.
+ call assert_equal(std_attr, screenattr(3, 1))
set nocursorline
bwipe!
endfunc
@@ -888,6 +889,16 @@ func Test_highlight_ctermul()
highlight Normal ctermul=NONE
endfunc
+" Test for 'ctermfont' in a highlight group
+func Test_highlight_ctermfont()
+ CheckNotGui
+ call assert_notmatch('ctermfont=', HighlightArgs('Normal'))
+ highlight Normal ctermfont=3
+ call assert_match('ctermfont=3', HighlightArgs('Normal'))
+ call assert_equal('3', synIDattr(synIDtrans(hlID('Normal')), 'font'))
+ highlight Normal ctermfont=NONE
+endfunc
+
" Test for specifying 'start' and 'stop' in a highlight group
func Test_highlight_start_stop()
hi HlGrp1 start=<Esc>[27h;<Esc>[<Space>r;
@@ -1314,6 +1325,7 @@ func Test_hlset()
call hlset([{'name': 'hlg11', 'ctermfg': ''}])
call hlset([{'name': 'hlg11', 'ctermbg': ''}])
call hlset([{'name': 'hlg11', 'ctermul': ''}])
+ call hlset([{'name': 'hlg11', 'ctermfont': ''}])
call hlset([{'name': 'hlg11', 'font': ''}])
call hlset([{'name': 'hlg11', 'gui': {}}])
call hlset([{'name': 'hlg11', 'guifg': ''}])
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 61ddcd3..52306e8 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -412,6 +412,62 @@ func Test_completefunc_info()
set completefunc&
endfunc
+func CompleteInfoUserDefinedFn(findstart, query)
+ " User defined function (i_CTRL-X_CTRL-U)
+ if a:findstart
+ return col('.')
+ endif
+ return [{'word': 'foo'}, {'word': 'bar'}, {'word': 'baz'}, {'word': 'qux'}]
+endfunc
+
+func CompleteInfoTestUserDefinedFn(mvmt, idx, noselect)
+ new
+ if a:noselect
+ set completeopt=menuone,popup,noinsert,noselect
+ else
+ set completeopt=menu,preview
+ endif
+ set completefunc=CompleteInfoUserDefinedFn
+ call feedkeys("i\<C-X>\<C-U>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
+ let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
+ call assert_equal(completed. "{'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': [" .
+ \ "{'word': 'foo', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " .
+ \ "{'word': 'bar', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " .
+ \ "{'word': 'baz', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " .
+ \ "{'word': 'qux', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}" .
+ \ "]}", getline(1))
+ bwipe!
+ set completeopt&
+ set completefunc&
+endfunc
+
+func Test_complete_info_user_defined_fn()
+ " forward
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 1, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 2, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 2, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 3, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>", -1, v:false)
+ " backward
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 2, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 1, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>", -1, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 3, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 2, v:false)
+ " forward backward
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 1, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 0, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 2, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 3, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 1, v:false)
+ " backward forward
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 0, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 2, v:true)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 1, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 3, v:false)
+ call CompleteInfoTestUserDefinedFn("\<C-P>\<C-N>\<C-N>", 1, v:false)
+endfunc
+
" Test that mouse scrolling/movement should not interrupt completion.
func Test_mouse_scroll_move_during_completion()
new
@@ -2345,7 +2401,7 @@ func Test_complete_info_index()
call assert_equal(-1, g:compl_info['selected'])
call feedkeys("Go\<C-X>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx')
- call assert_equal(0, g:compl_info['selected'])
+ call assert_equal(5, g:compl_info['selected'])
call assert_equal(6 , len(g:compl_info['items']))
call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
@@ -2359,4 +2415,18 @@ func Test_complete_info_index()
bwipe!
endfunc
-" vim: shiftwidth=2 sts=2 expandtab
+func Test_complete_changed_complete_info()
+ CheckRunVimInTerminal
+ " this used to crash vim, see #13929
+ let lines =<< trim END
+ set completeopt=menuone
+ autocmd CompleteChanged * call complete_info(['items'])
+ call feedkeys("iii\<cr>\<c-p>")
+ END
+ call writefile(lines, 'Xsegfault', 'D')
+ let buf = RunVimInTerminal('-S Xsegfault', #{rows: 5})
+ call WaitForAssert({-> assert_match('^ii', term_getline(buf, 1))}, 1000)
+ call StopVimInTerminal(buf)
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/src/testdir/test_listchars.vim b/src/testdir/test_listchars.vim
index 57ddcda..46e96de 100644
--- a/src/testdir/test_listchars.vim
+++ b/src/testdir/test_listchars.vim
@@ -429,52 +429,52 @@ func Test_listchars_invalid()
call assert_fails('set listchars=leadmultispace', 'E474:')
" Too short
- call assert_fails('set listchars=space:', 'E474:')
- call assert_fails('set listchars=tab:x', 'E474:')
- call assert_fails('set listchars=multispace:', 'E474:')
- call assert_fails('set listchars=leadmultispace:', 'E474:')
+ call assert_fails('set listchars=space:', 'E1511:')
+ call assert_fails('set listchars=tab:x', 'E1511:')
+ call assert_fails('set listchars=multispace:', 'E1511:')
+ call assert_fails('set listchars=leadmultispace:', 'E1511:')
" One occurrence too short
- call assert_fails('set listchars=space:,space:x', 'E474:')
- call assert_fails('set listchars=space:x,space:', 'E474:')
- call assert_fails('set listchars=tab:x,tab:xx', 'E474:')
- call assert_fails('set listchars=tab:xx,tab:x', 'E474:')
- call assert_fails('set listchars=multispace:,multispace:x', 'E474:')
- call assert_fails('set listchars=multispace:x,multispace:', 'E474:')
- call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E474:')
- call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E474:')
+ call assert_fails('set listchars=space:x,space:', 'E1511:')
+ call assert_fails('set listchars=space:,space:x', 'E1511:')
+ call assert_fails('set listchars=tab:xx,tab:x', 'E1511:')
+ call assert_fails('set listchars=tab:x,tab:xx', 'E1511:')
+ call assert_fails('set listchars=multispace:,multispace:x', 'E1511:')
+ call assert_fails('set listchars=multispace:x,multispace:', 'E1511:')
+ call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E1511:')
+ call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E1511:')
" Too long
- call assert_fails('set listchars=space:xx', 'E474:')
- call assert_fails('set listchars=tab:xxxx', 'E474:')
+ call assert_fails('set listchars=space:xx', 'E1511:')
+ call assert_fails('set listchars=tab:xxxx', 'E1511:')
" Has double-width character
- call assert_fails('set listchars=space:·', 'E474:')
- call assert_fails('set listchars=tab:·x', 'E474:')
- call assert_fails('set listchars=tab:x·', 'E474:')
- call assert_fails('set listchars=tab:xx·', 'E474:')
- call assert_fails('set listchars=multispace:·', 'E474:')
- call assert_fails('set listchars=multispace:xxx·', 'E474:')
- call assert_fails('set listchars=leadmultispace:·', 'E474:')
- call assert_fails('set listchars=leadmultispace:xxx·', 'E474:')
+ call assert_fails('set listchars=space:·', 'E1512:')
+ call assert_fails('set listchars=tab:·x', 'E1512:')
+ call assert_fails('set listchars=tab:x·', 'E1512:')
+ call assert_fails('set listchars=tab:xx·', 'E1512:')
+ call assert_fails('set listchars=multispace:·', 'E1512:')
+ call assert_fails('set listchars=multispace:xxx·', 'E1512:')
+ call assert_fails('set listchars=leadmultispace:·', 'E1512:')
+ call assert_fails('set listchars=leadmultispace:xxx·', 'E1512:')
" Has control character
- call assert_fails("set listchars=space:\x01", 'E474:')
- call assert_fails("set listchars=tab:\x01x", 'E474:')
- call assert_fails("set listchars=tab:x\x01", 'E474:')
- call assert_fails("set listchars=tab:xx\x01", 'E474:')
- call assert_fails("set listchars=multispace:\x01", 'E474:')
- call assert_fails("set listchars=multispace:xxx\x01", 'E474:')
- call assert_fails('set listchars=space:\\x01', 'E474:')
- call assert_fails('set listchars=tab:\\x01x', 'E474:')
- call assert_fails('set listchars=tab:x\\x01', 'E474:')
- call assert_fails('set listchars=tab:xx\\x01', 'E474:')
- call assert_fails('set listchars=multispace:\\x01', 'E474:')
- call assert_fails('set listchars=multispace:xxx\\x01', 'E474:')
- call assert_fails("set listchars=leadmultispace:\x01", 'E474:')
- call assert_fails('set listchars=leadmultispace:\\x01', 'E474:')
- call assert_fails("set listchars=leadmultispace:xxx\x01", 'E474:')
- call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E474:')
+ call assert_fails("set listchars=space:\x01", 'E1512:')
+ call assert_fails("set listchars=tab:\x01x", 'E1512:')
+ call assert_fails("set listchars=tab:x\x01", 'E1512:')
+ call assert_fails("set listchars=tab:xx\x01", 'E1512:')
+ call assert_fails("set listchars=multispace:\x01", 'E1512:')
+ call assert_fails("set listchars=multispace:xxx\x01", 'E1512:')
+ call assert_fails('set listchars=space:\\x01', 'E1512:')
+ call assert_fails('set listchars=tab:\\x01x', 'E1512:')
+ call assert_fails('set listchars=tab:x\\x01', 'E1512:')
+ call assert_fails('set listchars=tab:xx\\x01', 'E1512:')
+ call assert_fails('set listchars=multispace:\\x01', 'E1512:')
+ call assert_fails('set listchars=multispace:xxx\\x01', 'E1512:')
+ call assert_fails("set listchars=leadmultispace:\x01", 'E1512:')
+ call assert_fails('set listchars=leadmultispace:\\x01', 'E1512:')
+ call assert_fails("set listchars=leadmultispace:xxx\x01", 'E1512:')
+ call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E1512:')
enew!
set ambiwidth& listchars& ff&
diff --git a/src/testdir/test_listlbr.vim b/src/testdir/test_listlbr.vim
index bcbd886..68bf948 100644
--- a/src/testdir/test_listlbr.vim
+++ b/src/testdir/test_listlbr.vim
@@ -374,13 +374,13 @@ endfunc
func Test_linebreak_no_break_after_whitespace_only()
call s:test_windows('setl ts=4 linebreak wrap')
- call setline(1, "\tabcdefghijklmnopqrstuvwxyz" ..
+ call setline(1, "\t abcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
-\ " abcdefghijklmnop",
-\ "qrstuvwxyzabcdefghij",
-\ "klmnopqrstuvwxyz ",
+\ " abcdefghijklmn",
+\ "opqrstuvwxyzabcdefgh",
+\ "ijklmnopqrstuvwxyz ",
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
diff --git a/src/testdir/test_listlbr_utf8.vim b/src/testdir/test_listlbr_utf8.vim
index 1bbbd2d..313ff30 100644
--- a/src/testdir/test_listlbr_utf8.vim
+++ b/src/testdir/test_listlbr_utf8.vim
@@ -9,6 +9,7 @@ CheckFeature conceal
CheckFeature signs
source view_util.vim
+source screendump.vim
func s:screen_lines(lnum, width) abort
return ScreenLines(a:lnum, a:width)
@@ -358,4 +359,24 @@ func Test_unprintable_char_on_wrap_column()
call s:close_windows()
endfunc
+" Test that Visual selection is drawn correctly when 'linebreak' is set and
+" selection ends before multibyte 'showbreak'.
+func Test_visual_ends_before_showbreak()
+ CheckScreendump
+
+ let lines =<< trim END
+ vim9script
+ &wrap = true
+ &linebreak = true
+ &showbreak = '↪ '
+ ['xxxxx ' .. 'y'->repeat(&columns - 6) .. ' zzzz']->setline(1)
+ normal! wvel
+ END
+ call writefile(lines, 'XvisualEndsBeforeShowbreak', 'D')
+ let buf = RunVimInTerminal('-S XvisualEndsBeforeShowbreak', #{rows: 6})
+ call VerifyScreenDump(buf, 'Test_visual_ends_before_showbreak', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_lua.vim b/src/testdir/test_lua.vim
index 7e72728..a99affc 100644
--- a/src/testdir/test_lua.vim
+++ b/src/testdir/test_lua.vim
@@ -28,21 +28,37 @@ func TearDown()
endfunc
" Check that switching to another buffer does not trigger ml_get error.
-func Test_lua_command_new_no_ml_get_error()
+func Test_lua_luado_change_buffer()
new
+
let wincount = winnr('$')
call setline(1, ['one', 'two', 'three'])
luado vim.command("new")
call assert_equal(wincount + 1, winnr('$'))
+
%bwipe!
endfunc
-" Test vim.command()
-func Test_lua_command()
+" Check that :luado deleting lines does not trigger ml_get error.
+func Test_lua_luado_delete_lines()
new
+
+ call setline(1, ['one', 'two', 'three'])
+ luado vim.command("%d_")
+ call assert_equal([''], getline(1, '$'))
+
call setline(1, ['one', 'two', 'three'])
luado vim.command("1,2d_")
call assert_equal(['three'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ luado vim.command("2,3d_"); return "REPLACED"
+ call assert_equal(['REPLACED'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ 2,3luado vim.command("1,2d_"); return "REPLACED"
+ call assert_equal(['three'], getline(1, '$'))
+
bwipe!
endfunc
diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim
index e81173d..71d9046 100644
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -120,7 +120,7 @@ func Test_map_langmap()
unmap x
bwipe!
- " 'langnoremap' follows 'langremap' and vise versa
+ " 'langnoremap' follows 'langremap' and vice versa
set langremap
set langnoremap
call assert_equal(0, &langremap)
@@ -247,6 +247,24 @@ func Test_map_meta_multibyte()
iunmap <M-á>
endfunc
+func Test_map_super_quotes()
+ if has('gui_gtk') || has('gui_gtk3') || has("macos")
+ imap <D-"> foo
+ call feedkeys("Go-\<*D-\">-\<Esc>", "xt")
+ call assert_equal("-foo-", getline('$'))
+ set nomodified
+ iunmap <D-">
+ endif
+endfunc
+
+func Test_map_super_multibyte()
+ if has('gui_gtk') || has('gui_gtk3') || has("macos")
+ imap <D-á> foo
+ call assert_match('i <D-á>\s*foo', execute('imap'))
+ iunmap <D-á>
+ endif
+endfunc
+
func Test_abbr_after_line_join()
new
abbr foo bar
diff --git a/src/testdir/test_matchparen.vim b/src/testdir/test_matchparen.vim
index 6d09b6f..70aa38f 100644
--- a/src/testdir/test_matchparen.vim
+++ b/src/testdir/test_matchparen.vim
@@ -61,6 +61,31 @@ func Test_matchparen_clear_highlight()
call StopVimInTerminal(buf)
endfunc
+" Test for matchparen highlight when switching buffer in win_execute()
+func Test_matchparen_win_execute()
+ CheckScreendump
+
+ let lines =<< trim END
+ source $VIMRUNTIME/plugin/matchparen.vim
+ let s:win = win_getid()
+ call setline(1, '{}')
+ split
+
+ func SwitchBuf()
+ call win_execute(s:win, 'enew | buffer #')
+ endfunc
+ END
+ call writefile(lines, 'XMatchparenWinExecute', 'D')
+ let buf = RunVimInTerminal('-S XMatchparenWinExecute', #{rows: 5})
+ call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {})
+
+ " Switching buffer away and back shouldn't change matchparen highlight.
+ call term_sendkeys(buf, ":call SwitchBuf()\<CR>:\<Esc>")
+ call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for scrolling that modifies buffer during visual block
func Test_matchparen_pum_clear()
CheckScreendump
diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim
index 48f1bab..46f3368 100644
--- a/src/testdir/test_messages.vim
+++ b/src/testdir/test_messages.vim
@@ -162,8 +162,18 @@ func Test_echospace()
call assert_equal(&columns - 12, v:echospace)
set showcmd ruler
call assert_equal(&columns - 29, v:echospace)
+ set showcmdloc=statusline
+ call assert_equal(&columns - 19, v:echospace)
+ set showcmdloc=tabline
+ call assert_equal(&columns - 19, v:echospace)
+ call assert_fails('set showcmdloc=leap', 'E474:')
+ call assert_equal(&columns - 19, v:echospace)
+ set showcmdloc=last
+ call assert_equal(&columns - 29, v:echospace)
+ call assert_fails('set showcmdloc=jump', 'E474:')
+ call assert_equal(&columns - 29, v:echospace)
- set ruler& showcmd&
+ set ruler& showcmd& showcmdloc&
endfunc
func Test_warning_scroll()
diff --git a/src/testdir/test_mswin_event.vim b/src/testdir/test_mswin_event.vim
index 4de0169..3b7b3c7 100644
--- a/src/testdir/test_mswin_event.vim
+++ b/src/testdir/test_mswin_event.vim
@@ -36,6 +36,17 @@ func SendKey(key)
call SendKeyWithModifiers(a:key, 0)
endfunc
+" getcharstr(0) but catch Vim:Interrupt
+func Getcharstr()
+ try
+ let ch = getcharstr(0)
+ catch /^Vim:Interrupt$/
+ let ch = "\<c-c>"
+ endtry
+ return ch
+endfunc
+
+
" Send a string of individual key-press events, without modifiers.
func SendKeyStr(keystring)
for k in a:keystring
@@ -347,7 +358,7 @@ func s:LoopTestKeyArray(arr)
for [kcodes, kstr] in a:arr
" Send as a sequence of key presses.
call SendKeyGroup(kcodes)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
" need to deal a bit differently with the non-printable ascii chars < 0x20
if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0
call assert_equal(nr2char(kstr), $"{ch}")
@@ -374,7 +385,7 @@ func s:LoopTestKeyArray(arr)
endif
endfor
call SendKeyWithModifiers(key, modifiers)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
" need to deal a bit differently with the non-printable ascii chars < 0x20
if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0
call assert_equal(nr2char(kstr), $"{ch}")
@@ -408,10 +419,10 @@ func Test_mswin_event_character_keys()
" (0x30 - 0x39) : VK_0 - VK_9 are the same as ASCII '0' - '9'
for kc in range(48, 57)
call SendKey(kc)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc), ch)
call SendKeyWithModifiers(kc, 0)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc), ch)
endfor
@@ -437,10 +448,10 @@ func Test_mswin_event_character_keys()
" numbered 32 higher than their uppercase versions.
for kc in range(65, 90)
call SendKey(kc)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc + 32), ch)
call SendKeyWithModifiers(kc, 0)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc + 32), ch)
endfor
@@ -449,23 +460,28 @@ func Test_mswin_event_character_keys()
for modkey in [s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT]
for kc in range(65, 90)
call SendKeyGroup([modkey, kc])
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc), ch)
call SendKeyWithModifiers(kc, s:MOD_MASK_SHIFT)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc), ch)
endfor
endfor
- " Test for <Ctrl-A> to <Ctrl-Z> keys
- " Expect the unicode characters 0x01 to 0x1A
+" Test for <Ctrl-A> to <Ctrl-Z> keys
+" Expect the unicode characters 0x01 to 0x1A
+" Note: Skip C because it triggers an Interrupt (CTRL-C)
+" which causes a test failure
for modkey in [s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL]
for kc in range(65, 90)
+ if kc == 67
+ continue
+ endif
call SendKeyGroup([modkey, kc])
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc - 64), ch)
call SendKeyWithModifiers(kc, s:MOD_MASK_CTRL)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(kc - 64), ch)
endfor
endfor
@@ -518,7 +534,7 @@ func Test_mswin_event_function_keys()
while getchar(0)
endwhile
call SendKeyWithModifiers(111+n, vim_mod_mask)
- let ch = getcharstr(0)
+ let ch = Getcharstr()
let mod_mask = getcharmod()
call assert_equal(keycode, $"{ch}", $"key = {kstr}")
" workaround for the virtual termcap maps changing the character
@@ -590,21 +606,21 @@ func Test_mswin_event_movement_keys()
while getchar(0)
endwhile
execute 'call feedkeys("\<' .. kstr .. '>")'
- let chstr_fk = getcharstr(0)
+ let chstr_fk = Getcharstr()
call assert_equal(chstr_eval, chstr_fk, $"feedkeys = <{kstr}>")
" flush out the typeahead buffer
while getchar(0)
endwhile
call SendKey(kcode)
- let chstr_alone = getcharstr(0)
+ let chstr_alone = Getcharstr()
let chstr_alone_end = chstr_alone[len(chstr_alone)-2:len(chstr_alone)-1]
" flush out the typeahead buffer
while getchar(0)
endwhile
call SendKeyGroup(mod_keycodes + [kcode])
- let chstr_mswin = getcharstr(0)
+ let chstr_mswin = Getcharstr()
let chstr_mswin_end = chstr_mswin[len(chstr_mswin)-2:len(chstr_mswin)-1]
let mod_mask = getcharmod()
@@ -653,7 +669,7 @@ func Test_QWERTY_Ctrl_minus()
new
call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS])
- let ch = getcharstr(0)
+ let ch = Getcharstr()
call assert_equal(nr2char(0x1f),ch)
call SendKey(s:VK.KEY_I)
@@ -727,14 +743,14 @@ func Test_mswin_event_mouse()
if has('gui_running')
let args = { }
let args.row = 9
- let args.col = 7
+ let args.col = 5
let args.move = 1
let args.cell = 1
call test_mswin_event("mouse", args)
call feedkeys("\<Esc>", 'Lx!')
let pos = getmousepos()
call assert_equal(9, pos.screenrow)
- call assert_equal(7, pos.screencol)
+ call assert_equal(5, pos.screencol)
let args.cell = 0
call test_mswin_event("mouse", args)
diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim
index 38ad810..b180637 100644
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -2235,7 +2235,7 @@ func Test_normal29_brace()
[DATA]
call assert_equal(expected, getline(1, '$'))
- " Test with { in cpooptions
+ " Test with { in cpoptions
%d
call append(0, text)
set cpo+={
@@ -2347,23 +2347,31 @@ func Test_normal30_changecase()
norm! 1ggVu
call assert_equal('this is a simple test: äüöß', getline('.'))
norm! VU
- call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! guu
- call assert_equal('this is a simple test: äüöss', getline('.'))
+ call assert_equal('this is a simple test: äüöß', getline('.'))
norm! gUgU
- call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! gugu
- call assert_equal('this is a simple test: äüöss', getline('.'))
+ call assert_equal('this is a simple test: äüöß', getline('.'))
norm! gUU
- call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! 010~
- call assert_equal('this is a SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('this is a SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! V~
- call assert_equal('THIS IS A simple test: äüöss', getline('.'))
+ call assert_equal('THIS IS A simple test: äüöß', getline('.'))
call assert_beeps('norm! c~')
%d
call assert_beeps('norm! ~')
+ " Test with multiple lines
+ call setline(1, ['AA', 'BBBB', 'CCCCCC', 'DDDDDDDD'])
+ norm! ggguG
+ call assert_equal(['aa', 'bbbb', 'cccccc', 'dddddddd'], getline(1, '$'))
+ norm! GgUgg
+ call assert_equal(['AA', 'BBBB', 'CCCCCC', 'DDDDDDDD'], getline(1, '$'))
+ %d
+
" Test for changing case across lines using 'whichwrap'
call setline(1, ['aaaaaa', 'aaaaaa'])
normal! gg10~
@@ -3158,7 +3166,7 @@ func Test_normal50_commandline()
CheckFeature cmdline_hist
func! DoTimerWork(id)
- call assert_equal('[Command Line]', bufname(''))
+ call assert_equal(1, getbufinfo('')[0].command)
" should fail, with E11, but does fail with E23?
"call feedkeys("\<c-^>", 'tm')
diff --git a/src/testdir/test_number.vim b/src/testdir/test_number.vim
index 81f8f73..b57c1ed 100644
--- a/src/testdir/test_number.vim
+++ b/src/testdir/test_number.vim
@@ -146,8 +146,7 @@ func Test_number_with_linewrap1()
call s:close_windows()
endfunc
-" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI
-func XTest_number_with_linewrap2()
+func Test_number_with_linewrap2()
call s:test_windows(3, 20)
normal! 61ia
setl number wrap
@@ -164,8 +163,7 @@ func XTest_number_with_linewrap2()
call s:close_windows()
endfunc
-" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI
-func XTest_number_with_linewrap3()
+func Test_number_with_linewrap3()
call s:test_windows(4, 20)
normal! 81ia
setl number wrap
@@ -174,7 +172,7 @@ func XTest_number_with_linewrap3()
call s:validate_cursor()
let lines = s:screen_lines(1, 4)
let expect = [
-\ "aaaaaaaa",
+\ "<<<aaaaa",
\ "aaaaaaaa",
\ "aaaaaaaa",
\ "a ",
@@ -278,9 +276,7 @@ func Test_relativenumber_colors()
[CODE]
call writefile(lines, 'XTest_relnr', 'D')
- " Check that the balloon shows up after a mouse move
let buf = RunVimInTerminal('-S XTest_relnr', {'rows': 10, 'cols': 50})
- call TermWait(buf, 50)
" Default colors
call VerifyScreenDump(buf, 'Test_relnr_colors_1', {})
@@ -297,6 +293,36 @@ func Test_relativenumber_colors()
call StopVimInTerminal(buf)
endfunc
+func Test_relativenumber_colors_wrapped()
+ CheckScreendump
+
+ let lines =<< trim [CODE]
+ set display=lastline scrolloff=0
+ call setline(1, range(200)->map('v:val->string()->repeat(40)'))
+ 111
+ set number relativenumber
+ hi LineNr ctermbg=red ctermfg=black
+ hi LineNrAbove ctermbg=blue ctermfg=black
+ hi LineNrBelow ctermbg=green ctermfg=black
+ [CODE]
+ call writefile(lines, 'XTest_relnr_wrap', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_relnr_wrap', {'rows': 20, 'cols': 50})
+
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_1', {})
+ call term_sendkeys(buf, "k")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_2', {})
+ call term_sendkeys(buf, "2j")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_3', {})
+ call term_sendkeys(buf, "2j")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_4', {})
+ call term_sendkeys(buf, "k")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_5', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_relativenumber_callback()
CheckScreendump
CheckFeature timers
@@ -321,6 +347,31 @@ func Test_relativenumber_callback()
call StopVimInTerminal(buf)
endfunc
+" Test that line numbers below inserted/deleted lines are updated.
+func Test_number_insert_delete_lines()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, range(1, 7))
+ set number
+ call cursor(2, 1)
+ END
+ call writefile(lines, 'Xnumber_insert_delete_lines', 'D')
+
+ let buf = RunVimInTerminal('-S Xnumber_insert_delete_lines', #{rows: 8})
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {})
+ call term_sendkeys(buf, "dd")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_2', {})
+ call term_sendkeys(buf, "P")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {})
+ call term_sendkeys(buf, "2dd")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_3', {})
+ call term_sendkeys(buf, "P")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for displaying line numbers with 'rightleft'
func Test_number_rightleft()
CheckFeature rightleft
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index 37dc201..fbfbaae 100644
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -1293,6 +1293,44 @@ func Test_shortmess_F2()
call assert_fails('call test_getvalue("abc")', 'E475:')
endfunc
+func Test_shortmess_F3()
+ call writefile(['foo'], 'X_dummy', 'D')
+
+ set hidden
+ set autoread
+ e X_dummy
+ e Xotherfile
+ call assert_equal(['foo'], getbufline('X_dummy', 1, '$'))
+ set shortmess+=F
+ echo ''
+
+ if has('nanotime')
+ sleep 10m
+ else
+ sleep 2
+ endif
+ call writefile(['bar'], 'X_dummy')
+ bprev
+ call assert_equal('', Screenline(&lines))
+ call assert_equal(['bar'], getbufline('X_dummy', 1, '$'))
+
+ if has('nanotime')
+ sleep 10m
+ else
+ sleep 2
+ endif
+ call writefile(['baz'], 'X_dummy')
+ checktime
+ call assert_equal('', Screenline(&lines))
+ call assert_equal(['baz'], getbufline('X_dummy', 1, '$'))
+
+ set shortmess&
+ set autoread&
+ set hidden&
+ bwipe X_dummy
+ bwipe Xotherfile
+endfunc
+
func Test_local_scrolloff()
set so=5
set siso=7
@@ -2234,4 +2272,34 @@ func Test_set_wrap()
set wrap& smoothscroll& scrolloff&
endfunc
+func Test_delcombine()
+ new
+ set backspace=indent,eol,start
+
+ set delcombine
+ call setline(1, 'β̳̈:β̳̈')
+ normal! 0x
+ call assert_equal('β̈:β̳̈', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal('β̈:β̈', getline(1))
+ normal! 0x
+ call assert_equal('β:β̈', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal('β:β', getline(1))
+ normal! 0x
+ call assert_equal(':β', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal(':', getline(1))
+
+ set nodelcombine
+ call setline(1, 'β̳̈:β̳̈')
+ normal! 0x
+ call assert_equal(':β̳̈', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal(':', getline(1))
+
+ set backspace& delcombine&
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_perl.vim b/src/testdir/test_perl.vim
index 681aaae..721179c 100644
--- a/src/testdir/test_perl.vim
+++ b/src/testdir/test_perl.vim
@@ -211,10 +211,25 @@ func Test_perldo()
call assert_false(search('\Cperl'))
bw!
- " Check deleting lines does not trigger ml_get error.
new
+
+ " Check deleting lines does not trigger ml_get error.
call setline(1, ['one', 'two', 'three'])
perldo VIM::DoCommand("%d_")
+ call assert_equal([''], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ perldo VIM::DoCommand("1,2d_")
+ call assert_equal(['three'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ perldo VIM::DoCommand("2,3d_"); $_ = "REPLACED"
+ call assert_equal(['REPLACED'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ 2,3perldo VIM::DoCommand("1,2d_"); $_ = "REPLACED"
+ call assert_equal(['three'], getline(1, '$'))
+
bwipe!
" Check a Perl expression which gives an error.
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
index a0a1f74..f5cb8b2 100644
--- a/src/testdir/test_popup.vim
+++ b/src/testdir/test_popup.vim
@@ -1139,6 +1139,10 @@ func Test_CompleteChanged()
let g:event = copy(v:event)
let g:item = get(v:event, 'completed_item', {})
let g:word = get(g:item, 'word', v:null)
+ let l:line = getline('.')
+ if g:word == v:null && l:line == "bc"
+ let g:word = l:line
+ endif
endfunction
augroup AAAAA_Group
au!
@@ -1158,10 +1162,24 @@ func Test_CompleteChanged()
call assert_equal(v:null, g:word)
call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'tx')
call assert_equal('foobar', g:word)
+ call feedkeys("S\<C-N>bc", 'tx')
+ call assert_equal("bc", g:word)
+
+ func Omni_test(findstart, base)
+ if a:findstart
+ return col(".")
+ endif
+ return [#{word: "one"}, #{word: "two"}, #{word: "five"}]
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt=menu,menuone
+ call feedkeys("i\<C-X>\<C-O>\<BS>\<BS>\<BS>f", 'tx')
+ call assert_equal('five', g:word)
autocmd! AAAAA_Group
set complete& completeopt&
delfunc! OnPumChange
+ delfunc! Omni_test
bw!
endfunc
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index c20ff48..a397f70 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -4215,4 +4215,22 @@ func Test_popup_close_callback_recursive()
set maxfuncdepth&
endfunc
+func Test_popupwin_setbufvar_changing_window_view()
+ " Test for Github Issue https://github.com/vim/vim/issues/13863
+ " using setbufvar(buf, '&option') should not scroll
+ " the current window
+ 20new
+ call append(0, range(1, 25))
+ setlocal scrollbind
+ norm! G
+ let topline = winsaveview()['topline']
+ call setbufvar(winbufnr(popup_atcursor(['foobar'], {})), '&syntax', 'python')
+ " close popup
+ call popup_clear()
+ call assert_equal(topline, winsaveview()['topline'])
+
+ " clean up
+ bw!
+endfunc
+
" vim: shiftwidth=2 sts=2
diff --git a/src/testdir/test_prompt_buffer.vim b/src/testdir/test_prompt_buffer.vim
index d173731..c5ef010 100644
--- a/src/testdir/test_prompt_buffer.vim
+++ b/src/testdir/test_prompt_buffer.vim
@@ -297,4 +297,49 @@ func Test_prompt_appending_while_hidden()
call StopVimInTerminal(buf)
endfunc
+" Modifying a hidden buffer while leaving a prompt buffer should not prevent
+" stopping of Insert mode, and returning to the prompt buffer later should
+" restore Insert mode.
+func Test_prompt_leave_modify_hidden()
+ call CanTestPromptBuffer()
+
+ let script =<< trim END
+ file hidden
+ set bufhidden=hide
+ enew
+ new prompt
+ set buftype=prompt
+
+ inoremap <buffer> w <Cmd>wincmd w<CR>
+ inoremap <buffer> q <Cmd>bwipe!<CR>
+ autocmd BufLeave prompt call appendbufline('hidden', '$', 'Leave')
+ autocmd BufEnter prompt call appendbufline('hidden', '$', 'Enter')
+ autocmd BufWinLeave prompt call appendbufline('hidden', '$', 'Close')
+ END
+ call writefile(script, 'XpromptLeaveModifyHidden', 'D')
+
+ let buf = RunVimInTerminal('-S XpromptLeaveModifyHidden', {'rows': 10})
+ call TermWait(buf)
+
+ call term_sendkeys(buf, "a")
+ call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "w")
+ call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "\<C-W>w")
+ call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "q")
+ call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, ":bwipe!\<CR>")
+ call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 2))})
+ call WaitForAssert({-> assert_equal('Enter', term_getline(buf, 3))})
+ call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 4))})
+ call WaitForAssert({-> assert_equal('Close', term_getline(buf, 5))})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim
index 72479ac..5b5c354 100644
--- a/src/testdir/test_put.vim
+++ b/src/testdir/test_put.vim
@@ -12,6 +12,16 @@ func Test_put_block()
bwipe!
endfunc
+func Test_put_block_unicode()
+ new
+ call setreg('a', "À\nÀÀ\naaaaaaaaaaaa", "\<C-V>")
+ call setline(1, [' 1', ' 2', ' 3'])
+ exe "norm! \<C-V>jj\"ap"
+ let expected = ['À 1', 'ÀÀ 2', 'aaaaaaaaaaaa3']
+ call assert_equal(expected, getline(1, 3))
+ bw!
+endfunc
+
func Test_put_char_block()
new
call setline(1, ['Line 1', 'Line 2'])
@@ -280,5 +290,33 @@ func Test_put_in_last_displayed_line()
call StopVimInTerminal(buf)
endfunc
+func Test_put_visual_replace_whole_fold()
+ new
+ let lines = repeat(['{{{1', 'foo', 'bar', ''], 2)
+ call setline(1, lines)
+ setlocal foldmethod=marker
+ call setreg('"', 'baz')
+ call setreg('1', '')
+ normal! Vp
+ call assert_equal("{{{1\nfoo\nbar\n\n", getreg('1'))
+ call assert_equal(['baz', '{{{1', 'foo', 'bar', ''], getline(1, '$'))
+
+ bwipe!
+endfunc
+
+func Test_put_visual_replace_fold_marker()
+ new
+ let lines = repeat(['{{{1', 'foo', 'bar', ''], 4)
+ call setline(1, lines)
+ setlocal foldmethod=marker
+ normal! Gkzo
+ call setreg('"', '{{{1')
+ call setreg('1', '')
+ normal! Vp
+ call assert_equal("{{{1\n", getreg('1'))
+ call assert_equal(lines, getline(1, '$'))
+
+ bwipe!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_python2.vim b/src/testdir/test_python2.vim
index 066b4bd..ac43e60 100644
--- a/src/testdir/test_python2.vim
+++ b/src/testdir/test_python2.vim
@@ -56,10 +56,25 @@ func Test_AAA_python_setup()
endfunc
func Test_pydo()
- " Check deleting lines does not trigger an ml_get error.
new
+
+ " Check deleting lines does not trigger an ml_get error.
call setline(1, ['one', 'two', 'three'])
pydo vim.command("%d_")
+ call assert_equal([''], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ pydo vim.command("1,2d_")
+ call assert_equal(['three'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ pydo vim.command("2,3d_"); return "REPLACED"
+ call assert_equal(['REPLACED'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ 2,3pydo vim.command("1,2d_"); return "REPLACED"
+ call assert_equal(['three'], getline(1, '$'))
+
bwipe!
" Check switching to another buffer does not trigger an ml_get error.
diff --git a/src/testdir/test_python3.vim b/src/testdir/test_python3.vim
index e975cb6..7f04f11 100644
--- a/src/testdir/test_python3.vim
+++ b/src/testdir/test_python3.vim
@@ -88,10 +88,25 @@ func Test_AAA_python3_setup()
endfunc
func Test_py3do()
- " Check deleting lines does not trigger an ml_get error.
new
+
+ " Check deleting lines does not trigger an ml_get error.
call setline(1, ['one', 'two', 'three'])
py3do vim.command("%d_")
+ call assert_equal([''], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ py3do vim.command("1,2d_")
+ call assert_equal(['three'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ py3do vim.command("2,3d_"); return "REPLACED"
+ call assert_equal(['REPLACED'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ 2,3py3do vim.command("1,2d_"); return "REPLACED"
+ call assert_equal(['three'], getline(1, '$'))
+
bwipe!
" Check switching to another buffer does not trigger an ml_get error.
diff --git a/src/testdir/test_quotestar.vim b/src/testdir/test_quotestar.vim
index 1d26942..322ce62 100644
--- a/src/testdir/test_quotestar.vim
+++ b/src/testdir/test_quotestar.vim
@@ -139,8 +139,8 @@ func Test_quotestar()
if has('macunix')
let skipped = Do_test_quotestar_for_macunix()
elseif has('x11')
- if empty($DISPLAY)
- let skipped = "Test can only run when $DISPLAY is set."
+ if empty($DISPLAY) || !empty($WAYLAND_DISPLAY)
+ let skipped = "Test can only run when $DISPLAY is set and $WAYLAND_DISPLAY is not set."
else
let skipped = Do_test_quotestar_for_x11()
endif
diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim
index 50f3910..cb4cee7 100644
--- a/src/testdir/test_registers.vim
+++ b/src/testdir/test_registers.vim
@@ -868,6 +868,8 @@ func Test_replay_charsearch_omap()
call timer_start(10, {-> feedkeys(",bar\<Esc>q", 't')})
call feedkeys('qrct[', 'xt!')
call assert_equal(',bar[blah]', getline(1))
+ call assert_equal("ct[\<Ignore>,bar\<Esc>", @r)
+ call assert_equal('ct[<Ignore>,bar<Esc>', keytrans(@r))
undo
call assert_equal('foo[blah]', getline(1))
call feedkeys('@r', 'xt!')
@@ -949,7 +951,7 @@ endfunc
func Test_insert_small_delete_replace_mode()
new
call setline(1, ['foo', 'bar', 'foobar', 'bar'])
- let @-='foo'
+ let @- = 'foo'
call cursor(2, 1)
exe ":norm! R\<C-R>-\<C-R>-"
call assert_equal('foofoo', getline(2))
@@ -960,9 +962,21 @@ func Test_insert_small_delete_replace_mode()
exe ":norm! R\<C-R>-ZZZZ"
call assert_equal(['foo', 'foofoo', '', 'bfoobarZZZZ'], getline(1, 4))
call cursor(1, 1)
- let @-=''
+ let @- = ''
exe ":norm! R\<C-R>-ZZZ"
call assert_equal(['ZZZ', 'foofoo', '', 'bfoobarZZZZ'], getline(1, 4))
+ let @- = 'βbβ'
+ call cursor(4, 1)
+ exe ":norm! R\<C-R>-"
+ call assert_equal(['ZZZ', 'foofoo', '', 'βbβobarZZZZ'], getline(1, 4))
+ let @- = 'bβb'
+ call cursor(4, 1)
+ exe ":norm! R\<C-R>-"
+ call assert_equal(['ZZZ', 'foofoo', '', 'bβbobarZZZZ'], getline(1, 4))
+ let @- = 'βbβ'
+ call cursor(4, 1)
+ exe ":norm! R\<C-R>-"
+ call assert_equal(['ZZZ', 'foofoo', '', 'βbβobarZZZZ'], getline(1, 4))
bwipe!
endfunc
diff --git a/src/testdir/test_remote.vim b/src/testdir/test_remote.vim
new file mode 100644
index 0000000..ae931fd
--- /dev/null
+++ b/src/testdir/test_remote.vim
@@ -0,0 +1,79 @@
+" Test for the --remote functionality
+
+source check.vim
+CheckFeature clientserver
+CheckFeature terminal
+
+source shared.vim
+source screendump.vim
+source mouse.vim
+source term_util.vim
+
+let s:remote_works = 0
+let s:skip = 'Skipped: --remote feature is not possible'
+
+" nees to be run as first test to verify, that vim --servername works
+func Verify_remote_feature_works()
+ CheckRunVimInTerminal
+ enew
+ let buf = RunVimInTerminal('--servername XVIMTEST', {'rows': 8})
+ call TermWait(buf)
+ let cmd = GetVimCommandCleanTerm() .. '--serverlist'
+ call term_sendkeys(buf, ":r! " .. cmd .. "\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":w! XVimRemoteTest.txt\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":q\<CR>")
+ call StopVimInTerminal(buf)
+ bw!
+ let result = readfile('XVimRemoteTest.txt')
+ call delete('XVimRemoteTest.txt')
+ if empty(result)
+ throw s:skip
+ endif
+ let s:remote = 1
+endfunc
+
+call Verify_remote_feature_works()
+
+if !s:remote
+ finish
+endif
+
+func Test_remote_servername()
+ CheckRunVimInTerminal
+
+ " That is the file we want the server to open,
+ " despite the wildignore setting
+ call writefile(range(1, 20), 'XTEST.txt', 'D')
+ " just a dummy file, so that the ':wq' further down is successful
+ call writefile(range(1, 20), 'Xdummy.log', 'D')
+
+ " Run Vim in a terminal and open a terminal window to run Vim in.
+ let lines =<< trim END
+ set wildignore=*.txt
+ END
+ call writefile(lines, 'XRemoteEditing.vim', 'D')
+ let buf = RunVimInTerminal('--servername XVIMTEST -S XRemoteEditing.vim Xdummy.log', {'rows': 8})
+ call TermWait(buf)
+ botright new
+ " wildignore setting should be ignored and the XVIMTEST server should now
+ " open XTEST.txt, if wildignore setting is not ignored, the server
+ " will continue with the Xdummy.log file
+ let buf2 = RunVimInTerminal('--servername XVIMTEST --remote-silent XTEST.txt', {'rows': 5, 'wait_for_ruler': 0})
+ " job should be no-longer running, so we can just close it
+ exe buf2 .. 'bw!'
+ call term_sendkeys(buf, ":sil :3,$d\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":wq!\<CR>")
+ call TermWait(buf)
+ if term_getstatus(buf) == 'running'
+ call StopVimInTerminal(buf)
+ endif
+ let buf_contents = readfile('XTEST.txt')
+ call assert_equal(2, len(buf_contents))
+ bw!
+ close
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_ruby.vim b/src/testdir/test_ruby.vim
index 2e0835c..f155168 100644
--- a/src/testdir/test_ruby.vim
+++ b/src/testdir/test_ruby.vim
@@ -11,10 +11,25 @@ func Test_ruby_change_buffer()
endfunc
func Test_rubydo()
- " Check deleting lines does not trigger ml_get error.
new
+
+ " Check deleting lines does not trigger ml_get error.
call setline(1, ['one', 'two', 'three'])
rubydo Vim.command("%d_")
+ call assert_equal(['one'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ rubydo Vim.command("1,2d_")
+ call assert_equal(['one'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ rubydo Vim.command("2,3d_"); $_ = "REPLACED"
+ call assert_equal(['REPLACED'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ 2,3rubydo Vim.command("1,2d_"); $_ = "REPLACED"
+ call assert_equal(['three'], getline(1, '$'))
+
bwipe!
" Check switching to another buffer does not trigger ml_get error.
diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim
index f41f0e2..3467760 100644
--- a/src/testdir/test_scroll_opt.vim
+++ b/src/testdir/test_scroll_opt.vim
@@ -960,4 +960,42 @@ func Test_smoothscroll_insert_bottom()
call StopVimInTerminal(buf)
endfunc
+func Test_smoothscroll_in_zero_width_window()
+ set cpo+=n number smoothscroll
+ set winwidth=99999 winminwidth=0
+
+ vsplit
+ call assert_equal(0, winwidth(winnr('#')))
+ call win_execute(win_getid(winnr('#')), "norm! \<C-Y>")
+
+ only!
+ set winwidth& winminwidth&
+ set cpo-=n nonumber nosmoothscroll
+endfunc
+
+func Test_smoothscroll_textoff_small_winwidth()
+ set smoothscroll number
+ call setline(1, 'llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch')
+ vsplit
+
+ let textoff = getwininfo(win_getid())[0].textoff
+ execute 'vertical resize' textoff + 1
+ redraw
+ call assert_equal(0, winsaveview().skipcol)
+ execute "normal! 0\<C-E>"
+ redraw
+ call assert_equal(1, winsaveview().skipcol)
+ execute 'vertical resize' textoff - 1
+ " This caused a signed integer overflow.
+ redraw
+ call assert_equal(1, winsaveview().skipcol)
+ execute 'vertical resize' textoff
+ " This caused an infinite loop.
+ redraw
+ call assert_equal(1, winsaveview().skipcol)
+
+ %bw!
+ set smoothscroll& number&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim
index 1a81318..7c70391 100644
--- a/src/testdir/test_startup.vim
+++ b/src/testdir/test_startup.vim
@@ -518,18 +518,24 @@ func Test_geometry()
call writefile([&columns, &lines, getwinposx(), getwinposy(), string(getwinpos())], "Xtest_geometry")
qall
[CODE]
+ " Hide menu because gtk insists to make the window wide enough to show it completely
" Some window managers have a bar at the top that pushes windows down,
" need to use at least 130, let's do 150
- if RunVim([], after, '-f -g -geometry 31x13+41+150')
+ if RunVim(['set guioptions-=m'], after, '-f -g -geometry 31x13+41+150')
let lines = readfile('Xtest_geometry')
" Depending on the GUI library and the windowing system the final size
" might be a bit different, allow for some tolerance. Tuned based on
" actual failures.
call assert_inrange(31, 35, str2nr(lines[0]))
- call assert_equal('13', lines[1])
- call assert_equal('41', lines[2])
- call assert_equal('150', lines[3])
- call assert_equal('[41, 150]', lines[4])
+ " for some reason, the window may contain fewer lines than requested
+ " for GTK, so allow some tolerance
+ call assert_inrange(8, 13, str2nr(lines[1]))
+ " on Wayland there is no way to set or retrieve window positions
+ if empty($WAYLAND_DISPLAY)
+ call assert_equal('41', lines[2])
+ call assert_equal('150', lines[3])
+ call assert_equal('[41, 150]', lines[4])
+ endif
endif
endif
diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim
index 906fefc..a531f19 100644
--- a/src/testdir/test_tabpage.vim
+++ b/src/testdir/test_tabpage.vim
@@ -156,14 +156,85 @@ func Test_tabpage_drop()
tab split f3
normal! gt
call assert_equal(1, tabpagenr())
+ tab drop f4
+ call assert_equal(1, tabpagenr('#'))
tab drop f3
- call assert_equal(3, tabpagenr())
- call assert_equal(1, tabpagenr('#'))
+ call assert_equal(4, tabpagenr())
+ call assert_equal(2, tabpagenr('#'))
+ bwipe!
bwipe!
bwipe!
bwipe!
call assert_equal(1, tabpagenr('$'))
+
+ call assert_equal(1, winnr('$'))
+ call assert_equal('', bufname(''))
+ call writefile(['L1', 'L2'], 'Xdropfile', 'D')
+
+ " Test for ':tab drop single-file': reuse current buffer
+ let expected_nr = bufnr()
+ tab drop Xdropfile
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ bwipe!
+
+ " Test for ':tab drop single-file': not reuse modified buffer
+ set modified
+ let expected_nr = bufnr() + 1
+ tab drop Xdropfile
+ call assert_equal(2, tabpagenr())
+ call assert_equal(2, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ bwipe!
+
+ " Test for ':tab drop single-file': multiple tabs already exist
+ tab split f2
+ tab split f3
+ let expected_nr = bufnr() + 1
+ tab drop Xdropfile
+ call assert_equal(4, tabpagenr())
+ call assert_equal(4, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
+
+ " Test for ':tab drop multi-files': reuse current buffer
+ let expected_nr = bufnr()
+ tab drop Xdropfile f1 f2 f3
+ call assert_equal(1, tabpagenr())
+ call assert_equal(4, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
+
+ " Test for ':tab drop multi-files': not reuse modified buffer
+ set modified
+ let expected_nr = bufnr() + 1
+ tab drop Xdropfile f1 f2 f3
+ call assert_equal(2, tabpagenr())
+ call assert_equal(5, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
+
+ " Test for ':tab drop multi-files': multiple tabs already exist
+ tab split f2
+ tab split f3
+ let expected_nr = bufnr() + 1
+ tab drop a b c
+ call assert_equal(4, tabpagenr())
+ call assert_equal(6, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ let expected_nr = bufnr() + 3
+ tab drop Xdropfile f1 f2 f3
+ call assert_equal(5, tabpagenr())
+ call assert_equal(8, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
endfunc
" Test autocommands
@@ -260,14 +331,14 @@ function Test_tabpage_with_autocmd_tab_drop()
let s:li = []
tab drop test1
- call assert_equal(['BufLeave', 'BufEnter'], s:li)
+ call assert_equal(['BufEnter'], s:li)
let s:li = []
tab drop test2 test3
call assert_equal([
\ 'TabLeave', 'TabEnter', 'TabLeave', 'TabEnter',
\ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter',
- \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter'], s:li)
+ \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter', 'BufEnter'], s:li)
autocmd! TestTabpageGroup
augroup! TestTabpageGroup
@@ -922,4 +993,21 @@ func Test_tabpage_drop_tabmove()
bwipe!
endfunc
+" Test that settabvar() shouldn't change the last accessed tabpage.
+func Test_lastused_tabpage_settabvar()
+ tabonly!
+ tabnew
+ tabnew
+ tabnew
+ call assert_equal(3, tabpagenr('#'))
+
+ call settabvar(2, 'myvar', 'tabval')
+ call assert_equal('tabval', gettabvar(2, 'myvar'))
+ call assert_equal(3, tabpagenr('#'))
+
+ bwipe!
+ bwipe!
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim
index 8b85bd6..2abf1f6 100644
--- a/src/testdir/test_tagjump.vim
+++ b/src/testdir/test_tagjump.vim
@@ -900,18 +900,33 @@ func Test_tag_stack()
endfor
call writefile(l, 'Xfoo', 'D')
- " Jump to a tag when the tag stack is full. Oldest entry should be removed.
enew
+ " Jump to a tag when the tag stack is full. Oldest entry should be removed.
for i in range(10, 30)
exe "tag var" .. i
endfor
- let l = gettagstack()
- call assert_equal(20, l.length)
- call assert_equal('var11', l.items[0].tagname)
+ let t = gettagstack()
+ call assert_equal(20, t.length)
+ call assert_equal('var11', t.items[0].tagname)
+ let full = deepcopy(t.items)
+ tag var31
+ let t = gettagstack()
+ call assert_equal('var12', t.items[0].tagname)
+ call assert_equal('var31', t.items[19].tagname)
+
+ " Jump to a tag when the tag stack is full, but with user data this time.
+ call foreach(full, {i, item -> extend(item, {'user_data': $'udata{i}'})})
+ call settagstack(0, {'items': full})
+ let t = gettagstack()
+ call assert_equal(20, t.length)
+ call assert_equal('var11', t.items[0].tagname)
+ call assert_equal('udata0', t.items[0].user_data)
tag var31
- let l = gettagstack()
- call assert_equal('var12', l.items[0].tagname)
- call assert_equal('var31', l.items[19].tagname)
+ let t = gettagstack()
+ call assert_equal('var12', t.items[0].tagname)
+ call assert_equal('udata1', t.items[0].user_data)
+ call assert_equal('var31', t.items[19].tagname)
+ call assert_false(has_key(t.items[19], 'user_data'))
" Use tnext with a single match
call assert_fails('tnext', 'E427:')
diff --git a/src/testdir/test_tcl.vim b/src/testdir/test_tcl.vim
index 4c6537f..68a6d63 100644
--- a/src/testdir/test_tcl.vim
+++ b/src/testdir/test_tcl.vim
@@ -11,10 +11,25 @@ func TclEval(tcl_expr)
endfunc
func Test_tcldo()
- " Check deleting lines does not trigger ml_get error.
new
+
+ " Check deleting lines does not trigger ml_get error.
call setline(1, ['one', 'two', 'three'])
tcldo ::vim::command %d_
+ call assert_equal(['one'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ tcldo ::vim::command 1,2d_
+ call assert_equal(['one'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ tcldo ::vim::command 2,3d_ ; set line REPLACED
+ call assert_equal(['REPLACED'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three'])
+ 2,3tcldo ::vim::command 1,2d_ ; set line REPLACED
+ call assert_equal(['three'], getline(1, '$'))
+
bwipe!
" Check that switching to another buffer does not trigger ml_get error.
diff --git a/src/testdir/test_terminal2.vim b/src/testdir/test_terminal2.vim
index 9798c51..05b228e 100644
--- a/src/testdir/test_terminal2.vim
+++ b/src/testdir/test_terminal2.vim
@@ -535,6 +535,7 @@ func Test_term_getcursor()
endfunc
" Test for term_gettitle()
+" Known to be flaky on Mac-OS X and the GH runners
func Test_term_gettitle()
" term_gettitle() returns an empty string for a non-terminal buffer
" and for a non-existing buffer.
@@ -544,6 +545,13 @@ func Test_term_gettitle()
if !has('title') || empty(&t_ts)
throw "Skipped: can't get/set title"
endif
+ if has('osx') && !empty($CI) && system('uname -m') =~# 'arm64'
+ " This test often fails with the following error message on Github runners
+ " MacOS-14
+ " '^\\[No Name\\] - VIM\\d*$' does not match 'e] - VIM'
+ " Why? Is the terminal that runs Vim too small?
+ throw 'Skipped: FIXME: Running this test on M1 Mac fails on GitHub Actions'
+ endif
let term = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', '-c', 'set title'])
call TermWait(term)
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index 97fea60..a06f733 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -3075,10 +3075,17 @@ func Test_prop_with_text_above_below_empty()
let vt = 'test'
call prop_type_add(vt, {'highlight': 'ToDo'})
for ln in range(1, line('$'))
- call prop_add(ln, 0, {'type': vt, 'text': '---', 'text_align': 'above'})
- call prop_add(ln, 0, {'type': vt, 'text': '+++', 'text_align': 'below'})
+ " use 1 character text to test for off-by-one regressions
+ call prop_add(ln, 0, {'type': vt, 'text': '-', 'text_align': 'above'})
+ call prop_add(ln, 0, {'type': vt, 'text': '+', 'text_align': 'below'})
endfor
normal G
+
+ func AddMore()
+ call prop_add(5, 0, {'type': g:vt, 'text': '!', 'text_align': 'above'})
+ call prop_add(5, 0, {'type': g:vt, 'text': '!', 'text_align': 'above'})
+ call prop_add(5, 0, {'type': g:vt, 'text': '!', 'text_align': 'above'})
+ endfunc
END
call writefile(lines, 'XscriptPropAboveBelowEmpty', 'D')
let buf = RunVimInTerminal('-S XscriptPropAboveBelowEmpty', #{rows: 16, cols: 60})
@@ -3100,6 +3107,12 @@ func Test_prop_with_text_above_below_empty()
call term_sendkeys(buf, "kk")
call VerifyScreenDump(buf, 'Test_prop_above_below_empty_5', {})
+ " This was drawing line number over cmdline and leaking memory.
+ call term_sendkeys(buf, ":call AddMore()\<CR>")
+ call term_sendkeys(buf, "gg")
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_prop_above_below_empty_6', {})
+
call StopVimInTerminal(buf)
endfunc
@@ -4090,6 +4103,46 @@ func Test_text_below_nowrap()
call StopVimInTerminal(buf)
endfunc
+func Test_virtual_text_overlap_with_highlight()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ vim9script
+ setline(1, ['one', 'two', 'three', 'four', 'five'])
+ set number
+
+ prop_type_add('demo_highlight_warning', {highlight: 'WarningMsg'})
+ prop_type_add('demo_virtual_text_error', {highlight: 'Error'})
+
+ prop_add(2, 4, {
+ type: 'demo_highlight_warning',
+ end_col: 4,
+ })
+ prop_add(2, 0, {
+ type: 'demo_virtual_text_error',
+ text: 'syntax error',
+ text_align: 'below',
+ })
+ normal 2j
+
+ prop_add(4, 4, {
+ type: 'demo_highlight_warning',
+ end_lnum: 5,
+ end_col: 1,
+ })
+ prop_add(4, 0, {
+ type: 'demo_virtual_text_error',
+ text: 'other error',
+ text_align: 'right',
+ })
+ END
+ call writefile(lines, 'XVirtualTextOverlapWithHighlight', 'D')
+ let buf = RunVimInTerminal('-S XVirtualTextOverlapWithHighlight', #{rows: 8, cols: 60})
+ call VerifyScreenDump(buf, 'Test_virtual_text_overlap_with_highlight_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_virtual_text_in_popup_highlight()
CheckRunVimInTerminal
@@ -4425,4 +4478,81 @@ func Test_textprop_notype_join()
bwipe!
endfunc
+" This was causing text property corruption.
+func Test_textprop_backspace_fo_aw()
+ new
+ call setline(1, 'foobar')
+ call prop_type_add('test', {'highlight': 'ErrorMsg'})
+ call prop_add(1, 1, {'type': 'test', 'length': 3})
+ set backspace=indent,eol,start
+ setlocal formatoptions+=aw
+ call feedkeys("A \<CR>\<BS>\<Esc>", 'tx')
+ call assert_equal('foobar', getline(1))
+ call assert_equal([
+ \ #{id: 0, col: 1, start: 1, end: 1, type_bufnr: 0,
+ \ type: 'test', length: 3}], prop_list(1))
+
+ bwipe!
+ set backspace&
+ call prop_type_delete('test')
+endfunc
+
+func Test_textprop_with_wincolor()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ call setline(1, 'some text here')
+ call setline(2, 'some much longer text here')
+ call setline(3, 'more text here')
+ call prop_type_add('afterprop', #{highlight: 'Search'})
+ call prop_type_add('belowprop', #{highlight: 'DiffAdd'})
+ call prop_add(3, 0, #{type: 'afterprop', text: 'AFTER',
+ \ text_align: 'after', text_padding_left: 3})
+ call prop_add(1, 0, #{type: 'belowprop', text: 'BELOW',
+ \ text_align: 'below', text_padding_left: 3})
+ set wincolor=DiffChange wrap
+ END
+ call writefile(lines, 'XtextPropWincolor', 'D')
+ let buf = RunVimInTerminal('-S XtextPropWincolor', #{rows: 8, cols: 60})
+
+ call term_sendkeys(buf, ":\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_1', {})
+
+ call term_sendkeys(buf, ":set cursorline\<CR>:\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_2', {})
+
+ call term_sendkeys(buf, ":set nowrap\<CR>:\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_2', {})
+
+ call term_sendkeys(buf, ":set nocursorline\<CR>:\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_1', {})
+
+ call term_sendkeys(buf, ":set cursorline colorcolumn=30\<CR>:\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_3', {})
+
+ call term_sendkeys(buf, ":hi CursorLine ctermbg=Brown\<CR>:\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_4', {})
+
+ call term_sendkeys(buf, ":set cursorcolumn\<CR>:\<CR>")
+ call term_sendkeys(buf, '$')
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_5', {})
+
+ call term_sendkeys(buf, 'j')
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_6', {})
+
+ call term_sendkeys(buf, ":set virtualedit=all\<CR>:\<CR>")
+ call term_sendkeys(buf, 'l')
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_7', {})
+
+ call term_sendkeys(buf, 'k')
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_8', {})
+
+ if has('rightleft')
+ call term_sendkeys(buf, ":set rightleft\<CR>:\<CR>")
+ call VerifyScreenDump(buf, 'Test_prop_wincolor_9', {})
+ endif
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim
index 13c4990..eec0e0b 100644
--- a/src/testdir/test_undo.vim
+++ b/src/testdir/test_undo.vim
@@ -583,7 +583,7 @@ funct Test_undofile()
endif
call assert_equal('', undofile(''))
- " Test undofile() with 'undodir' set to to an existing directory.
+ " Test undofile() with 'undodir' set to an existing directory.
call mkdir('Xundodir')
set undodir=Xundodir
let cwd = getcwd()
diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim
index 57a093c..992329b 100644
--- a/src/testdir/test_user_func.vim
+++ b/src/testdir/test_user_func.vim
@@ -968,4 +968,23 @@ func Test_multidefer_with_exception()
delfunc Foo
endfunc
+func Test_func_curly_brace_invalid_name()
+ func Fail()
+ func Foo{'()'}bar()
+ endfunc
+ endfunc
+
+ call assert_fails('call Fail()', 'E475: Invalid argument: Foo()bar')
+
+ silent! call Fail()
+ call assert_equal([], getcompletion('Foo', 'function'))
+
+ set formatexpr=Fail()
+ normal! gqq
+ call assert_equal([], getcompletion('Foo', 'function'))
+
+ set formatexpr&
+ delfunc Fail
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_utf8_comparisons.vim b/src/testdir/test_utf8_comparisons.vim
index 3431226..2c1972b 100644
--- a/src/testdir/test_utf8_comparisons.vim
+++ b/src/testdir/test_utf8_comparisons.vim
@@ -93,4 +93,39 @@ func Test_gap()
call assert_equal(["ABCD", "", "defg"], getline(1,3))
endfunc
+" test that g~, ~ and gU correctly upper-cases ß
+func Test_uppercase_sharp_ss()
+ new
+ call setline(1, repeat(['ß'], 4))
+
+ call cursor(1, 1)
+ norm! ~
+ call assert_equal('ẞ', getline(line('.')))
+ norm! ~
+ call assert_equal('ß', getline(line('.')))
+
+ call cursor(2, 1)
+ norm! g~l
+ call assert_equal('ẞ', getline(line('.')))
+ norm! g~l
+ call assert_equal('ß', getline(line('.')))
+
+ call cursor(3, 1)
+ norm! gUl
+ call assert_equal('ẞ', getline(line('.')))
+ norm! vgU
+ call assert_equal('ẞ', getline(line('.')))
+ norm! vgu
+ call assert_equal('ß', getline(line('.')))
+ norm! gul
+ call assert_equal('ß', getline(line('.')))
+
+ call cursor(4, 1)
+ norm! vgU
+ call assert_equal('ẞ', getline(line('.')))
+ norm! vgu
+ call assert_equal('ß', getline(line('.')))
+ bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index aef09c5..4414f55 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -3484,4 +3484,101 @@ def Test_assign_type_to_list_dict()
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value')
enddef
+" Test for modifying a final variable using a compound operator
+def Test_final_var_modification_with_compound_op()
+ var lines =<< trim END
+ vim9script
+
+ final i: number = 1000
+ assert_fails('i += 2', 'E46: Cannot change read-only variable "i"')
+ assert_fails('i -= 2', 'E46: Cannot change read-only variable "i"')
+ assert_fails('i *= 2', 'E46: Cannot change read-only variable "i"')
+ assert_fails('i /= 2', 'E46: Cannot change read-only variable "i"')
+ assert_fails('i %= 2', 'E46: Cannot change read-only variable "i"')
+ assert_equal(1000, i)
+
+ final f: float = 1000.0
+ assert_fails('f += 2', 'E46: Cannot change read-only variable "f"')
+ assert_fails('f -= 2', 'E46: Cannot change read-only variable "f"')
+ assert_fails('f *= 2', 'E46: Cannot change read-only variable "f"')
+ assert_fails('f /= 2', 'E46: Cannot change read-only variable "f"')
+ assert_equal(1000.0, f)
+
+ final s: string = 'abc'
+ assert_fails('s ..= "y"', 'E46: Cannot change read-only variable "s"')
+ assert_equal('abc', s)
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
+" Test for modifying a final variable with a List value
+def Test_final_var_with_list_value()
+ var lines =<< trim END
+ vim9script
+
+ final listA: list<string> = []
+ var listB = listA
+
+ listB->add('a')
+ assert_true(listA is listB)
+ assert_equal(['a'], listA)
+ assert_equal(['a'], listB)
+
+ listB += ['b']
+ assert_true(listA is listB)
+ assert_equal(['a', 'b'], listA)
+ assert_equal(['a', 'b'], listB)
+
+ listA->add('c')
+ assert_true(listA is listB)
+ assert_equal(['a', 'b', 'c'], listA)
+ assert_equal(['a', 'b', 'c'], listB)
+
+ listA += ['d']
+ assert_true(listA is listB)
+ assert_equal(['a', 'b', 'c', 'd'], listA)
+ assert_equal(['a', 'b', 'c', 'd'], listB)
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
+" Test for modifying a final variable with a List value using "+=" from a legacy
+" function.
+func Test_final_var_with_list_value_legacy()
+ vim9cmd final g:TestVar = ['a']
+ vim9cmd g:TestVar += ['b']
+ call assert_equal(['a', 'b'], g:TestVar)
+endfunc
+
+" Test for modifying a final variable with a Blob value
+def Test_final_var_with_blob_value()
+ var lines =<< trim END
+ vim9script
+
+ final blobA: blob = 0z10
+ var blobB = blobA
+
+ blobB->add(32)
+ assert_true(blobA is blobB)
+ assert_equal(0z1020, blobA)
+ assert_equal(0z1020, blobB)
+
+ blobB += 0z30
+ assert_true(blobA is blobB)
+ assert_equal(0z102030, blobA)
+ assert_equal(0z102030, blobB)
+
+ blobA->add(64)
+ assert_true(blobA is blobB)
+ assert_equal(0z10203040, blobA)
+ assert_equal(0z10203040, blobB)
+
+ blobA += 0z50
+ assert_true(blobA is blobB)
+ assert_equal(0z1020304050, blobA)
+ assert_equal(0z1020304050, blobB)
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 9af0d07..442d375 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -3409,7 +3409,7 @@ def Test_remote_foreground()
CheckFeature clientserver
# remote_foreground() doesn't fail on MS-Windows
CheckNotMSWindows
- CheckEnv DISPLAY
+ CheckX11
v9.CheckDefAndScriptFailure(['remote_foreground(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'])
assert_fails('remote_foreground("NonExistingServer")', 'E241:')
@@ -4101,30 +4101,10 @@ def Test_simplify()
enddef
def Test_slice()
- assert_equal('12345', slice('012345', 1))
- assert_equal('123', slice('012345', 1, 4))
- assert_equal('1234', slice('012345', 1, -1))
- assert_equal('1', slice('012345', 1, -4))
- assert_equal('', slice('012345', 1, -5))
- assert_equal('', slice('012345', 1, -6))
-
- assert_equal([1, 2, 3, 4, 5], slice(range(6), 1))
- assert_equal([1, 2, 3], slice(range(6), 1, 4))
- assert_equal([1, 2, 3, 4], slice(range(6), 1, -1))
- assert_equal([1], slice(range(6), 1, -4))
- assert_equal([], slice(range(6), 1, -5))
- assert_equal([], slice(range(6), 1, -6))
-
var lds: list<dict<string>> = [{key: 'value'}]
assert_equal(['val'], lds->slice(0, 1)->map((_, v) => 'val'))
assert_equal(['val'], lds[ : ]->map((_, v) => 'val'))
- assert_equal(0z1122334455, slice(0z001122334455, 1))
- assert_equal(0z112233, slice(0z001122334455, 1, 4))
- assert_equal(0z11223344, slice(0z001122334455, 1, -1))
- assert_equal(0z11, slice(0z001122334455, 1, -4))
- assert_equal(0z, slice(0z001122334455, 1, -5))
- assert_equal(0z, slice(0z001122334455, 1, -6))
v9.CheckDefAndScriptFailure(['slice({"a": 10}, 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1'])
v9.CheckDefAndScriptFailure(['slice([1, 2, 3], "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2'])
v9.CheckDefAndScriptFailure(['slice("abc", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3'])
@@ -5197,4 +5177,12 @@ def Test_passing_type_to_builtin()
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value')
enddef
+def Test_getregion()
+ assert_equal(['x'], getregion(getpos('.'), getpos('.'))->map((_, _) => 'x'))
+
+ v9.CheckDefAndScriptFailure(['getregion(10, getpos("."))'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1'])
+ assert_equal([''], getregion(getpos('.'), getpos('.')))
+ v9.CheckDefExecFailure(['getregion(getpos("a"), getpos("."))'], 'E1209:')
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index b34d2ad..d6c55bf 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -67,7 +67,23 @@ def Test_class_basic()
END
v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
- # Use old "this." prefixed member variable declaration syntax (without intialization)
+ # Try to define a class with the same name as an existing variable
+ lines =<< trim END
+ vim9script
+ var Something: list<number> = [1]
+ class Thing
+ endclass
+ interface Api
+ endinterface
+ class Something extends Thing implements Api
+ var v1: string = ''
+ def Foo()
+ enddef
+ endclass
+ END
+ v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 7)
+
+ # Use old "this." prefixed member variable declaration syntax (without initialization)
lines =<< trim END
vim9script
class Something
@@ -76,7 +92,7 @@ def Test_class_basic()
END
v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number', 3)
- # Use old "this." prefixed member variable declaration syntax (with intialization)
+ # Use old "this." prefixed member variable declaration syntax (with initialization)
lines =<< trim END
vim9script
class Something
@@ -9659,31 +9675,749 @@ def Test_const_class_object_variable()
v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3)
enddef
-" Test for using double underscore prefix in a class/object method name.
-def Test_method_double_underscore_prefix()
- # class method
+" Test for compiling class/object methods using :defcompile
+def Test_defcompile_class()
+ # defcompile all the classes in the current script
var lines =<< trim END
vim9script
class A
- static def __foo()
- echo "foo"
+ def Foo()
+ var i = 10
+ enddef
+ endclass
+ class B
+ def Bar()
+ var i = 20
+ xxx
enddef
endclass
defcompile
END
- v9.CheckSourceFailure(lines, 'E1034: Cannot use reserved name __foo()', 3)
+ v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2)
- # object method
+ # defcompile a specific class
lines =<< trim END
vim9script
class A
- def __foo()
- echo "foo"
+ def Foo()
+ xxx
+ enddef
+ endclass
+ class B
+ def Bar()
+ yyy
+ enddef
+ endclass
+ defcompile B
+ END
+ v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1)
+
+ # defcompile a non-class
+ lines =<< trim END
+ vim9script
+ class A
+ def Foo()
+ enddef
+ endclass
+ var X: list<number> = []
+ defcompile X
+ END
+ v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7)
+
+ # defcompile a class twice
+ lines =<< trim END
+ vim9script
+ class A
+ def new()
+ enddef
+ endclass
+ defcompile A
+ defcompile A
+ assert_equal('Function A.new does not need compiling', v:statusmsg)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ # defcompile should not compile an imported class
+ lines =<< trim END
+ vim9script
+ export class A
+ def Foo()
+ xxx
enddef
endclass
+ END
+ writefile(lines, 'Xdefcompileimport.vim', 'D')
+ lines =<< trim END
+ vim9script
+
+ import './Xdefcompileimport.vim'
+ class B
+ endclass
defcompile
END
- v9.CheckSourceFailure(lines, 'E1034: Cannot use reserved name __foo()', 3)
+ v9.CheckScriptSuccess(lines)
+enddef
+
+" Test for cases common to all the object builtin methods
+def Test_object_builtin_method()
+ var lines =<< trim END
+ vim9script
+ class A
+ def abc()
+ enddef
+ endclass
+ END
+ v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3)
+
+ for funcname in ["len", "string", "empty"]
+ lines =<< trim eval END
+ vim9script
+ class A
+ static def {funcname}(): number
+ enddef
+ endclass
+ END
+ v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3)
+ endfor
+enddef
+
+" Test for using the empty() builtin method with an object
+" This is a legacy function to use the test_garbagecollect_now() function.
+func Test_object_empty()
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal(true, empty(afoo))
+ assert_equal(true, afoo->empty())
+ enddef
+
+ var a = A.new()
+ assert_equal(1, empty(a))
+ assert_equal(1, a->empty())
+ test_garbagecollect_now()
+ assert_equal(1, empty(a))
+ Foo()
+ test_garbagecollect_now()
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " empty() should return 1 without a builtin method
+ let lines =<< trim END
+ vim9script
+ class A
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal(1, empty(afoo))
+ enddef
+
+ var a = A.new()
+ assert_equal(1, empty(a))
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Unsupported signature for the empty() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty()
+ enddef
+ endclass
+ END
+ call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4)
+
+ " Error when calling the empty() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ throw "Failed to check emptiness"
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ var i = empty(afoo)
+ enddef
+
+ var a = A.new()
+ assert_fails('empty(a)', 'Failed to check emptiness')
+ assert_fails('Foo()', 'Failed to check emptiness')
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call empty() using an object from a script
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ var afoo = A.new()
+ assert_equal(true, afoo.empty())
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call empty() using an object from a method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ def Foo()
+ var afoo = A.new()
+ assert_equal(true, afoo.empty())
+ enddef
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call empty() using "this" from an object method
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ def Foo(): bool
+ return this.empty()
+ enddef
+ endclass
+ def Bar()
+ var abar = A.new()
+ assert_equal(true, abar.Foo())
+ enddef
+ Bar()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Call empty() from a derived object
+ let lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return false
+ enddef
+ endclass
+ class B extends A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ def Foo(afoo: A)
+ assert_equal(true, empty(afoo))
+ var bfoo = B.new()
+ assert_equal(true, empty(bfoo))
+ enddef
+ var b = B.new()
+ assert_equal(1, empty(b))
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Invoking empty method using an interface
+ let lines =<< trim END
+ vim9script
+ interface A
+ def empty(): bool
+ endinterface
+ class B implements A
+ def empty(): bool
+ return false
+ enddef
+ endclass
+ def Foo(a: A)
+ assert_equal(false, empty(a))
+ enddef
+ var b = B.new()
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
+" Test for using the len() builtin method with an object
+" This is a legacy function to use the test_garbagecollect_now() function.
+func Test_object_length()
+ let lines =<< trim END
+ vim9script
+ class A
+ var mylen: number = 0
+ def new(n: number)
+ this.mylen = n
+ enddef
+ def len(): number
+ return this.mylen
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new(12)
+ assert_equal(12, len(afoo))
+ assert_equal(12, afoo->len())
+ enddef
+
+ var a = A.new(22)
+ assert_equal(22, len(a))
+ assert_equal(22, a->len())
+ test_garbagecollect_now()
+ assert_equal(22, len(a))
+ Foo()
+ test_garbagecollect_now()
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " len() should return 0 without a builtin method
+ let lines =<< trim END
+ vim9script
+ class A
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal(0, len(afoo))
+ enddef
+
+ var a = A.new()
+ assert_equal(0, len(a))
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Unsupported signature for the len() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len()
+ enddef
+ endclass
+ END
+ call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4)
+
+ " Error when calling the len() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ throw "Failed to compute length"
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ var i = len(afoo)
+ enddef
+
+ var a = A.new()
+ assert_fails('len(a)', 'Failed to compute length')
+ assert_fails('Foo()', 'Failed to compute length')
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call len() using an object from a script
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 5
+ enddef
+ endclass
+ var afoo = A.new()
+ assert_equal(5, afoo.len())
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call len() using an object from a method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 5
+ enddef
+ endclass
+ def Foo()
+ var afoo = A.new()
+ assert_equal(5, afoo.len())
+ enddef
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call len() using "this" from an object method
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 8
+ enddef
+ def Foo(): number
+ return this.len()
+ enddef
+ endclass
+ def Bar()
+ var abar = A.new()
+ assert_equal(8, abar.Foo())
+ enddef
+ Bar()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Call len() from a derived object
+ let lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 10
+ enddef
+ endclass
+ class B extends A
+ def len(): number
+ return 20
+ enddef
+ endclass
+ def Foo(afoo: A)
+ assert_equal(20, len(afoo))
+ var bfoo = B.new()
+ assert_equal(20, len(bfoo))
+ enddef
+ var b = B.new()
+ assert_equal(20, len(b))
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Invoking len method using an interface
+ let lines =<< trim END
+ vim9script
+ interface A
+ def len(): number
+ endinterface
+ class B implements A
+ def len(): number
+ return 123
+ enddef
+ endclass
+ def Foo(a: A)
+ assert_equal(123, len(a))
+ enddef
+ var b = B.new()
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
+" Test for using the string() builtin method with an object
+" This is a legacy function to use the test_garbagecollect_now() function.
+func Test_object_string()
+ let lines =<< trim END
+ vim9script
+ class A
+ var name: string
+ def string(): string
+ return this.name
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new("foo-A")
+ assert_equal('foo-A', string(afoo))
+ assert_equal('foo-A', afoo->string())
+ enddef
+
+ var a = A.new("script-A")
+ assert_equal('script-A', string(a))
+ assert_equal('script-A', a->string())
+ assert_equal(['script-A'], execute('echo a')->split("\n"))
+ test_garbagecollect_now()
+ assert_equal('script-A', string(a))
+ Foo()
+ test_garbagecollect_now()
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " string() should return "object of A {}" without a builtin method
+ let lines =<< trim END
+ vim9script
+ class A
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ assert_equal('object of A {}', string(afoo))
+ enddef
+
+ var a = A.new()
+ assert_equal('object of A {}', string(a))
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Unsupported signature for the string() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string()
+ enddef
+ endclass
+ END
+ call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4)
+
+ " Error when calling the string() method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ throw "Failed to get text"
+ enddef
+ endclass
+
+ def Foo()
+ var afoo = A.new()
+ var i = string(afoo)
+ enddef
+
+ var a = A.new()
+ assert_fails('string(a)', 'Failed to get text')
+ assert_fails('Foo()', 'Failed to get text')
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call string() using an object from a script
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ var afoo = A.new()
+ assert_equal('A', afoo.string())
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call string() using an object from a method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ def Foo()
+ var afoo = A.new()
+ assert_equal('A', afoo.string())
+ enddef
+ Foo()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " call string() using "this" from an object method
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ def Foo(): string
+ return this.string()
+ enddef
+ endclass
+ def Bar()
+ var abar = A.new()
+ assert_equal('A', abar.string())
+ enddef
+ Bar()
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Call string() from a derived object
+ let lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ class B extends A
+ def string(): string
+ return 'B'
+ enddef
+ endclass
+ def Foo(afoo: A)
+ assert_equal('B', string(afoo))
+ var bfoo = B.new()
+ assert_equal('B', string(bfoo))
+ enddef
+ var b = B.new()
+ assert_equal('B', string(b))
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+
+ " Invoking string method using an interface
+ let lines =<< trim END
+ vim9script
+ interface A
+ def string(): string
+ endinterface
+ class B implements A
+ def string(): string
+ return 'B'
+ enddef
+ endclass
+ def Foo(a: A)
+ assert_equal('B', string(a))
+ enddef
+ var b = B.new()
+ Foo(b)
+ END
+ call v9.CheckSourceSuccess(lines)
+endfunc
+
+" Test for using a class in the class definition
+def Test_Ref_Class_Within_Same_Class()
+ var lines =<< trim END
+ vim9script
+ class A
+ var n: number = 0
+ def Equals(other: A): bool
+ return this.n == other.n
+ enddef
+ endclass
+
+ var a1 = A.new(10)
+ var a2 = A.new(10)
+ var a3 = A.new(20)
+ assert_equal(true, a1.Equals(a2))
+ assert_equal(false, a2.Equals(a3))
+ END
+ v9.CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+
+ class Foo
+ var num: number
+ def Clone(): Foo
+ return Foo.new(this.num)
+ enddef
+ endclass
+
+ var f1 = Foo.new(1)
+
+ def F()
+ var f2: Foo = f1.Clone()
+ assert_equal(false, f2 is f1)
+ assert_equal(true, f2.num == f1.num)
+ enddef
+ F()
+
+ var f3: Foo = f1.Clone()
+ assert_equal(false, f3 is f1)
+ assert_equal(true, f3.num == f1.num)
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # Test for trying to use a class to extend when defining the same class
+ lines =<< trim END
+ vim9script
+ class A extends A
+ endclass
+ END
+ v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3)
+
+ # Test for trying to use a class to implement when defining the same class
+ lines =<< trim END
+ vim9script
+ class A implements A
+ endclass
+ END
+ v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3)
+enddef
+
+" Test for using a compound operator from a lambda function in an object method
+def Test_compound_op_in_objmethod_lambda()
+ # Test using the "+=" operator
+ var lines =<< trim END
+ vim9script
+ class A
+ var n: number = 10
+ def Foo()
+ var Fn = () => {
+ this.n += 1
+ }
+ Fn()
+ enddef
+ endclass
+
+ var a = A.new()
+ a.Foo()
+ assert_equal(11, a.n)
+ END
+ v9.CheckScriptSuccess(lines)
+
+ # Test using the "..=" operator
+ lines =<< trim END
+ vim9script
+ class A
+ var s: string = "a"
+ def Foo()
+ var Fn = () => {
+ this.s ..= "a"
+ }
+ Fn()
+ enddef
+ endclass
+
+ var a = A.new()
+ a.Foo()
+ a.Foo()
+ assert_equal("aaa", a.s)
+ END
+ v9.CheckScriptSuccess(lines)
+enddef
+
+" call a lambda function in one object from another object
+def Test_lambda_invocation_across_classes()
+ var lines =<< trim END
+ vim9script
+ class A
+ var s: string = "foo"
+ def GetFn(): func
+ var Fn = (): string => {
+ return this.s
+ }
+ return Fn
+ enddef
+ endclass
+
+ class B
+ var s: string = "bar"
+ def GetFn(): func
+ var a = A.new()
+ return a.GetFn()
+ enddef
+ endclass
+
+ var b = B.new()
+ var Fn = b.GetFn()
+ assert_equal("foo", Fn())
+ END
+ v9.CheckScriptSuccess(lines)
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 1a192cc..1daef22 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -3273,4 +3273,199 @@ def Test_funcref_with_class()
unlet g:instr
enddef
+" Disassemble instructions for calls to a string() function in an object
+def Test_disassemble_object_string()
+ var lines =<< trim END
+ vim9script
+ class A
+ def string(): string
+ return 'A'
+ enddef
+ endclass
+ def Bar()
+ var a = A.new()
+ var s = string(a)
+ s = string(A)
+ enddef
+ g:instr = execute('disassemble Bar')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<SNR>\d*_Bar\_s*' ..
+ 'var a = A.new()\_s*' ..
+ '0 DCALL new(argc 0)\_s*' ..
+ '1 STORE $0\_s*' ..
+ 'var s = string(a)\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 METHODCALL A.string(argc 0)\_s*' ..
+ '4 STORE $1\_s*' ..
+ 's = string(A)\_s*' ..
+ '5 LOADSCRIPT A-0 from .*\_s*' ..
+ '6 BCALL string(argc 1)\_s*' ..
+ '7 STORE $1\_s*' ..
+ '8 RETURN void', g:instr)
+ unlet g:instr
+
+ # Use the default string() function for a class
+ lines =<< trim END
+ vim9script
+ class A
+ endclass
+ def Bar()
+ var a = A.new()
+ var s = string(a)
+ s = string(A)
+ enddef
+ g:instr = execute('disassemble Bar')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<SNR>\d*_Bar\_s*' ..
+ 'var a = A.new()\_s*' ..
+ '0 DCALL new(argc 0)\_s*' ..
+ '1 STORE $0\_s*' ..
+ 'var s = string(a)\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 BCALL string(argc 1)\_s*' ..
+ '4 STORE $1\_s*' ..
+ 's = string(A)\_s*' ..
+ '5 LOADSCRIPT A-0 from .*\_s*' ..
+ '6 BCALL string(argc 1)\_s*' ..
+ '7 STORE $1\_s*' ..
+ '8 RETURN void', g:instr)
+ unlet g:instr
+enddef
+
+" Disassemble instructions for calls to a empty() function in an object
+def Test_disassemble_object_empty()
+ var lines =<< trim END
+ vim9script
+ class A
+ def empty(): bool
+ return true
+ enddef
+ endclass
+ def Bar()
+ var a = A.new()
+ var s = empty(a)
+ enddef
+ g:instr = execute('disassemble Bar')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<SNR>\d*_Bar\_s*' ..
+ 'var a = A.new()\_s*' ..
+ '0 DCALL new(argc 0)\_s*' ..
+ '1 STORE $0\_s*' ..
+ 'var s = empty(a)\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 METHODCALL A.empty(argc 0)\_s*' ..
+ '4 STORE $1\_s*' ..
+ '5 RETURN void', g:instr)
+ unlet g:instr
+
+ # Use the default empty() function for a class
+ lines =<< trim END
+ vim9script
+ class A
+ endclass
+ def Bar()
+ var a = A.new()
+ var s = empty(a)
+ enddef
+ g:instr = execute('disassemble Bar')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<SNR>\d*_Bar\_s*' ..
+ 'var a = A.new()\_s*' ..
+ '0 DCALL new(argc 0)\_s*' ..
+ '1 STORE $0\_s*' ..
+ 'var s = empty(a)\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 BCALL empty(argc 1)\_s*' ..
+ '4 STORE $1\_s*' ..
+ '5 RETURN void', g:instr)
+ unlet g:instr
+enddef
+
+" Disassemble instructions for calls to a len() function in an object
+def Test_disassemble_object_len()
+ var lines =<< trim END
+ vim9script
+ class A
+ def len(): number
+ return 10
+ enddef
+ endclass
+ def Bar()
+ var a = A.new()
+ var s = len(a)
+ enddef
+ g:instr = execute('disassemble Bar')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<SNR>\d*_Bar\_s*' ..
+ 'var a = A.new()\_s*' ..
+ '0 DCALL new(argc 0)\_s*' ..
+ '1 STORE $0\_s*' ..
+ 'var s = len(a)\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 METHODCALL A.len(argc 0)\_s*' ..
+ '4 STORE $1\_s*' ..
+ '5 RETURN void', g:instr)
+ unlet g:instr
+
+ # Use the default len() function for a class
+ lines =<< trim END
+ vim9script
+ class A
+ endclass
+ def Bar()
+ var a = A.new()
+ var s = len(a)
+ enddef
+ g:instr = execute('disassemble Bar')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<SNR>\d*_Bar\_s*' ..
+ 'var a = A.new()\_s*' ..
+ '0 DCALL new(argc 0)\_s*' ..
+ '1 STORE $0\_s*' ..
+ 'var s = len(a)\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 BCALL len(argc 1)\_s*' ..
+ '4 STORE $1\_s*' ..
+ '5 RETURN void', g:instr)
+ unlet g:instr
+enddef
+
+" Disassemble instructions for using a compound operator in a closure
+def Test_disassemble_compound_op_in_closure()
+ var lines =<< trim END
+ vim9script
+ class A
+ var foo: number = 1
+ def Foo(): func
+ var Fn = () => {
+ this.foo += 1
+ }
+ return Fn
+ enddef
+ endclass
+ var a = A.new()
+ var Lambda = a.Foo()
+ var num = matchstr(string(Lambda), '\d\+')
+ g:instr = execute($'disassemble <lambda>{num}')
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_match('<lambda>\d\+\_s*' ..
+ 'this.foo += 1\_s*' ..
+ '0 LOADOUTER level 0 $0\_s*' ..
+ '1 OBJ_MEMBER 0\_s*' ..
+ '2 PUSHNR 1\_s*' ..
+ '3 OPNR +\_s*' ..
+ '4 PUSHNR 0\_s*' ..
+ '5 LOADOUTER level 0 $0\_s*' ..
+ '6 STOREINDEX object\_s*' ..
+ '7 RETURN void', g:instr)
+ unlet g:instr
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index 6285ba1..7764b37 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -311,6 +311,33 @@ def Test_expr2()
assert_equal([1], g:vals)
END
v9.CheckDefAndScriptSuccess(lines)
+
+ # test the short-circuit operation
+ lines =<< trim END
+ assert_equal(true, true && true)
+ assert_equal(false, true && !true)
+ assert_equal(false, !true && true)
+ assert_equal(false, !true && !true)
+
+ assert_equal(true, true || true)
+ assert_equal(true, true || !true)
+ assert_equal(true, !true || true)
+ assert_equal(false, !true || !true)
+
+ assert_equal(false, false && false)
+ assert_equal(false, false && !false)
+ assert_equal(false, !false && false)
+ assert_equal(true, !false && !false)
+
+ assert_equal(false, false || false)
+ assert_equal(true, false || !false)
+ assert_equal(true, !false || false)
+ assert_equal(true, !false || !false)
+
+ assert_equal(false, !true && !true && !true)
+ assert_equal(true, !false || !false || !false)
+ END
+ v9.CheckDefAndScriptSuccess(lines)
enddef
def Test_expr2_vimscript()
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index d470a34..fa1aeb1 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -2929,5 +2929,54 @@ def Test_export_in_conditional_block()
v9.CheckScriptSuccess(lines)
enddef
+" Import fails when an autoloaded script is imported again.
+" Github issue #14171
+def Test_import_autloaded_script()
+ mkdir('Ximporttwice', 'pR')
+ mkdir('Ximporttwice/plugin')
+ mkdir('Ximporttwice/autoload')
+ var save_rtp = &rtp
+ exe 'set rtp^=' .. getcwd() .. '/Ximporttwice'
+
+ var lines =<< trim END
+ vim9script
+
+ export def H(): number
+ return 10
+ enddef
+ END
+ writefile(lines, 'Ximporttwice/autoload/hello.vim')
+
+ lines =<< trim END
+ vim9script
+
+ import "./hello.vim"
+ export def W(): number
+ return 20
+ enddef
+ END
+ writefile(lines, 'Ximporttwice/autoload/world.vim')
+
+ lines =<< trim END
+ vim9script
+
+ import autoload '../autoload/hello.vim'
+ import autoload '../autoload/world.vim'
+
+ command Hello echo hello.H()
+ command World echo world.W()
+ END
+ writefile(lines, 'Ximporttwice/plugin/main.vim')
+
+ lines =<< trim END
+ vim9script
+
+ source ./Ximporttwice/plugin/main.vim
+ assert_equal(['20'], execute('World')->split("\n"))
+ END
+ v9.CheckScriptSuccess(lines)
+
+ &rtp = save_rtp
+enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 7ae4d55..77b8831 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -4906,6 +4906,31 @@ def Test_for_stmt_space_before_type()
v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: :number in range(10)', 2)
enddef
+" This test used to cause an use-after-free memory access
+def Test_for_empty_line_after_lambda()
+ var lines =<< trim END
+ vim9script
+ echomsg range(0, 2)->map((_, v) => {
+ return 1
+ })
+
+ assert_equal('[1, 1, 1]', v:statusmsg)
+ END
+ v9.CheckSourceSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ echomsg range(0, 1)->map((_, v) => {
+ return 1
+ }) range(0, 1)->map((_, v) => {
+ return 2
+ }) # comment
+
+ assert_equal('[1, 1] [2, 2]', v:statusmsg)
+ END
+ v9.CheckSourceSuccess(lines)
+enddef
+
" Keep this last, it messes up highlighting.
def Test_substitute_cmd()
new
diff --git a/src/testdir/test_vim9_typealias.vim b/src/testdir/test_vim9_typealias.vim
index 4155744..998079c 100644
--- a/src/testdir/test_vim9_typealias.vim
+++ b/src/testdir/test_vim9_typealias.vim
@@ -641,7 +641,7 @@ def Test_type_as_func_argument_or_return_value()
END
v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
- # check defered function using typealias as arg
+ # check deferred function using typealias as arg
lines =<< trim END
vim9script
type A = number
@@ -764,7 +764,7 @@ def Test_class_as_func_argument_or_return_value()
END
v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value', 1)
- # check defered function using class typealias as arg
+ # check deferred function using class typealias as arg
lines =<< trim END
vim9script
class C
diff --git a/src/testdir/test_virtualedit.vim b/src/testdir/test_virtualedit.vim
index ec2b276..48d4aa0 100644
--- a/src/testdir/test_virtualedit.vim
+++ b/src/testdir/test_virtualedit.vim
@@ -77,13 +77,30 @@ endfunc
func Test_edit_change()
new
set virtualedit=all
+
call setline(1, "\t⒌")
normal Cx
call assert_equal('x', getline(1))
+
+ call setline(1, "\ta̳")
+ normal Cx
+ call assert_equal('x', getline(1))
+
+ call setline(1, "\tβ̳")
+ normal Cx
+ call assert_equal('x', getline(1))
+
+ if has('arabic')
+ call setline(1, "\tلا")
+ normal Cx
+ call assert_equal('x', getline(1))
+ endif
+
" Do a visual block change
call setline(1, ['a', 'b', 'c'])
exe "normal gg3l\<C-V>2jcx"
call assert_equal(['a x', 'b x', 'c x'], getline(1, '$'))
+
bwipe!
set virtualedit=
endfunc
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index 401a350..fd174a9 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -3,6 +3,7 @@
source shared.vim
source check.vim
source screendump.vim
+import './vim9.vim' as v9
func Test_block_shift_multibyte()
" Uses double-wide character.
@@ -1008,7 +1009,7 @@ endfunc
" Test for changing case
func Test_visual_change_case()
new
- " gUe must uppercase a whole word, also when ß changes to SS
+ " gUe must uppercase a whole word, also when ß changes to ẞ
exe "normal Gothe youtußeuu end\<Esc>Ypk0wgUe\r"
" gUfx must uppercase until x, inclusive.
exe "normal O- youßtußexu -\<Esc>0fogUfx\r"
@@ -1020,9 +1021,9 @@ func Test_visual_change_case()
exe "normal Oblah di\rdoh dut\<Esc>VkUj\r"
" Uppercase part of two lines
exe "normal ddppi333\<Esc>k0i222\<Esc>fyllvjfuUk"
- call assert_equal(['the YOUTUSSEUU end', '- yOUSSTUSSEXu -',
- \ 'THE YOUTUSSEUU END', '111THE YOUTUSSEUU END', 'BLAH DI', 'DOH DUT',
- \ '222the yoUTUSSEUU END', '333THE YOUTUßeuu end'], getline(2, '$'))
+ call assert_equal(['the YOUTUẞEUU end', '- yOUẞTUẞEXu -',
+ \ 'THE YOUTUẞEUU END', '111THE YOUTUẞEUU END', 'BLAH DI', 'DOH DUT',
+ \ '222the yoUTUẞEUU END', '333THE YOUTUßeuu end'], getline(2, '$'))
bwipe!
endfunc
@@ -1622,4 +1623,336 @@ func Test_visual_drag_out_of_window()
bwipe!
endfunc
+func Test_visual_substitute_visual()
+ new
+ call setline(1, ['one', 'two', 'three'])
+ call feedkeys("Gk\<C-V>j$:s/\\%V\\_.*\\%V/foobar\<CR>", 'tx')
+ call assert_equal(['one', 'foobar'], getline(1, '$'))
+ bwipe!
+endfunc
+
+func Test_visual_getregion()
+ let lines =<< trim END
+ new
+
+ call setline(1, ['one', 'two', 'three'])
+
+ #" Visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>vjl", 'tx')
+ call assert_equal(['one', 'tw'],
+ \ 'v'->getpos()->getregion(getpos('.')))
+ call assert_equal(['one', 'tw'],
+ \ '.'->getpos()->getregion(getpos('v')))
+ call assert_equal(['o'],
+ \ 'v'->getpos()->getregion(getpos('v')))
+ call assert_equal(['w'],
+ \ '.'->getpos()->getregion(getpos('.'), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ getpos('.')->getregion(getpos('v'), {'type': 'V' }))
+ call assert_equal(['on', 'tw'],
+ \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
+
+ #" Line visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>Vl", 'tx')
+ call assert_equal(['one'],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ getregion(getpos('.'), getpos('v'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ getregion(getpos('v'), getpos('v'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ getregion(getpos('.'), getpos('.'), {'type': 'V' }))
+ call assert_equal(['on'],
+ \ getpos('.')->getregion(getpos('v'), {'type': 'v' }))
+ call assert_equal(['on'],
+ \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
+
+ #" Block visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>ll", 'tx')
+ call assert_equal(['one'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call assert_equal(['one'],
+ \ getregion(getpos('.'), getpos('v'), {'type': "\<C-v>" }))
+ call assert_equal(['o'],
+ \ getregion(getpos('v'), getpos('v'), {'type': "\<C-v>" }))
+ call assert_equal(['e'],
+ \ getregion(getpos('.'), getpos('.'), {'type': "\<C-v>" }))
+ call assert_equal(['one'],
+ \ '.'->getpos()->getregion(getpos('v'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ '.'->getpos()->getregion(getpos('v'), {'type': 'v' }))
+
+ #" Using Marks
+ call setpos("'a", [0, 2, 3, 0])
+ call cursor(1, 1)
+ call assert_equal(['one', 'two'],
+ \ "'a"->getpos()->getregion(getpos('.'), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ "."->getpos()->getregion(getpos("'a"), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ "."->getpos()->getregion(getpos("'a"), {'type': 'V' }))
+ call assert_equal(['two'],
+ \ "'a"->getpos()->getregion(getpos("'a"), {'type': 'V' }))
+ call assert_equal(['one', 'two'],
+ \ "."->getpos()->getregion(getpos("'a"), {'type': "\<c-v>" }))
+
+ #" Using List
+ call cursor(1, 1)
+ call assert_equal(['one', 'two'],
+ \ [0, 2, 3, 0]->getregion(getpos('.'), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'V' }))
+ call assert_equal(['two'],
+ \ [0, 2, 3, 0]->getregion([0, 2, 3, 0], {'type': 'V' }))
+ call assert_equal(['one', 'two'],
+ \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': "\<c-v>" }))
+
+ #" Multiline with line visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>Vjj", 'tx')
+ call assert_equal(['one', 'two', 'three'],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'V' }))
+
+ #" Multiline with block visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>jj", 'tx')
+ call assert_equal(['o', 't', 't'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>jj$", 'tx')
+ call assert_equal(['one', 'two', 'three'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+ #" 'virtualedit'
+ set virtualedit=all
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>10ljj$", 'tx')
+ call assert_equal(['one ', 'two ', 'three '],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ set virtualedit&
+
+ #" using wrong types for positions
+ call cursor(1, 1)
+ call feedkeys("\<ESC>vjj$", 'tx')
+ call assert_fails("call getregion(1, 2)", 'E1211:')
+ call assert_fails("call getregion(getpos('.'), {})", 'E1211:')
+ call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:')
+
+ #" using invalid value for "type"
+ call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '' })", 'E475:')
+
+ #" using a mark from another buffer to current buffer
+ new
+ LET g:buf = bufnr()
+ call setline(1, range(10))
+ normal! GmA
+ wincmd p
+ call assert_equal([g:buf, 10, 1, 0], getpos("'A"))
+ call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' }))
+ call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' }))
+
+ #" using two marks from another buffer
+ wincmd p
+ normal! GmB
+ wincmd p
+ call assert_equal([g:buf, 10, 1, 0], getpos("'B"))
+ call assert_equal(['9'], getregion(getpos("'B"), getpos("'A"), {'type': 'v' }))
+
+ #" using two positions from another buffer
+ for type in ['v', 'V', "\<C-V>"]
+ for exclusive in [v:false, v:true]
+ call assert_equal(range(10)->mapnew('string(v:val)'),
+ \ getregion([g:buf, 1, 1, 0], [g:buf, 10, 2, 0],
+ \ {'type': type, 'exclusive': exclusive }))
+ call assert_equal(range(10)->mapnew('string(v:val)'),
+ \ getregion([g:buf, 10, 2, 0], [g:buf, 1, 1, 0],
+ \ {'type': type, 'exclusive': exclusive }))
+ endfor
+ endfor
+
+ #" using invalid positions in buffer
+ call assert_fails('call getregion([g:buf, 0, 1, 0], [g:buf, 10, 2, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 10, 2, 0], [g:buf, 0, 1, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 11, 2, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 11, 2, 0], [g:buf, 1, 1, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 0, 0])', 'E964:')
+ call assert_fails('call getregion([g:buf, 10, 0, 0], [g:buf, 1, 1, 0])', 'E964:')
+ call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 3, 0])', 'E964:')
+ call assert_fails('call getregion([g:buf, 10, 3, 0], [g:buf, 1, 1, 0])', 'E964:')
+
+ #" using invalid buffer
+ call assert_fails('call getregion([10000, 10, 1, 0], [10000, 10, 1, 0])', 'E681:')
+
+ exe $':{g:buf}bwipe!'
+ unlet g:buf
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+
+ bwipe!
+
+ let lines =<< trim END
+ #" Selection in starts or ends in the middle of a multibyte character
+ new
+ call setline(1, [
+ \ "abcdefghijk\u00ab",
+ \ "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9",
+ \ "1234567890"
+ \ ])
+ call cursor(1, 3)
+ call feedkeys("\<Esc>\<C-v>ljj", 'xt')
+ call assert_equal(['cd', "\u00ab ", '34'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 4)
+ call feedkeys("\<Esc>\<C-v>ljj", 'xt')
+ call assert_equal(['de', "\U0001f1e7", '45'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 5)
+ call feedkeys("\<Esc>\<C-v>jj", 'xt')
+ call assert_equal(['e', ' ', '5'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>vj", 'xt')
+ call assert_equal(['abcdefghijk«', "\U0001f1e6"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+
+ #" marks on multibyte chars
+ :set selection=exclusive
+ call setpos("'a", [0, 1, 11, 0])
+ call setpos("'b", [0, 2, 16, 0])
+ call setpos("'c", [0, 2, 0, 0])
+ call cursor(1, 1)
+ call assert_equal(['ghijk', '🇨«🇩'],
+ \ getregion(getpos("'a"), getpos("'b"), {'type': "\<c-v>" }))
+ call assert_equal(['k«', '🇦«🇧«🇨'],
+ \ getregion(getpos("'a"), getpos("'b"), {'type': 'v' }))
+ call assert_equal(['k«'],
+ \ getregion(getpos("'a"), getpos("'c"), {'type': 'v' }))
+
+ #" use inclusive selection, although 'selection' is exclusive
+ call setpos("'a", [0, 1, 11, 0])
+ call setpos("'b", [0, 1, 1, 0])
+ call assert_equal(['abcdefghijk'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': "\<c-v>", 'exclusive': v:false }))
+ call assert_equal(['abcdefghij'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': "\<c-v>", 'exclusive': v:true }))
+ call assert_equal(['abcdefghijk'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'v', 'exclusive': 0 }))
+ call assert_equal(['abcdefghij'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'v', 'exclusive': 1 }))
+ call assert_equal(['abcdefghijk«'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'V', 'exclusive': 0 }))
+ call assert_equal(['abcdefghijk«'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'V', 'exclusive': 1 }))
+ :set selection&
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+
+ bwipe!
+
+ let lines =<< trim END
+ #" Exclusive selection
+ new
+ set selection=exclusive
+ call setline(1, ["a\tc", "x\tz", '', ''])
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v2l", 'xt')
+ call assert_equal(["a\t"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$G", 'xt')
+ call assert_equal(["a\tc", "x\tz", ''],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$G", 'xt')
+ call assert_equal(["a", "x", '', ''],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>wv2j", 'xt')
+ call assert_equal(["c", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ set selection&
+
+ #" Exclusive selection 2
+ new
+ call setline(1, ["a\tc", "x\tz", '', ''])
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v2l", 'xt')
+ call assert_equal(["a\t"],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$G", 'xt')
+ call assert_equal(["a\tc", "x\tz", ''],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'),
+ \ {'exclusive': v:true, 'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$G", 'xt')
+ call assert_equal(["a", "x", '', ''],
+ \ getregion(getpos('v'), getpos('.'),
+ \ {'exclusive': v:true, 'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>wv2j", 'xt')
+ call assert_equal(["c", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+
+ #" virtualedit
+ set selection=exclusive
+ set virtualedit=all
+ call cursor(1, 1)
+ call feedkeys("\<Esc>2lv2lj", 'xt')
+ call assert_equal([' c', 'x '],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
+ call assert_equal([' ', ' ', ' '],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ set virtualedit&
+ set selection&
+
+ bwipe!
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+endfunc
+
+func Test_getregion_invalid_buf()
+ new
+ help
+ call cursor(5, 7)
+ norm! mA
+ call cursor(5, 18)
+ norm! mB
+ call assert_equal(['Move around:'], getregion(getpos("'A"), getpos("'B")))
+ " close the help window
+ q
+ call assert_fails("call getregion(getpos(\"'A\"), getpos(\"'B\"))", 'E681:')
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim
index 6b7dccb..91adb9b 100644
--- a/src/testdir/test_window_cmd.vim
+++ b/src/testdir/test_window_cmd.vim
@@ -131,64 +131,6 @@ func Test_window_quit()
bw Xa Xb
endfunc
-func Test_window_curwin_not_prevwin()
- botright split
- call assert_equal(2, winnr())
- call assert_equal(1, winnr('#'))
- quit
- call assert_equal(1, winnr())
- call assert_equal(0, winnr('#'))
-
- botright split
- botright split
- call assert_equal(3, winnr())
- call assert_equal(2, winnr('#'))
- 1quit
- call assert_equal(2, winnr())
- call assert_equal(1, winnr('#'))
-
- botright split
- call assert_equal(1, tabpagenr())
- call assert_equal(3, winnr())
- call assert_equal(2, winnr('#'))
- wincmd T
- call assert_equal(2, tabpagenr())
- call assert_equal(1, winnr())
- call assert_equal(0, winnr('#'))
- tabfirst
- call assert_equal(1, tabpagenr())
- call assert_equal(2, winnr())
- call assert_equal(0, winnr('#'))
-
- tabonly
- botright split
- wincmd t
- wincmd p
- call assert_equal(3, winnr())
- call assert_equal(1, winnr('#'))
- quit
- call assert_equal(2, winnr())
- call assert_equal(1, winnr('#'))
-
- botright split
- wincmd t
- wincmd p
- call assert_equal(1, tabpagenr())
- call assert_equal(3, winnr())
- call assert_equal(1, winnr('#'))
- wincmd T
- call assert_equal(2, tabpagenr())
- call assert_equal(1, winnr())
- call assert_equal(0, winnr('#'))
- tabfirst
- call assert_equal(1, tabpagenr())
- call assert_equal(2, winnr())
- call assert_equal(1, winnr('#'))
-
- tabonly
- only
-endfunc
-
func Test_window_horizontal_split()
call assert_equal(1, winnr('$'))
3wincmd s
@@ -276,6 +218,20 @@ func Test_window_split_edit_bufnr()
%bw!
endfunc
+func s:win_layout_info(tp = tabpagenr()) abort
+ return #{
+ \ layout: winlayout(a:tp),
+ \ pos_sizes: range(1, tabpagewinnr(a:tp, '$'))
+ \ ->map({_, nr -> win_getid(nr, a:tp)->getwininfo()[0]})
+ \ ->map({_, wininfo -> #{id: wininfo.winid,
+ \ row: wininfo.winrow,
+ \ col: wininfo.wincol,
+ \ width: wininfo.width,
+ \ height: wininfo.height}})
+ \ ->sort({a, b -> a.id - b.id})
+ \ }
+endfunc
+
func Test_window_split_no_room()
" N horizontal windows need >= 2*N + 1 lines:
" - 1 line + 1 status line in each window
@@ -290,6 +246,14 @@ func Test_window_split_no_room()
for s in range(1, hor_split_count) | split | endfor
call assert_fails('split', 'E36:')
+ botright vsplit
+ wincmd |
+ let info = s:win_layout_info()
+ call assert_fails('wincmd J', 'E36:')
+ call assert_fails('wincmd K', 'E36:')
+ call assert_equal(info, s:win_layout_info())
+ only
+
" N vertical windows need >= 2*(N - 1) + 1 columns:
" - 1 column + 1 separator for each window (except last window)
" - 1 column for the last window which does not have separator
@@ -302,7 +266,37 @@ func Test_window_split_no_room()
for s in range(1, ver_split_count) | vsplit | endfor
call assert_fails('vsplit', 'E36:')
+ split
+ wincmd |
+ let info = s:win_layout_info()
+ call assert_fails('wincmd H', 'E36:')
+ call assert_fails('wincmd L', 'E36:')
+ call assert_equal(info, s:win_layout_info())
+
+ " Check that the last statusline isn't lost.
+ " Set its window's width to 2 for the test.
+ wincmd j
+ set laststatus=0 winminwidth=0
+ vertical resize 2
+ " Update expected positions/sizes after the resize. Layout is unchanged.
+ let info.pos_sizes = s:win_layout_info().pos_sizes
+ set winminwidth&
+ call setwinvar(winnr('k'), '&statusline', '@#')
+ let last_stl_row = win_screenpos(0)[0] - 1
+ redraw
+ call assert_equal('@#|', GetScreenStr(last_stl_row))
+ call assert_equal('~ |', GetScreenStr(&lines - &cmdheight))
+
+ call assert_fails('wincmd H', 'E36:')
+ call assert_fails('wincmd L', 'E36:')
+ call assert_equal(info, s:win_layout_info())
+ call setwinvar(winnr('k'), '&statusline', '=-')
+ redraw
+ call assert_equal('=-|', GetScreenStr(last_stl_row))
+ call assert_equal('~ |', GetScreenStr(&lines - &cmdheight))
+
%bw!
+ set laststatus&
endfunc
func Test_window_exchange()
@@ -1066,6 +1060,18 @@ func Test_win_splitmove()
leftabove split b
leftabove vsplit c
leftabove split d
+
+ " win_splitmove doesn't actually create or close any windows, so expect an
+ " unchanged winid and no WinNew/WinClosed events, like :wincmd H/J/K/L.
+ let s:triggered = []
+ augroup WinSplitMove
+ au!
+ au WinNewPre * let s:triggered += ['WinNewPre']
+ au WinNew * let s:triggered += ['WinNew', win_getid()]
+ au WinClosed * let s:triggered += ['WinClosed', str2nr(expand('<afile>'))]
+ augroup END
+ let winid = win_getid()
+
call assert_equal(0, win_splitmove(winnr(), winnr('l')))
call assert_equal(bufname(winbufnr(1)), 'c')
call assert_equal(bufname(winbufnr(2)), 'd')
@@ -1088,6 +1094,11 @@ func Test_win_splitmove()
call assert_equal(bufname(winbufnr(3)), 'a')
call assert_equal(bufname(winbufnr(4)), 'd')
call assert_fails('call win_splitmove(winnr(), winnr("k"), test_null_dict())', 'E1297:')
+ call assert_equal([], s:triggered)
+ call assert_equal(winid, win_getid())
+
+ unlet! s:triggered
+ au! WinSplitMove
only | bd
call assert_fails('call win_splitmove(winnr(), 123)', 'E957:')
@@ -1097,6 +1108,54 @@ func Test_win_splitmove()
tabnew
call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:')
tabclose
+
+ split
+ augroup WinSplitMove
+ au!
+ au WinEnter * ++once call win_gotoid(win_getid(winnr('#')))
+ augroup END
+ call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E855:')
+
+ augroup WinSplitMove
+ au!
+ au WinLeave * ++once quit
+ augroup END
+ call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E855:')
+
+ split
+ split
+ augroup WinSplitMove
+ au!
+ au WinEnter * ++once let s:triggered = v:true
+ \| call assert_fails('call win_splitmove(winnr(), winnr("$"))', 'E242:')
+ \| call assert_fails('call win_splitmove(winnr("$"), winnr())', 'E242:')
+ augroup END
+ quit
+ call assert_equal(v:true, s:triggered)
+ unlet! s:triggered
+
+ new
+ augroup WinSplitMove
+ au!
+ au BufHidden * ++once let s:triggered = v:true
+ \| call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E1159:')
+ augroup END
+ hide
+ call assert_equal(v:true, s:triggered)
+ unlet! s:triggered
+
+ split
+ let close_win = winnr('#')
+ augroup WinSplitMove
+ au!
+ au WinEnter * ++once quit!
+ augroup END
+ call win_splitmove(close_win, winnr())
+ call assert_equal(0, win_id2win(close_win))
+
+ au! WinSplitMove
+ augroup! WinSplitMove
+ %bw!
endfunc
" Test for the :only command
@@ -2060,24 +2119,160 @@ func Test_new_help_window_on_error()
call assert_equal(expand("<cword>"), "'mod'")
endfunc
-func Test_smoothscroll_in_zero_width_window()
- let save_lines = &lines
- let save_columns = &columns
+func Test_splitmove_flatten_frame()
+ split
+ vsplit
- winsize 0 24
- set cpo+=n
- exe "noremap 0 \<C-W>n\<C-W>L"
- norm 000000
- set number smoothscroll
- exe "norm \<C-Y>"
+ wincmd L
+ let layout = winlayout()
+ wincmd K
+ wincmd L
+ call assert_equal(winlayout(), layout)
only!
- let &lines = save_lines
- let &columns = save_columns
- set cpo-=n
- unmap 0
- set nonumber nosmoothscroll
endfunc
+func Test_autocmd_window_force_room()
+ " Open as many windows as possible
+ while v:true
+ try
+ split
+ catch /E36:/
+ break
+ endtry
+ endwhile
+ while v:true
+ try
+ vsplit
+ catch /E36:/
+ break
+ endtry
+ endwhile
+
+ wincmd j
+ vsplit
+ call assert_fails('wincmd H', 'E36:')
+ call assert_fails('wincmd J', 'E36:')
+ call assert_fails('wincmd K', 'E36:')
+ call assert_fails('wincmd L', 'E36:')
+
+ edit unload me
+ enew
+ bunload! unload\ me
+ augroup AucmdWinForceRoom
+ au!
+ au BufEnter * ++once let s:triggered = v:true
+ \| call assert_equal('autocmd', win_gettype())
+ augroup END
+ let info = s:win_layout_info()
+ " bufload opening the autocommand window shouldn't give E36.
+ call bufload('unload me')
+ call assert_equal(v:true, s:triggered)
+ call assert_equal(info, s:win_layout_info())
+
+ unlet! s:triggered
+ au! AucmdWinForceRoom
+ augroup! AucmdWinForceRoom
+ %bw!
+endfunc
+
+func Test_win_gotoid_splitmove_textlock_cmdwin()
+ call setline(1, 'foo')
+ new
+ let curwin = win_getid()
+ call setline(1, 'bar')
+
+ set debug+=throw indentexpr=win_gotoid(win_getid(winnr('#')))
+ call assert_fails('normal! ==', 'E565:')
+ call assert_equal(curwin, win_getid())
+ " No error if attempting to switch to curwin; nothing happens.
+ set indentexpr=assert_equal(1,win_gotoid(win_getid()))
+ normal! ==
+ call assert_equal(curwin, win_getid())
+
+ set indentexpr=win_splitmove(winnr('#'),winnr())
+ call assert_fails('normal! ==', 'E565:')
+ call assert_equal(curwin, win_getid())
+
+ %bw!
+ set debug-=throw indentexpr&
+
+ call feedkeys('q:'
+ \ .. ":call assert_fails('call win_splitmove(winnr(''#''), winnr())', 'E11:')\<CR>"
+ \ .. ":call assert_equal('command', win_gettype())\<CR>"
+ \ .. ":call assert_equal('', win_gettype(winnr('#')))\<CR>", 'ntx')
+
+ call feedkeys('q:'
+ \ .. ":call assert_fails('call win_gotoid(win_getid(winnr(''#'')))', 'E11:')\<CR>"
+ "\ No error if attempting to switch to curwin; nothing happens.
+ \ .. ":call assert_equal(1, win_gotoid(win_getid()))\<CR>"
+ \ .. ":call assert_equal('command', win_gettype())\<CR>"
+ \ .. ":call assert_equal('', win_gettype(winnr('#')))\<CR>", 'ntx')
+endfunc
+
+func Test_winfixsize_positions()
+ " Check positions are correct when closing a window in a non-current tabpage
+ " causes non-adjacent window to fill the space due to 'winfix{width,height}'.
+ tabnew
+ vsplit
+ wincmd |
+ split
+ set winfixheight
+ split foo
+ tabfirst
+
+ bwipe! foo
+ " Save actual values before entering the tabpage.
+ let info = s:win_layout_info(2)
+ tabnext
+ " Compare it with the expected value (after win_comp_pos) from entering.
+ call assert_equal(s:win_layout_info(), info)
+
+ $tabnew
+ split
+ split
+ wincmd k
+ belowright vsplit
+ set winfixwidth
+ belowright vsplit foo
+ tabprevious
+
+ bwipe! foo
+ " Save actual values before entering the tabpage.
+ let info = s:win_layout_info(3)
+ tabnext
+ " Compare it with the expected value (after win_comp_pos) from entering.
+ call assert_equal(s:win_layout_info(), info)
+
+ " Check positions unchanged when failing to move a window, if 'winfix{width,
+ " height}' would otherwise cause a non-adjacent window to fill the space.
+ %bwipe
+ call assert_fails('execute "split|"->repeat(&lines)', 'E36:')
+ wincmd p
+ vsplit
+ set winfixwidth
+ vsplit
+ set winfixwidth
+ vsplit
+ vsplit
+ set winfixwidth
+ wincmd p
+
+ let info = s:win_layout_info()
+ call assert_fails('wincmd J', 'E36:')
+ call assert_equal(info, s:win_layout_info())
+
+ only
+ call assert_fails('execute "vsplit|"->repeat(&columns)', 'E36:')
+ belowright split
+ set winfixheight
+ belowright split
+
+ let info = s:win_layout_info()
+ call assert_fails('wincmd H', 'E36:')
+ call assert_equal(info, s:win_layout_info())
+
+ %bwipe
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_winfixbuf.vim b/src/testdir/test_winfixbuf.vim
new file mode 100644
index 0000000..04043f8
--- /dev/null
+++ b/src/testdir/test_winfixbuf.vim
@@ -0,0 +1,3286 @@
+" Test 'winfixbuf'
+
+source check.vim
+
+" Find the number of open windows in the current tab
+func s:get_windows_count()
+ return tabpagewinnr(tabpagenr(), '$')
+endfunc
+
+" Create some unnamed buffers.
+func s:make_buffers_list()
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file middle
+ let l:middle = bufnr()
+
+ enew
+ file last
+ let l:last = bufnr()
+
+ set winfixbuf
+
+ return [l:first, l:last]
+endfunc
+
+" Create some unnamed buffers and add them to an args list
+func s:make_args_list()
+ let [l:first, l:last] = s:make_buffers_list()
+
+ args! first middle last
+
+ return [l:first, l:last]
+endfunc
+
+" Create two buffers and then set the window to 'winfixbuf'
+func s:make_buffer_pairs(...)
+ let l:reversed = get(a:, 1, 0)
+
+ if l:reversed == 1
+ enew
+ file original
+
+ set winfixbuf
+
+ enew!
+ file other
+ let l:other = bufnr()
+
+ return l:other
+ endif
+
+ enew
+ file other
+ let l:other = bufnr()
+
+ enew
+ file current
+
+ set winfixbuf
+
+ return l:other
+endfunc
+
+" Create 3 quick buffers and set the window to 'winfixbuf'
+func s:make_buffer_trio()
+ edit first
+ let l:first = bufnr()
+ edit second
+ let l:second = bufnr()
+
+ set winfixbuf
+
+ edit! third
+ let l:third = bufnr()
+
+ execute ":buffer! " . l:second
+
+ return [l:first, l:second, l:third]
+endfunc
+
+" Create a location list with at least 2 entries + a 'winfixbuf' window.
+func s:make_simple_location_list()
+ enew
+ file middle
+ let l:middle = bufnr()
+ call append(0, ["winfix search-term", "another line"])
+
+ enew!
+ file first
+ let l:first = bufnr()
+ call append(0, "first search-term")
+
+ enew!
+ file last
+ let l:last = bufnr()
+ call append(0, "last search-term")
+
+ call setloclist(
+ \ 0,
+ \ [
+ \ {
+ \ "filename": "first",
+ \ "bufnr": l:first,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "middle",
+ \ "bufnr": l:middle,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "middle",
+ \ "bufnr": l:middle,
+ \ "lnum": 2,
+ \ },
+ \ {
+ \ "filename": "last",
+ \ "bufnr": l:last,
+ \ "lnum": 1,
+ \ },
+ \ ]
+ \)
+
+ set winfixbuf
+
+ return [l:first, l:middle, l:last]
+endfunc
+
+" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window.
+func s:make_simple_quickfix()
+ enew
+ file current
+ let l:current = bufnr()
+ call append(0, ["winfix search-term", "another line"])
+
+ enew!
+ file first
+ let l:first = bufnr()
+ call append(0, "first search-term")
+
+ enew!
+ file last
+ let l:last = bufnr()
+ call append(0, "last search-term")
+
+ call setqflist(
+ \ [
+ \ {
+ \ "filename": "first",
+ \ "bufnr": l:first,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "current",
+ \ "bufnr": l:current,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "current",
+ \ "bufnr": l:current,
+ \ "lnum": 2,
+ \ },
+ \ {
+ \ "filename": "last",
+ \ "bufnr": l:last,
+ \ "lnum": 1,
+ \ },
+ \ ]
+ \)
+
+ set winfixbuf
+
+ return [l:current, l:last]
+endfunc
+
+" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window.
+func s:make_quickfix_windows()
+ let [l:current, _] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ split
+ let l:first_window = win_getid()
+ execute "normal \<C-w>j"
+ let l:winfix_window = win_getid()
+
+ " Open the quickfix in a separate split and go to it
+ copen
+ let l:quickfix_window = win_getid()
+
+ return [l:first_window, l:winfix_window, l:quickfix_window]
+endfunc
+
+" Revert all changes that occurred in any past test
+func s:reset_all_buffers()
+ %bwipeout!
+ set nowinfixbuf
+
+ call setqflist([])
+
+ for l:window_info in getwininfo()
+ call setloclist(l:window_info["winid"], [])
+ endfor
+
+ delmarks A-Z0-9
+endfunc
+
+" Find and set the first quickfix entry that points to `buffer`
+func s:set_quickfix_by_buffer(buffer)
+ let l:index = 1 " quickfix indices start at 1
+ for l:entry in getqflist()
+ if l:entry["bufnr"] == a:buffer
+ execute l:index . "cc"
+
+ return
+ endif
+
+ let l:index += 1
+ endfor
+
+ echoerr 'No quickfix entry matching "' . a:buffer . '" could be found.'
+endfunc
+
+" Fail to call :Next on a 'winfixbuf' window unless :Next! is used.
+func Test_Next()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("Next", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ Next!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Call :argdo and choose the next available 'nowinfixbuf' window.
+func Test_argdo_choose_available_window()
+ call s:reset_all_buffers()
+
+ let [_, l:last] = s:make_args_list()
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :argdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+ let l:expected_windows = s:get_windows_count()
+
+ argdo echo ''
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :argdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_argdo_make_new_window()
+ call s:reset_all_buffers()
+
+ let [l:first, l:last] = s:make_args_list()
+ let l:current = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ argdo echo ''
+ call assert_notequal(l:current, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :argedit but :argedit! is allowed
+func Test_argedit()
+ call s:reset_all_buffers()
+
+ args! first middle last
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file middle
+ let l:middle = bufnr()
+
+ enew
+ file last
+ let l:last = bufnr()
+
+ set winfixbuf
+
+ let l:current = bufnr()
+ call assert_fails("argedit first middle last", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ argedit! first middle last
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :arglocal but :arglocal! is allowed
+func Test_arglocal()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+ argglobal! other
+ execute "buffer! " . l:current
+
+ call assert_fails("arglocal other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ arglocal! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :argglobal but :argglobal! is allowed
+func Test_argglobal()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("argglobal other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ argglobal! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :args but :args! is allowed
+func Test_args()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_buffers_list()
+ let l:current = bufnr()
+
+ call assert_fails("args first middle last", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ args! first middle last
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :bNext but :bNext! is allowed
+func Test_bNext()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ call assert_fails("bNext", "E1513:")
+ let l:current = bufnr()
+
+ call assert_equal(l:current, bufnr())
+
+ bNext!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Allow :badd because it doesn't actually change the current window's buffer
+func Test_badd()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ badd other
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow :balt because it doesn't actually change the current window's buffer
+func Test_balt()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ balt other
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail :bfirst but :bfirst! is allowed
+func Test_bfirst()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("bfirst", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bfirst!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :blast but :blast! is allowed
+func Test_blast()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs(1)
+ bfirst!
+ let l:current = bufnr()
+
+ call assert_fails("blast", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ blast!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :bmodified but :bmodified! is allowed
+func Test_bmodified()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ execute "buffer! " . l:other
+ set modified
+ execute "buffer! " . l:current
+
+ call assert_fails("bmodified", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bmodified!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :bnext but :bnext! is allowed
+func Test_bnext()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("bnext", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bnext!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :bprevious but :bprevious! is allowed
+func Test_bprevious()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("bprevious", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bprevious!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :brewind but :brewind! is allowed
+func Test_brewind()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("brewind", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ brewind!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :browse edit but :browse edit! is allowed
+func Test_browse_edit_fail()
+ " A GUI dialog may stall the test.
+ CheckNotGui
+
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("browse edit other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ try
+ browse edit! other
+ call assert_equal(l:other, bufnr())
+ catch /^Vim\%((\a\+)\)\=:E338:/
+ " Ignore E338, which occurs if console Vim is built with +browse.
+ " Console Vim without +browse will treat this as a regular :edit.
+ endtry
+endfunc
+
+" Allow :browse w because it doesn't change the buffer in the current file
+func Test_browse_edit_pass()
+ " A GUI dialog may stall the test.
+ CheckNotGui
+
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ try
+ browse write other
+ catch /^Vim\%((\a\+)\)\=:E338:/
+ " Ignore E338, which occurs if console Vim is built with +browse.
+ " Console Vim without +browse will treat this as a regular :write.
+ endtry
+
+ call delete("other")
+endfunc
+
+" Call :bufdo and choose the next available 'nowinfixbuf' window.
+func Test_bufdo_choose_available_window()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :bufdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+
+ let l:current = bufnr()
+ let l:expected_windows = s:get_windows_count()
+
+ call assert_notequal(l:current, l:other)
+
+ bufdo echo ''
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_notequal(l:other, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :bufdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_bufdo_make_new_window()
+ call s:reset_all_buffers()
+
+ let [l:first, l:last] = s:make_buffers_list()
+ execute "buffer! " . l:first
+ let l:current = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ bufdo echo ''
+ call assert_notequal(l:current, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :buffer but :buffer! is allowed
+func Test_buffer()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("buffer " . l:other, "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ execute "buffer! " . l:other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Allow :buffer on a 'winfixbuf' window if there is no change in buffer
+func Test_buffer_same_buffer()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ execute "buffer " . l:current
+ call assert_equal(l:current, bufnr())
+
+ execute "buffer! " . l:current
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow :cNext but the 'nowinfixbuf' window is selected, instead
+func Test_cNext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cNext` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cNext
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cNfile but the 'nowinfixbuf' window is selected, instead
+func Test_cNfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cNfile` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cNfile
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :caddexpr because it doesn't change the current buffer
+func Test_caddexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ execute 'caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")'
+ call assert_equal(l:current, bufnr())
+
+ call delete(l:file_path)
+endfunc
+
+" Fail :cbuffer but :cbuffer! is allowed
+func Test_cbuffer()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ call assert_fails("cbuffer " . l:file_buffer)
+ call assert_equal(l:current, bufnr())
+
+ execute "cbuffer! " . l:file_buffer
+ call assert_equal("first.unittest", expand("%:t"))
+
+ call delete(l:file_path)
+endfunc
+
+" Allow :cc but the 'nowinfixbuf' window is selected, instead
+func Test_cc()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+ " Go up one line in the quickfix window to an quickfix entry that doesn't
+ " point to a winfixbuf buffer
+ normal k
+ " Attempt to make the previous window, winfixbuf buffer, to go to the
+ " non-winfixbuf quickfix entry
+ .cc
+
+ " Confirm that :.cc did not change the winfixbuf-enabled window
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Call :cdo and choose the next available 'nowinfixbuf' window.
+func Test_cdo_choose_available_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :cdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+ let l:expected_windows = s:get_windows_count()
+
+ cdo echo ''
+
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :cdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_cdo_make_new_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current_buffer, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current_buffer
+
+ let l:current_window = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ cdo echo ''
+ call assert_notequal(l:current_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current_buffer, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :cexpr but :cexpr! is allowed
+func Test_cexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ let l:entry = '["' . l:file . ':1:bar"]'
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("cexpr " . l:entry)
+ call assert_equal(l:current, bufnr())
+
+ execute "cexpr! " . l:entry
+ call assert_equal(fnamemodify(l:file, ":t"), expand("%:t"))
+endfunc
+
+" Call :cfdo and choose the next available 'nowinfixbuf' window.
+func Test_cfdo_choose_available_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :cfdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+ let l:expected_windows = s:get_windows_count()
+
+ cfdo echo ''
+
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :cfdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_cfdo_make_new_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current_buffer, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current_buffer
+
+ let l:current_window = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ cfdo echo ''
+ call assert_notequal(l:current_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current_buffer, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :cfile but :cfile! is allowed
+func Test_cfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+ write
+ let l:first = bufnr()
+
+ edit! second.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ let l:file = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file)
+
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails(":cfile " . l:file)
+ call assert_equal(l:current, bufnr())
+
+ execute ":cfile! " . l:file
+ call assert_equal(l:first, bufnr())
+
+ call delete(l:file)
+ call delete("first.unittest")
+ call delete("second.unittest")
+endfunc
+
+" Allow :cfirst but the 'nowinfixbuf' window is selected, instead
+func Test_cfirst()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cfirst` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cfirst
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :clast but the 'nowinfixbuf' window is selected, instead
+func Test_clast()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:clast` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ clast
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cnext but the 'nowinfixbuf' window is selected, instead
+" Make sure no new windows are created and previous windows are reused
+func Test_cnext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+ let l:expected = s:get_windows_count()
+
+ " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ cnext!
+ call assert_equal(l:expected, s:get_windows_count())
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cnext
+ call assert_equal(l:first_window, win_getid())
+ call assert_equal(l:expected, s:get_windows_count())
+endfunc
+
+" Make sure :cnext creates a split window if no previous window exists
+func Test_cnext_no_previous_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, _] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ let l:expected = s:get_windows_count()
+
+ " Open the quickfix in a separate split and go to it
+ copen
+
+ call assert_equal(l:expected + 1, s:get_windows_count())
+endfunc
+
+" Allow :cnext and create a 'nowinfixbuf' window if none exists
+func Test_cnext_make_new_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, _] = s:make_simple_quickfix()
+ let l:current = win_getid()
+
+ cfirst!
+
+ let l:windows = s:get_windows_count()
+ let l:expected = l:windows + 1 " We're about to create a new split window
+
+ cnext
+ call assert_equal(l:expected, s:get_windows_count())
+
+ cnext!
+ call assert_equal(l:expected, s:get_windows_count())
+endfunc
+
+" Allow :cprevious but the 'nowinfixbuf' window is selected, instead
+func Test_cprevious()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cprevious` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cprevious
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cnfile but the 'nowinfixbuf' window is selected, instead
+func Test_cnfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cnfile` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cnfile
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cpfile but the 'nowinfixbuf' window is selected, instead
+func Test_cpfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cpfile` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cpfile
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :crewind but the 'nowinfixbuf' window is selected, instead
+func Test_crewind()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:crewind` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ crewind
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow <C-w>f because it opens in a new split
+func Test_ctrl_w_f()
+ call s:reset_all_buffers()
+
+ enew
+ let l:file_name = tempname()
+ call writefile([], l:file_name)
+ let l:file_buffer = bufnr()
+
+ enew
+ file other
+ let l:other_buffer = bufnr()
+
+ set winfixbuf
+
+ call setline(1, l:file_name)
+ let l:current_windows = s:get_windows_count()
+ execute "normal \<C-w>f"
+
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+
+ call delete(l:file_name)
+endfunc
+
+" Fail :djump but :djump! is allowed
+func Test_djump()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("djump 1 /min/", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ djump! 1 /min/
+ call assert_notequal(l:current, bufnr())
+
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail :drop but :drop! is allowed
+func Test_drop()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("drop other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ drop! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :edit but :edit! is allowed
+func Test_edit()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("edit other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ edit! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :enew but :enew! is allowed
+func Test_enew()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("enew", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ enew!
+ call assert_notequal(l:other, bufnr())
+ call assert_notequal(3, bufnr())
+endfunc
+
+" Fail :ex but :ex! is allowed
+func Test_ex()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("ex other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ ex! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :find but :find! is allowed
+func Test_find()
+ call s:reset_all_buffers()
+
+ let l:current = bufnr()
+ let l:file = tempname()
+ call writefile([], l:file)
+ let l:file = fnamemodify(l:file, ':p') " In case it's Windows 8.3-style.
+ let l:directory = fnamemodify(l:file, ":p:h")
+ let l:name = fnamemodify(l:file, ":p:t")
+
+ let l:original_path = &path
+ execute "set path=" . l:directory
+
+ set winfixbuf
+
+ call assert_fails("execute 'find " . l:name . "'", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ execute "find! " . l:name
+ call assert_equal(l:file, expand("%:p"))
+
+ execute "set path=" . l:original_path
+ call delete(l:file)
+endfunc
+
+" Fail :first but :first! is allowed
+func Test_first()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("first", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ first!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :grep but :grep! is allowed
+func Test_grep()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:first = bufnr()
+
+ edit current.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ set winfixbuf
+
+ buffer! current.unittest
+
+ call assert_fails("silent! grep some-search-term *.unittest", "E1513:")
+ call assert_equal(l:current, bufnr())
+ execute "edit! " . l:first
+
+ silent! grep! some-search-term *.unittest
+ call assert_notequal(l:first, bufnr())
+
+ call delete("first.unittest")
+ call delete("current.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :ijump but :ijump! is allowed
+func Test_ijump()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile([
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ set define=^\\s*#\\s*define
+ set include=^\\s*#\\s*include
+ set path=.,/usr/include,,
+
+ call assert_fails("ijump /min/", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ ijump! /min/
+ call assert_notequal(l:current, bufnr())
+
+ set define&
+ set include&
+ set path&
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail :lNext but :lNext! is allowed
+func Test_lNext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, _] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ call assert_fails("lNext", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lnext!
+ call assert_equal(3, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lNext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lNext!
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :lNfile but :lNfile! is allowed
+func Test_lNfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:current, _] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ call assert_fails("lNfile", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ lnext!
+ call assert_equal(3, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ lNfile!
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Allow :laddexpr because it doesn't change the current buffer
+func Test_laddexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ execute 'laddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")'
+ call assert_equal(l:current, bufnr())
+
+ call delete(l:file_path)
+endfunc
+
+" Fail :last but :last! is allowed
+func Test_last()
+ call s:reset_all_buffers()
+
+ let [_, l:last] = s:make_args_list()
+ next!
+
+ call assert_fails("last", "E1513:")
+ call assert_notequal(l:last, bufnr())
+
+ last!
+ call assert_equal(l:last, bufnr())
+endfunc
+
+" Fail :lbuffer but :lbuffer! is allowed
+func Test_lbuffer()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ call assert_fails("lbuffer " . l:file_buffer)
+ call assert_equal(l:current, bufnr())
+
+ execute "lbuffer! " . l:file_buffer
+ call assert_equal("first.unittest", expand("%:t"))
+
+ call delete(l:file_path)
+endfunc
+
+" Fail :ldo but :ldo! is allowed
+func Test_ldo()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails('execute "ldo buffer ' . l:first . '"', "E1513:")
+ call assert_equal(l:middle, bufnr())
+ execute "ldo! buffer " . l:first
+ call assert_notequal(l:last, bufnr())
+endfunc
+
+" Fail :lfdo but :lfdo! is allowed
+func Test_lexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ let l:entry = '["' . l:file . ':1:bar"]'
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("lexpr " . l:entry)
+ call assert_equal(l:current, bufnr())
+
+ execute "lexpr! " . l:entry
+ call assert_equal(fnamemodify(l:file, ":t"), expand("%:t"))
+endfunc
+
+" Fail :lfdo but :lfdo! is allowed
+func Test_lfdo()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails('execute "lfdo buffer ' . l:first . '"', "E1513:")
+ call assert_equal(l:middle, bufnr())
+ execute "lfdo! buffer " . l:first
+ call assert_notequal(l:last, bufnr())
+endfunc
+
+" Fail :lfile but :lfile! is allowed
+func Test_lfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+ write
+ let l:first = bufnr()
+
+ edit! second.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ let l:file = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file)
+
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails(":lfile " . l:file)
+ call assert_equal(l:current, bufnr())
+
+ execute ":lfile! " . l:file
+ call assert_equal(l:first, bufnr())
+
+ call delete(l:file)
+ call delete("first.unittest")
+ call delete("second.unittest")
+endfunc
+
+" Fail :ll but :ll! is allowed
+func Test_ll()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ lopen
+ lfirst!
+ execute "normal \<C-w>j"
+ normal j
+
+ call assert_fails(".ll", "E1513:")
+ execute "normal \<C-w>k"
+ call assert_equal(l:first, bufnr())
+ execute "normal \<C-w>j"
+ .ll!
+ execute "normal \<C-w>k"
+ call assert_equal(l:middle, bufnr())
+endfunc
+
+" Fail :llast but :llast! is allowed
+func Test_llast()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, _, l:last] = s:make_simple_location_list()
+ lfirst!
+
+ call assert_fails("llast", "E1513:")
+ call assert_equal(l:first, bufnr())
+
+ llast!
+ call assert_equal(l:last, bufnr())
+endfunc
+
+" Fail :lnext but :lnext! is allowed
+func Test_lnext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ ll!
+
+ call assert_fails("lnext", "E1513:")
+ call assert_equal(l:first, bufnr())
+
+ lnext!
+ call assert_equal(l:middle, bufnr())
+endfunc
+
+" Fail :lnfile but :lnfile! is allowed
+func Test_lnfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [_, l:current, l:last] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ call assert_fails("lnfile", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ lnfile!
+ call assert_equal(4, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:last, bufnr())
+endfunc
+
+" Fail :lpfile but :lpfile! is allowed
+func Test_lpfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:current, _] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails("lpfile", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ lnext! " Reset for the next test call
+
+ lpfile!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :lprevious but :lprevious! is allowed
+func Test_lprevious()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, _] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ call assert_fails("lprevious", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lprevious!
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :lrewind but :lrewind! is allowed
+func Test_lrewind()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, _] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails("lrewind", "E1513:")
+ call assert_equal(l:middle, bufnr())
+
+ lrewind!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :ltag but :ltag! is allowed
+func Test_ltag()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("ltag one", "E1513:")
+
+ ltag! one
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail vim.command if we try to change buffers while 'winfixbuf' is set
+func Test_lua_command()
+ CheckFeature lua
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let l:previous = bufnr()
+
+ enew
+ file second
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails('lua vim.command("buffer " .. ' . l:previous . ')')
+ call assert_equal(l:current, bufnr())
+
+ execute 'lua vim.command("buffer! " .. ' . l:previous . ')'
+ call assert_equal(l:previous, bufnr())
+endfunc
+
+" Fail :lvimgrep but :lvimgrep! is allowed
+func Test_lvimgrep()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("lvimgrep /some-search-term/ *.unittest", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ lvimgrep! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :lvimgrepadd but :lvimgrepadd! is allowed
+func Test_lvimgrepadd()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("lvimgrepadd /some-search-term/ *.unittest")
+ call assert_equal(l:current, bufnr())
+
+ lvimgrepadd! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Don't allow global marks to change the current 'winfixbuf' window
+func Test_marks_mappings_fail()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+ execute "buffer! " . l:other
+ normal mA
+ execute "buffer! " . l:current
+ normal mB
+
+ call assert_fails("normal `A", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ call assert_fails("normal 'A", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ normal `A
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Allow global marks in a 'winfixbuf' window if the jump is the same buffer
+func Test_marks_mappings_pass_intra_move()
+ call s:reset_all_buffers()
+
+ let l:current = bufnr()
+ call append(0, ["some line", "another line"])
+ normal mA
+ normal j
+ normal mB
+
+ set winfixbuf
+
+ normal `A
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail :next but :next! is allowed
+func Test_next()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ first!
+
+ call assert_fails("next", "E1513:")
+ call assert_equal(l:first, bufnr())
+
+ next!
+ call assert_notequal(l:first, bufnr())
+endfunc
+
+" Ensure :mksession saves 'winfixbuf' details
+func Test_mksession()
+ CheckFeature mksession
+ call s:reset_all_buffers()
+
+ set sessionoptions+=options
+ set winfixbuf
+
+ mksession test_winfixbuf_Test_mksession.vim
+
+ call s:reset_all_buffers()
+ let l:winfixbuf = &winfixbuf
+ call assert_equal(0, l:winfixbuf)
+
+ source test_winfixbuf_Test_mksession.vim
+
+ let l:winfixbuf = &winfixbuf
+ call assert_equal(1, l:winfixbuf)
+
+ set sessionoptions&
+ call delete("test_winfixbuf_Test_mksession.vim")
+endfunc
+
+" Allow :next if the next index is the same as the current buffer
+func Test_next_same_buffer()
+ call s:reset_all_buffers()
+
+ enew
+ file foo
+ enew
+ file bar
+ enew
+ file fizz
+ enew
+ file buzz
+ args foo foo bar fizz buzz
+
+ edit foo
+ set winfixbuf
+ let l:current = bufnr()
+
+ " Allow :next because the args list is `[foo] foo bar fizz buzz
+ next
+ call assert_equal(l:current, bufnr())
+
+ " Fail :next because the args list is `foo [foo] bar fizz buzz
+ " and the next buffer would be bar, which is a different buffer
+ call assert_fails("next", "E1513:")
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail to jump to a tag with g<C-]> if 'winfixbuf' is enabled
+func Test_normal_g_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal g\<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with g<RightMouse> if 'winfixbuf' is enabled
+func Test_normal_g_rightmouse()
+ call s:reset_all_buffers()
+ set mouse=n
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal g\<RightMouse>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ set mouse&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with g] if 'winfixbuf' is enabled
+func Test_normal_g_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal g]", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with <C-RightMouse> if 'winfixbuf' is enabled
+func Test_normal_ctrl_rightmouse()
+ call s:reset_all_buffers()
+ set mouse=n
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-RightMouse>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ set mouse&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with <C-t> if 'winfixbuf' is enabled
+func Test_normal_ctrl_t()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-t>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Disallow <C-^> in 'winfixbuf' windows
+func Test_normal_ctrl_hat()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal \<C-^>", "E1513:")
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow <C-i> in 'winfixbuf' windows if the movement stays within the buffer
+func Test_normal_ctrl_i_pass()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew!
+ file current
+ let l:current = bufnr()
+ " Add some lines so we can populate a jumplist"
+ call append(0, ["some line", "another line"])
+ " Add an entry to the jump list
+ " Go up another line
+ normal m`
+ normal k
+ execute "normal \<C-o>"
+
+ set winfixbuf
+
+ let l:line = getcurpos()[1]
+ execute "normal 1\<C-i>"
+ call assert_notequal(l:line, getcurpos()[1])
+endfunc
+
+" Disallow <C-o> in 'winfixbuf' windows if it would cause the buffer to switch
+func Test_normal_ctrl_o_fail()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal \<C-o>", "E1513:")
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow <C-o> in 'winfixbuf' windows if the movement stays within the buffer
+func Test_normal_ctrl_o_pass()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew!
+ file current
+ let l:current = bufnr()
+ " Add some lines so we can populate a jumplist
+ call append(0, ["some line", "another line"])
+ " Add an entry to the jump list
+ " Go up another line
+ normal m`
+ normal k
+
+ set winfixbuf
+
+ execute "normal \<C-o>"
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled
+func Test_normal_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Allow <C-w><C-]> with 'winfixbuf' enabled because it runs in a new, split window
+func Test_normal_ctrl_w_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current_windows = s:get_windows_count()
+ execute "normal \<C-w>\<C-]>"
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Allow <C-w>g<C-]> with 'winfixbuf' enabled because it runs in a new, split window
+func Test_normal_ctrl_w_g_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current_windows = s:get_windows_count()
+ execute "normal \<C-w>g\<C-]>"
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled
+func Test_normal_gt()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one", "two", "three"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Prevent gF from switching a 'winfixbuf' window's buffer
+func Test_normal_gF()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gF, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal gF", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal gF
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Prevent gf from switching a 'winfixbuf' window's buffer
+func Test_normal_gf()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gf, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal gf", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal gf
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Fail "goto file under the cursor" (using [f, which is the same as `:normal gf`)
+func Test_normal_square_bracket_left_f()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gf, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal [f", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal [f
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Fail to go to a C macro with [<C-d> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_left_ctrl_d()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+ normal ]\<C-d>
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal [\<C-d>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ execute "normal [\<C-d>"
+ call assert_notequal(l:current, bufnr())
+
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail to go to a C macro with ]<C-d> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_right_ctrl_d()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal ]\<C-d>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ execute "normal ]\<C-d>"
+ call assert_notequal(l:current, bufnr())
+
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail to go to a C macro with [<C-i> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_left_ctrl_i()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(['#include "' . l:include_file . '"',
+ \ "min(1, 12);",
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+ " Move to the line with `min(1, 12);` on it"
+ normal j
+
+ set define=^\\s*#\\s*define
+ set include=^\\s*#\\s*include
+ set path=.,/usr/include,,
+
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal [\<C-i>", "E1513:")
+
+ set nowinfixbuf
+
+ execute "normal [\<C-i>"
+ call assert_notequal(l:current, bufnr())
+
+ set define&
+ set include&
+ set path&
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail to go to a C macro with ]<C-i> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_right_ctrl_i()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ set define=^\\s*#\\s*define
+ set include=^\\s*#\\s*include
+ set path=.,/usr/include,,
+
+ let l:current = bufnr()
+
+ call assert_fails("normal ]\<C-i>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ execute "normal ]\<C-i>"
+ call assert_notequal(l:current, bufnr())
+
+ set define&
+ set include&
+ set path&
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail "goto file under the cursor" (using ]f, which is the same as `:normal gf`)
+func Test_normal_square_bracket_right_f()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gf, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal ]f", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal ]f
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Fail to jump to a tag with v<C-]> if 'winfixbuf' is enabled
+func Test_normal_v_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal v\<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with vg<C-]> if 'winfixbuf' is enabled
+func Test_normal_v_g_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal vg\<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Allow :pedit because, unlike :edit, it uses a separate window
+func Test_pedit()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+
+ pedit other
+
+ execute "normal \<C-w>w"
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :pop but :pop! is allowed
+func Test_pop()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("pop", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ pop!
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :previous but :previous! is allowed
+func Test_previous()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("previous", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ previous!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail pyxdo if it changes a window with 'winfixbuf' is set
+func Test_pythonx_pyxdo()
+ CheckFeature pythonx
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let g:_previous_buffer = bufnr()
+
+ enew
+ file second
+
+ set winfixbuf
+
+ pythonx << EOF
+import vim
+
+def test_winfixbuf_Test_pythonx_pyxdo_set_buffer():
+ buffer = vim.vars['_previous_buffer']
+ vim.current.buffer = vim.buffers[buffer]
+EOF
+
+ try
+ pyxdo test_winfixbuf_Test_pythonx_pyxdo_set_buffer()
+ catch /Vim\%((\a\+)\)\=:E1513:/
+ let l:caught = 1
+ endtry
+
+ call assert_equal(1, l:caught)
+
+ unlet g:_previous_buffer
+endfunc
+
+" Fail pyxfile if it changes a window with 'winfixbuf' is set
+func Test_pythonx_pyxfile()
+ CheckFeature pythonx
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let g:_previous_buffer = bufnr()
+
+ enew
+ file second
+
+ set winfixbuf
+
+ call writefile(["import vim",
+ \ "buffer = vim.vars['_previous_buffer']",
+ \ "vim.current.buffer = vim.buffers[buffer]",
+ \ ],
+ \ "file.py")
+
+ try
+ pyxfile file.py
+ catch /Vim\%((\a\+)\)\=:E1513:/
+ let l:caught = 1
+ endtry
+
+ call assert_equal(1, l:caught)
+
+ call delete("file.py")
+ unlet g:_previous_buffer
+endfunc
+
+" Fail vim.current.buffer if 'winfixbuf' is set
+func Test_pythonx_vim_current_buffer()
+ CheckFeature pythonx
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let g:_previous_buffer = bufnr()
+
+ enew
+ file second
+
+ let l:caught = 0
+
+ set winfixbuf
+
+ try
+ pythonx << EOF
+import vim
+
+buffer = vim.vars["_previous_buffer"]
+vim.current.buffer = vim.buffers[buffer]
+EOF
+ catch /Vim\%((\a\+)\)\=:E1513:/
+ let l:caught = 1
+ endtry
+
+ call assert_equal(1, l:caught)
+ unlet g:_previous_buffer
+endfunc
+
+" Ensure remapping to a disabled action still triggers failures
+func Test_remap_key_fail()
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ nnoremap g <C-^>
+
+ call assert_fails("normal g", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ nunmap g
+endfunc
+
+" Ensure remapping a disabled key to something valid does trigger any failures
+func Test_remap_key_pass()
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal \<C-^>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ " Disallow <C-^> by default but allow it if the command does something else
+ nnoremap <C-^> :echo "hello!"
+
+ execute "normal \<C-^>"
+ call assert_equal(l:current, bufnr())
+
+ nunmap <C-^>
+endfunc
+
+" Fail :rewind but :rewind! is allowed
+func Test_rewind()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("rewind", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ rewind!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Allow :sblast because it opens the buffer in a new, split window
+func Test_sblast()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs(1)
+ bfirst!
+ let l:current = bufnr()
+
+ sblast
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :sbprevious but :sbprevious! is allowed
+func Test_sbprevious()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ sbprevious
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Make sure 'winfixbuf' can be set using 'winfixbuf' or 'wfb'
+func Test_short_option()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+
+ set winfixbuf
+ call assert_fails("edit something_else", "E1513")
+
+ set nowinfixbuf
+ set wfb
+ call assert_fails("edit another_place", "E1513")
+
+ set nowfb
+ edit last_place
+endfunc
+
+" Allow :snext because it makes a new window
+func Test_snext()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ first!
+
+ let l:current_window = win_getid()
+
+ snext
+ call assert_notequal(l:current_window, win_getid())
+ call assert_notequal(l:first, bufnr())
+endfunc
+
+" Ensure the first has 'winfixbuf' and a new split window is 'nowinfixbuf'
+func Test_split_window()
+ call s:reset_all_buffers()
+
+ split
+ execute "normal \<C-w>j"
+
+ set winfixbuf
+
+ let l:winfix_window_1 = win_getid()
+ vsplit
+ let l:winfix_window_2 = win_getid()
+
+ call assert_equal(1, getwinvar(l:winfix_window_1, "&winfixbuf"))
+ call assert_equal(0, getwinvar(l:winfix_window_2, "&winfixbuf"))
+endfunc
+
+" Fail :tNext but :tNext! is allowed
+func Test_tNext()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+ execute "normal \<C-^>"
+ tnext!
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tNext", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tNext!
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Call :tabdo and choose the next available 'nowinfixbuf' window.
+func Test_tabdo_choose_available_window()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :tabdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+
+ let l:expected_windows = s:get_windows_count()
+ tabdo echo ''
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :tabdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_tabdo_make_new_window()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_buffers_list()
+ execute "buffer! " . l:first
+
+ let l:current = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ tabdo echo ''
+ call assert_notequal(l:current, win_getid())
+ call assert_equal(l:first, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :tag but :tag! is allowed
+func Test_tag()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tag one", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tag! one
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+
+" Fail :tfirst but :tfirst! is allowed
+func Test_tfirst()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tfirst", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tfirst!
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :tjump but :tjump! is allowed
+func Test_tjump()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tjump one", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tjump! one
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :tlast but :tlast! is allowed
+func Test_tlast()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ edit Xfile
+ tjump one
+ edit Xfile
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tlast", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tlast!
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+endfunc
+
+" Fail :tnext but :tnext! is allowed
+func Test_tnext()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+ execute "normal \<C-^>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tnext", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tnext!
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :tprevious but :tprevious! is allowed
+func Test_tprevious()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+ execute "normal \<C-^>"
+ tnext!
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tprevious", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tprevious!
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :view but :view! is allowed
+func Test_view()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("view other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ view! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :visual but :visual! is allowed
+func Test_visual()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("visual other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ visual! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :vimgrep but :vimgrep! is allowed
+func Test_vimgrep()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("vimgrep /some-search-term/ *.unittest")
+ call assert_equal(l:current, bufnr())
+
+ " Don't error and also do swap to the first match because ! was included
+ vimgrep! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :vimgrepadd but ::vimgrepadd! is allowed
+func Test_vimgrepadd()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("vimgrepadd /some-search-term/ *.unittest")
+ call assert_equal(l:current, bufnr())
+
+ vimgrepadd! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :wNext but :wNext! is allowed
+func Test_wNext()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("wNext", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ wNext!
+ call assert_equal(l:first, bufnr())
+
+ call delete("first")
+ call delete("middle")
+ call delete("last")
+endfunc
+
+" Allow :windo unless `:windo foo` would change a 'winfixbuf' window's buffer
+func Test_windo()
+ call s:reset_all_buffers()
+
+ let l:current_window = win_getid()
+ let l:current_buffer = bufnr()
+ split
+ enew
+ file some_other_buffer
+
+ set winfixbuf
+
+ let l:current = win_getid()
+
+ windo echo ''
+ call assert_equal(l:current_window, win_getid())
+
+ call assert_fails('execute "windo buffer ' . l:current_buffer . '"', "E1513:")
+ call assert_equal(l:current_window, win_getid())
+
+ execute "windo buffer! " . l:current_buffer
+ call assert_equal(l:current_window, win_getid())
+endfunc
+
+" Fail :wnext but :wnext! is allowed
+func Test_wnext()
+ call s:reset_all_buffers()
+
+ let [_, l:last] = s:make_args_list()
+ next!
+
+ call assert_fails("wnext", "E1513:")
+ call assert_notequal(l:last, bufnr())
+
+ wnext!
+ call assert_equal(l:last, bufnr())
+
+ call delete("first")
+ call delete("middle")
+ call delete("last")
+endfunc
+
+" Fail :wprevious but :wprevious! is allowed
+func Test_wprevious()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("wprevious", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ wprevious!
+ call assert_equal(l:first, bufnr())
+
+ call delete("first")
+ call delete("middle")
+ call delete("last")
+endfunc
+
+func Test_quickfix_switchbuf_invalid_prevwin()
+ call s:reset_all_buffers()
+
+ call s:make_simple_quickfix()
+ call assert_equal(1, getqflist(#{idx: 0}).idx)
+
+ set switchbuf=uselast
+ split
+ copen
+ execute winnr('#') 'quit'
+ call assert_equal(2, winnr('$'))
+
+ cnext " Would've triggered a null pointer member access
+ call assert_equal(2, getqflist(#{idx: 0}).idx)
+
+ set switchbuf&
+endfunc
+
+func Test_listdo_goto_prevwin()
+ call s:reset_all_buffers()
+ call s:make_buffers_list()
+
+ new
+ call assert_equal(0, &winfixbuf)
+ wincmd p
+ call assert_equal(1, &winfixbuf)
+ call assert_notequal(bufnr(), bufnr('#'))
+
+ augroup ListDoGotoPrevwin
+ au!
+ au BufLeave * let s:triggered = 1
+ \| call assert_equal(bufnr(), winbufnr(winnr()))
+ augroup END
+ " Should correctly switch to the window without 'winfixbuf', and curbuf should
+ " be consistent with curwin->w_buffer for autocommands.
+ bufdo "
+ call assert_equal(0, &winfixbuf)
+ call assert_equal(1, s:triggered)
+ unlet! s:triggered
+ au! ListDoGotoPrevwin
+
+ set winfixbuf
+ wincmd p
+ call assert_equal(2, winnr('$'))
+ " Both curwin and prevwin have 'winfixbuf' set, so should split a new window
+ " without it set.
+ bufdo "
+ call assert_equal(0, &winfixbuf)
+ call assert_equal(3, winnr('$'))
+
+ quit
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, &winfixbuf)
+ augroup ListDoGotoPrevwin
+ au!
+ au WinEnter * ++once set winfixbuf
+ augroup END
+ " Same as before, but naughty autocommands set 'winfixbuf' for the new window.
+ " :bufdo should give up in this case.
+ call assert_fails('bufdo "', 'E1513:')
+
+ au! ListDoGotoPrevwin
+ augroup! ListDoGotoPrevwin
+endfunc
+
+func Test_quickfix_changed_split_failed()
+ call s:reset_all_buffers()
+
+ call s:make_simple_quickfix()
+ call assert_equal(1, winnr('$'))
+
+ " Quickfix code will open a split in an attempt to get a 'nowinfixbuf' window
+ " to switch buffers in. Interfere with things by setting 'winfixbuf' in it.
+ augroup QfChanged
+ au!
+ au WinEnter * ++once call assert_equal(2, winnr('$'))
+ \| set winfixbuf | call setqflist([], 'f')
+ augroup END
+ call assert_fails('cnext', ['E1513:', 'E925:'])
+ " Check that the split was automatically closed.
+ call assert_equal(1, winnr('$'))
+
+ au! QfChanged
+ augroup! QfChanged
+endfunc
+
+func Test_bufdo_cnext_splitwin_fails()
+ call s:reset_all_buffers()
+ call s:make_simple_quickfix()
+ call assert_equal(1, getqflist(#{idx: 0}).idx)
+ " Make sure there is not enough room to
+ " split the winfixedbuf window
+ let &winheight=&lines
+ let &winminheight=&lines-2
+ " Still want E1513, or it may not be clear why a split was attempted and why
+ " it failing caused the commands to abort.
+ call assert_fails(':bufdo echo 1', ['E36:', 'E1513:'])
+ call assert_fails(':cnext', ['E36:', 'E1513:'])
+ " Ensure the entry didn't change.
+ call assert_equal(1, getqflist(#{idx: 0}).idx)
+ set winminheight&vim winheight&vim
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testing.c b/src/testing.c
index 1835643..0d731da 100644
--- a/src/testing.c
+++ b/src/testing.c
@@ -1539,7 +1539,7 @@ f_test_gui_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
rettv->vval.v_number = test_gui_find_repl(argvars[1].vval.v_dict);
# endif
# ifdef MSWIN
- else if (STRCMP(event, "key") == 0 || STRCMP(event, "mouse") == 0)
+ else if (STRCMP(event, "key") == 0 || STRCMP(event, "mouse") == 0 || STRCMP(event, "set_keycode_trans_strategy") == 0)
rettv->vval.v_number = test_mswin_event(event, argvars[1].vval.v_dict);
# endif
else if (STRCMP(event, "mouse") == 0)
diff --git a/src/textformat.c b/src/textformat.c
index a1a3e16..14acc53 100644
--- a/src/textformat.c
+++ b/src/textformat.c
@@ -90,11 +90,18 @@ internal_format(
colnr_T end_col;
int wcc; // counter for whitespace chars
int did_do_comment = FALSE;
+ int first_pass;
- virtcol = get_nolist_virtcol()
- + char2cells(c != NUL ? c : gchar_cursor());
- if (virtcol <= (colnr_T)textwidth)
- break;
+ // Cursor is currently at the end of line. No need to format
+ // if line length is less than textwidth (8 * textwidth for
+ // utf safety)
+ if (curwin->w_cursor.col < 8 * textwidth)
+ {
+ virtcol = get_nolist_virtcol()
+ + char2cells(c != NUL ? c : gchar_cursor());
+ if (virtcol <= (colnr_T)textwidth)
+ break;
+ }
if (no_leader)
do_comments = FALSE;
@@ -144,9 +151,17 @@ internal_format(
coladvance((colnr_T)textwidth);
wantcol = curwin->w_cursor.col;
- curwin->w_cursor.col = startcol;
+ // If startcol is large (a long line), formatting takes too much
+ // time. The algorithm is O(n^2), it walks from the end of the
+ // line to textwidth border every time for each line break.
+ //
+ // Ceil to 8 * textwidth to optimize.
+ curwin->w_cursor.col = startcol < 8 * textwidth ? startcol :
+ 8 * textwidth;
+
foundcol = 0;
skip_pos = 0;
+ first_pass = TRUE;
// Find position to break at.
// Stop at first entered white when 'formatoptions' has 'v'
@@ -155,8 +170,11 @@ internal_format(
|| curwin->w_cursor.lnum != Insstart.lnum
|| curwin->w_cursor.col >= Insstart.col)
{
- if (curwin->w_cursor.col == startcol && c != NUL)
+ if (first_pass && c != NUL)
+ {
cc = c;
+ first_pass = FALSE;
+ }
else
cc = gchar_cursor();
if (WHITECHAR(cc))
@@ -437,7 +455,7 @@ internal_format(
// Check if cursor is not past the NUL off the line, cindent
// may have added or removed indent.
curwin->w_cursor.col += startcol;
- len = (colnr_T)STRLEN(ml_get_curline());
+ len = ml_get_curline_len();
if (curwin->w_cursor.col > len)
curwin->w_cursor.col = len;
}
@@ -513,9 +531,7 @@ ends_in_white(linenr_T lnum)
if (*s == NUL)
return FALSE;
- // Don't use STRLEN() inside VIM_ISWHITE(), SAS/C complains: "macro
- // invocation may call function multiple times".
- l = STRLEN(s) - 1;
+ l = ml_get_len(lnum) - 1;
return VIM_ISWHITE(s[l]);
}
@@ -555,7 +571,7 @@ same_leader(
return FALSE;
if (*p == COM_START)
{
- int line_len = (int)STRLEN(ml_get(lnum));
+ int line_len = ml_get_len(lnum);
if (line_len <= leader1_len)
return FALSE;
if (leader2_flags == NULL || leader2_len == 0)
@@ -666,7 +682,7 @@ auto_format(
// in 'formatoptions' and there is a single character before the cursor.
// Otherwise the line would be broken and when typing another non-white
// next they are not joined back together.
- wasatend = (pos.col == (colnr_T)STRLEN(old));
+ wasatend = (pos.col == ml_get_curline_len());
if (*old != NUL && !trailblank && wasatend)
{
dec_cursor();
@@ -722,7 +738,7 @@ auto_format(
if (!wasatend && has_format_option(FO_WHITE_PAR))
{
new = ml_get_curline();
- len = (colnr_T)STRLEN(new);
+ len = ml_get_curline_len();
if (curwin->w_cursor.col == len)
{
pnew = vim_strnsave(new, len + 2);
@@ -795,7 +811,7 @@ comp_textwidth(
// The width is the window width minus 'wrapmargin' minus all the
// things that add to the margin.
textwidth = curwin->w_width - curbuf->b_p_wm;
- if (cmdwin_type != 0)
+ if (curbuf == cmdwin_buf)
textwidth -= 1;
#ifdef FEAT_FOLDING
textwidth -= curwin->w_p_fdc;
@@ -1199,7 +1215,7 @@ format_lines(
}
first_par_line = FALSE;
// If the line is getting long, format it next time
- if (STRLEN(ml_get_curline()) > (size_t)max_len)
+ if (ml_get_curline_len() > max_len)
force_format = TRUE;
else
force_format = FALSE;
diff --git a/src/textobject.c b/src/textobject.c
index 015b33b..1890d7c 100644
--- a/src/textobject.c
+++ b/src/textobject.c
@@ -232,7 +232,7 @@ findpar(
// Put the cursor on the last character in the last line and make the
// motion inclusive.
- if ((curwin->w_cursor.col = (colnr_T)STRLEN(line)) != 0)
+ if ((curwin->w_cursor.col = ml_get_len(curr)) != 0)
{
--curwin->w_cursor.col;
curwin->w_cursor.col -=
diff --git a/src/textprop.c b/src/textprop.c
index 168b180..a976570 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -637,7 +637,7 @@ get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change)
// Fetch the line to get the ml_line_len field updated.
text = ml_get_buf(buf, lnum, will_change);
- textlen = STRLEN(text) + 1;
+ textlen = ml_get_buf_len(buf, lnum) + 1;
proplen = buf->b_ml.ml_line_len - textlen;
if (proplen == 0)
return 0;
@@ -758,6 +758,11 @@ text_prop_compare(const void *s1, const void *s2)
tp2 = &text_prop_compare_props[idx2];
col1 = tp1->tp_col;
col2 = tp2->tp_col;
+
+ // property that inserts text has priority over one that doesn't
+ if ((tp1->tp_id < 0) != (tp2->tp_id < 0))
+ return tp1->tp_id < 0 ? 1 : -1;
+
if (col1 == MAXCOL || col2 == MAXCOL)
{
int order1 = text_prop_order(tp1->tp_flags);
@@ -768,10 +773,6 @@ text_prop_compare(const void *s1, const void *s2)
return order1 < order2 ? 1 : -1;
}
- // property that inserts text has priority over one that doesn't
- if ((tp1->tp_id < 0) != (tp2->tp_id < 0))
- return tp1->tp_id < 0 ? 1 : -1;
-
// check highest priority, defined by the type
pt1 = text_prop_type_by_id(text_prop_compare_buf, tp1->tp_type);
pt2 = text_prop_type_by_id(text_prop_compare_buf, tp2->tp_type);
@@ -863,7 +864,7 @@ set_text_props(linenr_T lnum, char_u *props, int len)
int textlen;
text = ml_get(lnum);
- textlen = (int)STRLEN(text) + 1;
+ textlen = ml_get_len(lnum) + 1;
newtext = alloc(textlen + len);
if (newtext == NULL)
return;
@@ -1090,7 +1091,7 @@ f_prop_clear(typval_T *argvars, typval_T *rettv UNUSED)
if (lnum > buf->b_ml.ml_line_count)
break;
text = ml_get_buf(buf, lnum, FALSE);
- len = STRLEN(text) + 1;
+ len = ml_get_buf_len(buf, lnum) + 1;
if ((size_t)buf->b_ml.ml_line_len > len)
{
did_clear = TRUE;
@@ -1220,7 +1221,7 @@ f_prop_find(typval_T *argvars, typval_T *rettv)
while (1)
{
char_u *text = ml_get_buf(buf, lnum, FALSE);
- size_t textlen = STRLEN(text) + 1;
+ size_t textlen = ml_get_buf_len(buf, lnum) + 1;
int count = (int)((buf->b_ml.ml_line_len - textlen)
/ sizeof(textprop_T));
int i;
@@ -1341,7 +1342,7 @@ get_props_in_line(
int add_lnum)
{
char_u *text = ml_get_buf(buf, lnum, FALSE);
- size_t textlen = STRLEN(text) + 1;
+ size_t textlen = ml_get_buf_len(buf, lnum) + 1;
int count;
int i;
textprop_T prop;
@@ -1674,13 +1675,11 @@ f_prop_remove(typval_T *argvars, typval_T *rettv)
end = buf->b_ml.ml_line_count;
for (lnum = start; lnum <= end; ++lnum)
{
- char_u *text;
size_t len;
if (lnum > buf->b_ml.ml_line_count)
break;
- text = ml_get_buf(buf, lnum, FALSE);
- len = STRLEN(text) + 1;
+ len = ml_get_buf_len(buf, lnum) + 1;
if ((size_t)buf->b_ml.ml_line_len > len)
{
static textprop_T textprop; // static because of alignment
diff --git a/src/typval.c b/src/typval.c
index af96b31..62958f6 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -623,6 +623,16 @@ check_for_opt_dict_arg(typval_T *args, int idx)
|| check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
}
+/*
+ * Check for an optional non-NULL dict argument at 'idx'
+ */
+ int
+check_for_opt_nonnull_dict_arg(typval_T *args, int idx)
+{
+ return (args[idx].v_type == VAR_UNKNOWN
+ || check_for_nonnull_dict_arg(args, idx) != FAIL) ? OK : FAIL;
+}
+
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
/*
* Give an error and return FAIL unless "args[idx]" is a channel or a job.
diff --git a/src/undo.c b/src/undo.c
index b2c4e9a..1cd8912 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -123,6 +123,7 @@ static void serialize_visualinfo(bufinfo_T *bi, visualinfo_T *info);
static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info);
#endif
static void u_saveline(linenr_T lnum);
+static void u_blockfree(buf_T *buf);
#define U_ALLOC_LINE(size) lalloc(size, FALSE)
@@ -3472,7 +3473,7 @@ u_freeentry(u_entry_T *uep, long n)
/*
* invalidate the undo buffer; called when storage has already been released
*/
- void
+ static void
u_clearall(buf_T *buf)
{
buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
@@ -3484,6 +3485,30 @@ u_clearall(buf_T *buf)
}
/*
+ * Free all allocated memory blocks for the buffer 'buf'.
+ */
+ static void
+u_blockfree(buf_T *buf)
+{
+ while (buf->b_u_oldhead != NULL)
+ u_freeheader(buf, buf->b_u_oldhead, NULL);
+ vim_free(buf->b_u_line_ptr.ul_line);
+}
+
+/*
+ * Free all allocated memory blocks for the buffer 'buf'.
+ * and invalidate the undo buffer
+ */
+ void
+u_clearallandblockfree(buf_T *buf)
+{
+ u_blockfree(buf);
+ u_clearall(buf);
+}
+
+
+
+/*
* Save the line "lnum" for the "U" command.
*/
static void
@@ -3563,17 +3588,6 @@ u_undoline(void)
}
/*
- * Free all allocated memory blocks for the buffer 'buf'.
- */
- void
-u_blockfree(buf_T *buf)
-{
- while (buf->b_u_oldhead != NULL)
- u_freeheader(buf, buf->b_u_oldhead, NULL);
- vim_free(buf->b_u_line_ptr.ul_line);
-}
-
-/*
* Check if the 'modified' flag is set, or 'ff' has changed (only need to
* check the first character, because it can only be "dos", "unix" or "mac").
* "nofile" and "scratch" type buffers are considered to always be unchanged.
diff --git a/src/userfunc.c b/src/userfunc.c
index 64761ec..ce144a3 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -4459,12 +4459,13 @@ trans_function_name_ext(
}
}
// The function name must start with an upper case letter (unless it is a
- // Vim9 class new() function or a Vim9 class private method)
+ // Vim9 class new() function or a Vim9 class private method or one of the
+ // supported Vim9 object builtin functions)
else if (!(flags & TFN_INT)
&& (builtin_function(lv.ll_name, len)
|| (vim9script && *lv.ll_name == '_'))
&& !((flags & TFN_IN_CLASS)
- && (STRNCMP(lv.ll_name, "new", 3) == 0
+ && (is_valid_builtin_obj_methodname(lv.ll_name)
|| (*lv.ll_name == '_'))))
{
semsg(_(vim9script ? e_function_name_must_start_with_capital_str
@@ -4976,7 +4977,10 @@ define_function(
: eval_isnamec(name_base[i])); ++i)
;
if (name_base[i] != NUL)
+ {
emsg_funcname(e_invalid_argument_str, arg);
+ goto ret_free;
+ }
// In Vim9 script a function cannot have the same name as a
// variable.
@@ -5546,6 +5550,60 @@ find_func_by_name(char_u *name, compiletype_T *compile_type)
}
/*
+ * Compile the :def function "ufunc". If "cl" is not NULL, then compile the
+ * class or object method "ufunc" in "cl".
+ */
+ void
+defcompile_function(ufunc_T *ufunc, class_T *cl)
+{
+ compiletype_T compile_type = CT_NONE;
+
+ if (func_needs_compiling(ufunc, compile_type))
+ (void)compile_def_function(ufunc, FALSE, compile_type, NULL);
+ else
+ smsg(_("Function %s%s%s does not need compiling"),
+ cl != NULL ? cl->class_name : (char_u *)"",
+ cl != NULL ? (char_u *)"." : (char_u *)"",
+ ufunc->uf_name);
+}
+
+/*
+ * Compile all the :def functions defined in the current script
+ */
+ static void
+defcompile_funcs_in_script(void)
+{
+ long todo = (long)func_hashtab.ht_used;
+ int changed = func_hashtab.ht_changed;
+ hashitem_T *hi;
+
+ for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
+ {
+ if (!HASHITEM_EMPTY(hi))
+ {
+ --todo;
+ ufunc_T *ufunc = HI2UF(hi);
+ if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid
+ && ufunc->uf_def_status == UF_TO_BE_COMPILED
+ && (ufunc->uf_flags & FC_DEAD) == 0)
+ {
+ (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
+
+ if (func_hashtab.ht_changed != changed)
+ {
+ // a function has been added or removed, need to start
+ // over
+ todo = (long)func_hashtab.ht_used;
+ changed = func_hashtab.ht_changed;
+ hi = func_hashtab.ht_array;
+ --hi;
+ }
+ }
+ }
+ }
+}
+
+/*
* :defcompile - compile all :def functions in the current script that need to
* be compiled or the one specified by the argument.
* Skips dead functions. Doesn't do profiling.
@@ -5555,46 +5613,29 @@ ex_defcompile(exarg_T *eap)
{
if (*eap->arg != NUL)
{
- compiletype_T compile_type = CT_NONE;
- ufunc_T *ufunc = find_func_by_name(eap->arg, &compile_type);
- if (ufunc != NULL)
+ typval_T tv;
+
+ if (is_class_name(eap->arg, &tv))
{
- if (func_needs_compiling(ufunc, compile_type))
- (void)compile_def_function(ufunc, FALSE, compile_type, NULL);
- else
- smsg(_("Function %s does not need compiling"), eap->arg);
+ class_T *cl = tv.vval.v_class;
+
+ if (cl != NULL)
+ defcompile_class(cl);
+ }
+ else
+ {
+ compiletype_T compile_type = CT_NONE;
+ ufunc_T *ufunc = find_func_by_name(eap->arg, &compile_type);
+ if (ufunc != NULL)
+ defcompile_function(ufunc, NULL);
}
}
else
{
- long todo = (long)func_hashtab.ht_used;
- int changed = func_hashtab.ht_changed;
- hashitem_T *hi;
-
- for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
- {
- if (!HASHITEM_EMPTY(hi))
- {
- --todo;
- ufunc_T *ufunc = HI2UF(hi);
- if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid
- && ufunc->uf_def_status == UF_TO_BE_COMPILED
- && (ufunc->uf_flags & FC_DEAD) == 0)
- {
- (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
+ defcompile_funcs_in_script();
- if (func_hashtab.ht_changed != changed)
- {
- // a function has been added or removed, need to start
- // over
- todo = (long)func_hashtab.ht_used;
- changed = func_hashtab.ht_changed;
- hi = func_hashtab.ht_array;
- --hi;
- }
- }
- }
- }
+ // compile all the class defined in the current script
+ defcompile_classes_in_script();
}
}
diff --git a/src/version.c b/src/version.c
index 2e178f3..32037e3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,372 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 199,
+/**/
+ 198,
+/**/
+ 197,
+/**/
+ 196,
+/**/
+ 195,
+/**/
+ 194,
+/**/
+ 193,
+/**/
+ 192,
+/**/
+ 191,
+/**/
+ 190,
+/**/
+ 189,
+/**/
+ 188,
+/**/
+ 187,
+/**/
+ 186,
+/**/
+ 185,
+/**/
+ 184,
+/**/
+ 183,
+/**/
+ 182,
+/**/
+ 181,
+/**/
+ 180,
+/**/
+ 179,
+/**/
+ 178,
+/**/
+ 177,
+/**/
+ 176,
+/**/
+ 175,
+/**/
+ 174,
+/**/
+ 173,
+/**/
+ 172,
+/**/
+ 171,
+/**/
+ 170,
+/**/
+ 169,
+/**/
+ 168,
+/**/
+ 167,
+/**/
+ 166,
+/**/
+ 165,
+/**/
+ 164,
+/**/
+ 163,
+/**/
+ 162,
+/**/
+ 161,
+/**/
+ 160,
+/**/
+ 159,
+/**/
+ 158,
+/**/
+ 157,
+/**/
+ 156,
+/**/
+ 155,
+/**/
+ 154,
+/**/
+ 153,
+/**/
+ 152,
+/**/
+ 151,
+/**/
+ 150,
+/**/
+ 149,
+/**/
+ 148,
+/**/
+ 147,
+/**/
+ 146,
+/**/
+ 145,
+/**/
+ 144,
+/**/
+ 143,
+/**/
+ 142,
+/**/
+ 141,
+/**/
+ 140,
+/**/
+ 139,
+/**/
+ 138,
+/**/
+ 137,
+/**/
+ 136,
+/**/
+ 135,
+/**/
+ 134,
+/**/
+ 133,
+/**/
+ 132,
+/**/
+ 131,
+/**/
+ 130,
+/**/
+ 129,
+/**/
+ 128,
+/**/
+ 127,
+/**/
+ 126,
+/**/
+ 125,
+/**/
+ 124,
+/**/
+ 123,
+/**/
+ 122,
+/**/
+ 121,
+/**/
+ 120,
+/**/
+ 119,
+/**/
+ 118,
+/**/
+ 117,
+/**/
+ 116,
+/**/
+ 115,
+/**/
+ 114,
+/**/
+ 113,
+/**/
+ 112,
+/**/
+ 111,
+/**/
+ 110,
+/**/
+ 109,
+/**/
+ 108,
+/**/
+ 107,
+/**/
+ 106,
+/**/
+ 105,
+/**/
+ 104,
+/**/
+ 103,
+/**/
+ 102,
+/**/
+ 101,
+/**/
+ 100,
+/**/
+ 99,
+/**/
+ 98,
+/**/
+ 97,
+/**/
+ 96,
+/**/
+ 95,
+/**/
+ 94,
+/**/
+ 93,
+/**/
+ 92,
+/**/
+ 91,
+/**/
+ 90,
+/**/
+ 89,
+/**/
+ 88,
+/**/
+ 87,
+/**/
+ 86,
+/**/
+ 85,
+/**/
+ 84,
+/**/
+ 83,
+/**/
+ 82,
+/**/
+ 81,
+/**/
+ 80,
+/**/
+ 79,
+/**/
+ 78,
+/**/
+ 77,
+/**/
+ 76,
+/**/
+ 75,
+/**/
+ 74,
+/**/
+ 73,
+/**/
+ 72,
+/**/
+ 71,
+/**/
+ 70,
+/**/
+ 69,
+/**/
+ 68,
+/**/
+ 67,
+/**/
+ 66,
+/**/
+ 65,
+/**/
+ 64,
+/**/
+ 63,
+/**/
+ 62,
+/**/
+ 61,
+/**/
+ 60,
+/**/
+ 59,
+/**/
+ 58,
+/**/
+ 57,
+/**/
+ 56,
+/**/
+ 55,
+/**/
+ 54,
+/**/
+ 53,
+/**/
+ 52,
+/**/
+ 51,
+/**/
+ 50,
+/**/
+ 49,
+/**/
+ 48,
+/**/
+ 47,
+/**/
+ 46,
+/**/
+ 45,
+/**/
+ 44,
+/**/
+ 43,
+/**/
+ 42,
+/**/
+ 41,
+/**/
+ 40,
+/**/
+ 39,
+/**/
+ 38,
+/**/
+ 37,
+/**/
+ 36,
+/**/
+ 35,
+/**/
+ 34,
+/**/
+ 33,
+/**/
+ 32,
+/**/
+ 31,
+/**/
+ 30,
+/**/
+ 29,
+/**/
+ 28,
+/**/
+ 27,
+/**/
+ 26,
+/**/
+ 25,
+/**/
+ 24,
+/**/
+ 23,
+/**/
+ 22,
+/**/
+ 21,
+/**/
+ 20,
+/**/
+ 19,
+/**/
+ 18,
+/**/
+ 17,
+/**/
16,
/**/
15,
diff --git a/src/vim.h b/src/vim.h
index e41dfef..85d92d5 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -627,6 +627,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
// flags for screen_line()
#define SLF_RIGHTLEFT 1
#define SLF_POPUP 2
+#define SLF_INC_VCOL 4
#define MB_FILLER_CHAR '<' // character used when a double-width character
// doesn't fit.
@@ -1255,6 +1256,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define WSP_BELOW 0x40 // put new window below/right
#define WSP_ABOVE 0x80 // put new window above/left
#define WSP_NEWLOC 0x100 // don't copy location list
+#define WSP_FORCE_ROOM 0x200 // ignore "not enough room" errors
/*
* arguments for gui_set_shellsize()
@@ -1422,6 +1424,7 @@ enum auto_event
EVENT_TERMINALWINOPEN, // after a terminal buffer was created and
// entering its window
EVENT_TERMRESPONSE, // after setting "v:termresponse"
+ EVENT_TERMRESPONSEALL, // after setting terminal response vars
EVENT_TEXTCHANGED, // text was modified not in Insert mode
EVENT_TEXTCHANGEDI, // text was modified in Insert mode
EVENT_TEXTCHANGEDP, // TextChangedI with popup menu visible
@@ -1434,7 +1437,8 @@ enum auto_event
EVENT_VIMRESIZED, // after Vim window was resized
EVENT_WINENTER, // after entering a window
EVENT_WINLEAVE, // before leaving a window
- EVENT_WINNEW, // when entering a new window
+ EVENT_WINNEWPRE, // before creating a new window
+ EVENT_WINNEW, // after creating a new window
EVENT_WINCLOSED, // after closing a window
EVENT_VIMSUSPEND, // before Vim is suspended
EVENT_VIMRESUME, // after Vim is resumed
@@ -2377,6 +2381,7 @@ typedef int (*opt_expand_cb_T)(optexpand_T *args, int *numMatches, char_u ***mat
#define ASSIGN_FOR_LOOP 0x40 // assigning to loop variable
#define ASSIGN_INIT 0x80 // not assigning a value, just a declaration
#define ASSIGN_UPDATE_BLOCK_ID 0x100 // update sav_block_id
+#define ASSIGN_COMPOUND_OP 0x200 // compound operator e.g. "+="
#include "ex_cmds.h" // Ex command defines
#include "spell.h" // spell checking stuff
diff --git a/src/vim9class.c b/src/vim9class.c
index e5d9aeb..7227c3d 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -208,7 +208,7 @@ add_member(
* "parent_count" is the number of members in the parent class
* "members" will be set to the newly allocated array of members and
* "member_count" set to the number of members.
- * Returns OK or FAIL.
+ * Returns OK on success and FAIL on memory allocation failure.
*/
static int
add_members_to_class(
@@ -301,6 +301,7 @@ object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl)
*/
static int
validate_extends_class(
+ class_T *cl,
char_u *extends_name,
class_T **extends_clp,
int is_class)
@@ -308,6 +309,12 @@ validate_extends_class(
typval_T tv;
int success = FALSE;
+ if (STRCMP(cl->class_name, extends_name) == 0)
+ {
+ semsg(_(e_cannot_extend_str), extends_name);
+ return success;
+ }
+
tv.v_type = VAR_UNKNOWN;
if (eval_variable_import(extends_name, &tv) == FAIL)
{
@@ -974,6 +981,100 @@ is_valid_constructor(ufunc_T *uf, int is_abstract, int has_static)
}
/*
+ * Returns TRUE if 'uf' is a supported builtin method and has the correct
+ * method signature.
+ */
+ static int
+object_check_builtin_method_sig(ufunc_T *uf)
+{
+ char_u *name = uf->uf_name;
+ int valid = FALSE;
+ type_T method_sig;
+ type_T method_rt;
+ where_T where = WHERE_INIT;
+
+ // validate the method signature
+ CLEAR_FIELD(method_sig);
+ CLEAR_FIELD(method_rt);
+ method_sig.tt_type = VAR_FUNC;
+
+ if (STRCMP(name, "len") == 0)
+ {
+ // def __len(): number
+ method_rt.tt_type = VAR_NUMBER;
+ method_sig.tt_member = &method_rt;
+ valid = TRUE;
+ }
+ else if (STRCMP(name, "empty") == 0)
+ {
+ // def __empty(): bool
+ method_rt.tt_type = VAR_BOOL;
+ method_sig.tt_member = &method_rt;
+ valid = TRUE;
+ }
+ else if (STRCMP(name, "string") == 0)
+ {
+ // def __string(): string
+ method_rt.tt_type = VAR_STRING;
+ method_sig.tt_member = &method_rt;
+ valid = TRUE;
+ }
+ else
+ semsg(_(e_builtin_object_method_str_not_supported), uf->uf_name);
+
+ where.wt_func_name = (char *)uf->uf_name;
+ where.wt_kind = WT_METHOD;
+ if (valid && !check_type(&method_sig, uf->uf_func_type, TRUE, where))
+ valid = FALSE;
+
+ return valid;
+}
+
+/*
+ * Returns TRUE if "funcname" is a supported builtin object method name
+ */
+ int
+is_valid_builtin_obj_methodname(char_u *funcname)
+{
+ switch (funcname[0])
+ {
+ case 'e':
+ return STRNCMP(funcname, "empty", 5) == 0;
+
+ case 'l':
+ return STRNCMP(funcname, "len", 3) == 0;
+
+ case 'n':
+ return STRNCMP(funcname, "new", 3) == 0;
+
+ case 's':
+ return STRNCMP(funcname, "string", 6) == 0;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Returns the builtin method "name" in object "obj". Returns NULL if the
+ * method is not found.
+ */
+ ufunc_T *
+class_get_builtin_method(
+ class_T *cl,
+ class_builtin_T builtin_method,
+ int *method_idx)
+{
+ *method_idx = -1;
+
+ if (cl == NULL)
+ return NULL;
+
+ *method_idx = cl->class_builtin_methods[builtin_method];
+ return *method_idx != -1 ? cl->class_obj_methods[*method_idx] : NULL;
+}
+
+/*
* Update the interface class lookup table for the member index on the
* interface to the member index in the class implementing the interface.
* And a lookup table for the object method index on the interface
@@ -1327,6 +1428,33 @@ add_classfuncs_objmethods(
}
/*
+ * Update the index of object methods called by builtin functions.
+ */
+ static void
+update_builtin_method_index(class_T *cl)
+{
+ int i;
+
+ for (i = 0; i < CLASS_BUILTIN_MAX; i++)
+ cl->class_builtin_methods[i] = -1;
+
+ for (i = 0; i < cl->class_obj_method_count; i++)
+ {
+ ufunc_T *uf = cl->class_obj_methods[i];
+
+ if (cl->class_builtin_methods[CLASS_BUILTIN_STRING] == -1
+ && STRCMP(uf->uf_name, "string") == 0)
+ cl->class_builtin_methods[CLASS_BUILTIN_STRING] = i;
+ else if (cl->class_builtin_methods[CLASS_BUILTIN_EMPTY] == -1 &&
+ STRCMP(uf->uf_name, "empty") == 0)
+ cl->class_builtin_methods[CLASS_BUILTIN_EMPTY] = i;
+ else if (cl->class_builtin_methods[CLASS_BUILTIN_LEN] == -1 &&
+ STRCMP(uf->uf_name, "len") == 0)
+ cl->class_builtin_methods[CLASS_BUILTIN_LEN] = i;
+ }
+}
+
+/*
* Return the end of the class name starting at "arg". Valid characters in a
* class name are alphanumeric characters and "_". Also handles imported class
* names.
@@ -1521,6 +1649,36 @@ early_ret:
garray_T objmethods;
ga_init2(&objmethods, sizeof(ufunc_T *), 10);
+ class_T *cl = NULL;
+ class_T *extends_cl = NULL; // class from "extends" argument
+ class_T **intf_classes = NULL;
+
+ cl = ALLOC_CLEAR_ONE(class_T);
+ if (cl == NULL)
+ goto cleanup;
+ if (!is_class)
+ cl->class_flags = CLASS_INTERFACE;
+ else if (is_abstract)
+ cl->class_flags = CLASS_ABSTRACT;
+
+ cl->class_refcount = 1;
+ cl->class_name = vim_strnsave(name_start, name_end - name_start);
+ if (cl->class_name == NULL)
+ goto cleanup;
+
+ // Add the class to the script-local variables.
+ // TODO: handle other context, e.g. in a function
+ // TODO: does uf_hash need to be cleared?
+ typval_T tv;
+ tv.v_type = VAR_CLASS;
+ tv.vval.v_class = cl;
+ is_export = class_export;
+ SOURCING_LNUM = start_lnum;
+ int rc = set_var_const(cl->class_name, current_sctx.sc_sid,
+ NULL, &tv, FALSE, 0, 0);
+ if (rc == FAIL)
+ goto cleanup;
+
/*
* Go over the body of the class/interface until "endclass" or
* "endinterface" is found.
@@ -1721,13 +1879,10 @@ early_ret:
&varname_end, &has_type, &type_list, &type,
is_class ? &init_expr: NULL) == FAIL)
break;
- if (is_reserved_varname(varname, varname_end))
- {
- vim_free(init_expr);
- break;
- }
- if (is_duplicate_variable(&classmembers, &objmembers, varname,
- varname_end))
+
+ if (is_reserved_varname(varname, varname_end)
+ || is_duplicate_variable(&classmembers, &objmembers,
+ varname, varname_end))
{
vim_free(init_expr);
break;
@@ -1758,6 +1913,7 @@ early_ret:
{
exarg_T ea;
garray_T lines_to_free;
+ int is_new = STRNCMP(p, "new", 3) == 0;
if (has_public)
{
@@ -1774,12 +1930,17 @@ early_ret:
break;
}
- if (*p == '_' && *(p + 1) == '_')
+ if (!is_class && *p == '_')
{
- // double underscore prefix for a method name is currently
- // reserved. This could be used in the future to support
- // object methods called by Vim builtin functions.
- semsg(_(e_cannot_use_reserved_name_str), p);
+ // private methods are not supported in an interface
+ semsg(_(e_protected_method_not_supported_in_interface), p);
+ break;
+ }
+
+ if (has_static && !is_new && SAFE_islower(*p) &&
+ is_valid_builtin_obj_methodname(p))
+ {
+ semsg(_(e_builtin_class_method_not_supported), p);
break;
}
@@ -1803,9 +1964,9 @@ early_ret:
if (uf != NULL)
{
char_u *name = uf->uf_name;
- int is_new = STRNCMP(name, "new", 3) == 0;
- if (!is_class && *name == '_')
+ if (is_new && !is_valid_constructor(uf, is_abstract,
+ has_static))
{
// private variables are not supported in an interface
semsg(_(e_protected_method_not_supported_in_interface),
@@ -1813,8 +1974,10 @@ early_ret:
func_clear_free(uf, FALSE);
break;
}
- if (is_new && !is_valid_constructor(uf, is_abstract,
- has_static))
+
+ // check for builtin method
+ if (!is_new && SAFE_islower(*name) &&
+ !object_check_builtin_method_sig(uf))
{
func_clear_free(uf, FALSE);
break;
@@ -1855,15 +2018,13 @@ early_ret:
}
vim_free(theline);
- class_T *extends_cl = NULL; // class from "extends" argument
-
/*
* Check a few things before defining the class.
*/
// Check the "extends" class is valid.
if (success && extends != NULL)
- success = validate_extends_class(extends, &extends_cl, is_class);
+ success = validate_extends_class(cl, extends, &extends_cl, is_class);
VIM_CLEAR(extends);
// Check the new object methods to make sure their access (public or
@@ -1890,8 +2051,6 @@ early_ret:
success = validate_abstract_class_methods(&classfunctions,
&objmethods, extends_cl);
- class_T **intf_classes = NULL;
-
// Check all "implements" entries are valid.
if (success && ga_impl.ga_len > 0)
{
@@ -1906,24 +2065,10 @@ early_ret:
success = check_func_arg_names(&classfunctions, &objmethods,
&classmembers);
- class_T *cl = NULL;
if (success)
{
// "endclass" encountered without failures: Create the class.
- cl = ALLOC_CLEAR_ONE(class_T);
- if (cl == NULL)
- goto cleanup;
- if (!is_class)
- cl->class_flags = CLASS_INTERFACE;
- else if (is_abstract)
- cl->class_flags = CLASS_ABSTRACT;
-
- cl->class_refcount = 1;
- cl->class_name = vim_strnsave(name_start, name_end - name_start);
- if (cl->class_name == NULL)
- goto cleanup;
-
if (extends_cl != NULL)
{
cl->class_extends = extends_cl;
@@ -1997,6 +2142,8 @@ early_ret:
&objmethods) == FAIL)
goto cleanup;
+ update_builtin_method_index(cl);
+
cl->class_type.tt_type = VAR_CLASS;
cl->class_type.tt_class = cl;
cl->class_object_type.tt_type = VAR_OBJECT;
@@ -2008,41 +2155,10 @@ early_ret:
// TODO:
// - Fill hashtab with object members and methods ?
- // Add the class to the script-local variables.
- // TODO: handle other context, e.g. in a function
- // TODO: does uf_hash need to be cleared?
- typval_T tv;
- tv.v_type = VAR_CLASS;
- tv.vval.v_class = cl;
- is_export = class_export;
- SOURCING_LNUM = start_lnum;
- set_var_const(cl->class_name, current_sctx.sc_sid,
- NULL, &tv, FALSE, 0, 0);
return;
}
cleanup:
- if (cl != NULL)
- {
- vim_free(cl->class_name);
- vim_free(cl->class_class_functions);
- if (cl->class_interfaces != NULL)
- {
- for (int i = 0; i < cl->class_interface_count; ++i)
- vim_free(cl->class_interfaces[i]);
- vim_free(cl->class_interfaces);
- }
- if (cl->class_interfaces_cl != NULL)
- {
- for (int i = 0; i < cl->class_interface_count; ++i)
- class_unref(cl->class_interfaces_cl[i]);
- vim_free(cl->class_interfaces_cl);
- }
- vim_free(cl->class_obj_members);
- vim_free(cl->class_obj_methods);
- vim_free(cl);
- }
-
vim_free(extends);
class_unref(extends_cl);
@@ -3225,6 +3341,173 @@ member_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len)
}
/*
+ * Compile all the class and object methods in "cl".
+ */
+ void
+defcompile_class(class_T *cl)
+{
+ for (int loop = 1; loop <= 2; ++loop)
+ {
+ int func_count = loop == 1 ? cl->class_class_function_count
+ : cl->class_obj_method_count;
+ for (int i = 0; i < func_count; i++)
+ {
+ ufunc_T *ufunc = loop == 1 ? cl->class_class_functions[i]
+ : cl->class_obj_methods[i];
+ defcompile_function(ufunc, cl);
+ }
+ }
+}
+
+/*
+ * Compile all the classes defined in the current script
+ */
+ void
+defcompile_classes_in_script(void)
+{
+ for (class_T *cl = first_class; cl != NULL; cl = cl->class_next_used)
+ {
+ if (eval_variable(cl->class_name, 0, 0, NULL, NULL,
+ EVAL_VAR_NOAUTOLOAD | EVAL_VAR_NO_FUNC) != FAIL)
+ defcompile_class(cl);
+ }
+}
+
+/*
+ * Returns TRUE if "name" is the name of a class. The typval for the class is
+ * returned in "rettv".
+ */
+ int
+is_class_name(char_u *name, typval_T *rettv)
+{
+ rettv->v_type = VAR_UNKNOWN;
+
+ if (eval_variable(name, 0, 0, rettv, NULL, EVAL_VAR_NOAUTOLOAD |
+ EVAL_VAR_NO_FUNC) != FAIL)
+ return rettv->v_type == VAR_CLASS;
+ return FALSE;
+}
+
+/*
+ * Calls the object builtin method "name" with arguments "argv". The value
+ * returned by the builtin method is in "rettv". Returns OK or FAIL.
+ */
+ static int
+object_call_builtin_method(
+ object_T *obj,
+ class_builtin_T builtin_method,
+ int argc,
+ typval_T *argv,
+ typval_T *rettv)
+{
+ ufunc_T *uf;
+ int midx;
+
+ if (obj == NULL)
+ return FAIL;
+
+ uf = class_get_builtin_method(obj->obj_class, builtin_method, &midx);
+ if (uf == NULL)
+ return FAIL;
+
+ funccall_T *fc = create_funccal(uf, rettv);
+ int r;
+
+ if (fc == NULL)
+ return FAIL;
+
+ ++obj->obj_refcount;
+
+ r = call_def_function(uf, argc, argv, 0, NULL, obj, fc, rettv);
+
+ remove_funccal();
+
+ return r;
+}
+
+/*
+ * Calls the object "empty()" method and returns the method retun value. In
+ * case of an error, returns TRUE.
+ */
+ int
+object_empty(object_T *obj)
+{
+ typval_T rettv;
+
+ if (object_call_builtin_method(obj, CLASS_BUILTIN_EMPTY, 0, NULL, &rettv)
+ == FAIL)
+ return TRUE;
+
+ return tv_get_bool(&rettv);
+}
+
+/*
+ * Use the object "len()" method to get an object length. Returns 0 if the
+ * method is not found or there is an error.
+ */
+ int
+object_len(object_T *obj)
+{
+ typval_T rettv;
+
+ if (object_call_builtin_method(obj, CLASS_BUILTIN_LEN, 0, NULL, &rettv)
+ == FAIL)
+ return 0;
+
+ return tv_to_number(&rettv);
+}
+
+/*
+ * Return a textual representation of object "obj"
+ */
+ char_u *
+object_string(
+ object_T *obj,
+ char_u *numbuf,
+ int copyID,
+ int echo_style,
+ int restore_copyID,
+ int composite_val)
+{
+ typval_T rettv;
+
+ if (object_call_builtin_method(obj, CLASS_BUILTIN_STRING, 0, NULL, &rettv)
+ == OK
+ && rettv.vval.v_string != NULL)
+ return rettv.vval.v_string;
+ else
+ {
+ garray_T ga;
+ ga_init2(&ga, 1, 50);
+
+ ga_concat(&ga, (char_u *)"object of ");
+ class_T *cl = obj == NULL ? NULL : obj->obj_class;
+ ga_concat(&ga, cl == NULL ? (char_u *)"[unknown]"
+ : cl->class_name);
+ if (cl != NULL)
+ {
+ ga_concat(&ga, (char_u *)" {");
+ for (int i = 0; i < cl->class_obj_member_count; ++i)
+ {
+ if (i > 0)
+ ga_concat(&ga, (char_u *)", ");
+ ocmember_T *m = &cl->class_obj_members[i];
+ ga_concat(&ga, m->ocm_name);
+ ga_concat(&ga, (char_u *)": ");
+ char_u *tf = NULL;
+ ga_concat(&ga, echo_string_core(
+ (typval_T *)(obj + 1) + i,
+ &tf, numbuf, copyID, echo_style,
+ restore_copyID, composite_val));
+ vim_free(tf);
+ }
+ ga_concat(&ga, (char_u *)"}");
+ }
+ return ga.ga_data;
+ }
+}
+
+/*
* Return TRUE when the class "cl", its base class or one of the implemented
* interfaces matches the class "other_cl".
*/
diff --git a/src/vim9compile.c b/src/vim9compile.c
index d6faa7b..8f67d8a 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2285,7 +2285,17 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
if (dot - var_start == 4 && STRNCMP(var_start, "this", 4) == 0)
{
// load "this"
- if (generate_LOAD(cctx, ISN_LOAD, 0, NULL, lhs->lhs_type) == FAIL)
+ lvar_T *lvar = lhs->lhs_lvar;
+ int rc;
+
+ if (lvar->lv_from_outer > 0)
+ rc = generate_LOADOUTER(cctx, lvar->lv_idx,
+ lvar->lv_from_outer, lvar->lv_loop_depth,
+ lvar->lv_loop_idx, type);
+ else
+ rc = generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
+
+ if (rc == FAIL)
return FAIL;
}
else
diff --git a/src/vim9expr.c b/src/vim9expr.c
index 38a65d4..9d67aea 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1014,6 +1014,32 @@ failret:
}
/*
+ * Compile a builtin method call of an object (e.g. string(), len(), empty(),
+ * etc.) if the class implements it.
+ */
+ static int
+compile_builtin_method_call(cctx_T *cctx, class_builtin_T builtin_method)
+{
+ type_T *type = get_decl_type_on_stack(cctx, 0);
+ int res = FAIL;
+
+ // If the built in function is invoked on an object and the class
+ // implements the corresponding built in method, then invoke the object
+ // method.
+ if (type->tt_type == VAR_OBJECT)
+ {
+ int method_idx;
+ ufunc_T *uf = class_get_builtin_method(type->tt_class, builtin_method,
+ &method_idx);
+ if (uf != NULL)
+ res = generate_CALL(cctx, uf, type->tt_class, method_idx, 0);
+ }
+
+ return res;
+}
+
+
+/*
* Compile a function call: name(arg1, arg2)
* "arg" points to "name", "arg + varlen" to the "(".
* "argcount_init" is 1 for "value->method()"
@@ -1170,6 +1196,20 @@ compile_call(
idx = -1;
}
+ class_builtin_T builtin_method = CLASS_BUILTIN_INVALID;
+ if (STRCMP(name, "string") == 0)
+ builtin_method = CLASS_BUILTIN_STRING;
+ else if (STRCMP(name, "empty") == 0)
+ builtin_method = CLASS_BUILTIN_EMPTY;
+ else if (STRCMP(name, "len") == 0)
+ builtin_method = CLASS_BUILTIN_LEN;
+ if (builtin_method != CLASS_BUILTIN_INVALID)
+ {
+ res = compile_builtin_method_call(cctx, builtin_method);
+ if (res == OK)
+ idx = -1;
+ }
+
if (idx >= 0)
res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
}
@@ -2739,7 +2779,7 @@ compile_expr9(
if (compile_subscript(arg, cctx, start_leader, &end_leader,
ppconst) == FAIL)
return FAIL;
- if (ppconst->pp_used > 0)
+ if ((ppconst->pp_used > 0) && (cctx->ctx_skip != SKIP_YES))
{
// apply the '!', '-' and '+' before the constant
rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
diff --git a/src/window.c b/src/window.c
index 54e17be..9ffca77 100644
--- a/src/window.c
+++ b/src/window.c
@@ -17,8 +17,8 @@ static void frame_setheight(frame_T *curfrp, int height);
static void frame_setwidth(frame_T *curfrp, int width);
static void win_exchange(long);
static void win_rotate(int, int);
-static void win_totop(int size, int flags);
static void win_equal_rec(win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height);
+static void trigger_winnewpre(void);
static void trigger_winclosed(win_T *win);
static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp);
static frame_T *win_altframe(win_T *win, tabpage_T *tp);
@@ -53,8 +53,10 @@ static void win_goto_ver(int up, long count);
static void win_goto_hor(int left, long count);
static void frame_add_height(frame_T *frp, int n);
static void last_status_rec(frame_T *fr, int statusline);
+static void frame_flatten(frame_T *frp);
+static void winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr);
-static void make_snapshot_rec(frame_T *fr, frame_T **frp);
+static int make_snapshot_rec(frame_T *fr, frame_T **frp);
static void clear_snapshot(tabpage_T *tp, int idx);
static void clear_snapshot_rec(frame_T *fr);
static int check_snapshot_rec(frame_T *sn, frame_T *fr);
@@ -157,6 +159,37 @@ log_frame_layout(frame_T *frame)
#endif
/*
+ * Check if the current window is allowed to move to a different buffer.
+ * If the window has 'winfixbuf', this function will return FALSE.
+ */
+ int
+check_can_set_curbuf_disabled(void)
+{
+ if (curwin->w_p_wfb)
+ {
+ emsg(_(e_winfixbuf_cannot_go_to_buffer));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Check if the current window is allowed to move to a different buffer.
+ * If the window has 'winfixbuf', then forceit must be TRUE or this function
+ * will return FALSE.
+ */
+ int
+check_can_set_curbuf_forceit(int forceit)
+{
+ if (!forceit && curwin->w_p_wfb)
+ {
+ emsg(_(e_winfixbuf_cannot_go_to_buffer));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
* Return the current window, unless in the cmdline window and "prevwin" is
* set, then return "prevwin".
*/
@@ -493,9 +526,15 @@ newwindow:
case 'H':
case 'L':
CHECK_CMDWIN;
- win_totop((int)Prenum,
- ((nchar == 'H' || nchar == 'L') ? WSP_VERT : 0)
- | ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT));
+ if (ONE_WINDOW)
+ beep_flush();
+ else
+ {
+ int dir = ((nchar == 'H' || nchar == 'L') ? WSP_VERT : 0)
+ | ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT);
+
+ (void)win_splitmove(curwin, (int)Prenum, dir);
+ }
break;
// make all windows the same width and/or height
@@ -659,7 +698,7 @@ wingotofile:
find_pattern_in_path(ptr, 0, len, TRUE,
Prenum == 0 ? TRUE : FALSE, type,
- Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM);
+ Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM, FALSE);
vim_free(ptr);
curwin->w_set_curswant = TRUE;
break;
@@ -857,18 +896,18 @@ cmd_with_count(
}
/*
- * If "split_disallowed" is set give an error and return FAIL.
- * Otherwise return OK.
+ * If "split_disallowed" is set, or "wp"'s buffer is closing, give an error and
+ * return FAIL. Otherwise return OK.
*/
- static int
-check_split_disallowed(void)
+ int
+check_split_disallowed(win_T *wp)
{
if (split_disallowed > 0)
{
emsg(_(e_cant_split_window_while_closing_another));
return FAIL;
}
- if (curwin->w_buffer->b_locked_split)
+ if (wp->w_buffer->b_locked_split)
{
emsg(_(e_cannot_split_window_when_closing_buffer));
return FAIL;
@@ -897,7 +936,7 @@ win_split(int size, int flags)
if (ERROR_IF_ANY_POPUP_WINDOW)
return FAIL;
- if (check_split_disallowed() == FAIL)
+ if (check_split_disallowed(curwin) == FAIL)
return FAIL;
// When the ":tab" modifier was used open a new tab page instead.
@@ -919,13 +958,18 @@ win_split(int size, int flags)
else
clear_snapshot(curtab, SNAP_HELP_IDX);
- return win_split_ins(size, flags, NULL, 0);
+ return win_split_ins(size, flags, NULL, 0, NULL);
}
/*
* When "new_wp" is NULL: split the current window in two.
* When "new_wp" is not NULL: insert this window at the far
* top/left/right/bottom.
+ * When "to_flatten" is not NULL: flatten this frame before reorganising frames;
+ * remains unflattened on failure.
+ *
+ * On failure, if "new_wp" was not NULL, no changes will have been made to the
+ * window layout or sizes.
* Return FAIL for failure, OK otherwise.
*/
int
@@ -933,7 +977,8 @@ win_split_ins(
int size,
int flags,
win_T *new_wp,
- int dir)
+ int dir,
+ frame_T *to_flatten)
{
win_T *wp = new_wp;
win_T *oldwin;
@@ -955,6 +1000,9 @@ win_split_ins(
// Do not redraw here, curwin->w_buffer may be invalid.
++RedrawingDisabled;
+ if (new_wp == NULL)
+ trigger_winnewpre();
+
if (flags & WSP_TOP)
oldwin = firstwin;
else if (flags & WSP_BOT)
@@ -965,7 +1013,7 @@ win_split_ins(
// add a status line when p_ls == 1 and splitting the first window
if (ONE_WINDOW && p_ls == 1 && oldwin->w_status_height == 0)
{
- if (VISIBLE_HEIGHT(oldwin) <= p_wmh && new_wp == NULL)
+ if (!(flags & WSP_FORCE_ROOM) && VISIBLE_HEIGHT(oldwin) <= p_wmh)
{
emsg(_(e_not_enough_room));
goto theend;
@@ -1023,7 +1071,7 @@ win_split_ins(
available = oldwin->w_frame->fr_width;
needed += minwidth;
}
- if (available < needed && new_wp == NULL)
+ if (!(flags & WSP_FORCE_ROOM) && available < needed)
{
emsg(_(e_not_enough_room));
goto theend;
@@ -1106,7 +1154,7 @@ win_split_ins(
available = oldwin->w_frame->fr_height;
needed += minheight;
}
- if (available < needed && new_wp == NULL)
+ if (!(flags & WSP_FORCE_ROOM) && available < needed)
{
emsg(_(e_not_enough_room));
goto theend;
@@ -1205,6 +1253,10 @@ win_split_ins(
win_init(wp, curwin, flags);
}
+ // Going to reorganize frames now, make sure they're flat.
+ if (to_flatten != NULL)
+ frame_flatten(to_flatten);
+
/*
* Reorganise the tree of frames to insert the new window.
*/
@@ -1433,7 +1485,7 @@ win_split_ins(
/*
* make the new window the current window
*/
- (void)win_enter_ext(wp, WEE_TRIGGER_NEW_AUTOCMDS
+ (void)win_enter_ext(wp, (new_wp == NULL ? WEE_TRIGGER_NEW_AUTOCMDS : 0)
| WEE_TRIGGER_ENTER_AUTOCMDS | WEE_TRIGGER_LEAVE_AUTOCMDS);
if (flags & WSP_VERT)
p_wiw = i;
@@ -1897,35 +1949,51 @@ win_rotate(int upwards, int count)
}
/*
- * Move the current window to the very top/bottom/left/right of the screen.
+ * Move "wp" into a new split in a given direction, possibly relative to the
+ * current window.
+ * "wp" must be valid in the current tabpage.
+ * Returns FAIL for failure, OK otherwise.
*/
- static void
-win_totop(int size, int flags)
+ int
+win_splitmove(win_T *wp, int size, int flags)
{
int dir;
- int height = curwin->w_height;
+ int height = wp->w_height;
+ frame_T *unflat_altfr;
if (ONE_WINDOW)
- {
- beep_flush();
- return;
- }
- if (check_split_disallowed() == FAIL)
- return;
+ return OK; // nothing to do
+ if (check_split_disallowed(wp) == FAIL)
+ return FAIL;
- // Remove the window and frame from the tree of frames.
- (void)winframe_remove(curwin, &dir, NULL);
- win_remove(curwin, NULL);
+ // Remove the window and frame from the tree of frames. Don't flatten any
+ // frames yet so we can restore things if win_split_ins fails.
+ winframe_remove(wp, &dir, NULL, &unflat_altfr);
+ win_remove(wp, NULL);
last_status(FALSE); // may need to remove last status line
(void)win_comp_pos(); // recompute window positions
- // Split a window on the desired side and put the window there.
- (void)win_split_ins(size, flags, curwin, dir);
- if (!(flags & WSP_VERT))
+ // Split a window on the desired side and put "wp" there.
+ if (win_split_ins(size, flags, wp, dir, unflat_altfr) == FAIL)
+ {
+ // win_split_ins doesn't change sizes or layout if it fails to insert an
+ // existing window, so just undo winframe_remove.
+ winframe_restore(wp, dir, unflat_altfr);
+ win_append(wp->w_prev, wp);
+ return FAIL;
+ }
+
+ // If splitting horizontally, try to preserve height.
+ // Note that win_split_ins autocommands may have immediately closed "wp"!
+ if (size == 0 && !(flags & WSP_VERT) && win_valid(wp))
{
- win_setheight(height);
+ win_setheight_win(height, wp);
if (p_ea)
- win_equal(curwin, TRUE, 'v');
+ {
+ // Equalize windows. Note that win_split_ins autocommands may have
+ // made a window other than "wp" current.
+ win_equal(curwin, curwin == wp, 'v');
+ }
}
#if defined(FEAT_GUI)
@@ -1933,6 +2001,7 @@ win_totop(int size, int flags)
// scrollbars. Have to update them anyway.
gui_may_update_scrollbars();
#endif
+ return OK;
}
/*
@@ -2362,7 +2431,7 @@ leaving_window(win_T *win)
// When leaving the window (or closing the window) was done from a
// callback we need to break out of the Insert mode loop and restart Insert
// mode when entering the window again.
- if (State & MODE_INSERT)
+ if ((State & MODE_INSERT) && !stop_insert_mode)
{
stop_insert_mode = TRUE;
if (win->w_buffer->b_prompt_insert == NUL)
@@ -2485,7 +2554,7 @@ close_windows(
* "aucmd_win[]").
* Returns FALSE if there is a window, possibly in another tab page.
*/
- static int
+ int
last_window(void)
{
return (one_window() && first_tabpage->tp_next == NULL);
@@ -2515,7 +2584,7 @@ one_window(void)
/*
* Close the possibly last window in a tab page.
- * Returns TRUE when the window was closed already.
+ * Return FALSE if there are other windows and nothing is done, TRUE otherwise.
*/
static int
close_last_window_tabpage(
@@ -2653,7 +2722,7 @@ win_close(win_T *win, int free_buf)
// and then close the window and the tab page to avoid that curwin and
// curtab are invalid while we are freeing memory.
if (close_last_window_tabpage(win, free_buf, prev_curtab))
- return FAIL;
+ return FAIL;
// When closing the help window, try restoring a snapshot after closing
// the window. Otherwise clear the snapshot, it's now invalid.
@@ -2726,9 +2795,11 @@ win_close(win_T *win, int free_buf)
win_close_buffer(win, free_buf ? DOBUF_UNLOAD : 0, TRUE);
- if (only_one_window() && win_valid(win) && win->w_buffer == NULL
- && (last_window() || curtab != prev_curtab
- || close_last_window_tabpage(win, free_buf, prev_curtab)))
+ if (win_valid(win) && win->w_buffer == NULL
+#if defined(FEAT_PROP_POPUP)
+ && !popup_is_popup(win)
+#endif
+ && last_window())
{
// Autocommands have closed all windows, quit now. Restore
// curwin->w_buffer, otherwise writing viminfo may fail.
@@ -2742,10 +2813,7 @@ win_close(win_T *win, int free_buf)
&& win->w_buffer == NULL)
{
// Need to close the window anyway, since the buffer is NULL.
- // Don't trigger autocmds with a NULL buffer.
- block_autocmds();
win_close_othertab(win, FALSE, prev_curtab);
- unblock_autocmds();
return FAIL;
}
@@ -2887,6 +2955,14 @@ win_close(win_T *win, int free_buf)
}
static void
+trigger_winnewpre(void)
+{
+ window_layout_lock();
+ apply_autocmds(EVENT_WINNEWPRE, NULL, NULL, FALSE, NULL);
+ window_layout_unlock();
+}
+
+ static void
trigger_winclosed(win_T *win)
{
static int recursive = FALSE;
@@ -3274,10 +3350,15 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
return; // window is already being closed
// Trigger WinClosed just before starting to free window-related resources.
- trigger_winclosed(win);
- // autocmd may have freed the window already.
- if (!win_valid_any_tab(win))
- return;
+ // If the buffer is NULL, it isn't safe to trigger autocommands,
+ // and win_close() should have already triggered WinClosed.
+ if (win->w_buffer != NULL)
+ {
+ trigger_winclosed(win);
+ // autocmd may have freed the window already.
+ if (!win_valid_any_tab(win))
+ return;
+ }
if (win->w_buffer != NULL)
// Close the link to the buffer.
@@ -3355,7 +3436,7 @@ win_free_mem(
// Remove the window and its frame from the tree of frames.
frp = win->w_frame;
- wp = winframe_remove(win, dirp, tp);
+ wp = winframe_remove(win, dirp, tp, NULL);
vim_free(frp);
win_free(win, tp);
@@ -3375,6 +3456,8 @@ win_free_all(void)
// avoid an error for switching tabpage with the cmdline window open
cmdwin_type = 0;
+ cmdwin_buf = NULL;
+ cmdwin_win = NULL;
while (first_tabpage->tp_next != NULL)
tabpage_close(TRUE);
@@ -3403,11 +3486,14 @@ win_free_all(void)
winframe_remove(
win_T *win,
int *dirp UNUSED, // set to 'v' or 'h' for direction if 'ea'
- tabpage_T *tp) // tab page "win" is in, NULL for current
+ tabpage_T *tp, // tab page "win" is in, NULL for current
+ frame_T **unflat_altfr) // if not NULL, set to pointer of frame that got
+ // the space, and it is not flattened
{
frame_T *frp, *frp2, *frp3;
frame_T *frp_close = win->w_frame;
win_T *wp;
+ int row, col;
/*
* If there is only one window there is nothing to remove.
@@ -3415,6 +3501,12 @@ winframe_remove(
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin)
return NULL;
+ // Save the position of the containing frame (which will also contain the
+ // altframe) before we remove anything, to recompute window positions later.
+ wp = frame2win(frp_close->fr_parent);
+ row = wp->w_winrow;
+ col = wp->w_wincol;
+
/*
* Remove the window from its frame.
*/
@@ -3458,7 +3550,7 @@ winframe_remove(
}
}
frame_new_height(frp2, frp2->fr_height + frp_close->fr_height,
- frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+ frp2 == frp_close->fr_next, FALSE);
*dirp = 'v';
}
else
@@ -3495,64 +3587,127 @@ winframe_remove(
}
}
frame_new_width(frp2, frp2->fr_width + frp_close->fr_width,
- frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+ frp2 == frp_close->fr_next, FALSE);
*dirp = 'h';
}
- // If rows/columns go to a window below/right its positions need to be
- // updated. Can only be done after the sizes have been updated.
- if (frp2 == frp_close->fr_next)
- {
- int row = win->w_winrow;
- int col = win->w_wincol;
+ // If the altframe wasn't adjacent and left/above, resizing it will have
+ // changed window positions within the parent frame. Recompute them.
+ if (frp2 != frp_close->fr_prev)
+ frame_comp_pos(frp_close->fr_parent, &row, &col);
- frame_comp_pos(frp2, &row, &col);
- }
+ if (unflat_altfr == NULL)
+ frame_flatten(frp2);
+ else
+ *unflat_altfr = frp2;
- if (frp2->fr_next == NULL && frp2->fr_prev == NULL)
- {
- // There is no other frame in this list, move its info to the parent
- // and remove it.
- frp2->fr_parent->fr_layout = frp2->fr_layout;
- frp2->fr_parent->fr_child = frp2->fr_child;
- FOR_ALL_FRAMES(frp, frp2->fr_child)
- frp->fr_parent = frp2->fr_parent;
- frp2->fr_parent->fr_win = frp2->fr_win;
- if (frp2->fr_win != NULL)
- frp2->fr_win->w_frame = frp2->fr_parent;
- frp = frp2->fr_parent;
- if (topframe->fr_child == frp2)
- topframe->fr_child = frp;
- vim_free(frp2);
+ return wp;
+}
+
+/*
+ * Flatten "frp" into its parent frame if it's the only child, also merging its
+ * list with the grandparent if they share the same layout.
+ * Frees "frp" if flattened; also "frp->fr_parent" if it has the same layout.
+ */
+ static void
+frame_flatten(frame_T *frp)
+{
+ frame_T *frp2, *frp3;
+
+ if (frp->fr_next != NULL || frp->fr_prev != NULL)
+ return;
- frp2 = frp->fr_parent;
- if (frp2 != NULL && frp2->fr_layout == frp->fr_layout)
+ // There is no other frame in this list, move its info to the parent
+ // and remove it.
+ frp->fr_parent->fr_layout = frp->fr_layout;
+ frp->fr_parent->fr_child = frp->fr_child;
+ FOR_ALL_FRAMES(frp2, frp->fr_child)
+ frp2->fr_parent = frp->fr_parent;
+ frp->fr_parent->fr_win = frp->fr_win;
+ if (frp->fr_win != NULL)
+ frp->fr_win->w_frame = frp->fr_parent;
+ frp2 = frp->fr_parent;
+ if (topframe->fr_child == frp)
+ topframe->fr_child = frp2;
+ vim_free(frp);
+
+ frp = frp2->fr_parent;
+ if (frp != NULL && frp->fr_layout == frp2->fr_layout)
+ {
+ // The frame above the parent has the same layout, have to merge
+ // the frames into this list.
+ if (frp->fr_child == frp2)
+ frp->fr_child = frp2->fr_child;
+ frp2->fr_child->fr_prev = frp2->fr_prev;
+ if (frp2->fr_prev != NULL)
+ frp2->fr_prev->fr_next = frp2->fr_child;
+ for (frp3 = frp2->fr_child; ; frp3 = frp3->fr_next)
{
- // The frame above the parent has the same layout, have to merge
- // the frames into this list.
- if (frp2->fr_child == frp)
- frp2->fr_child = frp->fr_child;
- frp->fr_child->fr_prev = frp->fr_prev;
- if (frp->fr_prev != NULL)
- frp->fr_prev->fr_next = frp->fr_child;
- for (frp3 = frp->fr_child; ; frp3 = frp3->fr_next)
+ frp3->fr_parent = frp;
+ if (frp3->fr_next == NULL)
{
- frp3->fr_parent = frp2;
- if (frp3->fr_next == NULL)
- {
- frp3->fr_next = frp->fr_next;
- if (frp->fr_next != NULL)
- frp->fr_next->fr_prev = frp3;
- break;
- }
+ frp3->fr_next = frp2->fr_next;
+ if (frp2->fr_next != NULL)
+ frp2->fr_next->fr_prev = frp3;
+ break;
}
- if (topframe->fr_child == frp)
- topframe->fr_child = frp2;
- vim_free(frp);
}
+ if (topframe->fr_child == frp2)
+ topframe->fr_child = frp;
+ vim_free(frp2);
}
+}
- return wp;
+/*
+ * Undo changes from a prior call to winframe_remove, also restoring lost
+ * vertical separators and statuslines, and changed window positions for
+ * windows within "unflat_altfr".
+ * Caller must ensure no other changes were made to the layout or window sizes!
+ */
+ static void
+winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr)
+{
+ frame_T *frp = wp->w_frame;
+
+ // Put "wp"'s frame back where it was.
+ if (frp->fr_prev != NULL)
+ frame_append(frp->fr_prev, frp);
+ else
+ frame_insert(frp->fr_next, frp);
+
+ // Vertical separators to the left may have been lost. Restore them.
+ if (wp->w_vsep_width == 0
+ && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL)
+ frame_add_vsep(frp->fr_prev);
+
+ // Statuslines above may have been lost. Restore them.
+ if (wp->w_status_height == 0
+ && frp->fr_parent->fr_layout == FR_COL && frp->fr_prev != NULL)
+ frame_add_statusline(frp->fr_prev);
+
+ // Restore the lost room that was redistributed to the altframe. Also
+ // adjusts window sizes to fit restored statuslines/separators, if needed.
+ if (dir == 'v')
+ {
+ frame_new_height(unflat_altfr, unflat_altfr->fr_height - frp->fr_height,
+ unflat_altfr == frp->fr_next, FALSE);
+ }
+ else if (dir == 'h')
+ {
+ frame_new_width(unflat_altfr, unflat_altfr->fr_width - frp->fr_width,
+ unflat_altfr == frp->fr_next, FALSE);
+ }
+
+ // Recompute window positions within the parent frame to restore them.
+ // Positions were unchanged if the altframe was adjacent and left/above.
+ if (unflat_altfr != frp->fr_prev)
+ {
+ win_T *topleft = frame2win(frp->fr_parent);
+ int row = topleft->w_winrow;
+ int col = topleft->w_wincol;
+
+ frame_comp_pos(frp->fr_parent, &row, &col);
+ }
}
/*
@@ -4475,6 +4630,9 @@ win_new_tabpage(int after)
newtp->tp_localdir = (tp->tp_localdir == NULL)
? NULL : vim_strsave(tp->tp_localdir);
+
+ trigger_winnewpre();
+
// Create a new empty window.
if (win_alloc_firstwin(tp->tp_curwin) == OK)
{
@@ -5381,15 +5539,11 @@ win_enter_ext(win_T *wp, int flags)
// may have to copy the buffer options when 'cpo' contains 'S'
if (wp->w_buffer != curbuf)
buf_copy_options(wp->w_buffer, BCO_ENTER | BCO_NOHELP);
-
if (curwin_invalid == 0)
{
prevwin = curwin; // remember for CTRL-W p
curwin->w_redr_status = TRUE;
}
- else if (wp == prevwin)
- prevwin = NULL; // don't want it to be the new curwin
-
curwin = wp;
curbuf = wp->w_buffer;
check_cursor();
@@ -7131,17 +7285,17 @@ command_height(void)
// If the space for the command line is already more than 'cmdheight' there
// is nothing to do (window size must have decreased).
+ // Note: this makes curtab->tp_ch_used unreliable
if (p_ch > old_p_ch && cmdline_row <= Rows - p_ch)
return;
// Update cmdline_row to what it should be: just below the last window.
cmdline_row = topframe->fr_height + tabline_height();
- // If cmdline_row is smaller than what it is supposed to be for 'cmdheight'
- // then set old_p_ch to what it would be, so that the windows get resized
+ // old_p_ch may be unreliable, because of the early return above, so
+ // set old_p_ch to what it would be, so that the windows get resized
// properly for the new value.
- if (cmdline_row < Rows - p_ch)
- old_p_ch = Rows - cmdline_row;
+ old_p_ch = Rows - cmdline_row;
// Find bottom frame with width of screen.
frp = lastwin->w_frame;
@@ -7482,29 +7636,42 @@ reset_lnums(void)
/*
* Create a snapshot of the current frame sizes.
* "idx" is SNAP_HELP_IDX or SNAP_AUCMD_IDX.
+ * Return FAIL if out of memory, OK otherwise.
*/
- void
+ int
make_snapshot(int idx)
{
clear_snapshot(curtab, idx);
- make_snapshot_rec(topframe, &curtab->tp_snapshot[idx]);
+ if (make_snapshot_rec(topframe, &curtab->tp_snapshot[idx]) == FAIL)
+ {
+ clear_snapshot(curtab, idx);
+ return FAIL;
+ }
+ return OK;
}
- static void
+ static int
make_snapshot_rec(frame_T *fr, frame_T **frp)
{
*frp = ALLOC_CLEAR_ONE(frame_T);
if (*frp == NULL)
- return;
+ return FAIL;
(*frp)->fr_layout = fr->fr_layout;
(*frp)->fr_width = fr->fr_width;
(*frp)->fr_height = fr->fr_height;
if (fr->fr_next != NULL)
- make_snapshot_rec(fr->fr_next, &((*frp)->fr_next));
+ {
+ if (make_snapshot_rec(fr->fr_next, &((*frp)->fr_next)) == FAIL)
+ return FAIL;
+ }
if (fr->fr_child != NULL)
- make_snapshot_rec(fr->fr_child, &((*frp)->fr_child));
+ {
+ if (make_snapshot_rec(fr->fr_child, &((*frp)->fr_child)) == FAIL)
+ return FAIL;
+ }
if (fr->fr_layout == FR_LEAF && fr->fr_win == curwin)
(*frp)->fr_win = curwin;
+ return OK;
}
/*
@@ -7737,9 +7904,15 @@ frame_check_width(frame_T *topfrp, int width)
* Simple int comparison function for use with qsort()
*/
static int
-int_cmp(const void *a, const void *b)
+int_cmp(const void *pa, const void *pb)
{
- return *(const int *)a - *(const int *)b;
+ const int a = *(const int *)pa;
+ const int b = *(const int *)pb;
+ if (a > b)
+ return 1;
+ if (a < b)
+ return -1;
+ return 0;
}
/*
@@ -7812,3 +7985,9 @@ skip:
return NULL; // no error
}
#endif
+
+ int
+get_last_winid(void)
+{
+ return last_win_id;
+}
diff --git a/src/xxd/Makefile b/src/xxd/Makefile
index 97bbcc7..d08af7a 100644
--- a/src/xxd/Makefile
+++ b/src/xxd/Makefile
@@ -1,7 +1,7 @@
# The most simplistic Makefile
xxd: xxd.c
- $(CC) $(CFLAGS) $(LDFLAGS) -DUNIX -o xxd xxd.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DUNIX -o xxd xxd.c $(LIBS)
clean:
rm -f xxd xxd.o
diff --git a/src/xxd/xxd.c b/src/xxd/xxd.c
index 26f8d83..cf8b4ea 100644
--- a/src/xxd/xxd.c
+++ b/src/xxd/xxd.c
@@ -58,6 +58,10 @@
* 20.06.2022 Permit setting the variable names used by -i by David Gow
* 31.08.2023 -R never/auto/always prints colored output
* 06.10.2023 enable -r -b to reverse bit dumps
+ * 12.01.2024 disable auto-conversion for z/OS (MVS)
+ * 17.01.2024 use size_t instead of usigned int for code-generation (-i), #13876
+ * 25.01.2024 revert the previous patch (size_t instead of unsigned int)
+ * 10.02.2024 fix buffer-overflow when writing color output to buffer, #14003
*
* (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
*
@@ -138,7 +142,7 @@ extern void perror __P((char *));
# endif
#endif
-char version[] = "xxd 2023-10-25 by Juergen Weigert et al.";
+char version[] = "xxd 2024-02-10 by Juergen Weigert et al.";
#ifdef WIN32
char osver[] = " (Win32)";
#else
@@ -197,7 +201,33 @@ char osver[] = "";
#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
#define COLS 256 /* change here, if you ever need more columns */
-#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
+
+/*
+ * LLEN is the maximum length of a line; other than the visible characters
+ * we need to consider also the escape color sequence prologue/epilogue ,
+ * (11 bytes for each character). The most larger format is the default one:
+ * addr + 1 word for each col/2 + 1 char for each col
+ *
+ * addr 1st group 2nd group
+ * +-------+ +-----------------+ +------+
+ * 01234567: 1234 5678 9abc def0 12345678
+ *
+ * - addr: typically 012345678: -> from 10 up to 18 bytes (including trailing
+ * space)
+ * - 1st group: 1234 5678 9abc ... -> each byte may be colored, so add 11
+ * for each byte
+ * - space -> 1 byte
+ * - 2nd group: 12345678 -> each char may be colore so add 11
+ * for each byte
+ * - new line -> 1 byte
+ * - zero (end line) -> 1 byte
+ */
+#define LLEN (2*(int)sizeof(unsigned long) + 2 + /* addr + ": " */ \
+ (11 * 2 + 4 + 1) * (COLS / 2) + /* 1st group */ \
+ 1 + /* space */ \
+ (1 + 11) * COLS + /* 2nd group */ \
+ 1 + /* new line */ \
+ 1) /* zero */
char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
@@ -587,7 +617,7 @@ begin_coloring_char (char *l, int *c, int e, int ebcdic)
}
else /* ASCII */
{
- #ifdef __MVS__
+ #if defined(__MVS__) && __CHARSET_LIB == 0
if (e >= 64)
l[(*c)++] = COLOR_GREEN;
#else
@@ -905,6 +935,10 @@ main(int argc, char *argv[])
}
rewind(fpo);
}
+#ifdef __MVS__
+ // Disable auto-conversion on input file descriptors
+ __disableautocvt(fileno(fp));
+#endif
if (revert)
switch (hextype)
@@ -1066,7 +1100,7 @@ main(int argc, char *argv[])
COLOR_PROLOGUE
begin_coloring_char(l,&c,e,ebcdic);
-#ifdef __MVS__
+#if defined(__MVS__) && __CHARSET_LIB == 0
if (e >= 64)
l[c++] = e;
else
@@ -1094,7 +1128,7 @@ main(int argc, char *argv[])
c += addrlen + 3 + p;
l[c++] =
-#ifdef __MVS__
+#if defined(__MVS__) && __CHARSET_LIB == 0
(e >= 64)
#else
(e > 31 && e < 127)