aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/edit.c3
-rw-r--r--src/nvim/ex_getln.c14
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/window.c6
-rw-r--r--test/old/testdir/test_cmdwin.vim67
5 files changed, 88 insertions, 8 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 7670d6754f..e3321a8b99 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1528,8 +1528,9 @@ void edit_unputchar(void)
// Called when p_dollar is set: display a '$' at the end of the changed text
// Only works when cursor is in the line that changes.
-void display_dollar(colnr_T col)
+void display_dollar(colnr_T col_arg)
{
+ colnr_T col = col_arg < 0 ? 0 : col_arg;
colnr_T save_col;
if (!redrawing()) {
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 1345a29a21..a4c1863576 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -127,6 +127,7 @@ typedef struct command_line_state {
int break_ctrl_c;
expand_T xpc;
long *b_im_ptr;
+ buf_T *b_im_ptr_buf; ///< buffer where b_im_ptr is valid
} CommandLineState;
typedef struct cmdpreview_win_info {
@@ -736,7 +737,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
} else {
s->b_im_ptr = &curbuf->b_p_imsearch;
}
-
+ s->b_im_ptr_buf = curbuf;
if (*s->b_im_ptr == B_IMODE_LMAP) {
State |= MODE_LANGMAP;
}
@@ -1538,20 +1539,21 @@ static int command_line_erase_chars(CommandLineState *s)
/// language :lmap mappings and/or Input Method.
static void command_line_toggle_langmap(CommandLineState *s)
{
+ long *b_im_ptr = buf_valid(s->b_im_ptr_buf) ? s->b_im_ptr : NULL;
if (map_to_exists_mode("", MODE_LANGMAP, false)) {
// ":lmap" mappings exists, toggle use of mappings.
State ^= MODE_LANGMAP;
- if (s->b_im_ptr != NULL) {
+ if (b_im_ptr != NULL) {
if (State & MODE_LANGMAP) {
- *s->b_im_ptr = B_IMODE_LMAP;
+ *b_im_ptr = B_IMODE_LMAP;
} else {
- *s->b_im_ptr = B_IMODE_NONE;
+ *b_im_ptr = B_IMODE_NONE;
}
}
}
- if (s->b_im_ptr != NULL) {
- if (s->b_im_ptr == &curbuf->b_p_iminsert) {
+ if (b_im_ptr != NULL) {
+ if (b_im_ptr == &curbuf->b_p_iminsert) {
set_iminsert_global(curbuf);
} else {
set_imsearch_global(curbuf);
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 7e44e55a8e..c3fdb304a3 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -107,6 +107,8 @@ static int VIsual_mode_orig = NUL; // saved Visual mode
#endif
static const char e_changelist_is_empty[] = N_("E664: Changelist is empty");
+static const char e_cmdline_window_already_open[]
+ = N_("E1292: Command-line window is already open");
static inline void normal_state_init(NormalState *s)
{
@@ -6372,6 +6374,10 @@ static void nv_record(cmdarg_T *cap)
}
if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
+ if (cmdwin_type != 0) {
+ emsg(_(e_cmdline_window_already_open));
+ return;
+ }
stuffcharReadbuff(cap->nchar);
stuffcharReadbuff(K_CMDWIN);
} else {
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 45a48f13cc..87e936b92f 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2304,6 +2304,9 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
}
if (hnc) { // add next_curwin size
next_curwin_size -= (int)p_wiw - (m - n);
+ if (next_curwin_size < 0) {
+ next_curwin_size = 0;
+ }
new_size += next_curwin_size;
room -= new_size - next_curwin_size;
} else {
@@ -6686,7 +6689,8 @@ static int win_border_width(win_T *wp)
/// Set the width of a window.
void win_new_width(win_T *wp, int width)
{
- wp->w_width = width;
+ // Should we give an error if width < 0?
+ wp->w_width = width < 0 ? 0 : width;
wp->w_pos_changed = true;
win_set_inner_size(wp, true);
}
diff --git a/test/old/testdir/test_cmdwin.vim b/test/old/testdir/test_cmdwin.vim
new file mode 100644
index 0000000000..f948d46be1
--- /dev/null
+++ b/test/old/testdir/test_cmdwin.vim
@@ -0,0 +1,67 @@
+" Tests for editing the command line.
+
+source check.vim
+source screendump.vim
+
+
+func Test_cant_open_cmdwin_in_cmdwin()
+ try
+ call feedkeys("q:q::q\<CR>", "x!")
+ catch
+ let caught = v:exception
+ endtry
+ call assert_match('E1292:', caught)
+endfunc
+
+func Test_cmdwin_virtual_edit()
+ enew!
+ set ve=all cpo+=$
+ silent normal q/s
+
+ set ve= cpo-=$
+endfunc
+
+" Check that a :normal command can be used to stop Visual mode without side
+" effects.
+func Test_normal_escape()
+ call feedkeys("q:i\" foo\<Esc>:normal! \<C-V>\<Esc>\<CR>:\" bar\<CR>", 'ntx')
+ call assert_equal('" bar', @:)
+endfunc
+
+" This was using a pointer to a freed buffer
+func Test_cmdwin_freed_buffer_ptr()
+ " this does not work on MS-Windows because renaming an open file fails
+ CheckNotMSWindows
+
+ au BufEnter * next 0| file
+ edit 0
+ silent! norm q/
+
+ au! BufEnter
+ bwipe!
+endfunc
+
+" This was resulting in a window with negative width.
+" The test doesn't reproduce the illegal memory access though...
+func Test_cmdwin_split_often()
+ let lines = &lines
+ let columns = &columns
+ set t_WS=
+
+ try
+ " set encoding=iso8859
+ set ruler
+ winsize 0 0
+ noremap 0 H
+ sil norm 0000000q:
+ catch /E36:/
+ endtry
+
+ bwipe!
+ set encoding=utf8
+ let &lines = lines
+ let &columns = columns
+endfunc
+
+
+" vim: shiftwidth=2 sts=2 expandtab