diff options
author | oni-link <knil.ino@gmail.com> | 2015-03-31 20:17:45 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2015-04-26 23:47:59 -0400 |
commit | 2493b6fefc8e531d45ef681688c94d9dcbca3e50 (patch) | |
tree | 7ad1386a33eb4888c0761ff45ebf2374d4507ef5 | |
parent | e692930af2e400a456299695fbcd44176c0ab475 (diff) | |
download | rneovim-2493b6fefc8e531d45ef681688c94d9dcbca3e50.tar.gz rneovim-2493b6fefc8e531d45ef681688c94d9dcbca3e50.tar.bz2 rneovim-2493b6fefc8e531d45ef681688c94d9dcbca3e50.zip |
ex_getln: Fixes for some problems with getexmodeline()
Problems with line-input editing commands in Ex mode
('nvim -e' or 'Q' in normal mode):
CTRL_U: Only after the next keystroke the complete
line change is shown if the indentation was
not 0.
: asdfCTRL_U
CTRL_T: Memory reallocation with ga_grows() before a
memmove(), but pointers into the memory are
not updated.
:set sw=40
:CTRL_T
...
Should complain about a memory error.
CTRL_D: Trying to reduce an indentation of 0.
:set sw=1
:CTRL_D
Segfault
Helped-by: Scott Prager <splinterofchaos@gmail.com>
-rw-r--r-- | src/nvim/ex_getln.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e4c02a0c30..65d6dd676f 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1781,24 +1781,29 @@ getexmodeline ( msg_col = startcol; msg_clr_eos(); line_ga.ga_len = 0; - continue; + goto redraw; } + int num_spaces; if (c1 == Ctrl_T) { int sw = get_sw_value(curbuf); p = (char_u *)line_ga.ga_data; p[line_ga.ga_len] = NUL; indent = get_indent_str(p, 8, FALSE); - indent += sw - indent % sw; + num_spaces = sw - indent % sw; + indent += num_spaces; add_indent: - while (get_indent_str(p, 8, FALSE) < indent) { + if (num_spaces > 0) { + ga_grow(&line_ga, num_spaces + 1); + p = (char_u *)line_ga.ga_data; char_u *s = skipwhite(p); - ga_grow(&line_ga, 1); - memmove(s + 1, s, line_ga.ga_len - (s - p) + 1); - *s = ' '; - ++line_ga.ga_len; + // Insert spaces after leading whitespaces. + memmove(s + num_spaces, s, line_ga.ga_len - (s - p) + 1); + memset(s, ' ', num_spaces); + + line_ga.ga_len += num_spaces; } redraw: /* redraw the line */ @@ -1835,15 +1840,25 @@ redraw: } else { p[line_ga.ga_len] = NUL; indent = get_indent_str(p, 8, FALSE); + if (indent == 0) { + continue; + } --indent; indent -= indent % get_sw_value(curbuf); } - while (get_indent_str(p, 8, FALSE) > indent) { - char_u *s = skipwhite(p); - memmove(s - 1, s, line_ga.ga_len - (s - p) + 1); - --line_ga.ga_len; + // reduce the line's indentation + char_u *from = skipwhite(p); + char_u *to = from; + int old_indent; + while ((old_indent = get_indent_str(p, 8, FALSE)) > indent) { + *--to = NUL; } + memmove(to, from, line_ga.ga_len - (from - p) + 1); + line_ga.ga_len -= from - to; + + // Removed to much indentation, fix it before redrawing. + num_spaces = indent - old_indent; goto add_indent; } |