aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt1
-rw-r--r--src/nvim/api/vim.c12
-rw-r--r--src/nvim/api/window.c4
-rw-r--r--src/nvim/arabic.c18
-rw-r--r--src/nvim/assert.h4
-rw-r--r--src/nvim/buffer.c36
-rw-r--r--src/nvim/buffer_defs.h60
-rw-r--r--src/nvim/charset.c7
-rw-r--r--src/nvim/diff.c1
-rw-r--r--src/nvim/edit.c86
-rw-r--r--src/nvim/edit.h6
-rw-r--r--src/nvim/eval.c563
-rw-r--r--src/nvim/event/process.c6
-rw-r--r--src/nvim/ex_cmds.c188
-rw-r--r--src/nvim/ex_cmds.lua12
-rw-r--r--src/nvim/ex_cmds2.c54
-rw-r--r--src/nvim/ex_docmd.c163
-rw-r--r--src/nvim/ex_docmd.h14
-rw-r--r--src/nvim/ex_eval.c44
-rw-r--r--src/nvim/ex_getln.c136
-rw-r--r--src/nvim/ex_getln.h12
-rw-r--r--src/nvim/farsi.c31
-rw-r--r--src/nvim/file_search.c8
-rw-r--r--src/nvim/fileio.c168
-rw-r--r--src/nvim/fold.c17
-rw-r--r--src/nvim/getchar.c192
-rw-r--r--src/nvim/hardcopy.c26
-rw-r--r--src/nvim/if_cscope.c5
-rw-r--r--src/nvim/indent_c.c13
-rw-r--r--src/nvim/keymap.c178
-rw-r--r--src/nvim/keymap.h10
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/menu.c10
-rw-r--r--src/nvim/message.c75
-rw-r--r--src/nvim/misc1.c66
-rw-r--r--src/nvim/mouse.c94
-rw-r--r--src/nvim/mouse.h6
-rw-r--r--src/nvim/move.c9
-rw-r--r--src/nvim/msgpack_rpc/helpers.c4
-rw-r--r--src/nvim/msgpack_rpc/server.c2
-rw-r--r--src/nvim/normal.c335
-rw-r--r--src/nvim/normal.h15
-rw-r--r--src/nvim/ops.c421
-rw-r--r--src/nvim/ops.h8
-rw-r--r--src/nvim/option.c169
-rw-r--r--src/nvim/option_defs.h9
-rw-r--r--src/nvim/options.lua7
-rw-r--r--src/nvim/os/fs.c102
-rw-r--r--src/nvim/os/fs_defs.h6
-rw-r--r--src/nvim/os/input.c11
-rw-r--r--src/nvim/os/mem.c2
-rw-r--r--src/nvim/os/win_defs.h3
-rw-r--r--src/nvim/os_unix.c27
-rw-r--r--src/nvim/os_unix.h6
-rw-r--r--src/nvim/path.c105
-rw-r--r--src/nvim/path.h4
-rw-r--r--src/nvim/quickfix.c29
-rw-r--r--src/nvim/regexp.c25
-rw-r--r--src/nvim/regexp_nfa.c505
-rw-r--r--src/nvim/screen.c95
-rw-r--r--src/nvim/search.c229
-rw-r--r--src/nvim/search.h27
-rw-r--r--src/nvim/shada.c16
-rw-r--r--src/nvim/spell.c1
-rw-r--r--src/nvim/syntax.c10
-rw-r--r--src/nvim/tag.c59
-rw-r--r--src/nvim/tempfile.c139
-rw-r--r--src/nvim/tempfile.h8
-rw-r--r--src/nvim/terminal.c24
-rw-r--r--src/nvim/testdir/Makefile8
-rw-r--r--src/nvim/testdir/runtest.vim1
-rw-r--r--src/nvim/testdir/test49.in4
-rw-r--r--src/nvim/testdir/test_alot.vim3
-rw-r--r--src/nvim/testdir/test_cursor_func.vim52
-rw-r--r--src/nvim/tui/input.c12
-rw-r--r--src/nvim/tui/tui.c8
-rw-r--r--src/nvim/undo.c9
-rw-r--r--src/nvim/version.c561
-rw-r--r--src/nvim/vim.h9
-rw-r--r--src/nvim/window.c26
80 files changed, 3303 insertions, 2134 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index a473f99278..0711642868 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -87,7 +87,6 @@ set(CONV_SOURCES
ex_docmd.c
ex_getln.c
fileio.c
- getchar.c
mbyte.c
memline.c
message.c
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 10110b0f62..46ac3c9022 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -116,8 +116,14 @@ String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
}
char *ptr = NULL;
- replace_termcodes((char_u *)str.data, (char_u **)&ptr,
- from_part, do_lt, special);
+ // Set 'cpoptions' the way we want it.
+ // FLAG_CPO_BSLASH set - backslashes are *not* treated specially
+ // FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered
+ // FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted
+ // The third from end parameter of replace_termcodes() is true so that the
+ // <lt> sequence is recognised - needed for a real backslash.
+ replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr,
+ from_part, do_lt, special, CPO_TO_CPO_FLAGS);
return cstr_as_string(ptr);
}
@@ -291,7 +297,7 @@ void vim_change_directory(String dir, Error *err)
return;
}
- post_chdir(false);
+ post_chdir(kCdScopeGlobal);
try_end(err);
}
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index a52f53a3e6..f644453358 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -57,8 +57,8 @@ void window_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
{
win_T *win = find_window_by_handle(window, err);
- if (pos.size != 2 || pos.items[0].type != kObjectTypeInteger ||
- pos.items[1].type != kObjectTypeInteger) {
+ if (pos.size != 2 || pos.items[0].type != kObjectTypeInteger
+ || pos.items[1].type != kObjectTypeInteger) {
api_set_error(err,
Validation,
_("Argument \"pos\" must be a [row, col] array"));
diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c
index b432e12c02..db97bd9dc4 100644
--- a/src/nvim/arabic.c
+++ b/src/nvim/arabic.c
@@ -1367,8 +1367,8 @@ int arabic_shape(int c, int *ccp, int *c1p, int prev_c, int prev_c1,
int prev_laa = A_firstc_laa(prev_c, prev_c1);
if (curr_laa) {
- if (A_is_valid(prev_c) && !A_is_f(shape_c) && !A_is_s(shape_c) &&
- !prev_laa) {
+ if (A_is_valid(prev_c) && !A_is_f(shape_c) && !A_is_s(shape_c)
+ && !prev_laa) {
curr_c = chg_c_laa2f(curr_laa);
} else {
curr_c = chg_c_laa2i(curr_laa);
@@ -1454,19 +1454,19 @@ static bool A_is_harakat(int c)
// (alphabet/number/punctuation)
static bool A_is_iso(int c)
{
- return (c >= a_HAMZA && c <= a_GHAIN) ||
- (c >= a_TATWEEL && c <= a_HAMZA_BELOW) ||
- c == a_MINI_ALEF;
+ return ((c >= a_HAMZA && c <= a_GHAIN)
+ || (c >= a_TATWEEL && c <= a_HAMZA_BELOW)
+ || c == a_MINI_ALEF);
}
// A_is_formb returns true if 'c' is an Arabic 10646-1 FormB character.
// (alphabet/number/punctuation)
static bool A_is_formb(int c)
{
- return (c >= a_s_FATHATAN && c <= a_s_DAMMATAN) ||
- c == a_s_KASRATAN ||
- (c >= a_s_FATHA && c <= a_f_LAM_ALEF) ||
- c == a_BYTE_ORDER_MARK;
+ return ((c >= a_s_FATHATAN && c <= a_s_DAMMATAN)
+ || c == a_s_KASRATAN
+ || (c >= a_s_FATHA && c <= a_f_LAM_ALEF)
+ || c == a_BYTE_ORDER_MARK);
}
// A_is_ok returns true if 'c' is an Arabic 10646 (8859-6 or Form-B).
diff --git a/src/nvim/assert.h b/src/nvim/assert.h
index 0ce48e4766..2c43777858 100644
--- a/src/nvim/assert.h
+++ b/src/nvim/assert.h
@@ -46,10 +46,10 @@
#define STATIC_ASSERT_PRAGMA_START
#define STATIC_ASSERT_PRAGMA_END
-#define STATIC_ASSERT(...) \
+#define STATIC_ASSERT(cond, msg) \
do { \
STATIC_ASSERT_PRAGMA_START \
- STATIC_ASSERT_STATEMENT(__VA_ARGS__); \
+ STATIC_ASSERT_STATEMENT(cond, msg); \
STATIC_ASSERT_PRAGMA_END \
} while (0)
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index c514c4378e..72716daf0e 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -407,10 +407,9 @@ close_buffer (
buf->b_nwindows = nwindows;
buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
- if (
- win_valid(win) &&
- win->w_buffer == buf)
- win->w_buffer = NULL; /* make sure we don't use the buffer now */
+ if (win_valid(win) && win->w_buffer == buf) {
+ win->w_buffer = NULL; // make sure we don't use the buffer now
+ }
/* Autocommands may have deleted the buffer. */
if (!buf_valid(buf))
@@ -1294,14 +1293,15 @@ void enter_buffer(buf_T *buf)
redraw_later(NOT_VALID);
}
-/*
- * Change to the directory of the current buffer.
- */
+// Change to the directory of the current buffer.
+// Don't do this while still starting up.
void do_autochdir(void)
{
if (p_acd) {
- if (curbuf->b_ffname != NULL && vim_chdirfile(curbuf->b_ffname) == OK) {
- shorten_fnames(TRUE);
+ if (starting == 0
+ && curbuf->b_ffname != NULL
+ && vim_chdirfile(curbuf->b_ffname) == OK) {
+ shorten_fnames(true);
}
}
}
@@ -1339,8 +1339,8 @@ buflist_new (
/* We can use inode numbers when the file exists. Works better
* for hard links. */
FileID file_id;
- bool file_id_valid = (sfname != NULL &&
- os_fileid((char *)sfname, &file_id));
+ bool file_id_valid = (sfname != NULL
+ && os_fileid((char *)sfname, &file_id));
if (ffname != NULL && !(flags & BLN_DUMMY)
&& (buf = buflist_findname_file_id(ffname, &file_id,
file_id_valid)) != NULL) {
@@ -1553,6 +1553,7 @@ void free_buf_options(buf_T *buf, int free_p_ff)
clear_string_option(&buf->b_p_ep);
clear_string_option(&buf->b_p_path);
clear_string_option(&buf->b_p_tags);
+ clear_string_option(&buf->b_p_tc);
clear_string_option(&buf->b_p_dict);
clear_string_option(&buf->b_p_tsr);
clear_string_option(&buf->b_p_qe);
@@ -2194,15 +2195,16 @@ void buflist_list(exarg_T *eap)
len = vim_snprintf((char *)IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"",
buf->b_fnum,
buf->b_p_bl ? ' ' : 'u',
- buf == curbuf ? '%' :
- (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
- buf->b_ml.ml_mfp == NULL ? ' ' :
- (buf->b_nwindows == 0 ? 'h' : 'a'),
+ buf == curbuf ? '%' : (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
+ buf->b_ml.ml_mfp == NULL ? ' ' : (buf->b_nwindows == 0 ? 'h' : 'a'),
!MODIFIABLE(buf) ? '-' : (buf->b_p_ro ? '=' : ' '),
- (buf->b_flags & BF_READERR) ? 'x'
- : (bufIsChanged(buf) ? '+' : ' '),
+ (buf->b_flags & BF_READERR) ? 'x' : (bufIsChanged(buf) ? '+' : ' '),
NameBuff);
+ if (len > IOSIZE - 20) {
+ len = IOSIZE - 20;
+ }
+
/* put "line 999" in column 40 or after the file name */
i = 40 - vim_strsize(IObuff);
do {
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 86e63eb52c..0324f6b88a 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -141,8 +141,8 @@ struct buffblock {
struct buffheader {
buffblock_T bh_first; // first (dummy) block of list
buffblock_T *bh_curr; // buffblock for appending
- int bh_index; // index for reading
- int bh_space; // space in bh_curr for appending
+ size_t bh_index; // index for reading
+ size_t bh_space; // space in bh_curr for appending
};
/*
@@ -666,19 +666,21 @@ struct file_buffer {
long b_p_wm_nopaste; ///< b_p_wm saved for paste mode
char_u *b_p_keymap; ///< 'keymap'
- /* local values for options which are normally global */
- char_u *b_p_gp; /* 'grepprg' local value */
- char_u *b_p_mp; /* 'makeprg' local value */
- char_u *b_p_efm; /* 'errorformat' local value */
- char_u *b_p_ep; /* 'equalprg' local value */
- char_u *b_p_path; /* 'path' local value */
- int b_p_ar; /* 'autoread' local value */
- char_u *b_p_tags; /* 'tags' local value */
- char_u *b_p_dict; /* 'dictionary' local value */
- char_u *b_p_tsr; /* 'thesaurus' local value */
- long b_p_ul; /* 'undolevels' local value */
- int b_p_udf; /* 'undofile' */
- char_u *b_p_lw; // 'lispwords' local value
+ // local values for options which are normally global
+ char_u *b_p_gp; ///< 'grepprg' local value
+ char_u *b_p_mp; ///< 'makeprg' local value
+ char_u *b_p_efm; ///< 'errorformat' local value
+ char_u *b_p_ep; ///< 'equalprg' local value
+ char_u *b_p_path; ///< 'path' local value
+ int b_p_ar; ///< 'autoread' local value
+ char_u *b_p_tags; ///< 'tags' local value
+ char_u *b_p_tc; ///< 'tagcase' local value
+ unsigned b_tc_flags; ///< flags for 'tagcase'
+ char_u *b_p_dict; ///< 'dictionary' local value
+ char_u *b_p_tsr; ///< 'thesaurus' local value
+ long b_p_ul; ///< 'undolevels' local value
+ int b_p_udf; ///< 'undofile'
+ char_u *b_p_lw; ///< 'lispwords' local value
/* end of buffer options */
@@ -816,10 +818,12 @@ struct tabpage_S {
was set */
diff_T *tp_first_diff;
buf_T *(tp_diffbuf[DB_COUNT]);
- int tp_diff_invalid; /* list of diffs is outdated */
- frame_T *(tp_snapshot[SNAP_COUNT]); /* window layout snapshots */
- dictitem_T tp_winvar; /* variable for "t:" Dictionary */
- dict_T *tp_vars; /* internal variables, local to tab page */
+ int tp_diff_invalid; ///< list of diffs is outdated */
+ frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
+ dictitem_T tp_winvar; ///< variable for "t:" Dictionary
+ dict_T *tp_vars; ///< internal variables, local to tab page
+ char_u *localdir; ///< Absolute path of local directory or
+ ///< NULL
};
/*
@@ -953,16 +957,14 @@ struct window_S {
time through cursupdate() to the
current virtual column */
- /*
- * the next six are used to update the visual part
- */
- char w_old_visual_mode; /* last known VIsual_mode */
- linenr_T w_old_cursor_lnum; /* last known end of visual part */
- colnr_T w_old_cursor_fcol; /* first column for block visual part */
- colnr_T w_old_cursor_lcol; /* last column for block visual part */
- linenr_T w_old_visual_lnum; /* last known start of visual part */
- colnr_T w_old_visual_col; /* last known start of visual part */
- colnr_T w_old_curswant; /* last known value of Curswant */
+ // the next seven are used to update the visual part
+ char w_old_visual_mode; ///< last known VIsual_mode
+ linenr_T w_old_cursor_lnum; ///< last known end of visual part
+ colnr_T w_old_cursor_fcol; ///< first column for block visual part
+ colnr_T w_old_cursor_lcol; ///< last column for block visual part
+ linenr_T w_old_visual_lnum; ///< last known start of visual part
+ colnr_T w_old_visual_col; ///< last known start of visual part
+ colnr_T w_old_curswant; ///< last known value of Curswant
/*
* "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 83e2aaa6e6..d0dc7b66fc 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1794,10 +1794,11 @@ bool vim_isblankline(char_u *lbuf)
/// @param nptr Returns the signed result.
/// @param unptr Returns the unsigned result.
/// @param maxlen Max length of string to check.
-void vim_str2nr(char_u *start, int *prep, int *len, int what,
- long *nptr, unsigned long *unptr, int maxlen)
+void vim_str2nr(const char_u *const start, int *const prep, int *const len,
+ const int what, long *const nptr, unsigned long *const unptr,
+ const int maxlen)
{
- char_u *ptr = start;
+ const char_u *ptr = start;
int pre = 0; // default is decimal
bool negative = false;
unsigned long un = 0;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index a3063de869..4826e70727 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -29,7 +29,6 @@
#include "nvim/path.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
-#include "nvim/tempfile.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 3a4b475bc8..e131da8fe0 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1359,6 +1359,9 @@ ins_redraw (
update_screen(0);
}
if (has_event(EVENT_CURSORMOVEDI)) {
+ // Make sure curswant is correct, an autocommand may call
+ // getcurpos()
+ update_curswant();
apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, false, curbuf);
}
if (curwin->w_p_cole > 0) {
@@ -2319,6 +2322,22 @@ static int ins_compl_make_cyclic(void)
return count;
}
+
+// Set variables that store noselect and noinsert behavior from the
+// 'completeopt' value.
+void completeopt_was_set(void)
+{
+ compl_no_insert = false;
+ compl_no_select = false;
+ if (strstr((char *)p_cot, "noselect") != NULL) {
+ compl_no_select = true;
+ }
+ if (strstr((char *)p_cot, "noinsert") != NULL) {
+ compl_no_insert = true;
+ }
+}
+
+
/*
* Start completion for the complete() function.
* "startcol" is where the matched text starts (1 is first column).
@@ -3097,17 +3116,6 @@ static bool ins_compl_prep(int c)
}
- if (strstr((char *)p_cot, "noselect") != NULL) {
- compl_no_insert = FALSE;
- compl_no_select = TRUE;
- } else if (strstr((char *)p_cot, "noinsert") != NULL) {
- compl_no_insert = TRUE;
- compl_no_select = FALSE;
- } else {
- compl_no_insert = FALSE;
- compl_no_select = FALSE;
- }
-
if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET) {
/*
* We have just typed CTRL-X and aren't quite sure which CTRL-X mode
@@ -3298,6 +3306,12 @@ static bool ins_compl_prep(int c)
showmode();
}
+ // Avoid the popup menu remains displayed when leaving the
+ // command line window.
+ if (c == Ctrl_C && cmdwin_type != 0) {
+ update_screen(0);
+ }
+
/*
* Indent now if a key was typed that is in 'cinkeys'.
*/
@@ -4416,11 +4430,10 @@ static int ins_complete(int c, bool enable_pum)
prefix = (char_u *)"";
STRCPY((char *)compl_pattern, prefix);
(void)quote_meta(compl_pattern + STRLEN(prefix),
- line + compl_col, compl_length);
- } else if (--startcol < 0 ||
- !vim_iswordp(mb_prevptr(line, line + startcol + 1))
- ) {
- /* Match any word of at least two chars */
+ line + compl_col, compl_length);
+ } else if (--startcol < 0
+ || !vim_iswordp(mb_prevptr(line, line + startcol + 1))) {
+ // Match any word of at least two chars
compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
compl_col += curs_col;
compl_length = 0;
@@ -6676,8 +6689,8 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
} else if (*look == 'e') {
if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4) {
p = get_cursor_line_ptr();
- if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
- STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) {
+ if (skipwhite(p) == p + curwin->w_cursor.col - 4
+ && STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) {
return true;
}
}
@@ -7376,17 +7389,16 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
* can't backup past starting point unless 'backspace' > 1
* can backup to a previous line if 'backspace' == 0
*/
- if ( bufempty()
- || (
- !revins_on &&
- ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
- || (!can_bs(BS_START)
- && (arrow_used
- || (curwin->w_cursor.lnum == Insstart_orig.lnum
- && curwin->w_cursor.col <= Insstart_orig.col)))
- || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
- && curwin->w_cursor.col <= ai_col)
- || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0)))) {
+ if (bufempty()
+ || (!revins_on
+ && ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
+ || (!can_bs(BS_START)
+ && (arrow_used
+ || (curwin->w_cursor.lnum == Insstart_orig.lnum
+ && curwin->w_cursor.col <= Insstart_orig.col)))
+ || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
+ && curwin->w_cursor.col <= ai_col)
+ || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0)))) {
vim_beep(BO_BS);
return false;
}
@@ -7632,14 +7644,14 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
if (revins_on && gchar_cursor() == NUL)
break;
}
- /* Just a single backspace?: */
- if (mode == BACKSPACE_CHAR)
+ // Just a single backspace?:
+ if (mode == BACKSPACE_CHAR) {
break;
- } while (
- revins_on ||
- (curwin->w_cursor.col > mincol
- && (curwin->w_cursor.lnum != Insstart_orig.lnum
- || curwin->w_cursor.col != Insstart_orig.col)));
+ }
+ } while (revins_on
+ || (curwin->w_cursor.col > mincol
+ && (curwin->w_cursor.lnum != Insstart_orig.lnum
+ || curwin->w_cursor.col != Insstart_orig.col)));
}
did_backspace = true;
}
@@ -7741,6 +7753,8 @@ static void ins_mousescroll(int dir)
(long)(curwin->w_botline - curwin->w_topline));
else
scroll_redraw(dir, 3L);
+ } else {
+ mouse_scroll_horiz(dir);
}
did_scroll = TRUE;
}
diff --git a/src/nvim/edit.h b/src/nvim/edit.h
index 0289b2c3a6..0d61f26bcc 100644
--- a/src/nvim/edit.h
+++ b/src/nvim/edit.h
@@ -36,12 +36,6 @@ typedef int (*IndentGetter)(void);
#define INSCHAR_NO_FEX 8 /* don't use 'formatexpr' */
#define INSCHAR_COM_LIST 16 /* format comments with list/2nd line indent */
-/* direction for nv_mousescroll() and ins_mousescroll() */
-#define MSCR_DOWN 0 /* DOWN must be FALSE */
-#define MSCR_UP 1
-#define MSCR_LEFT -1
-#define MSCR_RIGHT -2
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "edit.h.generated.h"
#endif
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b51480afc6..d84bdfebfe 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -66,7 +66,6 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
-#include "nvim/tempfile.h"
#include "nvim/ui.h"
#include "nvim/mouse.h"
#include "nvim/terminal.h"
@@ -2267,8 +2266,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, true, false) == OK) {
if ((di == NULL
- || (!var_check_ro(di->di_flags, lp->ll_name, false) &&
- !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false)))
+ || (!var_check_ro(di->di_flags, lp->ll_name, false)
+ && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false)))
&& tv_op(&tv, rettv, op) == OK) {
set_var(lp->ll_name, &tv, false);
}
@@ -4741,13 +4740,14 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
++name;
break;
- /* Special key, e.g.: "\<C-W>" */
- case '<': extra = trans_special(&p, name, TRUE);
+ // Special key, e.g.: "\<C-W>"
+ case '<':
+ extra = trans_special((const char_u **) &p, STRLEN(p), name, true);
if (extra != 0) {
name += extra;
break;
}
- /* FALLTHROUGH */
+ // FALLTHROUGH
default: MB_COPY_CHAR(p, name);
break;
@@ -6656,7 +6656,7 @@ static struct fst {
} functions[] =
{
{ "abs", 1, 1, f_abs },
- { "acos", 1, 1, f_acos }, // WJMc
+ { "acos", 1, 1, f_acos }, // WJMc
{ "add", 2, 2, f_add },
{ "and", 2, 2, f_and },
{ "append", 2, 2, f_append },
@@ -6666,6 +6666,7 @@ static struct fst {
{ "argv", 0, 1, f_argv },
{ "asin", 1, 1, f_asin }, // WJMc
{ "assert_equal", 2, 3, f_assert_equal },
+ { "assert_exception", 1, 2, f_assert_exception },
{ "assert_false", 1, 2, f_assert_false },
{ "assert_true", 1, 2, f_assert_true },
{ "atan", 1, 1, f_atan },
@@ -6673,9 +6674,9 @@ static struct fst {
{ "browse", 4, 4, f_browse },
{ "browsedir", 2, 2, f_browsedir },
{ "bufexists", 1, 1, f_bufexists },
- { "buffer_exists", 1, 1, f_bufexists }, // obsolete
- { "buffer_name", 1, 1, f_bufname }, // obsolete
- { "buffer_number", 1, 1, f_bufnr }, // obsolete
+ { "buffer_exists", 1, 1, f_bufexists }, // obsolete
+ { "buffer_name", 1, 1, f_bufname }, // obsolete
+ { "buffer_number", 1, 1, f_bufnr }, // obsolete
{ "buflisted", 1, 1, f_buflisted },
{ "bufloaded", 1, 1, f_bufloaded },
{ "bufname", 1, 1, f_bufname },
@@ -6702,7 +6703,7 @@ static struct fst {
{ "cscope_connection", 0, 3, f_cscope_connection },
{ "cursor", 1, 3, f_cursor },
{ "deepcopy", 1, 2, f_deepcopy },
- { "delete", 1, 1, f_delete },
+ { "delete", 1, 2, f_delete },
{ "dictwatcheradd", 3, 3, f_dictwatcheradd },
{ "dictwatcherdel", 3, 3, f_dictwatcherdel },
{ "did_filetype", 0, 0, f_did_filetype },
@@ -6719,7 +6720,7 @@ static struct fst {
{ "expand", 1, 3, f_expand },
{ "extend", 2, 3, f_extend },
{ "feedkeys", 1, 2, f_feedkeys },
- { "file_readable", 1, 1, f_filereadable }, // obsolete
+ { "file_readable", 1, 1, f_filereadable }, // obsolete
{ "filereadable", 1, 1, f_filereadable },
{ "filewritable", 1, 1, f_filewritable },
{ "filter", 2, 2, f_filter },
@@ -6749,7 +6750,7 @@ static struct fst {
{ "getcmdtype", 0, 0, f_getcmdtype },
{ "getcmdwintype", 0, 0, f_getcmdwintype },
{ "getcurpos", 0, 0, f_getcurpos },
- { "getcwd", 0, 0, f_getcwd },
+ { "getcwd", 0, 2, f_getcwd },
{ "getfontname", 0, 1, f_getfontname },
{ "getfperm", 1, 1, f_getfperm },
{ "getfsize", 1, 1, f_getfsize },
@@ -6773,7 +6774,7 @@ static struct fst {
{ "globpath", 2, 5, f_globpath },
{ "has", 1, 1, f_has },
{ "has_key", 2, 2, f_has_key },
- { "haslocaldir", 0, 0, f_haslocaldir },
+ { "haslocaldir", 0, 2, f_haslocaldir },
{ "hasmapto", 1, 3, f_hasmapto },
{ "highlightID", 1, 1, f_hlID }, // obsolete
{ "highlight_exists", 1, 1, f_hlexists }, // obsolete
@@ -7628,14 +7629,35 @@ static void f_assert_equal(typval_T *argvars, typval_T *rettv)
}
}
+/// "assert_exception(string[, msg])" function
+static void f_assert_exception(typval_T *argvars, typval_T *rettv)
+{
+ garray_T ga;
+
+ char *error = (char *)get_tv_string_chk(&argvars[0]);
+ if (vimvars[VV_EXCEPTION].vv_str == NULL) {
+ prepare_assert_error(&ga);
+ ga_concat(&ga, (char_u *)"v:exception is not set");
+ assert_error(&ga);
+ ga_clear(&ga);
+ } else if (strstr((char *)vimvars[VV_EXCEPTION].vv_str, error) == NULL) {
+ prepare_assert_error(&ga);
+ fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
+ &vimvars[VV_EXCEPTION].vv_tv);
+ assert_error(&ga);
+ ga_clear(&ga);
+ }
+}
+
// Common for assert_true() and assert_false().
static void assert_bool(typval_T *argvars, bool is_true)
{
int error = (int)false;
garray_T ga;
- if ((argvars[0].v_type != VAR_NUMBER ||
- (get_tv_number_chk(&argvars[0], &error) == 0) == is_true || error)
+ if ((argvars[0].v_type != VAR_NUMBER
+ || (get_tv_number_chk(&argvars[0], &error) == 0) == is_true
+ || error)
&& (argvars[0].v_type != VAR_SPECIAL
|| (argvars[0].vval.v_special
!= (SpecialVarValue) (is_true
@@ -8305,12 +8327,12 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = cs_connection(num, dbpath, prepend);
}
-/*
- * "cursor(lnum, col)" function
- *
- * Moves the cursor to the specified line and column.
- * Returns 0 when the position could be set, -1 otherwise.
- */
+/// "cursor(lnum, col)" function, or
+/// "cursor(list)"
+///
+/// Moves the cursor to the specified line and column.
+///
+/// @returns 0 when the position could be set, -1 otherwise.
static void f_cursor(typval_T *argvars, typval_T *rettv)
{
long line, col;
@@ -8322,8 +8344,10 @@ static void f_cursor(typval_T *argvars, typval_T *rettv)
colnr_T curswant = -1;
if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL) {
+ EMSG(_(e_invarg));
return;
}
+
line = pos.lnum;
col = pos.col;
coladd = pos.coladd;
@@ -8374,15 +8398,42 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv)
}
}
-/*
- * "delete()" function
- */
+// "delete()" function
static void f_delete(typval_T *argvars, typval_T *rettv)
{
- if (check_restricted() || check_secure())
- rettv->vval.v_number = -1;
- else
- rettv->vval.v_number = os_remove((char *)get_tv_string(&argvars[0]));
+ char_u nbuf[NUMBUFLEN];
+ char_u *name;
+ char_u *flags;
+
+ rettv->vval.v_number = -1;
+ if (check_restricted() || check_secure()) {
+ return;
+ }
+
+ name = get_tv_string(&argvars[0]);
+ if (name == NULL || *name == NUL) {
+ EMSG(_(e_invarg));
+ return;
+ }
+
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ flags = get_tv_string_buf(&argvars[1], nbuf);
+ } else {
+ flags = (char_u *)"";
+ }
+
+ if (*flags == NUL) {
+ // delete a file
+ rettv->vval.v_number = os_remove((char *)name) == 0 ? 0 : -1;
+ } else if (STRCMP(flags, "d") == 0) {
+ // delete an empty directory
+ rettv->vval.v_number = os_rmdir((char *)name) == 0 ? 0 : -1;
+ } else if (STRCMP(flags, "rf") == 0) {
+ // delete a directory recursively
+ rettv->vval.v_number = delete_recursive(name);
+ } else {
+ EMSG2(_(e_invexpr2), flags);
+ }
}
// dictwatcheradd(dict, key, funcref) function
@@ -8641,7 +8692,11 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv)
*/
static void f_executable(typval_T *argvars, typval_T *rettv)
{
- rettv->vval.v_number = os_can_exe(get_tv_string(&argvars[0]), NULL);
+ char_u *name = get_tv_string(&argvars[0]);
+
+ // Check in $PATH and also check directly if there is a directory name
+ rettv->vval.v_number = os_can_exe(name, NULL, true)
+ || (gettail_dir(name) != name && os_can_exe(name, NULL, false));
}
/// "exepath()" function
@@ -8650,7 +8705,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv)
char_u *arg = get_tv_string(&argvars[0]);
char_u *path = NULL;
- (void)os_can_exe(arg, &path);
+ (void)os_can_exe(arg, &path, true);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = path;
@@ -9758,22 +9813,130 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string[0] = cmdwin_type;
}
-/*
- * "getcwd()" function
- */
+/// `getcwd([{win}[, {tab}]])` function
+///
+/// Every scope not specified implies the currently selected scope object.
+///
+/// @pre The arguments must be of type number.
+/// @pre There may not be more than two arguments.
+/// @pre An argument may not be -1 if preceding arguments are not all -1.
+///
+/// @post The return value will be a string.
static void f_getcwd(typval_T *argvars, typval_T *rettv)
{
- char_u *cwd;
+ // Possible scope of working directory to return.
+ CdScope scope = MIN_CD_SCOPE;
+
+ // Numbers of the scope objects (window, tab) we want the working directory
+ // of. A `-1` means to skip this scope, a `0` means the current object.
+ int scope_number[] = {
+ [kCdScopeWindow] = 0, // Number of window to look at.
+ [kCdScopeTab ] = 0, // Number of tab to look at.
+ };
+
+ char_u *cwd = NULL; // Current working directory to print
+ char_u *from = NULL; // The original string to copy
+
+ tabpage_T *tp = curtab; // The tabpage to look at.
+ win_T *win = curwin; // The window to look at.
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+
+ // Pre-conditions and scope extraction together
+ for (int i = MIN_CD_SCOPE; i < MAX_CD_SCOPE; i++) {
+ // If there is no argument there are no more scopes after it, break out.
+ if (argvars[i].v_type == VAR_UNKNOWN) {
+ break;
+ }
+ if (argvars[i].v_type != VAR_NUMBER) {
+ EMSG(_(e_invarg));
+ return;
+ }
+ scope_number[i] = argvars[i].vval.v_number;
+ // The scope is the current iteration step.
+ scope = i;
+ // It is an error for the scope number to be less than `-1`.
+ if (scope_number[i] < -1) {
+ EMSG(_(e_invarg));
+ return;
+ }
+ }
+
+ // Normalize scope, the number of the new scope will be 0.
+ if (scope_number[scope] < 0) {
+ // Arguments to `getcwd` always end at second-highest scope, so scope will
+ // always be <= `MAX_CD_SCOPE`.
+ scope++;
+ }
+
+ // Find the tabpage by number
+ if (scope_number[kCdScopeTab] == -1) {
+ tp = NULL;
+ } else if (scope_number[kCdScopeTab] > 0) {
+ tp = find_tabpage(scope_number[kCdScopeTab]);
+ if (!tp) {
+ EMSG(_("E5000: Cannot find tab number."));
+ return;
+ }
+ }
+
+ // Find the window in `tp` by number, `NULL` if none.
+ if (scope_number[kCdScopeWindow] == -1) {
+ win = NULL;
+ } else if (scope_number[kCdScopeWindow] >= 0) {
+ if (!tp) {
+ EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0."));
+ return;
+ }
+
+ if (scope_number[kCdScopeWindow] > 0) {
+ win = find_win_by_nr(&argvars[0], curtab);
+ if (!win) {
+ EMSG(_("E5002: Cannot find window number."));
+ return;
+ }
+ }
+ }
+
cwd = xmalloc(MAXPATHL);
- if (os_dirname(cwd, MAXPATHL) != FAIL) {
- rettv->vval.v_string = vim_strsave(cwd);
+
+ switch (scope) {
+ case kCdScopeWindow:
+ assert(win);
+ from = win->w_localdir;
+ if (from) {
+ break;
+ }
+ case kCdScopeTab: // FALLTHROUGH
+ assert(tp);
+ from = tp->localdir;
+ if (from) {
+ break;
+ }
+ case kCdScopeGlobal: // FALLTHROUGH
+ // The `globaldir` variable is not always set.
+ if (globaldir) {
+ from = globaldir;
+ } else {
+ // We have to copy the OS path directly into output string.
+ if (os_dirname(cwd, MAXPATHL) == FAIL) {
+ EMSG(_("E41: Could not display path."));
+ goto end;
+ }
+ }
+ break;
+ }
+
+ if (from) {
+ xstrlcpy((char *)cwd, (char *)from, MAXPATHL);
+ }
+
+ rettv->vval.v_string = vim_strsave(cwd);
#ifdef BACKSLASH_IN_FILENAME
- slash_adjust(rettv->vval.v_string);
+ slash_adjust(rettv->vval.v_string);
#endif
- }
+end:
xfree(cwd);
}
@@ -10024,6 +10187,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos)
list_append_number(l,
(fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0);
if (getcurpos) {
+ update_curswant();
list_append_number(l, curwin->w_curswant == MAXCOL
? (varnumber_T)MAXCOL
: (varnumber_T)curwin->w_curswant + 1);
@@ -10131,7 +10295,7 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv)
colnr_T reglen = 0;
char buf[NUMBUFLEN + 2];
- char_u reg_type = get_reg_type(regname, &reglen);
+ MotionType reg_type = get_reg_type(regname, &reglen);
format_reg_type(reg_type, reglen, buf, ARRAY_SIZE(buf));
rettv->v_type = VAR_STRING;
@@ -10593,12 +10757,103 @@ static void f_has_key(typval_T *argvars, typval_T *rettv)
get_tv_string(&argvars[1]), -1) != NULL;
}
-/*
- * "haslocaldir()" function
- */
+/// `haslocaldir([{win}[, {tab}]])` function
+///
+/// Returns `1` if the scope object has a local directory, `0` otherwise. If a
+/// scope object is not specified the current one is implied. This function
+/// share a lot of code with `f_getcwd`.
+///
+/// @pre The arguments must be of type number.
+/// @pre There may not be more than two arguments.
+/// @pre An argument may not be -1 if preceding arguments are not all -1.
+///
+/// @post The return value will be either the number `1` or `0`.
static void f_haslocaldir(typval_T *argvars, typval_T *rettv)
{
- rettv->vval.v_number = (curwin->w_localdir != NULL);
+ // Possible scope of working directory to return.
+ CdScope scope = MIN_CD_SCOPE;
+
+ // Numbers of the scope objects (window, tab) we want the working directory
+ // of. A `-1` means to skip this scope, a `0` means the current object.
+ int scope_number[] = {
+ [kCdScopeWindow] = 0, // Number of window to look at.
+ [kCdScopeTab ] = 0, // Number of tab to look at.
+ };
+
+ tabpage_T *tp = curtab; // The tabpage to look at.
+ win_T *win = curwin; // The window to look at.
+
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = 0;
+
+ // Pre-conditions and scope extraction together
+ for (int i = MIN_CD_SCOPE; i < MAX_CD_SCOPE; i++) {
+ if (argvars[i].v_type == VAR_UNKNOWN) {
+ break;
+ }
+ if (argvars[i].v_type != VAR_NUMBER) {
+ EMSG(_(e_invarg));
+ return;
+ }
+ scope_number[i] = argvars[i].vval.v_number;
+ // The scope is the current iteration step.
+ scope = i;
+ if (scope_number[i] < -1) {
+ EMSG(_(e_invarg));
+ return;
+ }
+ }
+
+ // Normalize scope, the number of the new scope will be 0.
+ if (scope_number[scope] < 0) {
+ // Arguments to `haslocaldir` always end at second-highest scope, so scope
+ // will always be <= `MAX_CD_SCOPE`.
+ scope++;
+ }
+
+ // Find the tabpage by number
+ if (scope_number[kCdScopeTab] == -1) {
+ tp = NULL;
+ } else if (scope_number[kCdScopeTab] > 0) {
+ tp = find_tabpage(scope_number[kCdScopeTab]);
+ if (!tp) {
+ EMSG(_("5000: Cannot find tab number."));
+ return;
+ }
+ }
+
+ // Find the window in `tp` by number, `NULL` if none.
+ if (scope_number[kCdScopeWindow] == -1) {
+ win = NULL;
+ } else if (scope_number[kCdScopeWindow] >= 0) {
+ if (!tp) {
+ EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0."));
+ return;
+ }
+
+ if (scope_number[kCdScopeWindow] > 0) {
+ win = find_win_by_nr(&argvars[0], curtab);
+ if (!win) {
+ EMSG(_("E5002: Cannot find window number."));
+ return;
+ }
+ }
+ }
+
+ switch (scope) {
+ case kCdScopeWindow:
+ assert(win);
+ rettv->vval.v_number = win->w_localdir ? 1 : 0;
+ break;
+ case kCdScopeTab:
+ assert(tp);
+ rettv->vval.v_number = tp->localdir ? 1 : 0;
+ break;
+ case kCdScopeGlobal:
+ // The global scope never has a local directory
+ rettv->vval.v_number = 0;
+ break;
+ }
}
/*
@@ -10631,21 +10886,22 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv)
*/
static void f_histadd(typval_T *argvars, typval_T *rettv)
{
- int histype;
+ HistoryType histype;
char_u *str;
char_u buf[NUMBUFLEN];
- rettv->vval.v_number = FALSE;
- if (check_restricted() || check_secure())
+ rettv->vval.v_number = false;
+ if (check_restricted() || check_secure()) {
return;
- str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
- histype = str != NULL ? get_histtype(str) : -1;
- if (histype >= 0) {
+ }
+ str = get_tv_string_chk(&argvars[0]); // NULL on type error
+ histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID;
+ if (histype != HIST_INVALID) {
str = get_tv_string_buf(&argvars[1], buf);
if (*str != NUL) {
init_history();
- add_to_history(histype, str, FALSE, NUL);
- rettv->vval.v_number = TRUE;
+ add_to_history(histype, str, false, NUL);
+ rettv->vval.v_number = true;
return;
}
}
@@ -10660,20 +10916,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv)
char_u buf[NUMBUFLEN];
char_u *str;
- str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
- if (str == NULL)
+ str = get_tv_string_chk(&argvars[0]); // NULL on type error
+ if (str == NULL) {
n = 0;
- else if (argvars[1].v_type == VAR_UNKNOWN)
- /* only one argument: clear entire history */
- n = clr_history(get_histtype(str));
- else if (argvars[1].v_type == VAR_NUMBER)
- /* index given: remove that entry */
- n = del_history_idx(get_histtype(str),
- (int)get_tv_number(&argvars[1]));
- else
- /* string given: remove all matching entries */
- n = del_history_entry(get_histtype(str),
- get_tv_string_buf(&argvars[1], buf));
+ } else if (argvars[1].v_type == VAR_UNKNOWN) {
+ // only one argument: clear entire history
+ n = clr_history(get_histtype(str, STRLEN(str), false));
+ } else if (argvars[1].v_type == VAR_NUMBER) {
+ // index given: remove that entry
+ n = del_history_idx(get_histtype(str, STRLEN(str), false),
+ (int) get_tv_number(&argvars[1]));
+ } else {
+ // string given: remove all matching entries
+ n = del_history_entry(get_histtype(str, STRLEN(str), false),
+ get_tv_string_buf(&argvars[1], buf));
+ }
rettv->vval.v_number = n;
}
@@ -10682,20 +10939,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv)
*/
static void f_histget(typval_T *argvars, typval_T *rettv)
{
- int type;
+ HistoryType type;
int idx;
char_u *str;
- str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
- if (str == NULL)
+ str = get_tv_string_chk(&argvars[0]); // NULL on type error
+ if (str == NULL) {
rettv->vval.v_string = NULL;
- else {
- type = get_histtype(str);
- if (argvars[1].v_type == VAR_UNKNOWN)
+ } else {
+ type = get_histtype(str, STRLEN(str), false);
+ if (argvars[1].v_type == VAR_UNKNOWN) {
idx = get_history_idx(type);
- else
+ } else {
idx = (int)get_tv_number_chk(&argvars[1], NULL);
- /* -1 on type error */
+ }
+ // -1 on type error
rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
}
rettv->v_type = VAR_STRING;
@@ -10710,11 +10968,13 @@ static void f_histnr(typval_T *argvars, typval_T *rettv)
char_u *history = get_tv_string_chk(&argvars[0]);
- i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
- if (i >= HIST_CMD && i < HIST_COUNT)
+ i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history),
+ false);
+ if (i != HIST_INVALID) {
i = get_history_idx(i);
- else
+ } else {
i = -1;
+ }
rettv->vval.v_number = i;
}
@@ -11350,7 +11610,7 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd)
assert(argl->lv_first);
const char_u *exe = get_tv_string_chk(&argl->lv_first->li_tv);
- if (!exe || !os_can_exe(exe, NULL)) {
+ if (!exe || !os_can_exe(exe, NULL, true)) {
// String is not executable
if (exe) {
EMSG2(e_jobexe, exe);
@@ -11851,8 +12111,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
mode = get_map_mode(&which, 0);
- keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
- rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
+ keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false,
+ CPO_TO_CPO_FLAGS);
+ rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local);
xfree(keys_buf);
if (!get_dict) {
@@ -13303,14 +13564,14 @@ static void f_reverse(typval_T *argvars, typval_T *rettv)
}
}
-#define SP_NOMOVE 0x01 /* don't move cursor */
-#define SP_REPEAT 0x02 /* repeat to find outer pair */
-#define SP_RETCOUNT 0x04 /* return matchcount */
-#define SP_SETPCMARK 0x08 /* set previous context mark */
-#define SP_START 0x10 /* accept match at start position */
-#define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */
-#define SP_END 0x40 /* leave cursor at end of match */
-
+#define SP_NOMOVE 0x01 ///< don't move cursor
+#define SP_REPEAT 0x02 ///< repeat to find outer pair
+#define SP_RETCOUNT 0x04 ///< return matchcount
+#define SP_SETPCMARK 0x08 ///< set previous context mark
+#define SP_START 0x10 ///< accept match at start position
+#define SP_SUBPAT 0x20 ///< return nr of matching sub-pattern
+#define SP_END 0x40 ///< leave cursor at end of match
+#define SP_COLUMN 0x80 ///< start at cursor column
/*
* Get flags for a search function.
@@ -13336,13 +13597,14 @@ static int get_search_arg(typval_T *varp, int *flagsp)
default: mask = 0;
if (flagsp != NULL)
switch (*flags) {
- case 'c': mask = SP_START; break;
- case 'e': mask = SP_END; break;
- case 'm': mask = SP_RETCOUNT; break;
- case 'n': mask = SP_NOMOVE; break;
- case 'p': mask = SP_SUBPAT; break;
- case 'r': mask = SP_REPEAT; break;
- case 's': mask = SP_SETPCMARK; break;
+ case 'c': mask = SP_START; break;
+ case 'e': mask = SP_END; break;
+ case 'm': mask = SP_RETCOUNT; break;
+ case 'n': mask = SP_NOMOVE; break;
+ case 'p': mask = SP_SUBPAT; break;
+ case 'r': mask = SP_REPEAT; break;
+ case 's': mask = SP_SETPCMARK; break;
+ case 'z': mask = SP_COLUMN; break;
}
if (mask == 0) {
EMSG2(_(e_invarg2), flags);
@@ -13358,9 +13620,7 @@ static int get_search_arg(typval_T *varp, int *flagsp)
return dir;
}
-/*
- * Shared by search() and searchpos() functions
- */
+// Shared by search() and searchpos() functions.
static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
{
int flags;
@@ -13381,10 +13641,15 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
if (dir == 0)
goto theend;
flags = *flagsp;
- if (flags & SP_START)
+ if (flags & SP_START) {
options |= SEARCH_START;
- if (flags & SP_END)
+ }
+ if (flags & SP_END) {
options |= SEARCH_END;
+ }
+ if (flags & SP_COLUMN) {
+ options |= SEARCH_COL;
+ }
/* Optional arguments: line number to stop searching and timeout. */
if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) {
@@ -14457,11 +14722,11 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
char_u *strregname;
char_u *stropt;
bool append = false;
- char_u yank_type;
+ MotionType yank_type;
long block_len;
block_len = -1;
- yank_type = MAUTO;
+ yank_type = kMTUnknown;
strregname = get_tv_string_chk(argvars);
rettv->vval.v_number = 1; /* FAIL is default */
@@ -14478,17 +14743,17 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
return; /* type error */
for (; *stropt != NUL; ++stropt)
switch (*stropt) {
- case 'a': case 'A': /* append */
+ case 'a': case 'A': // append
append = true;
break;
- case 'v': case 'c': /* character-wise selection */
- yank_type = MCHAR;
+ case 'v': case 'c': // character-wise selection
+ yank_type = kMTCharWise;
break;
- case 'V': case 'l': /* line-wise selection */
- yank_type = MLINE;
+ case 'V': case 'l': // line-wise selection
+ yank_type = kMTLineWise;
break;
- case 'b': case Ctrl_V: /* block-wise selection */
- yank_type = MBLOCK;
+ case 'b': case Ctrl_V: // block-wise selection
+ yank_type = kMTBlockWise;
if (ascii_isdigit(stropt[1])) {
++stropt;
block_len = getdigits_long(&stropt) - 1;
@@ -14714,6 +14979,8 @@ typedef struct {
static int item_compare_ic;
static bool item_compare_numeric;
+static bool item_compare_numbers;
+static bool item_compare_float;
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
@@ -14735,6 +15002,21 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
si2 = (sortItem_T *)s2;
typval_T *tv1 = &si1->item->li_tv;
typval_T *tv2 = &si2->item->li_tv;
+
+ if (item_compare_numbers) {
+ long v1 = get_tv_number(tv1);
+ long v2 = get_tv_number(tv2);
+
+ return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
+ }
+
+ if (item_compare_float) {
+ float_T v1 = get_tv_float(tv1);
+ float_T v2 = get_tv_float(tv2);
+
+ return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
+ }
+
// encode_tv2string() puts quotes around a string and allocates memory. Don't
// do that for string variables. Use a single quote when comparing with
// a non-string to do what the docs promise.
@@ -14863,12 +15145,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
} else {
l = argvars[0].vval.v_list;
- if (l == NULL ||
- tv_check_lock(l->lv_lock,
- (char_u *)(sort
- ? N_("sort() argument")
- : N_("uniq() argument")),
- true)) {
+ if (l == NULL
+ || tv_check_lock(l->lv_lock,
+ (char_u *)(sort
+ ? N_("sort() argument")
+ : N_("uniq() argument")),
+ true)) {
return;
}
rettv->vval.v_list = l;
@@ -14881,6 +15163,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
item_compare_ic = FALSE;
item_compare_numeric = false;
+ item_compare_numbers = false;
+ item_compare_float = false;
item_compare_func = NULL;
item_compare_selfdict = NULL;
@@ -14902,6 +15186,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
if (STRCMP(item_compare_func, "n") == 0) {
item_compare_func = NULL;
item_compare_numeric = true;
+ } else if (STRCMP(item_compare_func, "N") == 0) {
+ item_compare_func = NULL;
+ item_compare_numbers = true;
+ } else if (STRCMP(item_compare_func, "f") == 0) {
+ item_compare_func = NULL;
+ item_compare_float = true;
} else if (STRCMP(item_compare_func, "i") == 0) {
item_compare_func = NULL;
item_compare_ic = TRUE;
@@ -17603,6 +17893,33 @@ long get_tv_number_chk(typval_T *varp, int *denote)
return n;
}
+static float_T get_tv_float(typval_T *varp)
+{
+ switch (varp->v_type) {
+ case VAR_NUMBER:
+ return (float_T)(varp->vval.v_number);
+ case VAR_FLOAT:
+ return varp->vval.v_float;
+ break;
+ case VAR_FUNC:
+ EMSG(_("E891: Using a Funcref as a Float"));
+ break;
+ case VAR_STRING:
+ EMSG(_("E892: Using a String as a Float"));
+ break;
+ case VAR_LIST:
+ EMSG(_("E893: Using a List as a Float"));
+ break;
+ case VAR_DICT:
+ EMSG(_("E894: Using a Dictionary as a Float"));
+ break;
+ default:
+ EMSG2(_(e_intern2), "get_tv_float()");
+ break;
+ }
+ return 0;
+}
+
/*
* Get the lnum from the first argument.
* Also accepts ".", "$", etc., but that only works for the current buffer.
@@ -18953,9 +19270,10 @@ void ex_function(exarg_T *eap)
if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
|| (p[0] == 'i'
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
- && (!ASCII_ISALPHA(p[2]) ||
- (p[2] == 's'))))))
+ && (!ASCII_ISALPHA(p[2])
+ || (p[2] == 's')))))) {
skip_until = vim_strsave((char_u *)".");
+ }
// Check for ":python <<EOF", ":lua <<EOF", etc.
arg = skipwhite(skiptowhite(p));
@@ -19222,11 +19540,12 @@ trans_function_name (
*pp = end;
} else {
if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
- || lv.ll_dict == NULL ||
- fdp->fd_newkey == NULL))
+ || lv.ll_dict == NULL
+ || fdp->fd_newkey == NULL)) {
EMSG(_(e_funcref));
- else
+ } else {
*pp = end;
+ }
name = NULL;
}
goto theend;
@@ -20126,9 +20445,9 @@ call_user_func (
--RedrawingDisabled;
- /* when the function was aborted because of an error, return -1 */
- if ((did_emsg &&
- (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN) {
+ // when the function was aborted because of an error, return -1
+ if ((did_emsg
+ && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN) {
clear_tv(rettv);
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = -1;
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index e6012595fd..9bb62891c7 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -187,9 +187,9 @@ int process_wait(Process *proc, int ms, Queue *events) FUNC_ATTR_NONNULL_ARG(1)
// being freed) before we have a chance to get the status.
proc->refcount++;
LOOP_PROCESS_EVENTS_UNTIL(proc->loop, events, ms,
- // Until...
- got_int || // interrupted by the user
- proc->refcount == 1); // job exited
+ // Until...
+ got_int // interrupted by the user
+ || proc->refcount == 1); // job exited
// we'll assume that a user frantically hitting interrupt doesn't like
// the current job. Signal that it has to be killed.
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index d344daed11..e8314e02e0 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3,6 +3,7 @@
*/
#include <assert.h>
+#include <float.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
@@ -50,7 +51,6 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
-#include "nvim/tempfile.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -274,17 +274,26 @@ static int linelen(int *has_tab)
static char_u *sortbuf1;
static char_u *sortbuf2;
-static int sort_ic; /* ignore case */
-static int sort_nr; /* sort on number */
-static int sort_rx; /* sort on regex instead of skipping it */
+static int sort_ic; ///< ignore case
+static int sort_nr; ///< sort on number
+static int sort_rx; ///< sort on regex instead of skipping it
+static int sort_flt; ///< sort on floating number
-static int sort_abort; /* flag to indicate if sorting has been interrupted */
+static int sort_abort; ///< flag to indicate if sorting has been interrupted
-/* Struct to store info to be sorted. */
+/// Struct to store info to be sorted.
typedef struct {
- linenr_T lnum; /* line number */
- long start_col_nr; /* starting column number or number */
- long end_col_nr; /* ending column number */
+ linenr_T lnum; ///< line number
+ long start_col_nr; ///< starting column number or number
+ long end_col_nr; ///< ending column number
+ union {
+ struct {
+ long start_col_nr; ///< starting column number
+ long end_col_nr; ///< ending column number
+ } line;
+ long value; ///< value if sorting by integer
+ float_T value_flt; ///< value if sorting by float
+ } st_u;
} sorti_T;
@@ -303,21 +312,26 @@ static int sort_compare(const void *s1, const void *s2)
if (got_int)
sort_abort = TRUE;
- /* When sorting numbers "start_col_nr" is the number, not the column
- * number. */
- if (sort_nr)
- result = l1.start_col_nr == l2.start_col_nr ? 0
- : l1.start_col_nr > l2.start_col_nr ? 1 : -1;
- else {
- /* We need to copy one line into "sortbuf1", because there is no
- * guarantee that the first pointer becomes invalid when obtaining the
- * second one. */
- STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.start_col_nr,
- l1.end_col_nr - l1.start_col_nr + 1);
- sortbuf1[l1.end_col_nr - l1.start_col_nr] = 0;
- STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.start_col_nr,
- l2.end_col_nr - l2.start_col_nr + 1);
- sortbuf2[l2.end_col_nr - l2.start_col_nr] = 0;
+ // When sorting numbers "start_col_nr" is the number, not the column
+ // number.
+ if (sort_nr) {
+ result = l1.st_u.value == l2.st_u.value
+ ? 0 : l1.st_u.value > l2.st_u.value
+ ? 1 : -1;
+ } else if (sort_flt) {
+ result = l1.st_u.value_flt == l2.st_u.value_flt
+ ? 0 : l1.st_u.value_flt > l2.st_u.value_flt
+ ? 1 : -1;
+ } else {
+ // We need to copy one line into "sortbuf1", because there is no
+ // guarantee that the first pointer becomes invalid when obtaining the
+ // second one.
+ STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr,
+ l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1);
+ sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0;
+ STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr,
+ l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1);
+ sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0;
result = sort_ic ? STRICMP(sortbuf1, sortbuf2)
: STRCMP(sortbuf1, sortbuf2);
@@ -361,7 +375,7 @@ void ex_sort(exarg_T *eap)
regmatch.regprog = NULL;
sorti_T *nrs = xmalloc(count * sizeof(sorti_T));
- sort_abort = sort_ic = sort_rx = sort_nr = 0;
+ sort_abort = sort_ic = sort_rx = sort_nr = sort_flt = 0;
size_t format_found = 0;
for (p = eap->arg; *p != NUL; ++p) {
@@ -371,7 +385,10 @@ void ex_sort(exarg_T *eap)
} else if (*p == 'r') {
sort_rx = true;
} else if (*p == 'n') {
- sort_nr = 2;
+ sort_nr = 1;
+ format_found++;
+ } else if (*p == 'f') {
+ sort_flt = 1;
format_found++;
} else if (*p == 'b') {
sort_what = STR2NR_BIN + STR2NR_FORCE;
@@ -424,7 +441,8 @@ void ex_sort(exarg_T *eap)
goto sortend;
}
- // From here on "sort_nr" is used as a flag for any number sorting.
+ // From here on "sort_nr" is used as a flag for any integer number
+ // sorting.
sort_nr += sort_what;
// Make an array with all line numbers. This avoids having to copy all
@@ -453,7 +471,7 @@ void ex_sort(exarg_T *eap)
end_col = 0;
}
- if (sort_nr) {
+ if (sort_nr || sort_flt) {
// Make sure vim_str2nr doesn't read any digits past the end
// of the match, by temporarily terminating the string there
s2 = s + end_col;
@@ -461,29 +479,42 @@ void ex_sort(exarg_T *eap)
*s2 = NUL;
// Sorting on number: Store the number itself.
p = s + start_col;
- if (sort_what & STR2NR_HEX) {
- s = skiptohex(p);
- } else if (sort_what & STR2NR_BIN) {
- s = (char_u*) skiptobin((char*) p);
- } else {
- s = skiptodigit(p);
- }
- if (s > p && s[-1] == '-') {
- // include preceding negative sign
- s--;
- }
- if (*s == NUL) {
- // empty line should sort before any number
- nrs[lnum - eap->line1].start_col_nr = -MAXLNUM;
+ if (sort_nr) {
+ if (sort_what & STR2NR_HEX) {
+ s = skiptohex(p);
+ } else if (sort_what & STR2NR_BIN) {
+ s = (char_u *)skiptobin((char *)p);
+ } else {
+ s = skiptodigit(p);
+ }
+ if (s > p && s[-1] == '-') {
+ s--; // include preceding negative sign
+ }
+ if (*s == NUL) {
+ // empty line should sort before any number
+ nrs[lnum - eap->line1].st_u.value = -MAXLNUM;
+ } else {
+ vim_str2nr(s, NULL, NULL, sort_what,
+ &nrs[lnum - eap->line1].st_u.value, NULL, 0);
+ }
} else {
- vim_str2nr(s, NULL, NULL, sort_what,
- &nrs[lnum - eap->line1].start_col_nr, NULL, 0);
+ s = skipwhite(p);
+ if (*s == '+') {
+ s = skipwhite(s + 1);
+ }
+
+ if (*s == NUL) {
+ // empty line should sort before any number
+ nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX;
+ } else {
+ nrs[lnum - eap->line1].st_u.value_flt = strtod((char *)s, NULL);
+ }
}
*s2 = c;
} else {
// Store the column to sort at.
- nrs[lnum - eap->line1].start_col_nr = start_col;
- nrs[lnum - eap->line1].end_col_nr = end_col;
+ nrs[lnum - eap->line1].st_u.line.start_col_nr = start_col;
+ nrs[lnum - eap->line1].st_u.line.end_col_nr = end_col;
}
nrs[lnum - eap->line1].lnum = lnum;
@@ -619,13 +650,13 @@ void ex_retab(exarg_T *eap)
num_tabs += num_spaces / new_ts;
num_spaces -= (num_spaces / new_ts) * new_ts;
}
- if (curbuf->b_p_et || got_tab ||
- (num_spaces + num_tabs < len)) {
- if (did_undo == FALSE) {
- did_undo = TRUE;
+ if (curbuf->b_p_et || got_tab
+ || (num_spaces + num_tabs < len)) {
+ if (did_undo == false) {
+ did_undo = true;
if (u_save((linenr_T)(lnum - 1),
- (linenr_T)(lnum + 1)) == FAIL) {
- new_line = NULL; /* flag out-of-memory */
+ (linenr_T)(lnum + 1)) == FAIL) {
+ new_line = NULL; // flag out-of-memory
break;
}
}
@@ -1592,15 +1623,14 @@ int do_write(exarg_T *eap)
}
}
- /*
- * Writing to the current file is not allowed in readonly mode
- * and a file name is required.
- * "nofile" and "nowrite" buffers cannot be written implicitly either.
- */
- if (!other && (
- bt_dontwrite_msg(curbuf) ||
- check_fname() == FAIL || check_readonly(&eap->forceit, curbuf)))
+ // Writing to the current file is not allowed in readonly mode
+ // and a file name is required.
+ // "nofile" and "nowrite" buffers cannot be written implicitly either.
+ if (!other && (bt_dontwrite_msg(curbuf)
+ || check_fname() == FAIL
+ || check_readonly(&eap->forceit, curbuf))) {
goto theend;
+ }
if (!other) {
ffname = curbuf->b_ffname;
@@ -2227,16 +2257,15 @@ do_ecmd (
delbuf_msg(new_name); /* frees new_name */
goto theend;
}
- if (buf == curbuf) /* already in new buffer */
- auto_buf = TRUE;
- else {
- /*
- * <VN> We could instead free the synblock
- * and re-attach to buffer, perhaps.
- */
- if (curwin->w_buffer != NULL &&
- curwin->w_s == &(curwin->w_buffer->b_s))
+ if (buf == curbuf) { // already in new buffer
+ auto_buf = true;
+ } else {
+ // <VN> We could instead free the synblock
+ // and re-attach to buffer, perhaps.
+ if (curwin->w_buffer != NULL
+ && curwin->w_s == &(curwin->w_buffer->b_s)) {
curwin->w_s = &(buf->b_s);
+ }
curwin->w_buffer = buf;
curbuf = buf;
@@ -2263,11 +2292,11 @@ do_ecmd (
curwin->w_pcmark.lnum = 1;
curwin->w_pcmark.col = 0;
- } else { /* !other_file */
- if (
- (flags & ECMD_ADDBUF) ||
- check_fname() == FAIL)
+ } else { // !other_file
+ if ((flags & ECMD_ADDBUF)
+ || check_fname() == FAIL) {
goto theend;
+ }
oldbuf = (flags & ECMD_OLDBUF);
}
@@ -5017,7 +5046,9 @@ helptags_one (
/*
* Sort the tags.
*/
- sort_strings((char_u **)ga.ga_data, ga.ga_len);
+ if (ga.ga_data != NULL) {
+ sort_strings((char_u **)ga.ga_data, ga.ga_len);
+ }
/*
* Check for duplicates.
@@ -5785,13 +5816,14 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
switch (cmd_idx)
{
case SIGNCMD_DEFINE:
- if (STRNCMP(last, "texthl", p - last) == 0 ||
- STRNCMP(last, "linehl", p - last) == 0)
+ if (STRNCMP(last, "texthl", p - last) == 0
+ || STRNCMP(last, "linehl", p - last) == 0) {
xp->xp_context = EXPAND_HIGHLIGHT;
- else if (STRNCMP(last, "icon", p - last) == 0)
+ } else if (STRNCMP(last, "icon", p - last) == 0) {
xp->xp_context = EXPAND_FILES;
- else
+ } else {
xp->xp_context = EXPAND_NOTHING;
+ }
break;
case SIGNCMD_PLACE:
if (STRNCMP(last, "name", p - last) == 0)
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 6c8835b5c5..04fd88cc8d 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2575,6 +2575,18 @@ return {
func='ex_copymove',
},
{
+ command='tcd',
+ flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_cd',
+ },
+ {
+ command='tchdir',
+ flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_cd',
+ },
+ {
command='tNext',
flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
addr_type=ADDR_LINES,
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 2c8271c696..12efddc205 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -432,14 +432,12 @@ dbg_parsearg (
bp = &DEBUGGY(gap, gap->ga_len);
- /* Find "func" or "file". */
- if (STRNCMP(p, "func", 4) == 0)
+ // Find "func" or "file".
+ if (STRNCMP(p, "func", 4) == 0) {
bp->dbg_type = DBG_FUNC;
- else if (STRNCMP(p, "file", 4) == 0)
+ } else if (STRNCMP(p, "file", 4) == 0) {
bp->dbg_type = DBG_FILE;
- else if (
- gap != &prof_ga &&
- STRNCMP(p, "here", 4) == 0) {
+ } else if (gap != &prof_ga && STRNCMP(p, "here", 4) == 0) {
if (curbuf->b_ffname == NULL) {
EMSG(_(e_noname));
return FAIL;
@@ -452,16 +450,15 @@ dbg_parsearg (
}
p = skipwhite(p + 4);
- /* Find optional line number. */
- if (here)
+ // Find optional line number.
+ if (here) {
bp->dbg_lnum = curwin->w_cursor.lnum;
- else if (
- gap != &prof_ga &&
- ascii_isdigit(*p)) {
+ } else if (gap != &prof_ga && ascii_isdigit(*p)) {
bp->dbg_lnum = getdigits_long(&p);
p = skipwhite(p);
- } else
+ } else {
bp->dbg_lnum = 0;
+ }
/* Find the function or file name. Don't accept a function name with (). */
if ((!here && *p == NUL)
@@ -700,14 +697,13 @@ debuggy_find (
/* Skip entries that are not useful or are for a line that is beyond
* an already found breakpoint. */
bp = &DEBUGGY(gap, i);
- if (((bp->dbg_type == DBG_FILE) == file && (
- gap == &prof_ga ||
- (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum))))) {
- /*
- * Save the value of got_int and reset it. We don't want a
- * previous interruption cancel matching, only hitting CTRL-C
- * while matching should abort it.
- */
+ if (((bp->dbg_type == DBG_FILE) == file
+ && (gap == &prof_ga
+ || (bp->dbg_lnum > after
+ && (lnum == 0 || bp->dbg_lnum < lnum))))) {
+ // Save the value of got_int and reset it. We don't want a
+ // previous interruption cancel matching, only hitting CTRL-C
+ // while matching should abort it.
prev_got_int = got_int;
got_int = FALSE;
if (vim_regexec_prog(&bp->dbg_prog, false, name, (colnr_T)0)) {
@@ -1937,8 +1933,8 @@ void ex_listdo(exarg_T *eap)
if (buf != NULL) {
goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum);
}
- } else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
- eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
+ } else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
+ || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
qf_size = qf_get_size(eap);
assert(eap->line1 >= 0);
if (qf_size == 0 || (size_t)eap->line1 > qf_size) {
@@ -2040,8 +2036,8 @@ void ex_listdo(exarg_T *eap)
}
}
- if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
- eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
+ if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
+ || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
assert(i >= 0);
if ((size_t)i >= qf_size || i >= eap->line2) {
break;
@@ -2373,8 +2369,9 @@ static FILE *fopen_noinh_readbin(char *filename)
# ifdef HAVE_FD_CLOEXEC
{
int fdflags = fcntl(fd_tmp, F_GETFD);
- if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
- fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
+ if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
+ (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC);
+ }
}
# endif
@@ -3182,8 +3179,11 @@ void set_lang_var(void)
* back to LC_CTYPE if it's empty. */
# ifdef HAVE_WORKING_LIBINTL
loc = (char *) get_mess_env();
-# else
+# elif defined(LC_MESSAGES)
loc = get_locale_val(LC_MESSAGES);
+# else
+ // In Windows LC_MESSAGES is not defined fallback to LC_CTYPE
+ loc = get_locale_val(LC_CTYPE);
# endif
set_vim_var_string(VV_LANG, loc, -1);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 6391e023c3..89c35a3c45 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1654,16 +1654,15 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* If we got a line, but no command, then go to the line.
* If we find a '|' or '\n' we set ea.nextcmd.
*/
- if (*ea.cmd == NUL || *ea.cmd == '"' ||
- (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) {
- /*
- * strange vi behaviour:
- * ":3" jumps to line 3
- * ":3|..." prints line 3
- * ":|" prints current line
- */
- if (ea.skip) /* skip this if inside :if */
+ if (*ea.cmd == NUL || *ea.cmd == '"'
+ || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) {
+ // strange vi behaviour:
+ // ":3" jumps to line 3
+ // ":3|..." prints line 3
+ // ":|" prints current line
+ if (ea.skip) { // skip this if inside :if
goto doend;
+ }
if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2)) {
ea.cmdidx = CMD_print;
ea.argt = RANGE | COUNT | TRLBAR;
@@ -1826,9 +1825,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
correct_range(&ea);
- if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy) {
- /* Put the first line at the start of a closed fold, put the last line
- * at the end of a closed fold. */
+ if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
+ && ea.addr_type == ADDR_LINES) {
+ // Put the first line at the start of a closed fold, put the last line
+ // at the end of a closed fold.
(void)hasFolding(ea.line1, &ea.line1, NULL);
(void)hasFolding(ea.line2, NULL, &ea.line2);
}
@@ -2823,10 +2823,11 @@ set_one_cmd_context (
}
}
- /* no arguments allowed */
- if (!(ea.argt & EXTRA) && *arg != NUL &&
- vim_strchr((char_u *)"|\"", *arg) == NULL)
+ // no arguments allowed
+ if (!(ea.argt & EXTRA) && *arg != NUL
+ && vim_strchr((char_u *)"|\"", *arg) == NULL) {
return NULL;
+ }
/* Find start of last argument (argument just before cursor): */
p = buff;
@@ -2958,8 +2959,11 @@ set_one_cmd_context (
case CMD_chdir:
case CMD_lcd:
case CMD_lchdir:
- if (xp->xp_context == EXPAND_FILES)
+ case CMD_tcd:
+ case CMD_tchdir:
+ if (xp->xp_context == EXPAND_FILES) {
xp->xp_context = EXPAND_DIRECTORIES;
+ }
break;
case CMD_help:
xp->xp_context = EXPAND_HELP;
@@ -4553,7 +4557,8 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep,
char_u *rep_buf = NULL;
garray_T *gap;
- replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE);
+ replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, false,
+ CPO_TO_CPO_FLAGS);
if (rep_buf == NULL) {
/* Can't replace termcodes - try using the string as is */
rep_buf = vim_strsave(rep);
@@ -4767,14 +4772,15 @@ static void uc_list(char_u *name, size_t name_len)
IObuff[len++] = ' ';
} while (len < 11);
- /* Address Type */
- for (j = 0; addr_type_complete[j].expand != -1; ++j)
- if (addr_type_complete[j].expand != ADDR_LINES &&
- addr_type_complete[j].expand == cmd->uc_addr_type) {
+ // Address Type
+ for (j = 0; addr_type_complete[j].expand != -1; j++) {
+ if (addr_type_complete[j].expand != ADDR_LINES
+ && addr_type_complete[j].expand == cmd->uc_addr_type) {
STRCPY(IObuff + len, addr_type_complete[j].name);
len += (int)STRLEN(IObuff + len);
break;
}
+ }
do {
IObuff[len++] = ' ';
@@ -5499,7 +5505,8 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
int *addr_type_arg)
{
int i, a, b;
- for (i = 0; addr_type_complete[i].expand != -1; ++i) {
+
+ for (i = 0; addr_type_complete[i].expand != -1; i++) {
a = (int)STRLEN(addr_type_complete[i].name) == vallen;
b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0;
if (a && b) {
@@ -5510,8 +5517,8 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
if (addr_type_complete[i].expand == -1) {
char_u *err = value;
- for (i = 0; err[i] == NUL || !ascii_iswhite(err[i]); i++)
- ;
+
+ for (i = 0; err[i] != NUL && !ascii_iswhite(err[i]); i++) {}
err[i] = NUL;
EMSG2(_("E180: Invalid address type value: %s"), err);
return FAIL;
@@ -5648,12 +5655,13 @@ static void ex_quit(exarg_T *eap)
wp = curwin;
}
- apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
- /* Refuse to quit when locked or when the buffer in the last window is
- * being closed (can only happen in autocommands). */
- if (curbuf_locked() ||
- (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_closing))
+ apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, curbuf);
+ // Refuse to quit when locked or when the buffer in the last window is
+ // being closed (can only happen in autocommands).
+ if (curbuf_locked()
+ || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_closing)) {
return;
+ }
/*
@@ -6814,36 +6822,55 @@ void free_cd_dir(void)
#endif
-/*
- * Deal with the side effects of changing the current directory.
- * When "local" is TRUE then this was after an ":lcd" command.
- */
-void post_chdir(int local)
+/// Deal with the side effects of changing the current directory.
+///
+/// @param scope Scope of the function call (global, tab or window).
+void post_chdir(CdScope scope)
{
+ // The local directory of the current window is always overwritten.
xfree(curwin->w_localdir);
curwin->w_localdir = NULL;
- if (local) {
- /* If still in global directory, need to remember current
- * directory as global directory. */
- if (globaldir == NULL && prev_dir != NULL)
+
+ // Overwrite the local directory of the current tab page for `cd` and `tcd`
+ if (scope >= kCdScopeTab) {
+ xfree(curtab->localdir);
+ curtab->localdir = NULL;
+ }
+
+ if (scope < kCdScopeGlobal) {
+ // If still in global directory, need to remember current directory as
+ // global directory.
+ if (globaldir == NULL && prev_dir != NULL) {
globaldir = vim_strsave(prev_dir);
- /* Remember this local directory for the window. */
- if (os_dirname(NameBuff, MAXPATHL) == OK)
- curwin->w_localdir = vim_strsave(NameBuff);
- } else {
- /* We are now in the global directory, no need to remember its
- * name. */
+ }
+ }
+
+ switch (scope) {
+ case kCdScopeGlobal:
+ // We are now in the global directory, no need to remember its name.
xfree(globaldir);
globaldir = NULL;
+ break;
+ case kCdScopeTab:
+ // Remember this local directory for the tab page.
+ if (os_dirname(NameBuff, MAXPATHL) == OK) {
+ curtab->localdir = vim_strsave(NameBuff);
+ }
+ break;
+ case kCdScopeWindow:
+ // Remember this local directory for the window.
+ if (os_dirname(NameBuff, MAXPATHL) == OK) {
+ curwin->w_localdir = vim_strsave(NameBuff);
+ }
+ break;
}
shorten_fnames(TRUE);
}
-/*
- * ":cd", ":lcd", ":chdir" and ":lchdir".
- */
+
+/// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`.
void ex_cd(exarg_T *eap)
{
char_u *new_dir;
@@ -6884,10 +6911,25 @@ void ex_cd(exarg_T *eap)
new_dir = NameBuff;
}
#endif
- if (new_dir == NULL || vim_chdir(new_dir))
+ if (vim_chdir(new_dir)) {
EMSG(_(e_failed));
- else {
- post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir);
+ } else {
+ CdScope scope = kCdScopeGlobal; // Depends on command invoked
+
+ switch (eap->cmdidx) {
+ case CMD_tcd:
+ case CMD_tchdir:
+ scope = kCdScopeTab;
+ break;
+ case CMD_lcd:
+ case CMD_lchdir:
+ scope = kCdScopeWindow;
+ break;
+ default:
+ break;
+ }
+
+ post_chdir(scope);
/* Echo the new current directory if the command was typed. */
if (KeyTyped || p_verbose >= 5)
@@ -7031,9 +7073,9 @@ static void ex_operators(exarg_T *eap)
oa.start.lnum = eap->line1;
oa.end.lnum = eap->line2;
oa.line_count = eap->line2 - eap->line1 + 1;
- oa.motion_type = MLINE;
- virtual_op = FALSE;
- if (eap->cmdidx != CMD_yank) { /* position cursor for undo */
+ oa.motion_type = kMTLineWise;
+ virtual_op = false;
+ if (eap->cmdidx != CMD_yank) { // position cursor for undo
setpcmark();
curwin->w_cursor.lnum = eap->line1;
beginline(BL_SOL | BL_FIX);
@@ -9145,16 +9187,15 @@ static char *get_view_file(int c)
*/
int put_eol(FILE *fd)
{
- if (
-#ifdef USE_CRNL
- (
-# ifdef MKSESSION_NL
- !mksession_nl &&
-# endif
- (putc('\r', fd) < 0)) ||
+#if defined(USE_CRNL) && defined(MKSESSION_NL)
+ if ((!mksession_nl && putc('\r', fd) < 0) || putc('\n', fd) < 0) {
+#elif defined(USE_CRNL)
+ if (putc('\r', fd) < 0 || putc('\n', fd) < 0) {
+#else
+ if (putc('\n', fd) < 0) {
#endif
- (putc('\n', fd) < 0))
return FAIL;
+ }
return OK;
}
diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h
index a5a4edbbbf..dbfc64e2f1 100644
--- a/src/nvim/ex_docmd.h
+++ b/src/nvim/ex_docmd.h
@@ -19,6 +19,20 @@
#define EXMODE_NORMAL 1
#define EXMODE_VIM 2
+/// The scope of a working-directory command like `:cd`.
+///
+/// Scopes are enumerated from lowest to highest. When adding a scope make sure
+/// to update all functions using scopes as well, such as the implementation of
+/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes
+/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead.
+typedef enum {
+ kCdScopeWindow, ///< Affects one window.
+ kCdScopeTab, ///< Affects one tab page.
+ kCdScopeGlobal, ///< Affects the entire instance of Neovim.
+} CdScope;
+#define MIN_CD_SCOPE kCdScopeWindow
+#define MAX_CD_SCOPE kCdScopeGlobal
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_docmd.h.generated.h"
#endif
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 41ad96a378..82d4c2b2d5 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -403,14 +403,15 @@ char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should
&& (p[3] == ':'
|| (ascii_isdigit(p[3])
&& p[4] == ':')))))) {
- if (*p == NUL || p == mesg)
- STRCAT(val, mesg); /* 'E123' missing or at beginning */
- else {
- /* '"filename" E123: message text' */
- if (mesg[0] != '"' || p-2 < &mesg[1] ||
- p[-2] != '"' || p[-1] != ' ')
- /* "E123:" is part of the file name. */
+ if (*p == NUL || p == mesg) {
+ STRCAT(val, mesg); // 'E123' missing or at beginning
+ } else {
+ // '"filename" E123: message text'
+ if (mesg[0] != '"' || p-2 < &mesg[1]
+ || p[-2] != '"' || p[-1] != ' ') {
+ // "E123:" is part of the file name.
continue;
+ }
STRCAT(val, p);
p[-2] = NUL;
@@ -1565,22 +1566,21 @@ void ex_endtry(exarg_T *eap)
void *rettv = NULL;
struct condstack *cstack = eap->cstack;
- if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
+ if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) {
eap->errmsg = (char_u *)N_("E602: :endtry without :try");
- else {
- /*
- * Don't do something after an error, interrupt or throw in the try
- * block, catch clause, or finally clause preceding this ":endtry" or
- * when an error or interrupt occurred after a ":continue", ":break",
- * ":return", or ":finish" in a try block or catch clause preceding this
- * ":endtry" or when the try block never got active (because of an
- * inactive surrounding conditional or after an error or interrupt or
- * throw) or when there is a surrounding conditional and it has been
- * made inactive by a ":continue", ":break", ":return", or ":finish" in
- * the finally clause. The latter case need not be tested since then
- * anything pending has already been discarded. */
- skip = did_emsg || got_int || did_throw ||
- !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+ } else {
+ // Don't do something after an error, interrupt or throw in the try
+ // block, catch clause, or finally clause preceding this ":endtry" or
+ // when an error or interrupt occurred after a ":continue", ":break",
+ // ":return", or ":finish" in a try block or catch clause preceding this
+ // ":endtry" or when the try block never got active (because of an
+ // inactive surrounding conditional or after an error or interrupt or
+ // throw) or when there is a surrounding conditional and it has been
+ // made inactive by a ":continue", ":break", ":return", or ":finish" in
+ // the finally clause. The latter case need not be tested since then
+ // anything pending has already been discarded.
+ skip = (did_emsg || got_int || did_throw
+ || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE));
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
eap->errmsg = get_end_emsg(cstack);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index cffda1ca55..a4e5a4dcd7 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -289,7 +289,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
if (ccline.cmdbuff != NULL) {
// Put line in history buffer (":" and "=" only when it was typed).
- if (ccline.cmdlen && s->firstc != NUL
+ if (s->histype != HIST_INVALID
+ && ccline.cmdlen
+ && s->firstc != NUL
&& (s->some_key_typed || s->histype == HIST_SEARCH)) {
add_to_history(s->histype, ccline.cmdbuff, true,
s->histype == HIST_SEARCH ? s->firstc : NUL);
@@ -622,8 +624,8 @@ static int command_line_execute(VimState *state, int key)
// CTRL-\ e doesn't work when obtaining an expression, unless it
// is in a mapping.
if (s->c != Ctrl_N && s->c != Ctrl_G && (s->c != 'e'
- || (ccline.cmdfirstc == '=' &&
- KeyTyped))) {
+ || (ccline.cmdfirstc == '='
+ && KeyTyped))) {
vungetc(s->c);
s->c = Ctrl_BSL;
} else if (s->c == 'e') {
@@ -1268,7 +1270,7 @@ static int command_line_handle_key(CommandLineState *s)
case K_KPAGEUP:
case K_PAGEDOWN:
case K_KPAGEDOWN:
- if (hislen == 0 || s->firstc == NUL) {
+ if (s->histype == HIST_INVALID || hislen == 0 || s->firstc == NUL) {
// no history
return command_line_not_changed(s);
}
@@ -3981,6 +3983,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
char_u *s, *e;
int flags = flagsarg;
int ret;
+ bool did_curdir = false;
/* for ":set path=" and ":set tags=" halve backslashes for escaped
* space */
@@ -3989,7 +3992,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
if (pat[i] == '\\' && pat[i + 1] == ' ')
STRMOVE(pat + i, pat + i + 1);
- flags |= EW_FILE | EW_EXEC;
+ flags |= EW_FILE | EW_EXEC | EW_SHELLCMD;
bool mustfree = false; // Track memory allocation for *path.
/* For an absolute name we don't use $PATH. */
@@ -4009,12 +4012,24 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
/*
* Go over all directories in $PATH. Expand matches in that directory and
- * collect them in "ga".
+ * collect them in "ga". When "." is not in $PATH also expaned for the
+ * current directory, to find "subdir/cmd".
*/
ga_init(&ga, (int)sizeof(char *), 10);
- for (s = path; *s != NUL; s = e) {
- if (*s == ' ')
- ++s; /* Skip space used for absolute path name. */
+ for (s = path; ; s = e) {
+ if (*s == NUL) {
+ if (did_curdir) {
+ break;
+ }
+ // Find directories in the current directory, path is empty.
+ did_curdir = true;
+ } else if (*s == '.') {
+ did_curdir = true;
+ }
+
+ if (*s == ' ') {
+ s++; // Skip space used for absolute path name.
+ }
e = vim_strchr(s, ':');
if (e == NULL)
@@ -4272,20 +4287,33 @@ void globpath(char_u *path, char_u *file, garray_T *ga, int expand_options)
* Command line history stuff *
*********************************/
-/*
- * Translate a history character to the associated type number.
- */
-static int hist_char2type(int c)
+/// Translate a history character to the associated type number
+static HistoryType hist_char2type(const int c)
+ FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (c == ':')
- return HIST_CMD;
- if (c == '=')
- return HIST_EXPR;
- if (c == '@')
- return HIST_INPUT;
- if (c == '>')
- return HIST_DEBUG;
- return HIST_SEARCH; /* must be '?' or '/' */
+ switch (c) {
+ case ':': {
+ return HIST_CMD;
+ }
+ case '=': {
+ return HIST_EXPR;
+ }
+ case '@': {
+ return HIST_INPUT;
+ }
+ case '>': {
+ return HIST_DEBUG;
+ }
+ case '/':
+ case '?': {
+ return HIST_SEARCH;
+ }
+ default: {
+ return HIST_INVALID;
+ }
+ }
+ // Silence -Wreturn-type
+ return 0;
}
/*
@@ -4454,28 +4482,38 @@ in_history (
return false;
}
-/*
- * Convert history name (from table above) to its HIST_ equivalent.
- * When "name" is empty, return "cmd" history.
- * Returns -1 for unknown history name.
- */
-int get_histtype(char_u *name)
+/// Convert history name to its HIST_ equivalent
+///
+/// Names are taken from the table above. When `name` is empty returns currently
+/// active history or HIST_DEFAULT, depending on `return_default` argument.
+///
+/// @param[in] name Converted name.
+/// @param[in] len Name length.
+/// @param[in] return_default Determines whether HIST_DEFAULT should be
+/// returned or value based on `ccline.cmdfirstc`.
+///
+/// @return Any value from HistoryType enum, including HIST_INVALID. May not
+/// return HIST_DEFAULT unless return_default is true.
+HistoryType get_histtype(const char_u *const name, const size_t len,
+ const bool return_default)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- int i;
- int len = (int)STRLEN(name);
-
- /* No argument: use current history. */
- if (len == 0)
- return hist_char2type(ccline.cmdfirstc);
+ // No argument: use current history.
+ if (len == 0) {
+ return return_default ? HIST_DEFAULT : hist_char2type(ccline.cmdfirstc);
+ }
- for (i = 0; history_names[i] != NULL; ++i)
- if (STRNICMP(name, history_names[i], len) == 0)
+ for (HistoryType i = 0; history_names[i] != NULL; i++) {
+ if (STRNICMP(name, history_names[i], len) == 0) {
return i;
+ }
+ }
- if (vim_strchr((char_u *)":=@>?/", name[0]) != NULL && name[1] == NUL)
+ if (vim_strchr((char_u *)":=@>?/", name[0]) != NULL && len == 1) {
return hist_char2type(name[0]);
+ }
- return -1;
+ return HIST_INVALID;
}
static int last_maptick = -1; /* last seen maptick */
@@ -4496,8 +4534,10 @@ add_to_history (
histentry_T *hisptr;
int len;
- if (hislen == 0) /* no history */
+ if (hislen == 0 || histype == HIST_INVALID) { // no history
return;
+ }
+ assert(histype != HIST_DEFAULT);
if (cmdmod.keeppatterns && histype == HIST_SEARCH)
return;
@@ -4847,23 +4887,20 @@ void ex_history(exarg_T *eap)
while (ASCII_ISALPHA(*end)
|| vim_strchr((char_u *)":=@>/?", *end) != NULL)
end++;
- i = *end;
- *end = NUL;
- histype1 = get_histtype(arg);
- if (histype1 == -1) {
- if (STRNICMP(arg, "all", STRLEN(arg)) == 0) {
+ histype1 = get_histtype(arg, end - arg, false);
+ if (histype1 == HIST_INVALID) {
+ if (STRNICMP(arg, "all", end - arg) == 0) {
histype1 = 0;
histype2 = HIST_COUNT-1;
} else {
- *end = i;
EMSG(_(e_trailing));
return;
}
} else
histype2 = histype1;
- *end = i;
- } else
+ } else {
end = arg;
+ }
if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) {
EMSG(_(e_trailing));
return;
@@ -4971,7 +5008,6 @@ static int ex_window(void)
win_T *wp;
int i;
linenr_T lnum;
- int histtype;
garray_T winsizes;
char_u typestr[2];
int save_restart_edit = restart_edit;
@@ -5020,7 +5056,7 @@ static int ex_window(void)
/* Showing the prompt may have set need_wait_return, reset it. */
need_wait_return = FALSE;
- histtype = hist_char2type(cmdwin_type);
+ const int histtype = hist_char2type(cmdwin_type);
if (histtype == HIST_CMD || histtype == HIST_DEBUG) {
if (p_wc == TAB) {
add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT);
@@ -5035,7 +5071,7 @@ static int ex_window(void)
/* Fill the buffer with the history. */
init_history();
- if (hislen > 0) {
+ if (hislen > 0 && histtype != HIST_INVALID) {
i = hisidx[histtype];
if (i >= 0) {
lnum = 0;
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 21da8b9d42..24eebdc303 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -27,11 +27,13 @@
/// Present history tables
typedef enum {
- HIST_CMD, ///< Colon commands.
- HIST_SEARCH, ///< Search commands.
- HIST_EXPR, ///< Expressions (e.g. from entering = register).
- HIST_INPUT, ///< input() lines.
- HIST_DEBUG, ///< Debug commands.
+ HIST_DEFAULT = -2, ///< Default (current) history.
+ HIST_INVALID = -1, ///< Unknown history.
+ HIST_CMD = 0, ///< Colon commands.
+ HIST_SEARCH, ///< Search commands.
+ HIST_EXPR, ///< Expressions (e.g. from entering = register).
+ HIST_INPUT, ///< input() lines.
+ HIST_DEBUG, ///< Debug commands.
} HistoryType;
/// Number of history tables
diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c
index 47a132c0d0..61e17128ea 100644
--- a/src/nvim/farsi.c
+++ b/src/nvim/farsi.c
@@ -100,8 +100,9 @@ static char_u toF_Xor_X_(int c)
case F_HE :
tempc = _HE;
- if (p_ri &&
- (curwin->w_cursor.col + 1 < (colnr_T)STRLEN(get_cursor_line_ptr()))) {
+ if (p_ri
+ && (curwin->w_cursor.col + 1
+ < (colnr_T)STRLEN(get_cursor_line_ptr()))) {
inc_cursor();
if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) {
tempc = _HE_;
@@ -526,8 +527,8 @@ static void chg_l_toXor_X(void)
{
char_u tempc;
- if ((curwin->w_cursor.col != 0) &&
- (curwin->w_cursor.col + 1 == (colnr_T)STRLEN(get_cursor_line_ptr()))) {
+ if ((curwin->w_cursor.col != 0)
+ && (curwin->w_cursor.col + 1 == (colnr_T)STRLEN(get_cursor_line_ptr()))) {
return;
}
@@ -680,17 +681,17 @@ int fkmap(int c)
}
}
- if ((c < 0x100) &&
- (isalpha(c) ||
- (c == '&') ||
- (c == '^') ||
- (c == ';') ||
- (c == '\'') ||
- (c == ',') ||
- (c == '[') ||
- (c == ']') ||
- (c == '{') ||
- (c == '}'))) {
+ if ((c < 0x100)
+ && (isalpha(c)
+ || (c == '&')
+ || (c == '^')
+ || (c == ';')
+ || (c == '\'')
+ || (c == ',')
+ || (c == '[')
+ || (c == ']')
+ || (c == '{')
+ || (c == '}'))) {
chg_r_to_Xor_X_();
}
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 2929790ebf..beefc4238e 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1400,8 +1400,14 @@ find_file_in_path_option (
&& (ff_file_to_find[2] == NUL
|| vim_ispathsep(ff_file_to_find[2])))));
if (vim_isAbsName(ff_file_to_find)
- /* "..", "../path", "." and "./path": don't use the path_option */
+ // "..", "../path", "." and "./path": don't use the path_option
|| rel_to_curdir
+#if defined(WIN32)
+ // handle "\tmp" as absolute path
+ || vim_ispathsep(ff_file_to_find[0])
+ // handle "c:name" as absolute path
+ || (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
+#endif
) {
/*
* Absolute path, no need to use "path_option".
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 32e1b645d0..6c0bc59d93 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -45,7 +45,6 @@
#include "nvim/search.h"
#include "nvim/sha256.h"
#include "nvim/strings.h"
-#include "nvim/tempfile.h"
#include "nvim/ui.h"
#include "nvim/types.h"
#include "nvim/undo.h"
@@ -606,13 +605,14 @@ readfile (
* Don't do this for a "nofile" or "nowrite" buffer type. */
if (!bt_dontwrite(curbuf)) {
check_need_swap(newfile);
- if (!read_stdin && (curbuf != old_curbuf
- || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
- || (using_b_fname &&
- (old_b_fname != curbuf->b_fname)))) {
+ if (!read_stdin
+ && (curbuf != old_curbuf
+ || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
+ || (using_b_fname && (old_b_fname != curbuf->b_fname)))) {
EMSG(_(e_auchangedbuf));
- if (!read_buffer)
+ if (!read_buffer) {
close(fd);
+ }
return FAIL;
}
#ifdef UNIX
@@ -2577,7 +2577,7 @@ buf_write (
errmsg = (char_u *)_("is a directory");
goto fail;
}
- if (mch_nodetype(fname) != NODE_WRITABLE) {
+ if (os_nodetype((char *)fname) != NODE_WRITABLE) {
errnum = (char_u *)"E503: ";
errmsg = (char_u *)_("is not a file or writable device");
goto fail;
@@ -2589,11 +2589,11 @@ buf_write (
perm = -1;
}
}
-#else /* !UNIX */
+#else /* win32 */
/*
* Check for a writable device name.
*/
- c = mch_nodetype(fname);
+ c = os_nodetype((char *)fname);
if (c == NODE_OTHER) {
errnum = (char_u *)"E503: ";
errmsg = (char_u *)_("is not a file or writable device");
@@ -2689,7 +2689,6 @@ buf_write (
} else if ((bkc & BKC_AUTO)) { /* "auto" */
int i;
-# ifdef UNIX
/*
* Don't rename the file when:
* - it's a hard link
@@ -2700,9 +2699,7 @@ buf_write (
|| !os_fileinfo_link((char *)fname, &file_info)
|| !os_fileinfo_id_equal(&file_info, &file_info_old)) {
backup_copy = TRUE;
- } else
-# endif
- {
+ } else {
/*
* Check if we can create a file and set the owner/group to
* the ones from the original file.
@@ -4373,8 +4370,8 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
// (we need the full path in case :cd is used).
if (fname == NULL || *fname == NUL) {
retval = xmalloc(MAXPATHL + extlen + 3); // +3 for PATHSEP, "_" (Win), NUL
- if (os_dirname((char_u *)retval, MAXPATHL) == FAIL ||
- (fnamelen = strlen(retval)) == 0) {
+ if (os_dirname((char_u *)retval, MAXPATHL) == FAIL
+ || (fnamelen = strlen(retval)) == 0) {
xfree(retval);
return NULL;
}
@@ -5116,6 +5113,147 @@ void forward_slash(char_u *fname)
}
#endif
+/// Name of Vim's own temp dir. Ends in a slash.
+static char_u *vim_tempdir = NULL;
+
+/// Create a directory for private use by this instance of Neovim.
+/// This is done once, and the same directory is used for all temp files.
+/// This method avoids security problems because of symlink attacks et al.
+/// It's also a bit faster, because we only need to check for an existing
+/// file when creating the directory and not for each temp file.
+static void vim_maketempdir(void)
+{
+ static const char *temp_dirs[] = TEMP_DIR_NAMES;
+ // Try the entries in `TEMP_DIR_NAMES` to create the temp directory.
+ char_u template[TEMP_FILE_PATH_MAXLEN];
+ char_u path[TEMP_FILE_PATH_MAXLEN];
+ for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); i++) {
+ // Expand environment variables, leave room for "/nvimXXXXXX/999999999"
+ expand_env((char_u *)temp_dirs[i], template, TEMP_FILE_PATH_MAXLEN - 22);
+ if (!os_isdir(template)) { // directory doesn't exist
+ continue;
+ }
+
+ add_pathsep((char *)template);
+ // Concatenate with temporary directory name pattern
+ STRCAT(template, "nvimXXXXXX");
+
+ if (os_mkdtemp((const char *)template, (char *)path) != 0) {
+ continue;
+ }
+
+ if (vim_settempdir((char *)path)) {
+ // Successfully created and set temporary directory so stop trying.
+ break;
+ } else {
+ // Couldn't set `vim_tempdir` to `path` so remove created directory.
+ os_rmdir((char *)path);
+ }
+ }
+}
+
+/// Delete "name" and everything in it, recursively.
+/// @param name The path which should be deleted.
+/// @return 0 for success, -1 if some file was not deleted.
+int delete_recursive(char_u *name)
+{
+ int result = 0;
+
+ if (os_isrealdir(name)) {
+ snprintf((char *)NameBuff, MAXPATHL, "%s/*", name); // NOLINT
+
+ char_u **files;
+ int file_count;
+ char_u *exp = vim_strsave(NameBuff);
+ if (gen_expand_wildcards(1, &exp, &file_count, &files,
+ EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS
+ | EW_DODOT | EW_EMPTYOK) == OK) {
+ for (int i = 0; i < file_count; i++) {
+ if (delete_recursive(files[i]) != 0) {
+ result = -1;
+ }
+ }
+ FreeWild(file_count, files);
+ } else {
+ result = -1;
+ }
+
+ xfree(exp);
+ os_rmdir((char *)name);
+ } else {
+ result = os_remove((char *)name) == 0 ? 0 : -1;
+ }
+
+ return result;
+}
+
+/// Delete the temp directory and all files it contains.
+void vim_deltempdir(void)
+{
+ if (vim_tempdir != NULL) {
+ // remove the trailing path separator
+ path_tail(vim_tempdir)[-1] = NUL;
+ delete_recursive(vim_tempdir);
+ xfree(vim_tempdir);
+ vim_tempdir = NULL;
+ }
+}
+
+/// Get the name of temp directory. This directory would be created on the first
+/// call to this function.
+char_u *vim_gettempdir(void)
+{
+ if (vim_tempdir == NULL) {
+ vim_maketempdir();
+ }
+
+ return vim_tempdir;
+}
+
+/// Set Neovim own temporary directory name to `tempdir`. This directory should
+/// be already created. Expand this name to a full path and put it in
+/// `vim_tempdir`. This avoids that using `:cd` would confuse us.
+///
+/// @param tempdir must be no longer than MAXPATHL.
+///
+/// @return false if we run out of memory.
+static bool vim_settempdir(char *tempdir)
+{
+ char *buf = verbose_try_malloc(MAXPATHL + 2);
+ if (!buf) {
+ return false;
+ }
+ vim_FullName(tempdir, buf, MAXPATHL, false);
+ add_pathsep(buf);
+ vim_tempdir = (char_u *)xstrdup(buf);
+ xfree(buf);
+ return true;
+}
+
+/// Return a unique name that can be used for a temp file.
+///
+/// @note The temp file is NOT created.
+///
+/// @return pointer to the temp file name or NULL if Neovim can't create
+/// temporary directory for its own temporary files.
+char_u *vim_tempname(void)
+{
+ // Temp filename counter.
+ static uint32_t temp_count;
+
+ char_u *tempdir = vim_gettempdir();
+ if (!tempdir) {
+ return NULL;
+ }
+
+ // There is no need to check if the file exists, because we own the directory
+ // and nobody else creates a file in it.
+ char_u template[TEMP_FILE_PATH_MAXLEN];
+ snprintf((char *)template, TEMP_FILE_PATH_MAXLEN,
+ "%s%" PRIu32, tempdir, temp_count++);
+ return vim_strsave(template);
+}
+
/*
* Code for automatic commands.
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 7f46a37315..ac3cf959c8 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -2110,10 +2110,11 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level,
*/
if (getlevel == foldlevelMarker && flp->start <= flp->lvl - level
&& flp->lvl > 0) {
- foldFind(gap, startlnum - 1, &fp);
+ (void)foldFind(gap, startlnum - 1, &fp);
if (fp >= ((fold_T *)gap->ga_data) + gap->ga_len
- || fp->fd_top >= startlnum)
+ || fp->fd_top >= startlnum) {
fp = NULL;
+ }
}
/*
@@ -2167,13 +2168,15 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level,
}
}
if (lvl < level + i) {
- foldFind(&fp->fd_nested, flp->lnum - fp->fd_top, &fp2);
- if (fp2 != NULL)
+ (void)foldFind(&fp->fd_nested, flp->lnum - fp->fd_top, &fp2);
+ if (fp2 != NULL) {
bot = fp2->fd_top + fp2->fd_len - 1 + fp->fd_top;
- } else if (fp->fd_top + fp->fd_len <= flp->lnum && lvl >= level)
- finish = TRUE;
- else
+ }
+ } else if (fp->fd_top + fp->fd_len <= flp->lnum && lvl >= level) {
+ finish = true;
+ } else {
break;
+ }
}
/* At the start of the first nested fold and at the end of the current
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 437495faa4..dbf0322d78 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -144,7 +144,7 @@ static int KeyNoremap = 0; /* remapping flags */
static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf.tb_buf */
static char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */
-static int last_recorded_len = 0; /* number of last recorded chars */
+static size_t last_recorded_len = 0; // number of last recorded chars
static const uint8_t ui_toggle[] = { K_SPECIAL, KS_EXTRA, KE_PASTE, 0 };
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -211,7 +211,7 @@ char_u *get_recorded(void)
* (possibly mapped) characters that stopped the recording.
*/
len = STRLEN(p);
- if ((int)len >= last_recorded_len) {
+ if (len >= last_recorded_len) {
len -= last_recorded_len;
p[len] = NUL;
}
@@ -243,13 +243,15 @@ static void
add_buff (
buffheader_T *buf,
char_u *s,
- long slen /* length of "s" or -1 */
+ ssize_t slen // length of "s" or -1
)
{
- if (slen < 0)
- slen = (long)STRLEN(s);
- if (slen == 0) /* don't add empty strings */
+ if (slen < 0) {
+ slen = (ssize_t)STRLEN(s);
+ }
+ if (slen == 0) { // don't add empty strings
return;
+ }
if (buf->bh_first.b_next == NULL) { /* first add to list */
buf->bh_space = 0;
@@ -263,18 +265,19 @@ add_buff (
STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1);
buf->bh_index = 0;
- ssize_t len;
- if (buf->bh_space >= (int)slen) {
+ size_t len;
+ if (buf->bh_space >= (size_t)slen) {
len = STRLEN(buf->bh_curr->b_str);
STRLCPY(buf->bh_curr->b_str + len, s, slen + 1);
- buf->bh_space -= slen;
+ buf->bh_space -= (size_t)slen;
} else {
- if (slen < MINIMAL_SIZE)
+ if (slen < MINIMAL_SIZE) {
len = MINIMAL_SIZE;
- else
- len = slen;
+ } else {
+ len = (size_t)slen;
+ }
buffblock_T *p = xmalloc(sizeof(buffblock_T) + len);
- buf->bh_space = (int)(len - slen);
+ buf->bh_space = len - (size_t)slen;
STRLCPY(p->b_str, s, slen + 1);
p->b_next = buf->bh_curr->b_next;
@@ -317,11 +320,11 @@ static void add_char_buff(buffheader_T *buf, int c)
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
/* translate special key code into three byte sequence */
temp[0] = K_SPECIAL;
- temp[1] = K_SECOND(c);
- temp[2] = K_THIRD(c);
+ temp[1] = (char_u)K_SECOND(c);
+ temp[2] = (char_u)K_THIRD(c);
temp[3] = NUL;
} else {
- temp[0] = c;
+ temp[0] = (char_u)c;
temp[1] = NUL;
}
add_buff(buf, temp, -1L);
@@ -694,10 +697,11 @@ static int read_redo(int init, int old_redo)
bp = bp->b_next;
p = bp->b_str;
}
- buf[i] = c;
- if (i == n - 1) { /* last byte of a character */
- if (n != 1)
+ buf[i] = (char_u)c;
+ if (i == n - 1) { // last byte of a character
+ if (n != 1) {
c = (*mb_ptr2char)(buf);
+ }
break;
}
c = *p;
@@ -882,8 +886,8 @@ int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, bool silent)
setcursor();
return FAIL;
}
- s1 = xmalloc(newlen);
- s2 = xmalloc(newlen);
+ s1 = xmalloc((size_t)newlen);
+ s2 = xmalloc((size_t)newlen);
typebuf.tb_buflen = newlen;
/* copy the old chars, before the insertion point */
@@ -937,7 +941,7 @@ int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, bool silent)
nrm = noremap;
for (i = 0; i < addlen; ++i)
typebuf.tb_noremap[typebuf.tb_off + i + offset] =
- (--nrm >= 0) ? val : RM_YES;
+ (char_u)((--nrm >= 0) ? val : RM_YES);
/* tb_maplen and tb_silent only remember the length of mapped and/or
* silent mappings at the start of the buffer, assuming that a mapped
@@ -965,8 +969,8 @@ void ins_char_typebuf(int c)
char_u buf[MB_MAXBYTES + 1];
if (IS_SPECIAL(c)) {
buf[0] = K_SPECIAL;
- buf[1] = K_SECOND(c);
- buf[2] = K_THIRD(c);
+ buf[1] = (char_u)K_SECOND(c);
+ buf[2] = (char_u)K_THIRD(c);
buf[3] = NUL;
} else {
buf[(*mb_char2bytes)(c, buf)] = NUL;
@@ -1083,25 +1087,25 @@ void del_typebuf(int len, int offset)
* Write typed characters to script file.
* If recording is on put the character in the recordbuffer.
*/
-static void gotchars(char_u *chars, int len)
+static void gotchars(char_u *chars, size_t len)
{
char_u *s = chars;
int c;
char_u buf[2];
- int todo = len;
- /* remember how many chars were last recorded */
- if (Recording)
+ // remember how many chars were last recorded
+ if (Recording) {
last_recorded_len += len;
+ }
buf[1] = NUL;
- while (todo--) {
- /* Handle one byte at a time; no translation to be done. */
+ while (len--) {
+ // Handle one byte at a time; no translation to be done.
c = *s++;
updatescript(c);
if (Recording) {
- buf[0] = c;
+ buf[0] = (char_u)c;
add_buff(&recordbuff, buf, 1L);
}
}
@@ -1465,10 +1469,10 @@ int vgetc(void)
* Note: This will loop until enough bytes are received!
*/
if (has_mbyte && (n = MB_BYTE2LEN_CHECK(c)) > 1) {
- ++no_mapping;
- buf[0] = c;
- for (i = 1; i < n; ++i) {
- buf[i] = vgetorpeek(TRUE);
+ no_mapping++;
+ buf[0] = (char_u)c;
+ for (i = 1; i < n; i++) {
+ buf[i] = (char_u)vgetorpeek(true);
if (buf[i] == K_SPECIAL
) {
/* Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence,
@@ -1562,7 +1566,7 @@ int char_avail(void)
{
int retval;
- ++no_mapping;
+ no_mapping++;
retval = vpeekc();
--no_mapping;
return retval != NUL;
@@ -1711,7 +1715,7 @@ static int vgetorpeek(int advance)
if (advance) {
/* Also record this character, it might be needed to
* get out of Insert mode. */
- *typebuf.tb_buf = c;
+ *typebuf.tb_buf = (char_u)c;
gotchars(typebuf.tb_buf, 1);
}
cmd_silent = FALSE;
@@ -1877,19 +1881,19 @@ static int vgetorpeek(int advance)
match = typebuf_match_len(p_pt, &mlen);
}
if (match) {
- /* write chars to script file(s) */
- if (mlen > typebuf.tb_maplen)
- gotchars(typebuf.tb_buf + typebuf.tb_off
- + typebuf.tb_maplen,
- mlen - typebuf.tb_maplen);
+ // write chars to script file(s)
+ if (mlen > typebuf.tb_maplen) {
+ gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen,
+ (size_t)(mlen - typebuf.tb_maplen));
+ }
del_typebuf(mlen, 0); /* remove the chars */
set_option_value((char_u *)"paste",
(long)!p_paste, NULL, 0);
if (!(State & INSERT)) {
msg_col = 0;
- msg_row = Rows - 1;
- msg_clr_eos(); /* clear ruler */
+ msg_row = (int)Rows - 1;
+ msg_clr_eos(); // clear ruler
}
status_redraw_all();
redraw_statuslines();
@@ -1975,11 +1979,11 @@ static int vgetorpeek(int advance)
char_u *save_m_keys;
char_u *save_m_str;
- /* write chars to script file(s) */
- if (keylen > typebuf.tb_maplen)
- gotchars(typebuf.tb_buf + typebuf.tb_off
- + typebuf.tb_maplen,
- keylen - typebuf.tb_maplen);
+ // write chars to script file(s)
+ if (keylen > typebuf.tb_maplen) {
+ gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen,
+ (size_t)(keylen - typebuf.tb_maplen));
+ }
cmd_silent = (typebuf.tb_silent > 0);
del_typebuf(keylen, 0); /* remove the mapped keys */
@@ -2417,7 +2421,7 @@ inchar (
else
return -1;
} else {
- buf[0] = script_char;
+ buf[0] = (char_u)script_char;
len = 1;
}
}
@@ -2453,7 +2457,7 @@ inchar (
* Fill up to a third of the buffer, because each character may be
* tripled below.
*/
- len = os_inchar(buf, maxlen / 3, wait_time, tb_change_cnt);
+ len = os_inchar(buf, maxlen / 3, (int)wait_time, tb_change_cnt);
}
if (typebuf_changed(tb_change_cnt))
@@ -2496,8 +2500,8 @@ fix_input_buffer (
&& !script
&& (i < 2 || p[1] != KS_EXTRA))) {
memmove(p + 3, p + 1, (size_t)i);
- p[2] = K_THIRD(p[0]);
- p[1] = K_SECOND(p[0]);
+ p[2] = (char_u)K_THIRD(p[0]);
+ p[1] = (char_u)K_SECOND(p[0]);
p[0] = K_SPECIAL;
p += 2;
len += 2;
@@ -2573,11 +2577,11 @@ do_map (
int new_hash;
mapblock_T **abbr_table;
mapblock_T **map_table;
- int unique = FALSE;
- int nowait = FALSE;
- int silent = FALSE;
- int special = FALSE;
- int expr = FALSE;
+ bool unique = false;
+ bool nowait = false;
+ bool silent = false;
+ bool special = false;
+ bool expr = false;
int noremap;
char_u *orig_rhs;
@@ -2609,7 +2613,7 @@ do_map (
*/
if (STRNCMP(keys, "<nowait>", 8) == 0) {
keys = skipwhite(keys + 8);
- nowait = TRUE;
+ nowait = true;
continue;
}
@@ -2618,7 +2622,7 @@ do_map (
*/
if (STRNCMP(keys, "<silent>", 8) == 0) {
keys = skipwhite(keys + 8);
- silent = TRUE;
+ silent = true;
continue;
}
@@ -2627,7 +2631,7 @@ do_map (
*/
if (STRNCMP(keys, "<special>", 9) == 0) {
keys = skipwhite(keys + 9);
- special = TRUE;
+ special = true;
continue;
}
@@ -2645,7 +2649,7 @@ do_map (
*/
if (STRNCMP(keys, "<expr>", 6) == 0) {
keys = skipwhite(keys + 6);
- expr = TRUE;
+ expr = true;
continue;
}
/*
@@ -2653,7 +2657,7 @@ do_map (
*/
if (STRNCMP(keys, "<unique>", 8) == 0) {
keys = skipwhite(keys + 8);
- unique = TRUE;
+ unique = true;
continue;
}
break;
@@ -2669,13 +2673,14 @@ do_map (
p = keys;
do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
while (*p && (maptype == 1 || !ascii_iswhite(*p))) {
- if ((p[0] == Ctrl_V || (do_backslash && p[0] == '\\')) &&
- p[1] != NUL)
- ++p; /* skip CTRL-V or backslash */
- ++p;
+ if ((p[0] == Ctrl_V || (do_backslash && p[0] == '\\')) && p[1] != NUL) {
+ p++; // skip CTRL-V or backslash
+ }
+ p++;
}
- if (*p != NUL)
+ if (*p != NUL) {
*p++ = NUL;
+ }
p = skipwhite(p);
rhs = p;
@@ -2688,22 +2693,24 @@ do_map (
goto theend;
}
- /*
- * If mapping has been given as ^V<C_UP> say, then replace the term codes
- * with the appropriate two bytes. If it is a shifted special key, unshift
- * it too, giving another two bytes.
- * replace_termcodes() may move the result to allocated memory, which
- * needs to be freed later (*keys_buf and *arg_buf).
- * replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
- */
- if (haskey)
- keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special);
+ // If mapping has been given as ^V<C_UP> say, then replace the term codes
+ // with the appropriate two bytes. If it is a shifted special key, unshift
+ // it too, giving another two bytes.
+ // replace_termcodes() may move the result to allocated memory, which
+ // needs to be freed later (*keys_buf and *arg_buf).
+ // replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
+ if (haskey) {
+ keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, special,
+ CPO_TO_CPO_FLAGS);
+ }
orig_rhs = rhs;
if (hasarg) {
- if (STRICMP(rhs, "<nop>") == 0) /* "<Nop>" means nothing */
+ if (STRICMP(rhs, "<nop>") == 0) { // "<Nop>" means nothing
rhs = (char_u *)"";
- else
- rhs = replace_termcodes(rhs, &arg_buf, FALSE, TRUE, special);
+ } else {
+ rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, special,
+ CPO_TO_CPO_FLAGS);
+ }
}
/*
@@ -3270,7 +3277,8 @@ int map_to_exists(char_u *str, char_u *modechars, int abbr)
char_u *buf;
int retval;
- rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
+ rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false,
+ CPO_TO_CPO_FLAGS);
if (vim_strchr(modechars, 'n') != NULL)
mode |= NORMAL;
@@ -3465,7 +3473,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file)
mp = maphash[hash];
for (; mp; mp = mp->m_next) {
if (mp->m_mode & expand_mapmodes) {
- p = translate_mapping(mp->m_keys, TRUE);
+ p = translate_mapping(mp->m_keys, true, CPO_TO_CPO_FLAGS);
if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) {
if (round == 1)
++count;
@@ -3483,7 +3491,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file)
break; /* for (round) */
if (round == 1) {
- *file = (char_u **)xmalloc(count * sizeof(char_u *));
+ *file = (char_u **)xmalloc((size_t)count * sizeof(char_u *));
}
} /* for (round) */
@@ -3647,8 +3655,8 @@ int check_abbr(int c, char_u *ptr, int col, int mincol)
/* special key code, split up */
if (IS_SPECIAL(c) || c == K_SPECIAL) {
tb[j++] = K_SPECIAL;
- tb[j++] = K_SECOND(c);
- tb[j++] = K_THIRD(c);
+ tb[j++] = (char_u)K_SECOND(c);
+ tb[j++] = (char_u)K_THIRD(c);
} else {
if (c < ABBR_OFF && (c < ' ' || c > '~'))
tb[j++] = Ctrl_V; /* special char needs CTRL-V */
@@ -3657,8 +3665,9 @@ int check_abbr(int c, char_u *ptr, int col, int mincol)
if (c >= ABBR_OFF)
c -= ABBR_OFF;
j += (*mb_char2bytes)(c, tb + j);
- } else
- tb[j++] = c;
+ } else {
+ tb[j++] = (char_u)c;
+ }
}
tb[j] = NUL;
/* insert the last typed char */
@@ -4190,14 +4199,15 @@ void add_map(char_u *map, int mode)
// Returns NULL when there is a problem.
static char_u * translate_mapping (
char_u *str,
- int expmap // TRUE when expanding mappings on command-line
+ int expmap, // True when expanding mappings on command-line
+ int cpo_flags // Value of various flags present in &cpo
)
{
garray_T ga;
ga_init(&ga, 1, 40);
- int cpo_bslash = (vim_strchr(p_cpo, CPO_BSLASH) != NULL);
- int cpo_special = (vim_strchr(p_cpo, CPO_SPECI) != NULL);
+ bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH);
+ bool cpo_special = !(cpo_flags&FLAG_CPO_SPECI);
for (; *str; ++str) {
int c = *str;
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index cc49bcd074..916d27a964 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -32,7 +32,6 @@
#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/version.h"
-#include "nvim/tempfile.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
@@ -2191,18 +2190,19 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
mbfont_opts[OPT_MBFONT_BOLDOBLIQUE].strlen);
}
- /* Check if need to use Courier for ASCII code range, and if so pick up
- * the encoding to use */
- prt_use_courier = mbfont_opts[OPT_MBFONT_USECOURIER].present &&
- (TOLOWER_ASC(mbfont_opts[OPT_MBFONT_USECOURIER].string[0])
- == 'y');
+ // Check if need to use Courier for ASCII code range, and if so pick up
+ // the encoding to use
+ prt_use_courier = (
+ mbfont_opts[OPT_MBFONT_USECOURIER].present
+ && (TOLOWER_ASC(mbfont_opts[OPT_MBFONT_USECOURIER].string[0]) == 'y'));
if (prt_use_courier) {
- /* Use national ASCII variant unless ASCII wanted */
- if (mbfont_opts[OPT_MBFONT_ASCII].present &&
- (TOLOWER_ASC(mbfont_opts[OPT_MBFONT_ASCII].string[0]) == 'y'))
+ // Use national ASCII variant unless ASCII wanted
+ if (mbfont_opts[OPT_MBFONT_ASCII].present
+ && (TOLOWER_ASC(mbfont_opts[OPT_MBFONT_ASCII].string[0]) == 'y')) {
prt_ascii_encoding = "ascii";
- else
+ } else {
prt_ascii_encoding = prt_ps_mbfonts[cmap].ascii_enc;
+ }
}
prt_ps_font = &prt_ps_mb_font;
@@ -3030,10 +3030,10 @@ int mch_print_text_out(char_u *p, size_t len)
prt_text_run += char_width;
prt_pos_x += char_width;
- /* The downside of fp - use relative error on right margin check */
+ // The downside of fp - use relative error on right margin check
next_pos = prt_pos_x + prt_char_width;
- need_break = (next_pos > prt_right_margin) &&
- ((next_pos - prt_right_margin) > (prt_right_margin*1e-5));
+ need_break = ((next_pos > prt_right_margin)
+ && ((next_pos - prt_right_margin) > (prt_right_margin * 1e-5)));
if (need_break)
prt_flush_buffer();
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index a143490356..2f9ec0b3ff 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -27,7 +27,6 @@
#include "nvim/quickfix.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
-#include "nvim/tempfile.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
@@ -1063,8 +1062,8 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m",
*qfpos == '-', cmdline) > 0) {
if (postponed_split != 0) {
- win_split(postponed_split > 0 ? postponed_split : 0,
- postponed_split_flags);
+ (void)win_split(postponed_split > 0 ? postponed_split : 0,
+ postponed_split_flags);
RESET_BINDING(curwin);
postponed_split = 0;
}
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 17fadc4bfd..efe8e73a3c 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -2282,15 +2282,14 @@ int get_c_indent(void)
* location for b_ind_open_extra.
*/
- if (start_brace == BRACE_IN_COL0) { /* '{' is in column 0 */
+ if (start_brace == BRACE_IN_COL0) { // '{' is in column 0
amount = curbuf->b_ind_open_left_imag;
- lookfor_cpp_namespace = TRUE;
- } else if (start_brace == BRACE_AT_START &&
- lookfor_cpp_namespace) { /* '{' is at start */
-
- lookfor_cpp_namespace = TRUE;
+ lookfor_cpp_namespace = true;
+ } else if (start_brace == BRACE_AT_START
+ && lookfor_cpp_namespace) { // '{' is at start
+ lookfor_cpp_namespace = true;
} else {
- if (start_brace == BRACE_AT_END) { /* '{' is at end of line */
+ if (start_brace == BRACE_AT_END) { // '{' is at end of line
amount += curbuf->b_ind_open_imag;
l = skipwhite(get_cursor_line_ptr());
diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c
index 6c75d8bdf4..99e94fc60f 100644
--- a/src/nvim/keymap.c
+++ b/src/nvim/keymap.c
@@ -482,26 +482,28 @@ char_u *get_special_key_name(int c, int modifiers)
return string;
}
-/*
- * Try translating a <> name at (*srcp)[] to dst[].
- * Return the number of characters added to dst[], zero for no match.
- * If there is a match, srcp is advanced to after the <> name.
- * dst[] must be big enough to hold the result (up to six characters)!
- */
-unsigned int
-trans_special (
- char_u **srcp,
- char_u *dst,
- int keycode /* prefer key code, e.g. K_DEL instead of DEL */
-)
+/// Try translating a <> name
+///
+/// @param[in,out] srcp Source from which <> are translated. Is advanced to
+/// after the <> name if there is a match.
+/// @param[in] src_len Length of the srcp.
+/// @param[out] dst Location where translation result will be kept. Must have
+/// at least six bytes.
+/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL.
+///
+/// @return Number of characters added to dst, zero for no match.
+unsigned int trans_special(const char_u **srcp, const size_t src_len,
+ char_u *const dst, const bool keycode)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int modifiers = 0;
int key;
unsigned int dlen = 0;
- key = find_special_key(srcp, &modifiers, keycode, FALSE);
- if (key == 0)
+ key = find_special_key(srcp, src_len, &modifiers, keycode, false);
+ if (key == 0) {
return 0;
+ }
/* Put the appropriate modifier in a string */
if (modifiers != 0) {
@@ -514,69 +516,78 @@ trans_special (
dst[dlen++] = K_SPECIAL;
dst[dlen++] = (char_u)KEY2TERMCAP0(key);
dst[dlen++] = KEY2TERMCAP1(key);
- } else if (has_mbyte && !keycode)
+ } else if (has_mbyte && !keycode) {
dlen += (unsigned int)(*mb_char2bytes)(key, dst + dlen);
- else if (keycode) {
+ } else if (keycode) {
char_u *after = add_char2buf(key, dst + dlen);
assert(after >= dst && (uintmax_t)(after - dst) <= UINT_MAX);
dlen = (unsigned int)(after - dst);
- }
- else
+ } else {
dst[dlen++] = (char_u)key;
+ }
return dlen;
}
-// Try translating a <> name at (*srcp)[], return the key and modifiers.
-// srcp is advanced to after the <> name.
-// returns 0 if there is no match.
-int find_special_key(
- char_u **srcp,
- int *modp,
- int keycode, // prefer key code, e.g. K_DEL instead of DEL
- int keep_x_key // don't translate xHome to Home key
-)
+/// Try translating a <> name
+///
+/// @param[in,out] srcp Translated <> name. Is advanced to after the <> name.
+/// @param[in] src_len srcp length.
+/// @param[out] modp Location where information about modifiers is saved.
+/// @param[in] keycode Prefer key code, e.g. K_DEL in place of DEL.
+/// @param[in] keep_x_key Don’t translate xHome to Home key.
+///
+/// @return Key and modifiers or 0 if there is no match.
+int find_special_key(const char_u **srcp, const size_t src_len, int *const modp,
+ const bool keycode, const bool keep_x_key)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- char_u *last_dash;
- char_u *end_of_name;
- char_u *src;
- char_u *bp;
+ const char_u *last_dash;
+ const char_u *end_of_name;
+ const char_u *src;
+ const char_u *bp;
+ const char_u *const end = *srcp + src_len - 1;
int modifiers;
int bit;
int key;
unsigned long n;
int l;
+ if (src_len == 0) {
+ return 0;
+ }
+
src = *srcp;
- if (src[0] != '<')
+ if (src[0] != '<') {
return 0;
+ }
// Find end of modifier list
last_dash = src;
- for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++) {
+ for (bp = src + 1; bp <= end && (*bp == '-' || vim_isIDc(*bp)); bp++) {
if (*bp == '-') {
last_dash = bp;
- if (bp[1] != NUL) {
+ if (bp + 1 <= end) {
if (has_mbyte) {
- l = mb_ptr2len(bp + 1);
+ l = mb_ptr2len_len(bp + 1, (int) (end - bp) + 1);
} else {
l = 1;
}
- if (bp[l + 1] == '>') {
- bp += l; // anything accepted, like <C-?>
+ if (end - bp > l && bp[l + 1] == '>') {
+ bp += l; // anything accepted, like <C-?>
}
}
}
- if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) {
- bp += 3; // skip t_xx, xx may be '-' or '>'
- } else if (STRNICMP(bp, "char-", 5) == 0) {
+ if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') {
+ bp += 3; // skip t_xx, xx may be '-' or '>'
+ } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) {
vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0);
bp += l + 5;
break;
}
}
- if (*bp == '>') { /* found matching '>' */
+ if (bp <= end && *bp == '>') { // found matching '>'
end_of_name = bp + 1;
/* Which modifiers are given? */
@@ -696,7 +707,7 @@ int find_special_key_in_table(int c)
* termcap name.
* Return the key code, or 0 if not found.
*/
-int get_special_key_code(char_u *name)
+int get_special_key_code(const char_u *name)
{
char_u *table_name;
int i, j;
@@ -730,50 +741,58 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)
return 0; /* Shouldn't get here */
}
-// Replace any terminal code strings in from[] with the equivalent internal
-// vim representation. This is used for the "from" and "to" part of a
-// mapping, and the "to" part of a menu command.
-// Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains
-// '<'.
-// K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER.
-//
-// The replacement is done in result[] and finally copied into allocated
-// memory. If this all works well *bufp is set to the allocated memory and a
-// pointer to it is returned. If something fails *bufp is set to NULL and from
-// is returned.
-//
-// CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V
-// is included, otherwise it is removed (for ":map xx ^V", maps xx to
-// nothing). When 'cpoptions' does not contain 'B', a backslash can be used
-// instead of a CTRL-V.
-char_u * replace_termcodes (
- char_u *from,
- char_u **bufp,
- int from_part,
- int do_lt, // also translate <lt>
- int special // always accept <key> notation
-)
+/// Replace any terminal code strings with the equivalent internal
+/// representation
+///
+/// This is used for the "from" and "to" part of a mapping, and the "to" part of
+/// a menu command. Any strings like "<C-UP>" are also replaced, unless
+/// 'cpoptions' contains '<'. K_SPECIAL by itself is replaced by K_SPECIAL
+/// KS_SPECIAL KE_FILLER.
+///
+/// @param[in] from What characters to replace.
+/// @param[in] from_len Length of the "from" argument.
+/// @param[out] bufp Location where results were saved in case of success
+/// (allocated). Will be set to NULL in case of failure.
+/// @param[in] do_lt If true, also translate <lt>.
+/// @param[in] from_part If true, trailing <C-v> is included, otherwise it is
+/// removed (to make ":map xx ^V" map xx to nothing).
+/// When cpo_flags contains #FLAG_CPO_BSLASH, a backslash
+/// can be used in place of <C-v>. All other <C-v>
+/// characters are removed.
+/// @param[in] special If true, always accept <key> notation.
+/// @param[in] cpo_flags Relevant flags derived from p_cpo, see
+/// #CPO_TO_CPO_FLAGS.
+///
+/// @return Pointer to an allocated memory in case of success, "from" in case of
+/// failure. In case of success returned pointer is also saved to
+/// "bufp".
+char_u *replace_termcodes(const char_u *from, const size_t from_len,
+ char_u **bufp, const bool from_part, const bool do_lt,
+ const bool special, int cpo_flags)
+ FUNC_ATTR_NONNULL_ALL
{
ssize_t i;
size_t slen;
char_u key;
size_t dlen = 0;
- char_u *src;
+ const char_u *src;
+ const char_u *const end = from + from_len - 1;
int do_backslash; // backslash is a special character
int do_special; // recognize <> key codes
char_u *result; // buffer for resulting string
- do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
- do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL) || special;
+ do_backslash = !(cpo_flags&FLAG_CPO_BSLASH);
+ do_special = !(cpo_flags&FLAG_CPO_SPECI) || special;
// Allocate space for the translation. Worst case a single character is
// replaced by 6 bytes (shifted special key), plus a NUL at the end.
- result = xmalloc(STRLEN(from) * 6 + 1);
+ result = xmalloc(from_len * 6 + 1);
src = from;
// Check for #n at start only: function key n
- if (from_part && src[0] == '#' && ascii_isdigit(src[1])) { // function key
+ if (from_part && from_len > 1 && src[0] == '#'
+ && ascii_isdigit(src[1])) { // function key
result[dlen++] = K_SPECIAL;
result[dlen++] = 'k';
if (src[1] == '0') {
@@ -785,13 +804,14 @@ char_u * replace_termcodes (
}
// Copy each byte from *from to result[dlen]
- while (*src != NUL) {
+ while (src <= end) {
// If 'cpoptions' does not contain '<', check for special key codes,
// like "<C-S-LeftMouse>"
- if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0)) {
+ if (do_special && (do_lt || ((end - src) >= 3
+ && STRNCMP(src, "<lt>", 4) != 0))) {
// Replace <SID> by K_SNR <script-nr> _.
// (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
- if (STRNICMP(src, "<SID>", 5) == 0) {
+ if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) {
if (current_SID <= 0) {
EMSG(_(e_usingsid));
} else {
@@ -806,7 +826,7 @@ char_u * replace_termcodes (
}
}
- slen = trans_special(&src, result + dlen, TRUE);
+ slen = trans_special(&src, (size_t) (end - src) + 1, result + dlen, true);
if (slen) {
dlen += slen;
continue;
@@ -819,10 +839,10 @@ char_u * replace_termcodes (
// Replace <Leader> by the value of "mapleader".
// Replace <LocalLeader> by the value of "maplocalleader".
// If "mapleader" or "maplocalleader" isn't set use a backslash.
- if (STRNICMP(src, "<Leader>", 8) == 0) {
+ if (end - src >= 7 && STRNICMP(src, "<Leader>", 8) == 0) {
len = 8;
p = get_var_value((char_u *)"g:mapleader");
- } else if (STRNICMP(src, "<LocalLeader>", 13) == 0) {
+ } else if (end - src >= 12 && STRNICMP(src, "<LocalLeader>", 13) == 0) {
len = 13;
p = get_var_value((char_u *)"g:maplocalleader");
} else {
@@ -851,8 +871,8 @@ char_u * replace_termcodes (
// If 'cpoptions' does not contain 'B', also accept a backslash.
key = *src;
if (key == Ctrl_V || (do_backslash && key == '\\')) {
- ++src; // skip CTRL-V or backslash
- if (*src == NUL) {
+ src++; // skip CTRL-V or backslash
+ if (src > end) {
if (from_part) {
result[dlen++] = key;
}
@@ -861,7 +881,7 @@ char_u * replace_termcodes (
}
// skip multibyte char correctly
- for (i = (*mb_ptr2len)(src); i > 0; --i) {
+ for (i = (*mb_ptr2len_len)(src, (int) (end - src) + 1); i > 0; i--) {
// If the character is K_SPECIAL, replace it with K_SPECIAL
// KS_SPECIAL KE_FILLER.
// If compiled with the GUI replace CSI with K_CSI.
diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h
index 8f9980c6b4..bb8ba84a6a 100644
--- a/src/nvim/keymap.h
+++ b/src/nvim/keymap.h
@@ -1,6 +1,8 @@
#ifndef NVIM_KEYMAP_H
#define NVIM_KEYMAP_H
+#include "nvim/strings.h"
+
/*
* Keycode definitions for special keys.
*
@@ -461,6 +463,14 @@ enum key_extra {
// This is a total of 6 tokens, and is currently the longest one possible.
#define MAX_KEY_CODE_LEN 6
+#define FLAG_CPO_BSLASH 0x01
+#define FLAG_CPO_SPECI 0x02
+#define CPO_TO_CPO_FLAGS (((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \
+ ? 0 \
+ : FLAG_CPO_BSLASH)| \
+ (vim_strchr(p_cpo, CPO_SPECI) == NULL \
+ ? 0 \
+ : FLAG_CPO_SPECI))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "keymap.h.generated.h"
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 10176752d5..4e35dd481f 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -65,7 +65,6 @@
#include "nvim/strings.h"
#include "nvim/ui.h"
#include "nvim/version.h"
-#include "nvim/tempfile.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
@@ -787,9 +786,8 @@ void ml_recover(void)
if (fname == NULL) /* When there is no file name */
fname = (char_u *)"";
len = (int)STRLEN(fname);
- if (len >= 4 &&
- STRNICMP(fname + len - 4, ".s", 2)
- == 0
+ if (len >= 4
+ && STRNICMP(fname + len - 4, ".s", 2) == 0
&& vim_strchr((char_u *)"UVWuvw", fname[len - 2]) != NULL
&& ASCII_ISALPHA(fname[len - 1])) {
directly = TRUE;
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 91a72abfc5..3c2394d579 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -215,10 +215,12 @@ ex_menu (
if (STRICMP(map_to, "<nop>") == 0) { /* "<Nop>" means nothing */
map_to = (char_u *)"";
map_buf = NULL;
- } else if (modes & MENU_TIP_MODE)
- map_buf = NULL; /* Menu tips are plain text. */
- else
- map_to = replace_termcodes(map_to, &map_buf, FALSE, TRUE, special);
+ } else if (modes & MENU_TIP_MODE) {
+ map_buf = NULL; // Menu tips are plain text.
+ } else {
+ map_to = replace_termcodes(map_to, STRLEN(map_to), &map_buf, false, true,
+ special, CPO_TO_CPO_FLAGS);
+ }
menuarg.modes = modes;
menuarg.noremap[0] = noremap;
menuarg.silent[0] = silent;
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 97b098c6d2..f60b128712 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1570,39 +1570,31 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
int wrap;
int did_last_char;
- did_wait_return = FALSE;
+ did_wait_return = false;
while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL) {
- /*
- * We are at the end of the screen line when:
- * - When outputting a newline.
- * - When outputting a character in the last column.
- */
- if (!recurse && msg_row >= Rows - 1 && (*s == '\n' || (
- cmdmsg_rl
- ? (
- msg_col <= 1
- || (*s == TAB && msg_col <= 7)
- || (has_mbyte &&
- (*mb_ptr2cells)(s) > 1 &&
- msg_col <= 2)
- )
- :
- (msg_col + t_col >= Columns - 1
- || (*s == TAB && msg_col +
- t_col >= ((Columns - 1) & ~7))
- || (has_mbyte &&
- (*mb_ptr2cells)(s) > 1
- && msg_col + t_col >=
- Columns - 2)
- )))) {
- /*
- * The screen is scrolled up when at the last row (some terminals
- * scroll automatically, some don't. To avoid problems we scroll
- * ourselves).
- */
- if (t_col > 0)
- /* output postponed text */
+ // We are at the end of the screen line when:
+ // - When outputting a newline.
+ // - When outputting a character in the last column.
+ if (!recurse && msg_row >= Rows - 1
+ && (*s == '\n' || (cmdmsg_rl
+ ? (msg_col <= 1
+ || (*s == TAB && msg_col <= 7)
+ || (has_mbyte
+ && (*mb_ptr2cells)(s) > 1
+ && msg_col <= 2))
+ : (msg_col + t_col >= Columns - 1
+ || (*s == TAB
+ && msg_col + t_col >= ((Columns - 1) & ~7))
+ || (has_mbyte
+ && (*mb_ptr2cells)(s) > 1
+ && msg_col + t_col >= Columns - 2))))) {
+ // The screen is scrolled up when at the last row (some terminals
+ // scroll automatically, some don't. To avoid problems we scroll
+ // ourselves).
+ if (t_col > 0) {
+ // output postponed text
t_puts(&t_col, t_s, s, attr);
+ }
/* When no more prompt and no more room, truncate here */
if (msg_no_more && lines_left == 0)
@@ -1709,18 +1701,15 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse)
cw = 1;
l = 1;
}
- /* When drawing from right to left or when a double-wide character
- * doesn't fit, draw a single character here. Otherwise collect
- * characters and draw them all at once later. */
- if (
- cmdmsg_rl
- ||
- (cw > 1 && msg_col + t_col >= Columns - 1)
- ) {
- if (l > 1)
+ // When drawing from right to left or when a double-wide character
+ // doesn't fit, draw a single character here. Otherwise collect
+ // characters and draw them all at once later.
+ if (cmdmsg_rl || (cw > 1 && msg_col + t_col >= Columns - 1)) {
+ if (l > 1) {
s = screen_puts_mbyte(s, l, attr) - 1;
- else
+ } else {
msg_screen_putchar(*s, attr);
+ }
} else {
/* postpone this character until later */
if (t_col == 0)
@@ -3382,8 +3371,8 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
// leave negative numbers for sprintf to handle, to
// avoid handling tricky cases like (short int)-32768
} else if (alternate_form) {
- if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' ||
- fmt_spec == 'b' || fmt_spec == 'B')) {
+ if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X'
+ || fmt_spec == 'b' || fmt_spec == 'B')) {
tmp[str_arg_l++] = '0';
tmp[str_arg_l++] = fmt_spec;
}
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index a20ee562fa..53eceaa4ef 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -43,7 +43,6 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
-#include "nvim/tempfile.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -205,15 +204,12 @@ open_line (
else
lead_len = 0;
if (dir == FORWARD) {
- /*
- * Skip preprocessor directives, unless they are
- * recognised as comments.
- */
- if (
- lead_len == 0 &&
- ptr[0] == '#') {
- while (ptr[0] == '#' && curwin->w_cursor.lnum > 1)
+ // Skip preprocessor directives, unless they are
+ // recognised as comments.
+ if (lead_len == 0 && ptr[0] == '#') {
+ while (ptr[0] == '#' && curwin->w_cursor.lnum > 1) {
ptr = ml_get(--curwin->w_cursor.lnum);
+ }
newindent = get_indent();
}
if (flags & OPENLINE_DO_COM)
@@ -297,28 +293,26 @@ open_line (
&& cin_is_cinword(ptr))
did_si = TRUE;
}
- } else { /* dir == BACKWARD */
- /*
- * Skip preprocessor directives, unless they are
- * recognised as comments.
- */
- if (
- lead_len == 0 &&
- ptr[0] == '#') {
- int was_backslashed = FALSE;
-
- while ((ptr[0] == '#' || was_backslashed) &&
- curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- if (*ptr && ptr[STRLEN(ptr) - 1] == '\\')
- was_backslashed = TRUE;
- else
- was_backslashed = FALSE;
+ } else { // dir == BACKWARD
+ // Skip preprocessor directives, unless they are
+ // recognised as comments.
+ if (lead_len == 0 && ptr[0] == '#') {
+ bool was_backslashed = false;
+
+ while ((ptr[0] == '#' || was_backslashed)
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
+ if (*ptr && ptr[STRLEN(ptr) - 1] == '\\') {
+ was_backslashed = true;
+ } else {
+ was_backslashed = false;
+ }
ptr = ml_get(++curwin->w_cursor.lnum);
}
- if (was_backslashed)
- newindent = 0; /* Got to end of file */
- else
+ if (was_backslashed) {
+ newindent = 0; // Got to end of file
+ } else {
newindent = get_indent();
+ }
}
p = skipwhite(ptr);
if (*p == '}') /* if line starts with '}': do indent */
@@ -668,16 +662,12 @@ open_line (
did_si = can_si = FALSE;
} else if (comment_end != NULL) {
- /*
- * We have finished a comment, so we don't use the leader.
- * If this was a C-comment and 'ai' or 'si' is set do a normal
- * indent to align with the line containing the start of the
- * comment.
- */
- if (comment_end[0] == '*' && comment_end[1] == '/' &&
- (curbuf->b_p_ai
- || do_si
- )) {
+ // We have finished a comment, so we don't use the leader.
+ // If this was a C-comment and 'ai' or 'si' is set do a normal
+ // indent to align with the line containing the start of the
+ // comment.
+ if (comment_end[0] == '*' && comment_end[1] == '/'
+ && (curbuf->b_p_ai || do_si)) {
old_cursor = curwin->w_cursor;
curwin->w_cursor.col = (colnr_T)(comment_end - saved_line);
if ((pos = findmatch(NULL, NUL)) != NULL) {
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 3ae1a6a890..2f499e477c 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -14,6 +14,8 @@
#include "nvim/misc1.h"
#include "nvim/cursor.h"
#include "nvim/buffer_defs.h"
+#include "nvim/memline.h"
+#include "nvim/charset.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mouse.c.generated.h"
@@ -503,3 +505,95 @@ void set_mouse_topline(win_T *wp)
orig_topfill = wp->w_topfill;
}
+///
+/// Return length of line "lnum" for horizontal scrolling.
+///
+static colnr_T scroll_line_len(linenr_T lnum)
+{
+ colnr_T col = 0;
+ char_u *line = ml_get(lnum);
+ if (*line != NUL) {
+ for (;;) {
+ int numchar = chartabsize(line, col);
+ mb_ptr_adv(line);
+ if (*line == NUL) { // don't count the last character
+ break;
+ }
+ col += numchar;
+ }
+ }
+ return col;
+}
+
+///
+/// Find longest visible line number.
+///
+static linenr_T find_longest_lnum(void)
+{
+ linenr_T ret = 0;
+
+ // Calculate maximum for horizontal scrollbar. Check for reasonable
+ // line numbers, topline and botline can be invalid when displaying is
+ // postponed.
+ if (curwin->w_topline <= curwin->w_cursor.lnum
+ && curwin->w_botline > curwin->w_cursor.lnum
+ && curwin->w_botline <= curbuf->b_ml.ml_line_count + 1) {
+ long max = 0;
+
+ // Use maximum of all visible lines. Remember the lnum of the
+ // longest line, closest to the cursor line. Used when scrolling
+ // below.
+ for (linenr_T lnum = curwin->w_topline; lnum < curwin->w_botline; lnum++) {
+ colnr_T len = scroll_line_len(lnum);
+ if (len > (colnr_T)max) {
+ max = len;
+ ret = lnum;
+ } else if (len == (colnr_T)max
+ && abs((int)(lnum - curwin->w_cursor.lnum))
+ < abs((int)(ret - curwin->w_cursor.lnum))) {
+ ret = lnum;
+ }
+ }
+ } else {
+ // Use cursor line only.
+ ret = curwin->w_cursor.lnum;
+ }
+
+ return ret;
+}
+
+///
+/// Do a horizontal scroll. Return TRUE if the cursor moved, FALSE otherwise.
+///
+bool mouse_scroll_horiz(int dir)
+{
+ if (curwin->w_p_wrap) {
+ return false;
+ }
+
+ int step = 6;
+ if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) {
+ step = curwin->w_width;
+ }
+
+ int leftcol = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : +step);
+ if (leftcol < 0) {
+ leftcol = 0;
+ }
+
+ if (curwin->w_leftcol == leftcol) {
+ return false;
+ }
+
+ curwin->w_leftcol = (colnr_T)leftcol;
+
+ // When the line of the cursor is too short, move the cursor to the
+ // longest visible line.
+ if (!virtual_active()
+ && (colnr_T)leftcol > scroll_line_len(curwin->w_cursor.lnum)) {
+ curwin->w_cursor.lnum = find_longest_lnum();
+ curwin->w_cursor.col = 0;
+ }
+
+ return leftcol_changed();
+}
diff --git a/src/nvim/mouse.h b/src/nvim/mouse.h
index c824bcc8f0..0149f7c7c0 100644
--- a/src/nvim/mouse.h
+++ b/src/nvim/mouse.h
@@ -34,6 +34,12 @@
#define MOUSE_X1 0x300 // Mouse-button X1 (6th)
#define MOUSE_X2 0x400 // Mouse-button X2
+// Direction for nv_mousescroll() and ins_mousescroll()
+#define MSCR_DOWN 0 // DOWN must be FALSE
+#define MSCR_UP 1
+#define MSCR_LEFT -1
+#define MSCR_RIGHT -2
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mouse.h.generated.h"
diff --git a/src/nvim/move.c b/src/nvim/move.c
index ba79c0411a..b129c5cb7a 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -1010,12 +1010,9 @@ scrollup (
int byfold /* true: count a closed fold as one line */
)
{
- if (
- (byfold && hasAnyFolding(curwin))
- ||
- curwin->w_p_diff
- ) {
- /* count each sequence of folded lines as one logical line */
+ if ((byfold && hasAnyFolding(curwin))
+ || curwin->w_p_diff) {
+ // count each sequence of folded lines as one logical line
linenr_T lnum = curwin->w_topline;
while (line_count--) {
if (curwin->w_topfill > 0)
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index 5ef81721d4..0049ae6b95 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -419,8 +419,8 @@ void msgpack_rpc_validate(uint64_t *response_id,
return;
}
- if ((type == kMessageTypeRequest && req->via.array.size != 4) ||
- (type == kMessageTypeNotification && req->via.array.size != 3)) {
+ if ((type == kMessageTypeRequest && req->via.array.size != 4)
+ || (type == kMessageTypeNotification && req->via.array.size != 3)) {
api_set_error(err, Validation, _("Request array size should be 4 (request) "
"or 3 (notification)"));
return;
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index bf384e3379..6cc56ba3dd 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -14,7 +14,7 @@
#include "nvim/vim.h"
#include "nvim/memory.h"
#include "nvim/log.h"
-#include "nvim/tempfile.h"
+#include "nvim/fileio.h"
#include "nvim/path.h"
#include "nvim/strings.h"
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 5b7c4b68b1..57638ee388 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -569,36 +569,33 @@ static bool normal_need_aditional_char(NormalState *s)
static bool normal_need_redraw_mode_message(NormalState *s)
{
return (
- (
// 'showmode' is set and messages can be printed
- p_smd && msg_silent == 0
- // must restart insert mode(ctrl+o or ctrl+l) or we just entered visual
- // mode
- && (restart_edit != 0 || (VIsual_active
- && s->old_pos.lnum == curwin->w_cursor.lnum
- && s->old_pos.col == curwin->w_cursor.col))
- // command-line must be cleared or redrawn
- && (clear_cmdline || redraw_cmdline)
- // some message was printed or scrolled
- && (msg_didout || (msg_didany && msg_scroll))
- // it is fine to remove the current message
- && !msg_nowait
- // the command was the result of direct user input and not a mapping
- && KeyTyped
- )
- ||
- // must restart insert mode, not in visual mode and error message is
- // being shown
- (restart_edit != 0 && !VIsual_active && (msg_scroll && emsg_on_display))
- )
- // no register was used
- && s->oa.regname == 0
- && !(s->ca.retval & CA_COMMAND_BUSY)
- && stuff_empty()
- && typebuf_typed()
- && emsg_silent == 0
- && !did_wait_return
- && s->oa.op_type == OP_NOP;
+ ((p_smd && msg_silent == 0
+ // must restart insert mode(ctrl+o or ctrl+l) or we just entered visual
+ // mode
+ && (restart_edit != 0 || (VIsual_active
+ && s->old_pos.lnum == curwin->w_cursor.lnum
+ && s->old_pos.col == curwin->w_cursor.col))
+ // command-line must be cleared or redrawn
+ && (clear_cmdline || redraw_cmdline)
+ // some message was printed or scrolled
+ && (msg_didout || (msg_didany && msg_scroll))
+ // it is fine to remove the current message
+ && !msg_nowait
+ // the command was the result of direct user input and not a mapping
+ && KeyTyped)
+ // must restart insert mode, not in visual mode and error message is
+ // being shown
+ || (restart_edit != 0 && !VIsual_active && msg_scroll
+ && emsg_on_display))
+ // no register was used
+ && s->oa.regname == 0
+ && !(s->ca.retval & CA_COMMAND_BUSY)
+ && stuff_empty()
+ && typebuf_typed()
+ && emsg_silent == 0
+ && !did_wait_return
+ && s->oa.op_type == OP_NOP);
}
static void normal_redraw_mode_message(NormalState *s)
@@ -1436,19 +1433,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
}
curwin->w_p_lbr = false;
oap->is_VIsual = VIsual_active;
- if (oap->motion_force == 'V')
- oap->motion_type = MLINE;
- else if (oap->motion_force == 'v') {
- /* If the motion was linewise, "inclusive" will not have been set.
- * Use "exclusive" to be consistent. Makes "dvj" work nice. */
- if (oap->motion_type == MLINE)
+ if (oap->motion_force == 'V') {
+ oap->motion_type = kMTLineWise;
+ } else if (oap->motion_force == 'v') {
+ // If the motion was linewise, "inclusive" will not have been set.
+ // Use "exclusive" to be consistent. Makes "dvj" work nice.
+ if (oap->motion_type == kMTLineWise) {
oap->inclusive = false;
- /* If the motion already was characterwise, toggle "inclusive" */
- else if (oap->motion_type == MCHAR)
+ } else if (oap->motion_type == kMTCharWise) {
+ // If the motion already was characterwise, toggle "inclusive"
oap->inclusive = !oap->inclusive;
- oap->motion_type = MCHAR;
+ }
+ oap->motion_type = kMTCharWise;
} else if (oap->motion_force == Ctrl_V) {
- /* Change line- or characterwise motion into Visual block mode. */
+ // Change line- or characterwise motion into Visual block mode.
VIsual_active = true;
VIsual = oap->start;
VIsual_mode = Ctrl_V;
@@ -1586,13 +1584,15 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* automatically. */
curwin->w_valid &= ~VALID_VIRTCOL;
} else {
- /* Include folded lines completely. */
- if (!VIsual_active && oap->motion_type == MLINE) {
+ // Include folded lines completely.
+ if (!VIsual_active && oap->motion_type == kMTLineWise) {
if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum,
- NULL))
+ NULL)) {
curwin->w_cursor.col = 0;
- if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum))
+ }
+ if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum)) {
oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum));
+ }
}
oap->end = oap->start;
oap->start = curwin->w_cursor;
@@ -1663,17 +1663,16 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
}
}
- /*
- * oap->inclusive defaults to true.
- * If oap->end is on a NUL (empty line) oap->inclusive becomes
- * false. This makes "d}P" and "v}dP" work the same.
- */
- if (oap->motion_force == NUL || oap->motion_type == MLINE)
+ // oap->inclusive defaults to true.
+ // If oap->end is on a NUL (empty line) oap->inclusive becomes
+ // false. This makes "d}P" and "v}dP" work the same.
+ if (oap->motion_force == NUL || oap->motion_type == kMTLineWise) {
oap->inclusive = true;
+ }
if (VIsual_mode == 'V') {
- oap->motion_type = MLINE;
+ oap->motion_type = kMTLineWise;
} else if (VIsual_mode == 'v') {
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
if (*ml_get_pos(&(oap->end)) == NUL
&& (include_line_break || !virtual_op)
) {
@@ -1731,7 +1730,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
* oap->empty is set when start and end are the same. The inclusive
* flag affects this too, unless yanking and the end is on a NUL.
*/
- oap->empty = (oap->motion_type != MLINE
+ oap->empty = (oap->motion_type != kMTLineWise
&& (!oap->inclusive
|| (oap->op_type == OP_YANK
&& gchar_pos(&oap->end) == NUL))
@@ -1756,23 +1755,23 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
/*
* If the end of an operator is in column one while oap->motion_type
- * is MCHAR and oap->inclusive is false, we put op_end after the last
+ * is kMTCharWise and oap->inclusive is false, we put op_end after the last
* character in the previous line. If op_start is on or before the
* first non-blank in the line, the operator becomes linewise
* (strange, but that's the way vi does it).
*/
- if (oap->motion_type == MCHAR
+ if (oap->motion_type == kMTCharWise
&& oap->inclusive == false
&& !(cap->retval & CA_NO_ADJ_OP_END)
&& oap->end.col == 0
&& (!oap->is_VIsual || *p_sel == 'o')
&& oap->line_count > 1) {
oap->end_adjusted = true; // remember that we did this
- --oap->line_count;
- --oap->end.lnum;
- if (inindent(0))
- oap->motion_type = MLINE;
- else {
+ oap->line_count--;
+ oap->end.lnum--;
+ if (inindent(0)) {
+ oap->motion_type = kMTLineWise;
+ } else {
oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
if (oap->end.col) {
--oap->end.col;
@@ -1811,8 +1810,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
CancelRedo();
} else {
(void)op_delete(oap);
- if (oap->motion_type == MLINE && has_format_option(FO_AUTO))
- u_save_cursor(); /* cursor line wasn't saved yet */
+ if (oap->motion_type == kMTLineWise && has_format_option(FO_AUTO)) {
+ u_save_cursor(); // cursor line wasn't saved yet
+ }
auto_format(false, true);
}
break;
@@ -2011,7 +2011,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
/*
* if 'sol' not set, go back to old column for some commands
*/
- if (!p_sol && oap->motion_type == MLINE && !oap->end_adjusted
+ if (!p_sol && oap->motion_type == kMTLineWise && !oap->end_adjusted
&& (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT
|| oap->op_type == OP_DELETE)) {
curwin->w_p_lbr = false;
@@ -2086,13 +2086,14 @@ static void op_function(oparg_T *oap)
/* Set '[ and '] marks to text to be operated on. */
curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end;
- if (oap->motion_type != MLINE && !oap->inclusive)
- /* Exclude the end position. */
+ if (oap->motion_type != kMTLineWise && !oap->inclusive) {
+ // Exclude the end position.
decl(&curbuf->b_op_end);
+ }
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
argv[0] = (char_u *)"block";
- } else if (oap->motion_type == MLINE) {
+ } else if (oap->motion_type == kMTLineWise) {
argv[0] = (char_u *)"line";
} else {
argv[0] = (char_u *)"char";
@@ -2530,7 +2531,7 @@ do_mouse (
*/
if (!is_drag && oap != NULL && oap->op_type != OP_NOP) {
got_click = false;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
}
/* When releasing the button let jump_to_mouse() know. */
@@ -2598,11 +2599,10 @@ do_mouse (
end_visual.col = leftcol;
else
end_visual.col = rightcol;
- if (curwin->w_cursor.lnum <
- (start_visual.lnum + end_visual.lnum) / 2)
- end_visual.lnum = end_visual.lnum;
- else
+ if (curwin->w_cursor.lnum >=
+ (start_visual.lnum + end_visual.lnum) / 2) {
end_visual.lnum = start_visual.lnum;
+ }
/* move VIsual to the right column */
start_visual = curwin->w_cursor; /* save the cursor pos */
@@ -2770,21 +2770,23 @@ do_mouse (
end_visual = curwin->w_cursor;
while (gc = gchar_pos(&end_visual), ascii_iswhite(gc))
inc(&end_visual);
- if (oap != NULL)
- oap->motion_type = MCHAR;
+ if (oap != NULL) {
+ oap->motion_type = kMTCharWise;
+ }
if (oap != NULL
&& VIsual_mode == 'v'
&& !vim_iswordc(gchar_pos(&end_visual))
&& equalpos(curwin->w_cursor, VIsual)
&& (pos = findmatch(oap, NUL)) != NULL) {
curwin->w_cursor = *pos;
- if (oap->motion_type == MLINE)
+ if (oap->motion_type == kMTLineWise) {
VIsual_mode = 'V';
- else if (*p_sel == 'e') {
- if (lt(curwin->w_cursor, VIsual))
- ++VIsual.col;
- else
- ++curwin->w_cursor.col;
+ } else if (*p_sel == 'e') {
+ if (lt(curwin->w_cursor, VIsual)) {
+ VIsual.col++;
+ } else {
+ curwin->w_cursor.col++;
+ }
}
}
}
@@ -3244,9 +3246,9 @@ void clear_showcmd(void)
top = curwin->w_cursor.lnum;
bot = VIsual.lnum;
}
- /* Include closed folds as a whole. */
- hasFolding(top, &top, NULL);
- hasFolding(bot, NULL, &bot);
+ // Include closed folds as a whole.
+ (void)hasFolding(top, &top, NULL);
+ (void)hasFolding(bot, NULL, &bot);
lines = bot - top + 1;
if (VIsual_mode == Ctrl_V) {
@@ -3782,7 +3784,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
int width1; /* text width for first screen line */
int width2; /* test width for wrapped screen line */
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = (curwin->w_curswant == MAXCOL);
col_off1 = curwin_col_off();
@@ -3927,6 +3929,8 @@ static void nv_mousescroll(cmdarg_T *cap)
cap->count0 = 3;
nv_scroll_line(cap);
}
+ } else {
+ mouse_scroll_horiz(cap->arg);
}
curwin->w_redr_status = true;
@@ -4053,16 +4057,15 @@ static void nv_zet(cmdarg_T *cap)
}
dozet:
- if (
- /* "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
- * and "zC" only in Visual mode. "zj" and "zk" are motion
- * commands. */
- cap->nchar != 'f' && cap->nchar != 'F'
- && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar))
- && cap->nchar != 'j' && cap->nchar != 'k'
- &&
- checkclearop(cap->oap))
+ // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
+ // and "zC" only in Visual mode. "zj" and "zk" are motion
+ // commands. */
+ if (cap->nchar != 'f' && cap->nchar != 'F'
+ && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar))
+ && cap->nchar != 'j' && cap->nchar != 'k'
+ && checkclearop(cap->oap)) {
return;
+ }
/*
* For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
@@ -4463,8 +4466,8 @@ static void nv_colon(cmdarg_T *cap)
nv_operator(cap);
else {
if (cap->oap->op_type != OP_NOP) {
- /* Using ":" as a movement is characterwise exclusive. */
- cap->oap->motion_type = MCHAR;
+ // Using ":" as a movement is characterwise exclusive.
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
} else if (cap->count0) {
/* translate "count:" into ":.,.+(count - 1)" */
@@ -4863,7 +4866,7 @@ static void nv_scroll(cmdarg_T *cap)
linenr_T lnum;
int half;
- cap->oap->motion_type = MLINE;
+ cap->oap->motion_type = kMTLineWise;
setpcmark();
if (cap->cmdchar == 'L') {
@@ -4943,7 +4946,7 @@ static void nv_right(cmdarg_T *cap)
return;
}
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
PAST_LINE = (VIsual_active && *p_sel != 'o');
@@ -5030,7 +5033,7 @@ static void nv_left(cmdarg_T *cap)
return;
}
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
for (n = cap->count1; n > 0; --n) {
if (oneleft() == false) {
@@ -5092,11 +5095,12 @@ static void nv_up(cmdarg_T *cap)
cap->arg = BACKWARD;
nv_page(cap);
} else {
- cap->oap->motion_type = MLINE;
- if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false)
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) {
clearopbeep(cap->oap);
- else if (cap->arg)
+ } else if (cap->arg) {
beginline(BL_WHITE | BL_FIX);
+ }
}
}
@@ -5110,23 +5114,24 @@ static void nv_down(cmdarg_T *cap)
/* <S-Down> is page down */
cap->arg = FORWARD;
nv_page(cap);
- } else
- /* In a quickfix window a <CR> jumps to the error under the cursor. */
- if (bt_quickfix(curbuf) && cap->cmdchar == CAR)
- if (curwin->w_llist_ref == NULL)
- do_cmdline_cmd(".cc"); /* quickfix window */
- else
- do_cmdline_cmd(".ll"); /* location list window */
- else {
- /* In the cmdline window a <CR> executes the command. */
- if (cmdwin_type != 0 && cap->cmdchar == CAR)
+ } else if (bt_quickfix(curbuf) && cap->cmdchar == CAR) {
+ // In a quickfix window a <CR> jumps to the error under the cursor.
+ if (curwin->w_llist_ref == NULL) {
+ do_cmdline_cmd(".cc"); // quickfix window
+ } else {
+ do_cmdline_cmd(".ll"); // location list window
+ }
+ } else {
+ // In the cmdline window a <CR> executes the command.
+ if (cmdwin_type != 0 && cap->cmdchar == CAR) {
cmdwin_result = CAR;
- else {
- cap->oap->motion_type = MLINE;
- if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false)
+ } else {
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false) {
clearopbeep(cap->oap);
- else if (cap->arg)
+ } else if (cap->arg) {
beginline(BL_WHITE | BL_FIX);
+ }
}
}
}
@@ -5152,9 +5157,10 @@ static void nv_gotofile(cmdarg_T *cap)
ptr = grab_file_name(cap->count1, &lnum);
if (ptr != NULL) {
- /* do autowrite if necessary */
- if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
- autowrite(curbuf, false);
+ // do autowrite if necessary
+ if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf)) {
+ (void)autowrite(curbuf, false);
+ }
setpcmark();
(void)do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
P_HID(curbuf) ? ECMD_HIDE : 0, curwin);
@@ -5186,7 +5192,7 @@ static void nv_end(cmdarg_T *cap)
*/
static void nv_dollar(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = true;
/* In virtual mode when off the edge of a line and an operator
* is pending (whew!) keep the cursor where it is.
@@ -5261,18 +5267,19 @@ static int normal_search(
{
int i;
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
cap->oap->use_reg_one = true;
curwin->w_set_curswant = true;
i = do_search(cap->oap, dir, pat, cap->count1,
- opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL);
- if (i == 0)
+ opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL);
+ if (i == 0) {
clearop(cap->oap);
- else {
- if (i == 2)
- cap->oap->motion_type = MLINE;
+ } else {
+ if (i == 2) {
+ cap->oap->motion_type = kMTLineWise;
+ }
curwin->w_cursor.coladd = 0;
if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped)
foldOpenCursor();
@@ -5299,10 +5306,10 @@ static void nv_csearch(cmdarg_T *cap)
else
t_cmd = false;
- cap->oap->motion_type = MCHAR;
- if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false)
+ cap->oap->motion_type = kMTCharWise;
+ if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) {
clearopbeep(cap->oap);
- else {
+ } else {
curwin->w_set_curswant = true;
/* Include a Tab for "tx" and for "dfx". */
if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
@@ -5334,7 +5341,7 @@ static void nv_brackets(cmdarg_T *cap)
int findc;
int c;
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
old_pos = curwin->w_cursor;
curwin->w_cursor.coladd = 0; /* TODO: don't do this for an error. */
@@ -5624,11 +5631,11 @@ static void nv_percent(cmdarg_T *cap)
linenr_T lnum = curwin->w_cursor.lnum;
cap->oap->inclusive = true;
- if (cap->count0) { /* {cnt}% : goto {cnt} percentage in file */
- if (cap->count0 > 100)
+ if (cap->count0) { // {cnt}% : goto {cnt} percentage in file
+ if (cap->count0 > 100) {
clearopbeep(cap->oap);
- else {
- cap->oap->motion_type = MLINE;
+ } else {
+ cap->oap->motion_type = kMTLineWise;
setpcmark();
/* Round up, so CTRL-G will give same value. Watch out for a
* large line count, the line number must not go negative! */
@@ -5642,8 +5649,8 @@ static void nv_percent(cmdarg_T *cap)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
beginline(BL_SOL | BL_FIX);
}
- } else { /* "%" : go to matching paren */
- cap->oap->motion_type = MCHAR;
+ } else { // "%" : go to matching paren
+ cap->oap->motion_type = kMTCharWise;
cap->oap->use_reg_one = true;
if ((pos = findmatch(cap->oap, NUL)) == NULL)
clearopbeep(cap->oap);
@@ -5668,7 +5675,7 @@ static void nv_percent(cmdarg_T *cap)
*/
static void nv_brace(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->use_reg_one = true;
/* The motion used to be inclusive for "(", but that is not what Vi does. */
cap->oap->inclusive = false;
@@ -5702,7 +5709,7 @@ static void nv_mark(cmdarg_T *cap)
*/
static void nv_findpar(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
cap->oap->use_reg_one = true;
curwin->w_set_curswant = true;
@@ -5806,14 +5813,11 @@ static void nv_replace(cmdarg_T *cap)
return;
}
- /*
- * Replacing with a TAB is done by edit() when it is complicated because
- * 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB.
- * Other characters are done below to avoid problems with things like
- * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
- */
- if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' &&
- (curbuf->b_p_et || p_sta)) {
+ // Replacing with a TAB is done by edit() when it is complicated because
+ // 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB.
+ // Other characters are done below to avoid problems with things like
+ // CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
+ if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta)) {
stuffnumReadbuff(cap->count1);
stuffcharReadbuff('R');
stuffcharReadbuff('\t');
@@ -6080,10 +6084,11 @@ static void nv_cursormark(cmdarg_T *cap, int flag, pos_T *pos)
else
check_cursor();
}
- cap->oap->motion_type = flag ? MLINE : MCHAR;
- if (cap->cmdchar == '`')
+ cap->oap->motion_type = flag ? kMTLineWise : kMTCharWise;
+ if (cap->cmdchar == '`') {
cap->oap->use_reg_one = true;
- cap->oap->inclusive = false; /* ignored if not MCHAR */
+ }
+ cap->oap->inclusive = false; // ignored if not kMTCharWise
curwin->w_set_curswant = true;
}
@@ -6560,7 +6565,7 @@ static void nv_g_cmd(cmdarg_T *cap)
if (!curwin->w_p_wrap
|| hasFolding(curwin->w_cursor.lnum, NULL, NULL)
) {
- oap->motion_type = MLINE;
+ oap->motion_type = kMTLineWise;
i = cursor_down(cap->count1, oap->op_type == OP_NOP);
} else
i = nv_screengo(oap, FORWARD, cap->count1);
@@ -6575,7 +6580,7 @@ static void nv_g_cmd(cmdarg_T *cap)
if (!curwin->w_p_wrap
|| hasFolding(curwin->w_cursor.lnum, NULL, NULL)
) {
- oap->motion_type = MLINE;
+ oap->motion_type = kMTLineWise;
i = cursor_up(cap->count1, oap->op_type == OP_NOP);
} else
i = nv_screengo(oap, BACKWARD, cap->count1);
@@ -6602,7 +6607,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case 'm':
case K_HOME:
case K_KHOME:
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = false;
if (curwin->w_p_wrap
&& curwin->w_width != 0
@@ -6635,7 +6640,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case '_':
/* "g_": to the last non-blank character in the line or <count> lines
* downward. */
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = true;
curwin->w_curswant = MAXCOL;
if (cursor_down(cap->count1 - 1,
@@ -6663,7 +6668,7 @@ static void nv_g_cmd(cmdarg_T *cap)
{
int col_off = curwin_col_off();
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = true;
if (curwin->w_p_wrap
&& curwin->w_width != 0
@@ -6725,7 +6730,7 @@ static void nv_g_cmd(cmdarg_T *cap)
*/
case 'e':
case 'E':
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
curwin->w_set_curswant = true;
oap->inclusive = true;
if (bckend_word(cap->count1, cap->nchar == 'E', false) == false)
@@ -7085,17 +7090,19 @@ static void set_op_var(int optype)
*/
static void nv_lineop(cmdarg_T *cap)
{
- cap->oap->motion_type = MLINE;
- if (cursor_down(cap->count1 - 1L, cap->oap->op_type == OP_NOP) == false)
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_down(cap->count1 - 1L, cap->oap->op_type == OP_NOP) == false) {
clearopbeep(cap->oap);
- else if ( (cap->oap->op_type == OP_DELETE /* only with linewise motions */
+ } else if ((cap->oap->op_type == OP_DELETE
+ // only with linewise motions
&& cap->oap->motion_force != 'v'
&& cap->oap->motion_force != Ctrl_V)
|| cap->oap->op_type == OP_LSHIFT
- || cap->oap->op_type == OP_RSHIFT)
+ || cap->oap->op_type == OP_RSHIFT) {
beginline(BL_SOL | BL_FIX);
- else if (cap->oap->op_type != OP_YANK) /* 'Y' does not move cursor */
+ } else if (cap->oap->op_type != OP_YANK) { // 'Y' does not move cursor
beginline(BL_WHITE | BL_FIX);
+ }
}
/*
@@ -7119,7 +7126,7 @@ static void nv_home(cmdarg_T *cap)
*/
static void nv_pipe(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
beginline(0);
if (cap->count0 > 0) {
@@ -7138,7 +7145,7 @@ static void nv_pipe(cmdarg_T *cap)
*/
static void nv_bck_word(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
curwin->w_set_curswant = true;
if (bck_word(cap->count1, cap->arg, false) == false)
@@ -7187,7 +7194,7 @@ static void nv_wordcmd(cmdarg_T *cap)
}
}
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
curwin->w_set_curswant = true;
if (word_end)
n = end_word(cap->count1, cap->arg, flag, false);
@@ -7238,7 +7245,7 @@ static void adjust_cursor(oparg_T *oap)
*/
static void nv_beginline(cmdarg_T *cap)
{
- cap->oap->motion_type = MCHAR;
+ cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
beginline(cap->arg);
if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
@@ -7317,7 +7324,7 @@ static void nv_goto(cmdarg_T *cap)
lnum = curbuf->b_ml.ml_line_count;
else
lnum = 1L;
- cap->oap->motion_type = MLINE;
+ cap->oap->motion_type = kMTLineWise;
setpcmark();
/* When a count is given, use it instead of the default lnum */
@@ -7803,7 +7810,7 @@ static void get_op_vcol(
return;
}
- oap->motion_type = MBLOCK;
+ oap->motion_type = kMTBlockWise;
// prevent from moving onto a trail byte
if (has_mbyte) {
diff --git a/src/nvim/normal.h b/src/nvim/normal.h
index 95619c7ef6..51170105ed 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -10,18 +10,29 @@
#define FIND_STRING 2 /* find any string (WORD) */
#define FIND_EVAL 4 /* include "->", "[]" and "." */
+/// Motion types, used for operators and for yank/delete registers.
+///
+/// The three valid numerical values must not be changed, as they
+/// are used in external communication and serialization.
+typedef enum {
+ kMTCharWise = 0, ///< character-wise movement/register
+ kMTLineWise = 1, ///< line-wise movement/register
+ kMTBlockWise = 2, ///< block-wise movement/register
+ kMTUnknown = -1 ///< Unknown or invalid motion type
+} MotionType;
+
/*
* Arguments for operators.
*/
typedef struct oparg_S {
int op_type; // current pending operator type
int regname; // register to use for the operator
- int motion_type; // type of the current cursor motion
+ MotionType motion_type; // type of the current cursor motion
int motion_force; // force motion type: 'v', 'V' or CTRL-V
bool use_reg_one; // true if delete uses reg 1 even when not
// linewise
bool inclusive; // true if char motion is inclusive (only
- // valid when motion_type is MCHAR)
+ // valid when motion_type is kMTCharWise)
bool end_adjusted; // backuped b_op_end one char (only used by
// do_format())
pos_T start; // start of the operator
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 601890d133..a6ff68a8f8 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -191,7 +191,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
(linenr_T)(oap->end.lnum + 1)) == FAIL)
return;
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
block_col = curwin->w_cursor.col;
}
@@ -199,7 +199,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
first_char = *get_cursor_line_ptr();
if (first_char == NUL) { // empty line
curwin->w_cursor.col = 0;
- } else if (oap->motion_type == MBLOCK) {
+ } else if (oap->motion_type == kMTBlockWise) {
shift_block(oap, amount);
} else if (first_char != '#' || !preprocs_left()) {
// Move the line right if it doesn't start with '#', 'smartindent'
@@ -213,7 +213,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
/* The cursor line is not in a closed fold */
foldOpenCursor();
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
curwin->w_cursor.lnum = oap->start.lnum;
curwin->w_cursor.col = block_col;
} else if (curs_top) { /* put cursor on first line, for ">>" */
@@ -811,17 +811,17 @@ yankreg_T *copy_register(int name)
return copy;
}
-/*
- * return TRUE if the current yank register has type MLINE
- */
-int yank_register_mline(int regname)
+/// check if the current yank register has kMTLineWise register type
+bool yank_register_mline(int regname)
{
- if (regname != 0 && !valid_yank_reg(regname, false))
- return FALSE;
- if (regname == '_') /* black hole is always empty */
- return FALSE;
+ if (regname != 0 && !valid_yank_reg(regname, false)) {
+ return false;
+ }
+ if (regname == '_') { // black hole is always empty
+ return false;
+ }
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
- return reg->y_type == MLINE;
+ return reg->y_type == kMTLineWise;
}
/*
@@ -919,7 +919,7 @@ static int stuff_yank(int regname, char_u *p)
reg->y_array = (char_u **)xmalloc(sizeof(char_u *));
reg->y_array[0] = p;
reg->y_size = 1;
- reg->y_type = MCHAR; /* used to be MLINE, why? */
+ reg->y_type = kMTCharWise;
}
reg->timestamp = os_time();
return OK;
@@ -1011,8 +1011,8 @@ do_execreg (
for (i = reg->y_size - 1; i >= 0; i--) {
char_u *escaped;
- /* insert NL between lines and after last line if type is MLINE */
- if (reg->y_type == MLINE || i < reg->y_size - 1
+ // insert NL between lines and after last line if type is kMTLineWise
+ if (reg->y_type == kMTLineWise || i < reg->y_size - 1
|| addcr) {
if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL)
return FAIL;
@@ -1137,12 +1137,11 @@ insert_reg (
else {
for (i = 0; i < reg->y_size; i++) {
stuffescaped(reg->y_array[i], literally);
- /*
- * Insert a newline between lines and after last line if
- * y_type is MLINE.
- */
- if (reg->y_type == MLINE || i < reg->y_size - 1)
+ // Insert a newline between lines and after last line if
+ // y_type is kMTLineWise.
+ if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
stuffcharReadbuff('\n');
+ }
}
}
}
@@ -1283,9 +1282,9 @@ bool cmdline_paste_reg(int regname, bool literally, bool remcr)
for (i = 0; i < reg->y_size; i++) {
cmdline_paste_str(reg->y_array[i], literally);
- // Insert ^M between lines and after last line if type is MLINE.
+ // Insert ^M between lines and after last line if type is kMTLineWise.
// Don't do this when "remcr" is true.
- if ((reg->y_type == MLINE || i < reg->y_size - 1) && !remcr) {
+ if ((reg->y_type == kMTLineWise || i < reg->y_size - 1) && !remcr) {
cmdline_paste_str((char_u *)"\r", literally);
}
@@ -1329,10 +1328,10 @@ int op_delete(oparg_T *oap)
/*
* Imitate the strange Vi behaviour: If the delete spans more than one
- * line and motion_type == MCHAR and the result is a blank line, make the
+ * line and motion_type == kMTCharWise and the result is a blank line, make the
* delete linewise. Don't do this for the change command or Visual mode.
*/
- if (oap->motion_type == MCHAR
+ if (oap->motion_type == kMTCharWise
&& !oap->is_VIsual
&& oap->line_count > 1
&& oap->motion_force == NUL
@@ -1341,15 +1340,16 @@ int op_delete(oparg_T *oap)
if (*ptr != NUL)
ptr += oap->inclusive;
ptr = skipwhite(ptr);
- if (*ptr == NUL && inindent(0))
- oap->motion_type = MLINE;
+ if (*ptr == NUL && inindent(0)) {
+ oap->motion_type = kMTLineWise;
+ }
}
/*
* Check for trying to delete (e.g. "D") in an empty line.
* Note: For the change operator it is ok.
*/
- if (oap->motion_type != MLINE
+ if (oap->motion_type != kMTLineWise
&& oap->line_count == 1
&& oap->op_type == OP_DELETE
&& *ml_get(oap->start.lnum) == NUL) {
@@ -1385,7 +1385,7 @@ int op_delete(oparg_T *oap)
* Put deleted text into register 1 and shift number registers if the
* delete contains a line break, or when a regname has been specified.
*/
- if (oap->regname != 0 || oap->motion_type == MLINE
+ if (oap->regname != 0 || oap->motion_type == kMTLineWise
|| oap->line_count > 1 || oap->use_reg_one) {
free_register(&y_regs[9]); /* free register "9 */
for (n = 9; n > 1; n--)
@@ -1398,7 +1398,7 @@ int op_delete(oparg_T *oap)
/* Yank into small delete register when no named register specified
* and the delete is within one line. */
- if (oap->regname == 0 && oap->motion_type != MLINE
+ if (oap->regname == 0 && oap->motion_type != kMTLineWise
&& oap->line_count == 1) {
reg = get_yank_register('-', YREG_YANK);
op_yank_reg(oap, false, reg, false);
@@ -1414,7 +1414,7 @@ int op_delete(oparg_T *oap)
/*
* block mode delete
*/
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
if (u_save((linenr_T)(oap->start.lnum - 1),
(linenr_T)(oap->end.lnum + 1)) == FAIL) {
return FAIL;
@@ -1452,9 +1452,9 @@ int op_delete(oparg_T *oap)
check_cursor_col();
changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
- oap->end.lnum + 1, 0L);
- oap->line_count = 0; /* no lines deleted */
- } else if (oap->motion_type == MLINE) {
+ oap->end.lnum + 1, 0L);
+ oap->line_count = 0; // no lines deleted
+ } else if (oap->motion_type == kMTLineWise) {
if (oap->op_type == OP_CHANGE) {
/* Delete the lines except the first one. Temporarily move the
* cursor to the next line. Save the current line number, if the
@@ -1582,7 +1582,7 @@ int op_delete(oparg_T *oap)
msgmore(curbuf->b_ml.ml_line_count - old_lcount);
setmarks:
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
curbuf->b_op_end.lnum = oap->end.lnum;
curbuf->b_op_end.col = oap->start.col;
} else
@@ -1643,7 +1643,7 @@ int op_replace(oparg_T *oap, int c)
/*
* block mode replace
*/
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
bd.is_MAX = (curwin->w_curswant == MAXCOL);
for (; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) {
curwin->w_cursor.col = 0; /* make sure cursor position is valid */
@@ -1732,10 +1732,8 @@ int op_replace(oparg_T *oap, int c)
}
}
} else {
- /*
- * MCHAR and MLINE motion replace.
- */
- if (oap->motion_type == MLINE) {
+ // Characterwise or linewise motion replace.
+ if (oap->motion_type == kMTLineWise) {
oap->start.col = 0;
curwin->w_cursor.col = 0;
oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
@@ -1825,8 +1823,8 @@ void op_tilde(oparg_T *oap)
return;
pos = oap->start;
- if (oap->motion_type == MBLOCK) { // Visual block mode
- for (; pos.lnum <= oap->end.lnum; ++pos.lnum) {
+ if (oap->motion_type == kMTBlockWise) { // Visual block mode
+ for (; pos.lnum <= oap->end.lnum; pos.lnum++) {
int one_change;
block_prep(oap, &bd, pos.lnum, FALSE);
@@ -1837,8 +1835,8 @@ void op_tilde(oparg_T *oap)
}
if (did_change)
changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
- } else { /* not block mode */
- if (oap->motion_type == MLINE) {
+ } else { // not block mode
+ if (oap->motion_type == kMTLineWise) {
oap->start.col = 0;
pos.col = 0;
oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
@@ -1988,7 +1986,7 @@ void op_insert(oparg_T *oap, long count1)
curwin->w_cursor.lnum = oap->start.lnum;
update_screen(INVERTED);
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
// When 'virtualedit' is used, need to insert the extra spaces before
// doing block_prep(). When only "block" is used, virtual edit is
// already disabled, but still need it when calling
@@ -2014,7 +2012,7 @@ void op_insert(oparg_T *oap, long count1)
}
if (oap->op_type == OP_APPEND) {
- if (oap->motion_type == MBLOCK
+ if (oap->motion_type == kMTBlockWise
&& curwin->w_cursor.coladd == 0
) {
/* Move the cursor to the character right of the block. */
@@ -2048,8 +2046,8 @@ void op_insert(oparg_T *oap, long count1)
// When a tab was inserted, and the characters in front of the tab
// have been converted to a tab as well, the column of the cursor
// might have actually been reduced, so need to adjust here. */
- if (t1.lnum == curbuf->b_op_start_orig.lnum &&
- lt(curbuf->b_op_start_orig, t1)) {
+ if (t1.lnum == curbuf->b_op_start_orig.lnum
+ && lt(curbuf->b_op_start_orig, t1)) {
oap->start = curbuf->b_op_start_orig;
}
@@ -2059,7 +2057,7 @@ void op_insert(oparg_T *oap, long count1)
if (curwin->w_cursor.lnum != oap->start.lnum || got_int)
return;
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
struct block_def bd2;
/* The user may have moved the cursor before inserting something, try
@@ -2146,7 +2144,7 @@ int op_change(oparg_T *oap)
struct block_def bd;
l = oap->start.col;
- if (oap->motion_type == MLINE) {
+ if (oap->motion_type == kMTLineWise) {
l = 0;
if (!p_paste && curbuf->b_p_si
&& !curbuf->b_p_cin
@@ -2168,7 +2166,7 @@ int op_change(oparg_T *oap)
// check for still on same line (<CR> in inserted text meaningless)
// skip blank lines too
- if (oap->motion_type == MBLOCK) {
+ if (oap->motion_type == kMTBlockWise) {
// Add spaces before getting the current line length.
if (virtual_op && (curwin->w_cursor.coladd > 0
|| gchar_cursor() == NUL)) {
@@ -2180,8 +2178,9 @@ int op_change(oparg_T *oap)
bd.textcol = curwin->w_cursor.col;
}
- if (oap->motion_type == MLINE)
+ if (oap->motion_type == kMTLineWise) {
fix_indent();
+ }
retval = edit(NUL, FALSE, (linenr_T)1);
@@ -2190,7 +2189,7 @@ int op_change(oparg_T *oap)
* block.
* Don't repeat the insert when Insert mode ended with CTRL-C.
*/
- if (oap->motion_type == MBLOCK
+ if (oap->motion_type == kMTBlockWise
&& oap->start.lnum != oap->end.lnum && !got_int) {
// Auto-indenting may have changed the indent. If the cursor was past
// the indent, exclude that indent change from the inserted text.
@@ -2318,7 +2317,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
char_u **new_ptr;
linenr_T lnum; /* current line number */
long j;
- int yanktype = oap->motion_type;
+ MotionType yank_type = oap->motion_type;
long yanklines = oap->line_count;
linenr_T yankendlnum = oap->end.lnum;
char_u *p;
@@ -2336,19 +2335,19 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
* If the cursor was in column 1 before and after the movement, and the
* operator is not inclusive, the yank is always linewise.
*/
- if (oap->motion_type == MCHAR
+ if (oap->motion_type == kMTCharWise
&& oap->start.col == 0
&& !oap->inclusive
&& (!oap->is_VIsual || *p_sel == 'o')
&& oap->end.col == 0
&& yanklines > 1) {
- yanktype = MLINE;
- --yankendlnum;
- --yanklines;
+ yank_type = kMTLineWise;
+ yankendlnum--;
+ yanklines--;
}
reg->y_size = yanklines;
- reg->y_type = yanktype; /* set the yank register type */
+ reg->y_type = yank_type; // set the yank register type
reg->y_width = 0;
reg->y_array = xcalloc(yanklines, sizeof(char_u *));
reg->additional_data = NULL;
@@ -2357,7 +2356,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
y_idx = 0;
lnum = oap->start.lnum;
- if (yanktype == MBLOCK) {
+ if (yank_type == kMTBlockWise) {
// Visual block mode
reg->y_width = oap->end_vcol - oap->start_vcol;
@@ -2367,16 +2366,16 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
for (; lnum <= yankendlnum; lnum++, y_idx++) {
switch (reg->y_type) {
- case MBLOCK:
- block_prep(oap, &bd, lnum, FALSE);
+ case kMTBlockWise:
+ block_prep(oap, &bd, lnum, false);
yank_copy_line(reg, &bd, y_idx);
break;
- case MLINE:
+ case kMTLineWise:
reg->y_array[y_idx] = vim_strsave(ml_get(lnum));
break;
- case MCHAR:
+ case kMTCharWise:
{
colnr_T startcol = 0, endcol = MAXCOL;
int is_oneChar = FALSE;
@@ -2437,7 +2436,9 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
yank_copy_line(reg, &bd, y_idx);
break;
}
- /* NOTREACHED */
+ // NOTREACHED
+ case kMTUnknown:
+ assert(false);
}
}
@@ -2448,12 +2449,15 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
xfree(curr->y_array);
curr->y_array = new_ptr;
- if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */
- curr->y_type = MLINE;
+ if (yank_type == kMTLineWise) {
+ // kMTLineWise overrides kMTCharWise and kMTBlockWise
+ curr->y_type = kMTLineWise;
+ }
- /* Concatenate the last line of the old block with the first line of
- * the new block, unless being Vi compatible. */
- if (curr->y_type == MCHAR && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) {
+ // Concatenate the last line of the old block with the first line of
+ // the new block, unless being Vi compatible.
+ if (curr->y_type == kMTCharWise
+ && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) {
pnew = xmalloc(STRLEN(curr->y_array[curr->y_size - 1])
+ STRLEN(reg->y_array[0]) + 1);
STRCPY(pnew, curr->y_array[--j]);
@@ -2473,7 +2477,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
redraw_later(SOME_VALID); // cursor moved to start
}
if (message) { // Display message about yank?
- if (yanktype == MCHAR && yanklines == 1) {
+ if (yank_type == kMTCharWise && yanklines == 1) {
yanklines = 0;
}
// Some versions of Vi use ">=" here, some don't...
@@ -2481,12 +2485,12 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
// redisplay now, so message is not deleted
update_topline_redraw();
if (yanklines == 1) {
- if (yanktype == MBLOCK) {
+ if (yank_type == kMTBlockWise) {
MSG(_("block of 1 line yanked"));
} else {
MSG(_("1 line yanked"));
}
- } else if (yanktype == MBLOCK) {
+ } else if (yank_type == kMTBlockWise) {
smsg(_("block of %" PRId64 " lines yanked"),
(int64_t)yanklines);
} else {
@@ -2500,7 +2504,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
*/
curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end;
- if (yanktype == MLINE) {
+ if (yank_type == kMTLineWise) {
curbuf->b_op_start.col = 0;
curbuf->b_op_end.col = MAXCOL;
}
@@ -2590,8 +2594,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
int totlen = 0; /* init for gcc */
linenr_T lnum;
colnr_T col;
- long i; /* index in y_array[] */
- int y_type;
+ long i; // index in y_array[]
+ MotionType y_type;
long y_size;
int oldlen;
long y_width = 0;
@@ -2652,7 +2656,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
if (insert_string != NULL) {
- y_type = MCHAR;
+ y_type = kMTCharWise;
if (regname == '=') {
/* For the = register we need to split the string at NL
* characters.
@@ -2671,7 +2675,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
++ptr;
/* A trailing '\n' makes the register linewise. */
if (*ptr == NUL) {
- y_type = MLINE;
+ y_type = kMTLineWise;
break;
}
}
@@ -2712,7 +2716,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
return;
}
- if (y_type == MLINE) {
+ if (y_type == kMTLineWise) {
if (flags & PUT_LINE_SPLIT) {
// "p" or "P" in Visual mode: split the lines to put the text in
// between.
@@ -2746,8 +2750,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */
}
- if (flags & PUT_LINE) /* :put command or "p" in Visual line mode. */
- y_type = MLINE;
+ if (flags & PUT_LINE) { // :put command or "p" in Visual line mode.
+ y_type = kMTLineWise;
+ }
if (y_size == 0 || y_array == NULL) {
EMSG2(_("E353: Nothing in register %s"),
@@ -2755,13 +2760,13 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
goto end;
}
- if (y_type == MBLOCK) {
+ if (y_type == kMTBlockWise) {
lnum = curwin->w_cursor.lnum + y_size + 1;
if (lnum > curbuf->b_ml.ml_line_count)
lnum = curbuf->b_ml.ml_line_count + 1;
if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
goto end;
- } else if (y_type == MLINE) {
+ } else if (y_type == kMTLineWise) {
lnum = curwin->w_cursor.lnum;
/* Correct line number for closed fold. Don't move the cursor yet,
* u_save() uses it. */
@@ -2785,7 +2790,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
yanklen = (int)STRLEN(y_array[0]);
- if (ve_flags == VE_ALL && y_type == MCHAR) {
+ if (ve_flags == VE_ALL && y_type == kMTCharWise) {
if (gchar_cursor() == TAB) {
/* Don't need to insert spaces when "p" on the last position of a
* tab or "P" on the first position. */
@@ -2805,7 +2810,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
/*
* Block mode
*/
- if (y_type == MBLOCK) {
+ if (y_type == kMTBlockWise) {
char c = gchar_cursor();
colnr_T endcol2 = 0;
@@ -2953,12 +2958,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
} else
curwin->w_cursor.lnum = lnum;
} else {
- /*
- * Character or Line mode
- */
- if (y_type == MCHAR) {
- /* if type is MCHAR, FORWARD is the same as BACKWARD on the next
- * char */
+ // Character or Line mode
+ if (y_type == kMTCharWise) {
+ // if type is kMTCharWise, FORWARD is the same as BACKWARD on the next
+ // char
if (dir == FORWARD && gchar_cursor() != NUL) {
if (has_mbyte) {
int bytelen = (*mb_ptr2len)(get_cursor_pos_ptr());
@@ -2989,7 +2992,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
/*
* simple case: insert into current line
*/
- if (y_type == MCHAR && y_size == 1) {
+ if (y_type == kMTCharWise && y_size == 1) {
do {
totlen = count * yanklen;
if (totlen > 0) {
@@ -3024,18 +3027,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
++curwin->w_cursor.col;
changed_bytes(lnum, col);
} else {
- /*
- * Insert at least one line. When y_type is MCHAR, break the first
- * line in two.
- */
- for (cnt = 1; cnt <= count; ++cnt) {
+ // Insert at least one line. When y_type is kMTCharWise, break the first
+ // line in two.
+ for (cnt = 1; cnt <= count; cnt++) {
i = 0;
- if (y_type == MCHAR) {
- /*
- * Split the current line in two at the insert position.
- * First insert y_array[size - 1] in front of second line.
- * Then append y_array[0] to first line.
- */
+ if (y_type == kMTCharWise) {
+ // Split the current line in two at the insert position.
+ // First insert y_array[size - 1] in front of second line.
+ // Then append y_array[0] to first line.
lnum = new_cursor.lnum;
ptr = ml_get(lnum) + col;
totlen = (int)STRLEN(y_array[y_size - 1]);
@@ -3059,10 +3058,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
for (; i < y_size; i++) {
- if ((y_type != MCHAR || i < y_size - 1)
- && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
- == FAIL)
+ if ((y_type != kMTCharWise || i < y_size - 1)
+ && ml_append(lnum, y_array[i], (colnr_T)0, false)
+ == FAIL) {
goto error;
+ }
lnum++;
++nr_lines;
if (flags & PUT_FIXINDENT) {
@@ -3091,22 +3091,23 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
error:
- /* Adjust marks. */
- if (y_type == MLINE) {
+ // Adjust marks.
+ if (y_type == kMTLineWise) {
curbuf->b_op_start.col = 0;
if (dir == FORWARD)
curbuf->b_op_start.lnum++;
}
- mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
- (linenr_T)MAXLNUM, nr_lines, 0L);
+ mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise),
+ (linenr_T)MAXLNUM, nr_lines, 0L);
- /* note changed text for displaying and folding */
- if (y_type == MCHAR)
+ // note changed text for displaying and folding
+ if (y_type == kMTCharWise) {
changed_lines(curwin->w_cursor.lnum, col,
- curwin->w_cursor.lnum + 1, nr_lines);
- else
+ curwin->w_cursor.lnum + 1, nr_lines);
+ } else {
changed_lines(curbuf->b_op_start.lnum, 0,
- curbuf->b_op_start.lnum, nr_lines);
+ curbuf->b_op_start.lnum, nr_lines);
+ }
/* put '] mark at last inserted character */
curbuf->b_op_end.lnum = lnum;
@@ -3122,19 +3123,20 @@ error:
curwin->w_cursor.lnum = lnum;
beginline(BL_WHITE | BL_FIX);
} else if (flags & PUT_CURSEND) {
- /* put cursor after inserted text */
- if (y_type == MLINE) {
- if (lnum >= curbuf->b_ml.ml_line_count)
+ // put cursor after inserted text
+ if (y_type == kMTLineWise) {
+ if (lnum >= curbuf->b_ml.ml_line_count) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- else
+ } else {
curwin->w_cursor.lnum = lnum + 1;
+ }
curwin->w_cursor.col = 0;
} else {
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = col;
}
- } else if (y_type == MLINE) {
- /* put cursor on first non-blank in first inserted line */
+ } else if (y_type == kMTLineWise) {
+ // put cursor on first non-blank in first inserted line
curwin->w_cursor.col = 0;
if (dir == FORWARD)
++curwin->w_cursor.lnum;
@@ -3187,11 +3189,9 @@ void adjust_cursor_eol(void)
*/
int preprocs_left(void)
{
- return
- (curbuf->b_p_si && !curbuf->b_p_cin) ||
- (curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE)
- && curbuf->b_ind_hash_comment == 0)
- ;
+ return ((curbuf->b_p_si && !curbuf->b_p_cin)
+ || (curbuf->b_p_cin && in_cinkeys('#', ' ', true)
+ && curbuf->b_ind_hash_comment == 0));
}
/* Return the character name of the register with the given number */
@@ -3273,9 +3273,10 @@ void ex_display(exarg_T *eap)
p += clen - 1;
}
}
- if (n > 1 && yb->y_type == MLINE)
+ if (n > 1 && yb->y_type == kMTLineWise) {
MSG_PUTS_ATTR("^J", attr);
- ui_flush(); /* show one line at a time */
+ }
+ ui_flush(); // show one line at a time
}
os_breakcheck();
}
@@ -4265,18 +4266,18 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
}
pos = oap->start;
- for (; pos.lnum <= oap->end.lnum; ++pos.lnum) {
- if (oap->motion_type == MBLOCK) {
+ for (; pos.lnum <= oap->end.lnum; pos.lnum++) {
+ if (oap->motion_type == kMTBlockWise) {
// Visual block mode
block_prep(oap, &bd, pos.lnum, false);
pos.col = bd.textcol;
length = bd.textlen;
- } else if (oap->motion_type == MLINE) {
+ } else if (oap->motion_type == kMTLineWise) {
curwin->w_cursor.col = 0;
pos.col = 0;
length = (colnr_T)STRLEN(ml_get(pos.lnum));
} else {
- // oap->motion_type == MCHAR
+ // oap->motion_type == kMTCharWise
if (!oap->inclusive) {
dec(&(oap->end));
}
@@ -4396,8 +4397,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (dobin
&& dohex
&& !((col > 0
- && (ptr[col] == 'X' ||
- ptr[col] == 'x')
+ && (ptr[col] == 'X' || ptr[col] == 'x')
&& ptr[col - 1] == '0'
&& ascii_isxdigit(ptr[col + 1])))) {
// In case of binary/hexadecimal pattern overlap match, rescan
@@ -4411,17 +4411,15 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if ((dohex
&& col > 0
- && (ptr[col] == 'X'
- || ptr[col] == 'x')
+ && (ptr[col] == 'X' || ptr[col] == 'x')
&& ptr[col - 1] == '0'
- && ascii_isxdigit(ptr[col + 1])) ||
- (dobin
- && col > 0
- && (ptr[col] == 'B'
- || ptr[col] == 'b')
- && ptr[col - 1] == '0'
- && ascii_isbdigit(ptr[col + 1]))) {
- // Found hexadecimal or binary number, move to its start.
+ && ascii_isxdigit(ptr[col + 1]))
+ || (dobin
+ && col > 0
+ && (ptr[col] == 'B' || ptr[col] == 'b')
+ && ptr[col - 1] == '0'
+ && ascii_isbdigit(ptr[col + 1]))) {
+ // Found hexadecimal or binary number, move to its start.
col--;
} else {
// Search forward and then backward to find the start of number.
@@ -4442,8 +4440,8 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
if (visual) {
- while (ptr[col] != NUL && length > 0 && !ascii_isdigit(ptr[col]) &&
- !(doalp && ASCII_ISALPHA(ptr[col]))) {
+ while (ptr[col] != NUL && length > 0 && !ascii_isdigit(ptr[col])
+ && !(doalp && ASCII_ISALPHA(ptr[col]))) {
col++;
length--;
}
@@ -4605,8 +4603,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
*ptr++ = '0';
length--;
}
- if (pre == 'b' || pre == 'B' ||
- pre == 'x' || pre == 'X') {
+ if (pre == 'b' || pre == 'B' || pre == 'x' || pre == 'X') {
*ptr++ = pre;
length--;
}
@@ -4679,64 +4676,65 @@ theend:
/*
* Return the type of a register.
* Used for getregtype()
- * Returns MAUTO for error.
+ * Returns kMTUnknown for error.
*/
-char_u get_reg_type(int regname, colnr_T *reg_width)
+MotionType get_reg_type(int regname, colnr_T *reg_width)
{
switch (regname) {
- case '%': /* file name */
- case '#': /* alternate file name */
- case '=': /* expression */
- case ':': /* last command line */
- case '/': /* last search-pattern */
- case '.': /* last inserted text */
- case Ctrl_F: /* Filename under cursor */
- case Ctrl_P: /* Path under cursor, expand via "path" */
- case Ctrl_W: /* word under cursor */
- case Ctrl_A: /* WORD (mnemonic All) under cursor */
- case '_': /* black hole: always empty */
- return MCHAR;
+ case '%': // file name
+ case '#': // alternate file name
+ case '=': // expression
+ case ':': // last command line
+ case '/': // last search-pattern
+ case '.': // last inserted text
+ case Ctrl_F: // Filename under cursor
+ case Ctrl_P: // Path under cursor, expand via "path"
+ case Ctrl_W: // word under cursor
+ case Ctrl_A: // WORD (mnemonic All) under cursor
+ case '_': // black hole: always empty
+ return kMTCharWise;
}
- if (regname != NUL && !valid_yank_reg(regname, false))
- return MAUTO;
+ if (regname != NUL && !valid_yank_reg(regname, false)) {
+ return kMTUnknown;
+ }
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
if (reg->y_array != NULL) {
- if (reg_width != NULL && reg->y_type == MBLOCK) {
+ if (reg_width != NULL && reg->y_type == kMTBlockWise) {
*reg_width = reg->y_width;
}
return reg->y_type;
}
- return MAUTO;
+ return kMTUnknown;
}
/// Format the register type as a string.
///
/// @param reg_type The register type.
-/// @param reg_width The width, only used if "reg_type" is MBLOCK.
+/// @param reg_width The width, only used if "reg_type" is kMTBlockWise.
/// @param[out] buf Buffer to store formatted string. The allocated size should
/// be at least NUMBUFLEN+2 to always fit the value.
/// @param buf_len The allocated size of the buffer.
-void format_reg_type(char_u reg_type, colnr_T reg_width,
- char* buf, size_t buf_len)
+void format_reg_type(MotionType reg_type, colnr_T reg_width,
+ char *buf, size_t buf_len)
FUNC_ATTR_NONNULL_ALL
{
assert(buf_len > 1);
switch (reg_type) {
- case MLINE:
+ case kMTLineWise:
buf[0] = 'V';
buf[1] = NUL;
break;
- case MCHAR:
+ case kMTCharWise:
buf[0] = 'v';
buf[1] = NUL;
break;
- case MBLOCK:
+ case kMTBlockWise:
snprintf(buf, buf_len, CTRL_V_STR "%" PRIdCOLNR, reg_width + 1);
break;
- case MAUTO:
+ case kMTUnknown:
buf[0] = NUL;
break;
}
@@ -4821,10 +4819,11 @@ void *get_reg_contents(int regname, int flags)
len += STRLEN(reg->y_array[i]);
/*
* Insert a newline between lines and after last line if
- * y_type is MLINE.
+ * y_type is kMTLineWise.
*/
- if (reg->y_type == MLINE || i < reg->y_size - 1)
- ++len;
+ if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
+ len++;
+ }
}
retval = xmalloc(len + 1);
@@ -4839,10 +4838,11 @@ void *get_reg_contents(int regname, int flags)
/*
* Insert a NL between lines and after the last line if y_type is
- * MLINE.
+ * kMTLineWise.
*/
- if (reg->y_type == MLINE || i < reg->y_size - 1)
+ if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
retval[len++] = '\n';
+ }
}
retval[len] = NUL;
@@ -4883,11 +4883,12 @@ static void finish_write_reg(int name, yankreg_T *reg, yankreg_T *old_y_previous
void write_reg_contents(int name, const char_u *str, ssize_t len,
int must_append)
{
- write_reg_contents_ex(name, str, len, must_append, MAUTO, 0L);
+ write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L);
}
void write_reg_contents_lst(int name, char_u **strings, int maxlen,
- bool must_append, int yank_type, long block_len)
+ bool must_append, MotionType yank_type,
+ long block_len)
{
if (name == '/' || name == '=') {
char_u *s = strings[0];
@@ -4933,13 +4934,13 @@ void write_reg_contents_lst(int name, char_u **strings, int maxlen,
/// contents of the register. Note that regardless of
/// `must_append`, this function will append when `name`
/// is an uppercase letter.
-/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
+/// @param yank_type The motion type (kMTUnknown to auto detect)
/// @param block_len width of visual block
void write_reg_contents_ex(int name,
const char_u *str,
ssize_t len,
bool must_append,
- int yank_type,
+ MotionType yank_type,
long block_len)
{
if (len < 0) {
@@ -5013,24 +5014,24 @@ void write_reg_contents_ex(int name,
/// When the register is not empty, the string is appended.
///
/// @param y_ptr pointer to yank register
-/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
+/// @param yank_type The motion type (kMTUnknown to auto detect)
/// @param str string or list of strings to put in register
/// @param len length of the string (Ignored when str_list=true.)
/// @param blocklen width of visual block, or -1 for "I don't know."
/// @param str_list True if str is `char_u **`.
-static void str_to_reg(yankreg_T *y_ptr, int yank_type, const char_u *str,
- size_t len, colnr_T blocklen, bool str_list)
+static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type,
+ const char_u *str, size_t len, colnr_T blocklen,
+ bool str_list)
FUNC_ATTR_NONNULL_ALL
{
if (y_ptr->y_array == NULL) { // NULL means empty register
y_ptr->y_size = 0;
}
- int type = yank_type; // MCHAR, MLINE or MBLOCK
- if (yank_type == MAUTO) {
- type = ((str_list ||
- (len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)))
- ? MLINE : MCHAR);
+ if (yank_type == kMTUnknown) {
+ yank_type = ((str_list
+ || (len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)))
+ ? kMTLineWise : kMTCharWise);
}
size_t newlines = 0;
@@ -5044,11 +5045,11 @@ static void str_to_reg(yankreg_T *y_ptr, int yank_type, const char_u *str,
}
} else {
newlines = memcnt(str, '\n', len);
- if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
+ if (yank_type == kMTCharWise || len == 0 || str[len - 1] != '\n') {
extraline = 1;
++newlines; // count extra newline at the end
}
- if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR) {
+ if (y_ptr->y_size > 0 && y_ptr->y_type == kMTCharWise) {
append = true;
--newlines; // uncount newline when appending first line
}
@@ -5101,11 +5102,11 @@ static void str_to_reg(yankreg_T *y_ptr, int yank_type, const char_u *str,
memchrsub(pp[lnum], NUL, '\n', s_len);
}
}
- y_ptr->y_type = type;
+ y_ptr->y_type = yank_type;
y_ptr->y_size = lnum;
set_yreg_additional_data(y_ptr, NULL);
y_ptr->timestamp = os_time();
- if (type == MBLOCK) {
+ if (yank_type == kMTBlockWise) {
y_ptr->y_width = (blocklen == -1 ? (colnr_T) maxlen - 1 : blocklen);
} else {
y_ptr->y_width = 0;
@@ -5218,7 +5219,7 @@ void cursor_pos_info(void)
/* Make 'sbr' empty for a moment to get the correct size. */
p_sbr = empty_option;
oparg.is_VIsual = true;
- oparg.motion_type = MBLOCK;
+ oparg.motion_type = kMTBlockWise;
oparg.op_type = OP_NOP;
getvcols(curwin, &min_pos, &max_pos,
&oparg.start_vcol, &oparg.end_vcol);
@@ -5473,16 +5474,16 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
}
switch (regtype[0]) {
case 0:
- reg->y_type = MAUTO;
+ reg->y_type = kMTUnknown;
break;
case 'v': case 'c':
- reg->y_type = MCHAR;
+ reg->y_type = kMTCharWise;
break;
case 'V': case 'l':
- reg->y_type = MLINE;
+ reg->y_type = kMTLineWise;
break;
case 'b': case Ctrl_V:
- reg->y_type = MBLOCK;
+ reg->y_type = kMTBlockWise;
break;
default:
goto err;
@@ -5490,7 +5491,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
} else {
lines = res;
// provider did not specify regtype, calculate it below
- reg->y_type = MAUTO;
+ reg->y_type = kMTUnknown;
}
reg->y_array = xcalloc(lines->lv_len, sizeof(uint8_t *));
@@ -5511,20 +5512,20 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) {
// a known-to-be charwise yank might have a final linebreak
// but otherwise there is no line after the final newline
- if (reg->y_type != MCHAR) {
+ if (reg->y_type != kMTCharWise) {
xfree(reg->y_array[reg->y_size-1]);
reg->y_size--;
- if (reg->y_type == MAUTO) {
- reg->y_type = MLINE;
+ if (reg->y_type == kMTUnknown) {
+ reg->y_type = kMTLineWise;
}
}
} else {
- if (reg->y_type == MAUTO) {
- reg->y_type = MCHAR;
+ if (reg->y_type == kMTUnknown) {
+ reg->y_type = kMTCharWise;
}
}
- if (reg->y_type == MBLOCK) {
+ if (reg->y_type == kMTBlockWise) {
int maxlen = 0;
for (int i = 0; i < reg->y_size; i++) {
int rowlen = STRLEN(reg->y_array[i]);
@@ -5573,17 +5574,19 @@ static void set_clipboard(int name, yankreg_T *reg)
char_u regtype;
switch (reg->y_type) {
- case MLINE:
+ case kMTLineWise:
regtype = 'V';
list_append_string(lines, (char_u*)"", 0);
break;
- case MCHAR:
+ case kMTCharWise:
regtype = 'v';
break;
- case MBLOCK:
+ case kMTBlockWise:
regtype = 'b';
list_append_string(lines, (char_u*)"", 0);
break;
+ case kMTUnknown:
+ assert(false);
}
list_append_string(args, &regtype, 1);
@@ -5624,7 +5627,7 @@ static inline bool reg_empty(const yankreg_T *const reg)
return (reg->y_array == NULL
|| reg->y_size == 0
|| (reg->y_size == 1
- && reg->y_type == MCHAR
+ && reg->y_type == kMTCharWise
&& *(reg->y_array[0]) == NUL));
}
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index f33e87572f..8c8a586957 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -78,10 +78,10 @@ enum GRegFlags {
/// Definition of one register
typedef struct yankreg {
- char_u **y_array; ///< Pointer to an array of line pointers.
- linenr_T y_size; ///< Number of lines in y_array.
- char_u y_type; ///< Register type: MLINE, MCHAR or MBLOCK.
- colnr_T y_width; ///< Register width (only valid for y_type == MBLOCK).
+ char_u **y_array; ///< Pointer to an array of line pointers.
+ linenr_T y_size; ///< Number of lines in y_array.
+ MotionType y_type; ///< Register type
+ colnr_T y_width; ///< Register width (only valid for y_type == kBlockWise).
Timestamp timestamp; ///< Time when register was last modified.
dict_T *additional_data; ///< Additional data from ShaDa file.
} yankreg_T;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index f9d1cdbaec..2f22c245dd 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -32,6 +32,7 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
+#include "nvim/edit.h"
#include "nvim/option.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
@@ -1177,28 +1178,27 @@ do_set (
errmsg = e_invarg;
goto skip;
}
- arg[len] = NUL; /* put NUL after name */
- if (arg[1] == 't' && arg[2] == '_') /* could be term code */
- opt_idx = findoption(arg + 1);
- arg[len++] = '>'; /* restore '>' */
- if (opt_idx == -1)
+ if (arg[1] == 't' && arg[2] == '_') { // could be term code
+ opt_idx = findoption_len(arg + 1, (size_t) (len - 1));
+ }
+ len++;
+ if (opt_idx == -1) {
key = find_key_option(arg + 1);
+ }
} else {
len = 0;
- /*
- * The two characters after "t_" may not be alphanumeric.
- */
- if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
+ // The two characters after "t_" may not be alphanumeric.
+ if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) {
len = 4;
- else
- while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
- ++len;
- nextchar = arg[len];
- arg[len] = NUL; /* put NUL after name */
- opt_idx = findoption(arg);
- arg[len] = nextchar; /* restore nextchar */
- if (opt_idx == -1)
+ } else {
+ while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') {
+ len++;
+ }
+ }
+ opt_idx = findoption_len(arg, (size_t) len);
+ if (opt_idx == -1) {
key = find_key_option(arg);
+ }
}
/* remember character after option name */
@@ -2057,6 +2057,7 @@ static void didset_options(void)
(void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true);
(void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true);
(void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, true);
+ (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, false);
(void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
(void)spell_check_msm();
(void)spell_check_sps();
@@ -2144,6 +2145,7 @@ void check_buf_options(buf_T *buf)
check_string_option(&buf->b_p_ep);
check_string_option(&buf->b_p_path);
check_string_option(&buf->b_p_tags);
+ check_string_option(&buf->b_p_tc);
check_string_option(&buf->b_p_dict);
check_string_option(&buf->b_p_tsr);
check_string_option(&buf->b_p_lw);
@@ -2957,13 +2959,17 @@ did_set_string_option (
}
/* 'completeopt' */
else if (varp == &p_cot) {
- if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK)
+ if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
errmsg = e_invarg;
+ } else {
+ completeopt_was_set();
+ }
}
/* 'pastetoggle': translate key codes like in a mapping */
else if (varp == &p_pt) {
if (*p_pt) {
- (void)replace_termcodes(p_pt, &p, TRUE, TRUE, FALSE);
+ (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, false,
+ CPO_TO_CPO_FLAGS);
if (p != NULL) {
if (new_value_alloced)
free_string_option(p_pt);
@@ -2983,6 +2989,24 @@ did_set_string_option (
if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, true) != OK) {
errmsg = e_invarg;
}
+ } else if (gvarp == &p_tc) { // 'tagcase'
+ unsigned int *flags;
+
+ if (opt_flags & OPT_LOCAL) {
+ p = curbuf->b_p_tc;
+ flags = &curbuf->b_tc_flags;
+ } else {
+ p = p_tc;
+ flags = &tc_flags;
+ }
+
+ if ((opt_flags & OPT_LOCAL) && *p == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else if (*p == NUL
+ || opt_strings_flags(p, p_tc_values, flags, false) != OK) {
+ errmsg = e_invarg;
+ }
} else if (varp == &p_cmp) { // 'casemap'
if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true) != OK)
errmsg = e_invarg;
@@ -4283,14 +4307,16 @@ static void check_redraw(uint32_t flags)
redraw_all_later(NOT_VALID);
}
-/*
- * Find index for option 'arg'.
- * Return -1 if not found.
- */
-static int findoption(char_u *arg)
+/// Find index for named option
+///
+/// @param[in] arg Option to find index for.
+/// @param[in] len Length of the option.
+///
+/// @return Index of the option or -1 if option was not found.
+int findoption_len(const char_u *const arg, const size_t len)
{
- char *s, *p;
- static short quick_tab[27] = {0, 0}; /* quick access table */
+ char *s, *p;
+ static int quick_tab[27] = { 0, 0 }; // quick access table
int is_term_opt;
/*
@@ -4314,25 +4340,31 @@ static int findoption(char_u *arg)
/*
* Check for name starting with an illegal character.
*/
- if (arg[0] < 'a' || arg[0] > 'z')
+ if (len == 0 || arg[0] < 'a' || arg[0] > 'z') {
return -1;
+ }
int opt_idx;
- is_term_opt = (arg[0] == 't' && arg[1] == '_');
- if (is_term_opt)
+ is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_');
+ if (is_term_opt) {
opt_idx = quick_tab[26];
- else
+ } else {
opt_idx = quick_tab[CharOrdLow(arg[0])];
+ }
+ // Match full name
for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) {
- if (STRCMP(arg, s) == 0) /* match full name */
+ if (STRNCMP(arg, s, len) == 0 && s[len] == NUL) {
break;
+ }
}
if (s == NULL && !is_term_opt) {
opt_idx = quick_tab[CharOrdLow(arg[0])];
+ // Match short name
for (; options[opt_idx].fullname != NULL; opt_idx++) {
s = options[opt_idx].shortname;
- if (s != NULL && STRCMP(arg, s) == 0) /* match short name */
+ if (s != NULL && STRNCMP(arg, s, len) == 0 && s[len] == NUL) {
break;
+ }
s = NULL;
}
}
@@ -4400,6 +4432,15 @@ bool set_tty_option(char *name, char *value)
}
/*
+ * Find index for option 'arg'.
+ * Return -1 if not found.
+ */
+static int findoption(char_u *arg)
+{
+ return findoption_len(arg, STRLEN(arg));
+}
+
+/*
* Get the value for an option.
*
* Returns:
@@ -4655,27 +4696,32 @@ char_u *get_highlight_default(void)
/*
* Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
*/
-static int find_key_option(char_u *arg)
+int find_key_option_len(const char_u *arg, size_t len)
{
int key;
int modifiers;
- /*
- * Don't use get_special_key_code() for t_xx, we don't want it to call
- * add_termcap_entry().
- */
- if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
+ // Don't use get_special_key_code() for t_xx, we don't want it to call
+ // add_termcap_entry().
+ if (len >= 4 && arg[0] == 't' && arg[1] == '_') {
key = TERMCAP2KEY(arg[2], arg[3]);
- else {
- --arg; /* put arg at the '<' */
+ } else {
+ arg--; // put arg at the '<'
modifiers = 0;
- key = find_special_key(&arg, &modifiers, TRUE, TRUE);
- if (modifiers) /* can't handle modifiers here */
+ key = find_special_key(&arg, len + 1, &modifiers, true, true);
+ if (modifiers) { // can't handle modifiers here
key = 0;
+ }
}
return key;
}
+static int find_key_option(const char_u *arg)
+{
+ return find_key_option_len(arg, STRLEN(arg));
+}
+
+
/*
* if 'all' == 0: show changed options
* if 'all' == 1: show all normal options
@@ -4736,9 +4782,10 @@ showoptions (
option_value2string(p, opt_flags);
len = (int)STRLEN(p->fullname) + vim_strsize(NameBuff) + 1;
}
- if ((len <= INC - GAP && run == 1) ||
- (len > INC - GAP && run == 2))
+ if ((len <= INC - GAP && run == 1)
+ || (len > INC - GAP && run == 2)) {
items[item_count++] = p;
+ }
}
}
@@ -4927,18 +4974,15 @@ int makeset(FILE *fd, int opt_flags, int local_only)
} else { /* P_STRING */
int do_endif = FALSE;
- /* Don't set 'syntax' and 'filetype' again if the value is
- * already right, avoids reloading the syntax file. */
- if (
- p->indir == PV_SYN
- ||
- p->indir == PV_FT
- ) {
+ // Don't set 'syntax' and 'filetype' again if the value is
+ // already right, avoids reloading the syntax file.
+ if (p->indir == PV_SYN || p->indir == PV_FT) {
if (fprintf(fd, "if &%s != '%s'", p->fullname,
- *(char_u **)(varp)) < 0
- || put_eol(fd) < 0)
+ *(char_u **)(varp)) < 0
+ || put_eol(fd) < 0) {
return FAIL;
- do_endif = TRUE;
+ }
+ do_endif = true;
}
if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
(p->flags & P_EXPAND) != 0) == FAIL)
@@ -5111,6 +5155,10 @@ void unset_global_local_option(char *name, void *from)
case PV_TAGS:
clear_string_option(&buf->b_p_tags);
break;
+ case PV_TC:
+ clear_string_option(&buf->b_p_tc);
+ buf->b_tc_flags = 0;
+ break;
case PV_DEF:
clear_string_option(&buf->b_p_def);
break;
@@ -5164,6 +5212,7 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
case PV_PATH: return (char_u *)&(curbuf->b_p_path);
case PV_AR: return (char_u *)&(curbuf->b_p_ar);
case PV_TAGS: return (char_u *)&(curbuf->b_p_tags);
+ case PV_TC: return (char_u *)&(curbuf->b_p_tc);
case PV_DEF: return (char_u *)&(curbuf->b_p_def);
case PV_INC: return (char_u *)&(curbuf->b_p_inc);
case PV_DICT: return (char_u *)&(curbuf->b_p_dict);
@@ -5201,6 +5250,8 @@ static char_u *get_varp(vimoption_T *p)
? (char_u *)&(curbuf->b_p_ar) : p->var;
case PV_TAGS: return *curbuf->b_p_tags != NUL
? (char_u *)&(curbuf->b_p_tags) : p->var;
+ case PV_TC: return *curbuf->b_p_tc != NUL
+ ? (char_u *)&(curbuf->b_p_tc) : p->var;
case PV_BKC: return *curbuf->b_p_bkc != NUL
? (char_u *)&(curbuf->b_p_bkc) : p->var;
case PV_DEF: return *curbuf->b_p_def != NUL
@@ -5580,6 +5631,8 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_kp = empty_option;
buf->b_p_path = empty_option;
buf->b_p_tags = empty_option;
+ buf->b_p_tc = empty_option;
+ buf->b_tc_flags = 0;
buf->b_p_def = empty_option;
buf->b_p_inc = empty_option;
buf->b_p_inex = vim_strsave(p_inex);
@@ -6170,10 +6223,10 @@ int has_format_option(int x)
/// 'shortmess' contains 'a' and "x" is present in SHM_ALL_ABBREVIATIONS.
bool shortmess(int x)
{
- return p_shm != NULL &&
- (vim_strchr(p_shm, x) != NULL
- || (vim_strchr(p_shm, 'a') != NULL
- && vim_strchr((char_u *)SHM_ALL_ABBREVIATIONS, x) != NULL));
+ return (p_shm != NULL
+ && (vim_strchr(p_shm, x) != NULL
+ || (vim_strchr(p_shm, 'a') != NULL
+ && vim_strchr((char_u *)SHM_ALL_ABBREVIATIONS, x) != NULL)));
}
/*
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index bbe40873ec..87a9a7398c 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -597,6 +597,14 @@ static char *(p_swb_values[]) =
#define SWB_NEWTAB 0x008
#define SWB_VSPLIT 0x010
EXTERN int p_tbs; ///< 'tagbsearch'
+EXTERN char_u *p_tc; ///< 'tagcase'
+EXTERN unsigned tc_flags; ///< flags from 'tagcase'
+#ifdef IN_OPTION_C
+static char *(p_tc_values[]) = { "followic", "ignore", "match", NULL };
+#endif
+#define TC_FOLLOWIC 0x01
+#define TC_IGNORE 0x02
+#define TC_MATCH 0x04
EXTERN long p_tl; ///< 'taglength'
EXTERN int p_tr; ///< 'tagrelative'
EXTERN char_u *p_tags; ///< 'tags'
@@ -737,6 +745,7 @@ enum {
, BV_SW
, BV_SWF
, BV_TAGS
+ , BV_TC
, BV_TS
, BV_TW
, BV_TX
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index df77c374ec..a743e8c605 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2332,6 +2332,13 @@ return {
defaults={if_true={vi=true}}
},
{
+ full_name='tagcase', abbreviation='tc',
+ type='string', scope={'global', 'buffer'},
+ vim=true,
+ varname='p_tc',
+ defaults={if_true={vi="followic", vim="followic"}}
+ },
+ {
full_name='taglength', abbreviation='tl',
type='number', scope={'global'},
vi_def=true,
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 34d8fde4f1..49a74cf0d1 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -2,6 +2,7 @@
#include <stdbool.h>
#include <assert.h>
+#include <fcntl.h>
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
@@ -59,6 +60,23 @@ int os_dirname(char_u *buf, size_t len)
return OK;
}
+/// Check if the given path is a directory and not a symlink to a directory.
+/// @return `true` if `name` is a directory and NOT a symlink to a directory.
+/// `false` if `name` is not a directory or if an error occurred.
+bool os_isrealdir(const char_u *name)
+ FUNC_ATTR_NONNULL_ALL
+{
+ uv_fs_t request;
+ if (uv_fs_lstat(&fs_loop, &request, (char *)name, NULL) != kLibuvSuccess) {
+ return false;
+ }
+ if (S_ISLNK(request.statbuf.st_mode)) {
+ return false;
+ } else {
+ return S_ISDIR(request.statbuf.st_mode);
+ }
+}
+
/// Check if the given path is a directory or not.
///
/// @return `true` if `fname` is a directory.
@@ -77,10 +95,76 @@ bool os_isdir(const char_u *name)
return true;
}
+/// Check what `name` is:
+/// @return NODE_NORMAL: file or directory (or doesn't exist)
+/// NODE_WRITABLE: writable device, socket, fifo, etc.
+/// NODE_OTHER: non-writable things
+int os_nodetype(const char *name)
+{
+#ifdef WIN32
+ // Edge case from Vim os_win32.c:
+ // We can't open a file with a name "\\.\con" or "\\.\prn", trying to read
+ // from it later will cause Vim to hang. Thus return NODE_WRITABLE here.
+ if (STRNCMP(name, "\\\\.\\", 4) == 0) {
+ return NODE_WRITABLE;
+ }
+#endif
+
+ uv_stat_t statbuf;
+ if (os_stat(name, &statbuf) == 0) {
+ return NODE_NORMAL;
+ }
+
+#ifndef WIN32
+ // libuv does not handle BLK and DIR in uv_handle_type.
+ // Related: https://github.com/joyent/libuv/pull/1421
+ if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) {
+ return NODE_NORMAL;
+ }
+ if (S_ISBLK(statbuf.st_mode)) { // block device isn't writable
+ return NODE_OTHER;
+ }
+#endif
+
+ // Vim os_win32.c:mch_nodetype does this (since patch 7.4.015):
+ // if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) {
+ // wn = enc_to_utf16(name, NULL);
+ // hFile = CreatFile(wn, ...)
+ // to get a HANDLE. But libuv just calls win32's _get_osfhandle() on the fd we
+ // give it. uv_fs_open calls fs__capture_path which does a similar dance and
+ // saves us the hassle.
+
+ int nodetype = NODE_WRITABLE;
+ int fd = os_open(name, O_RDONLY, 0);
+ switch(uv_guess_handle(fd)) {
+ case UV_TTY: // FILE_TYPE_CHAR
+ nodetype = NODE_WRITABLE;
+ break;
+ case UV_FILE: // FILE_TYPE_DISK
+ nodetype = NODE_NORMAL;
+ break;
+ case UV_NAMED_PIPE: // not handled explicitly in Vim os_win32.c
+ case UV_UDP: // unix only
+ case UV_TCP: // unix only
+ case UV_UNKNOWN_HANDLE:
+ default:
+#ifdef WIN32
+ nodetype = NODE_NORMAL;
+#else
+ nodetype = NODE_WRITABLE; // Everything else is writable?
+#endif
+ break;
+ }
+
+ close(fd);
+ return nodetype;
+}
+
/// Checks if the given path represents an executable file.
///
-/// @param[in] name The name of the executable.
+/// @param[in] name Name of the executable.
/// @param[out] abspath Path of the executable, if found and not `NULL`.
+/// @param[in] use_path If 'false', only check if "name" is executable
///
/// @return `true` if `name` is executable and
/// - can be found in $PATH,
@@ -88,14 +172,18 @@ bool os_isdir(const char_u *name)
/// - is absolute.
///
/// @return `false` otherwise.
-bool os_can_exe(const char_u *name, char_u **abspath)
+bool os_can_exe(const char_u *name, char_u **abspath, bool use_path)
FUNC_ATTR_NONNULL_ARG(1)
{
- // If it's an absolute or relative path don't need to use $PATH.
- if (path_is_absolute_path(name) ||
- (name[0] == '.' && (name[1] == '/' ||
- (name[1] == '.' && name[2] == '/')))) {
- if (is_executable(name)) {
+ // when use_path is false or if it's an absolute or relative path don't
+ // need to use $PATH.
+ if (!use_path || path_is_absolute_path(name)
+ || (name[0] == '.'
+ && (name[1] == '/'
+ || (name[1] == '.' && name[2] == '/')))) {
+ // There must be a path separator, files in the current directory
+ // can't be executed
+ if (gettail_dir(name) != name && is_executable(name)) {
if (abspath != NULL) {
*abspath = save_absolute_path(name);
}
diff --git a/src/nvim/os/fs_defs.h b/src/nvim/os/fs_defs.h
index 52b2841514..0bd9c37750 100644
--- a/src/nvim/os/fs_defs.h
+++ b/src/nvim/os/fs_defs.h
@@ -26,4 +26,10 @@ typedef struct {
/// negative libuv error codes are returned by a number of os functions.
#define os_strerror uv_strerror
+// Values returned by os_nodetype()
+#define NODE_NORMAL 0 // file or directory, check with os_isdir()
+#define NODE_WRITABLE 1 // something we can write to (character
+ // device, fifo, socket, ..)
+#define NODE_OTHER 2 // non-writable thing (e.g., block device)
+
#endif // NVIM_OS_FS_DEFS_H
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index f317fd6b5a..7687b14f02 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -175,8 +175,9 @@ size_t input_enqueue(String keys)
char *ptr = keys.data, *end = ptr + keys.size;
while (rbuffer_space(input_buffer) >= 6 && ptr < end) {
- uint8_t buf[6] = {0};
- unsigned int new_size = trans_special((uint8_t **)&ptr, buf, true);
+ uint8_t buf[6] = { 0 };
+ unsigned int new_size = trans_special((const uint8_t **)&ptr, keys.size,
+ buf, true);
if (new_size) {
new_size = handle_mouse_event(&ptr, buf, new_size);
@@ -402,9 +403,9 @@ static int push_event_key(uint8_t *buf, int maxlen)
// Check if there's pending input
static bool input_ready(void)
{
- return typebuf_was_filled || // API call filled typeahead
- rbuffer_size(input_buffer) || // Input buffer filled
- pending_events(); // Events must be processed
+ return (typebuf_was_filled // API call filled typeahead
+ || rbuffer_size(input_buffer) // Input buffer filled
+ || pending_events()); // Events must be processed
}
// Exit because of an input read error.
diff --git a/src/nvim/os/mem.c b/src/nvim/os/mem.c
index 5e483c0c3d..871ece7a0e 100644
--- a/src/nvim/os/mem.c
+++ b/src/nvim/os/mem.c
@@ -8,5 +8,5 @@
uint64_t os_get_total_mem_kib(void)
{
// Convert bytes to KiB.
- return uv_get_total_memory() >> 10;
+ return uv_get_total_memory() / 1024;
}
diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h
index 242d355f77..55894e4d12 100644
--- a/src/nvim/os/win_defs.h
+++ b/src/nvim/os/win_defs.h
@@ -1,6 +1,9 @@
#ifndef NVIM_OS_WIN_DEFS_H
#define NVIM_OS_WIN_DEFS_H
+// winsock2.h must be first to avoid incompatibilities
+// with winsock.h (included by windows.h)
+#include <winsock2.h>
#include <windows.h>
#include <sys/stat.h>
#include <io.h>
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index cb9a58cc77..2ed0c2c856 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -34,7 +34,6 @@
#include "nvim/screen.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
-#include "nvim/tempfile.h"
#include "nvim/ui.h"
#include "nvim/types.h"
#include "nvim/os/os.h"
@@ -137,26 +136,6 @@ void mch_free_acl(vim_acl_T aclent)
}
#endif
-/*
- * Check what "name" is:
- * NODE_NORMAL: file or directory (or doesn't exist)
- * NODE_WRITABLE: writable device, socket, fifo, etc.
- * NODE_OTHER: non-writable things
- */
-int mch_nodetype(char_u *name)
-{
- struct stat st;
-
- if (stat((char *)name, &st))
- return NODE_NORMAL;
- if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
- return NODE_NORMAL;
- if (S_ISBLK(st.st_mode)) /* block device isn't writable */
- return NODE_OTHER;
- /* Everything else is writable? */
- return NODE_WRITABLE;
-}
-
void mch_exit(int r)
{
exiting = true;
@@ -597,9 +576,11 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file,
if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
continue;
- /* Skip files that are not executable if we check for that. */
- if (!dir && (flags & EW_EXEC) && !os_can_exe((*file)[i], NULL))
+ // Skip files that are not executable if we check for that.
+ if (!dir && (flags & EW_EXEC)
+ && !os_can_exe((*file)[i], NULL, !(flags & EW_SHELLCMD))) {
continue;
+ }
p = xmalloc(STRLEN((*file)[i]) + 1 + dir);
STRCPY(p, (*file)[i]);
diff --git a/src/nvim/os_unix.h b/src/nvim/os_unix.h
index 5a3eb84ba4..d627b16ec0 100644
--- a/src/nvim/os_unix.h
+++ b/src/nvim/os_unix.h
@@ -4,12 +4,6 @@
#include "nvim/types.h" // for vim_acl_T
#include "nvim/os/shell.h"
-/* Values returned by mch_nodetype() */
-#define NODE_NORMAL 0 /* file or directory, check with os_isdir()*/
-#define NODE_WRITABLE 1 /* something we can write to (character
- device, fifo, socket, ..) */
-#define NODE_OTHER 2 /* non-writable thing (e.g., block device) */
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os_unix.h.generated.h"
#endif
diff --git a/src/nvim/path.c b/src/nvim/path.c
index aaf54bc5b4..aff0ee2d48 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -604,7 +604,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
starstar = true;
// convert the file pattern to a regexp pattern
- int starts_with_dot = (*s == '.');
+ int starts_with_dot = *s == '.';
char_u *pat = file_pat_to_reg_pat(s, e, NULL, false);
if (pat == NULL) {
xfree(buf);
@@ -647,9 +647,12 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
if (os_file_is_readable(dirpath) && os_scandir(&dir, dirpath)) {
// Find all matching entries.
char_u *name;
- scandir_next_with_dots(NULL /* initialize */);
- while((name = (char_u *) scandir_next_with_dots(&dir)) && name != NULL) {
- if ((name[0] != '.' || starts_with_dot)
+ scandir_next_with_dots(NULL); // initialize
+ while ((name = (char_u *) scandir_next_with_dots(&dir)) && name != NULL) {
+ if ((name[0] != '.'
+ || starts_with_dot
+ || ((flags & EW_DODOT)
+ && name[1] != NUL && (name[1] != '.' || name[2] != NUL)))
&& ((regmatch.regprog != NULL && vim_regexec(&regmatch, name, 0))
|| ((flags & EW_NOTWILD)
&& fnamencmp(path + (s - buf), name, e - s) == 0))) {
@@ -978,12 +981,12 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
* "/path/file", "/path/dir/", "/path//dir", "/file"
* ^ ^ ^ ^
*/
-static char_u *gettail_dir(char_u *fname)
+char_u *gettail_dir(const char_u *fname)
{
- char_u *dir_end = fname;
- char_u *next_dir_end = fname;
+ const char_u *dir_end = fname;
+ const char_u *next_dir_end = fname;
bool look_for_sep = true;
- char_u *p;
+ const char_u *p;
for (p = fname; *p != NUL; ) {
if (vim_ispathsep(*p)) {
@@ -998,7 +1001,7 @@ static char_u *gettail_dir(char_u *fname)
}
mb_ptr_adv(p);
}
- return dir_end;
+ return (char_u *)dir_end;
}
@@ -1220,7 +1223,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
recursive = false;
- return (ga.ga_data != NULL) ? OK : FAIL;
+ return ((flags & EW_EMPTYOK) || ga.ga_data != NULL) ? OK : FAIL;
}
@@ -1298,9 +1301,10 @@ void addfile(
FileInfo file_info;
// if the file/dir/link doesn't exist, may not add it
- if (!(flags & EW_NOTFOUND) &&
- ((flags & EW_ALLLINKS) ?
- !os_fileinfo_link((char *)f, &file_info) : !os_file_exists(f))) {
+ if (!(flags & EW_NOTFOUND)
+ && ((flags & EW_ALLLINKS)
+ ? !os_fileinfo_link((char *)f, &file_info)
+ : !os_file_exists(f))) {
return;
}
@@ -1314,9 +1318,12 @@ void addfile(
if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE)))
return;
- /* If the file isn't executable, may not add it. Do accept directories. */
- if (!isdir && (flags & EW_EXEC) && !os_can_exe(f, NULL))
+ // If the file isn't executable, may not add it. Do accept directories.
+ // When invoked from expand_shellcmd() do not use $PATH.
+ if (!isdir && (flags & EW_EXEC)
+ && !os_can_exe(f, NULL, !(flags & EW_SHELLCMD))) {
return;
+ }
char_u *p = xmalloc(STRLEN(f) + 1 + isdir);
@@ -1380,9 +1387,9 @@ void simplify_filename(char_u *filename)
--p; /* strip preceding path separator */
STRMOVE(p, tail);
}
- } else if (p[0] == '.' && p[1] == '.' &&
- (vim_ispathsep(p[2]) || p[2] == NUL)) {
- /* Skip to after ".." or "../" or "..///". */
+ } else if (p[0] == '.' && p[1] == '.'
+ && (vim_ispathsep(p[2]) || p[2] == NUL)) {
+ // Skip to after ".." or "../" or "..///".
tail = p + 2;
while (vim_ispathsep(*tail))
mb_ptr_adv(tail);
@@ -1923,7 +1930,7 @@ int expand_wildcards_eval(char_u **pat, int *num_file, char_u ***file,
/// If FAIL is returned, *num_file and *file are either
/// unchanged or *num_file is set to 0 and *file is set to
/// NULL or points to "".
-int expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file,
+int expand_wildcards(int num_pat, char_u **pat, int *num_files, char_u ***files,
int flags)
{
int retval;
@@ -1931,7 +1938,7 @@ int expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file,
char_u *p;
int non_suf_match; /* number without matching suffix */
- retval = gen_expand_wildcards(num_pat, pat, num_file, file, flags);
+ retval = gen_expand_wildcards(num_pat, pat, num_files, files, flags);
/* When keeping all matches, return here */
if ((flags & EW_KEEPALL) || retval == FAIL)
@@ -1943,18 +1950,20 @@ int expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file,
if (*p_wig) {
char_u *ffname;
- /* check all files in (*file)[] */
- for (i = 0; i < *num_file; ++i) {
- ffname = (char_u *)FullName_save((char *)(*file)[i], FALSE);
- if (ffname == NULL) /* out of memory */
+ // check all filess in (*files)[]
+ for (i = 0; i < *num_files; i++) {
+ ffname = (char_u *)FullName_save((char *)(*files)[i], false);
+ if (ffname == NULL) { // out of memory
break;
- if (match_file_list(p_wig, (*file)[i], ffname)) {
- /* remove this matching file from the list */
- xfree((*file)[i]);
- for (j = i; j + 1 < *num_file; ++j)
- (*file)[j] = (*file)[j + 1];
- --*num_file;
- --i;
+ }
+ if (match_file_list(p_wig, (*files)[i], ffname)) {
+ // remove this matching files from the list
+ xfree((*files)[i]);
+ for (j = i; j + 1 < *num_files; j++) {
+ (*files)[j] = (*files)[j + 1];
+ }
+ (*num_files)--;
+ i--;
}
xfree(ffname);
}
@@ -1963,26 +1972,28 @@ int expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file,
/*
* Move the names where 'suffixes' match to the end.
*/
- if (*num_file > 1) {
+ if (*num_files > 1) {
non_suf_match = 0;
- for (i = 0; i < *num_file; ++i) {
- if (!match_suffix((*file)[i])) {
- /*
- * Move the name without matching suffix to the front
- * of the list.
- */
- p = (*file)[i];
- for (j = i; j > non_suf_match; --j)
- (*file)[j] = (*file)[j - 1];
- (*file)[non_suf_match++] = p;
+ for (i = 0; i < *num_files; i++) {
+ if (!match_suffix((*files)[i])) {
+ //
+ // Move the name without matching suffix to the front
+ // of the list.
+ //
+ p = (*files)[i];
+ for (j = i; j > non_suf_match; j--) {
+ (*files)[j] = (*files)[j - 1];
+ }
+ (*files)[non_suf_match++] = p;
}
}
}
// Free empty array of matches
- if (*num_file == 0) {
- xfree(*file);
- *file = NULL;
+ if (*num_files == 0) {
+ xfree(*files);
+ *files = NULL;
+ return FAIL;
}
return retval;
@@ -2009,8 +2020,8 @@ int match_suffix(char_u *fname)
break;
}
} else {
- if (fnamelen >= setsuflen &&
- fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
+ if (fnamelen >= setsuflen
+ && fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
break;
}
setsuflen = 0;
diff --git a/src/nvim/path.h b/src/nvim/path.h
index eac367d0ac..4e466d1b71 100644
--- a/src/nvim/path.h
+++ b/src/nvim/path.h
@@ -21,6 +21,10 @@
/* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
* is used when executing commands and EW_SILENT for interactive expanding. */
#define EW_ALLLINKS 0x1000 // also links not pointing to existing file
+#define EW_SHELLCMD 0x2000 // called from expand_shellcmd(), don't check
+ // if executable is in $PATH
+#define EW_DODOT 0x4000 // also files starting with a dot
+#define EW_EMPTYOK 0x8000 // no matches is not an error
/// Return value for the comparison of two files. Also @see path_full_compare.
typedef enum file_comparison {
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 28c0425e2c..17cb8a86aa 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -39,7 +39,6 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
-#include "nvim/tempfile.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
@@ -2758,8 +2757,8 @@ void ex_cc(exarg_T *eap)
// For cdo and ldo commands, jump to the nth valid error.
// For cfdo and lfdo commands, jump to the nth valid file entry.
- if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo ||
- eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
+ if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
+ || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
size_t n;
if (eap->addr_count > 0) {
assert(eap->line1 >= 0);
@@ -2802,9 +2801,9 @@ void ex_cnext(exarg_T *eap)
}
int errornr;
- if (eap->addr_count > 0 &&
- (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo &&
- eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) {
+ if (eap->addr_count > 0
+ && (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo
+ && eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) {
errornr = (int)eap->line2;
} else {
errornr = 1;
@@ -2973,16 +2972,18 @@ void ex_vimgrep(exarg_T *eap)
goto theend;
}
- if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd &&
- eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
- || qi->qf_curlist == qi->qf_listcount)
- /* make place for a new list */
+ if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd
+ && eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
+ || qi->qf_curlist == qi->qf_listcount) {
+ // make place for a new list
qf_new_list(qi, *eap->cmdlinep);
- else if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
- /* Adding to existing list, find last entry. */
+ } else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) {
+ // Adding to existing list, find last entry.
for (prevp = qi->qf_lists[qi->qf_curlist].qf_start;
- prevp->qf_next != prevp; prevp = prevp->qf_next)
- ;
+ prevp->qf_next != prevp;
+ prevp = prevp->qf_next) {
+ }
+ }
/* parse the list of arguments */
if (get_arglist_exp(p, &fcount, &fnames, true) == FAIL)
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 608aa38466..886a48e7c5 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -3445,13 +3445,14 @@ static long bt_regexec_both(char_u *line,
c = regline[col];
if (prog->regstart == NUL
|| prog->regstart == c
- || (ireg_ic && ((
- (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
- || (c < 255 && prog->regstart < 255 &&
- vim_tolower(prog->regstart) == vim_tolower(c)))))
+ || (ireg_ic
+ && (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
+ || (c < 255 && prog->regstart < 255
+ && vim_tolower(prog->regstart) == vim_tolower(c))))) {
retval = regtry(prog, col);
- else
+ } else {
retval = 0;
+ }
} else {
int tm_count = 0;
/* Messy cases: unanchored match. */
@@ -4121,15 +4122,15 @@ regmatch (
char_u *opnd;
opnd = OPERAND(scan);
- /* Inline the first byte, for speed. */
+ // Inline the first byte, for speed.
if (*opnd != *reginput
- && (!ireg_ic || (
- !enc_utf8 &&
- vim_tolower(*opnd) != vim_tolower(*reginput))))
+ && (!ireg_ic
+ || (!enc_utf8
+ && vim_tolower(*opnd) != vim_tolower(*reginput)))) {
status = RA_NOMATCH;
- else if (*opnd == NUL) {
- /* match empty string always works; happens when "~" is
- * empty. */
+ } else if (*opnd == NUL) {
+ // match empty string always works; happens when "~" is
+ // empty.
} else {
if (opnd[1] == NUL && !(enc_utf8 && ireg_ic)) {
len = 1; /* matched a single byte above */
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index e2849fb17a..7e53b2ccd1 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -3464,13 +3464,12 @@ static char *pim_info(nfa_pim_T *pim)
#endif
-/* Used during execution: whether a match has been found. */
+// Used during execution: whether a match has been found.
static int nfa_match;
+static proftime_T *nfa_time_limit;
+static int nfa_time_count;
-
-/*
- * Copy postponed invisible match info from "from" to "to".
- */
+// Copy postponed invisible match info from "from" to "to".
static void copy_pim(nfa_pim_T *to, nfa_pim_T *from)
{
to->result = from->result;
@@ -4566,7 +4565,7 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
if (log_fd != NULL) {
fprintf(log_fd, "****************************\n");
fprintf(log_fd, "FINISHED RUNNING nfa_regmatch() recursively\n");
- fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
+ fprintf(log_fd, "MATCH = %s\n", !result ? "FALSE" : "OK");
fprintf(log_fd, "****************************\n");
} else {
EMSG(_(
@@ -4778,8 +4777,8 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
int c2_len = PTR2LEN(s2);
int c2 = PTR2CHAR(s2);
- if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) ||
- c1_len != c2_len) {
+ if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2)))
+ || c1_len != c2_len) {
match = false;
break;
}
@@ -4813,22 +4812,21 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
#undef PTR2LEN
}
-/*
- * Main matching routine.
- *
- * Run NFA to determine whether it matches reginput.
- *
- * When "nfa_endp" is not NULL it is a required end-of-match position.
- *
- * Return TRUE if there is a match, FALSE otherwise.
- * When there is a match "submatch" contains the positions.
- * Note: Caller must ensure that: start != NULL.
- */
-static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *submatch, regsubs_T *m)
+/// Main matching routine.
+///
+/// Run NFA to determine whether it matches reginput.
+///
+/// When "nfa_endp" is not NULL it is a required end-of-match position.
+///
+/// Return TRUE if there is a match, FALSE otherwise.
+/// When there is a match "submatch" contains the positions.
+/// Note: Caller must ensure that: start != NULL.
+static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
+ regsubs_T *submatch, regsubs_T *m)
{
int result;
int flag = 0;
- int go_to_nextline = FALSE;
+ bool go_to_nextline = false;
nfa_thread_T *t;
nfa_list_T list[2];
int listidx;
@@ -4845,18 +4843,22 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
if (debug == NULL) {
EMSG2(_("(NFA) COULD NOT OPEN %s !"), NFA_REGEXP_DEBUG_LOG);
- return FALSE;
+ return false;
}
#endif
- /* Some patterns may take a long time to match, especially when using
- * recursive_regmatch(). Allow interrupting them with CTRL-C. */
+ // Some patterns may take a long time to match, especially when using
+ // recursive_regmatch(). Allow interrupting them with CTRL-C.
fast_breakcheck();
- if (got_int)
- return FALSE;
+ if (got_int) {
+ return false;
+ }
+ if (nfa_time_limit != NULL && profile_passed_limit(*nfa_time_limit)) {
+ return false;
+ }
- nfa_match = FALSE;
+ nfa_match = false;
- /* Allocate memory for the lists of nodes. */
+ // Allocate memory for the lists of nodes.
size_t size = (nstate + 1) * sizeof(nfa_thread_T);
list[0].t = xmalloc(size);
list[0].len = nstate + 1;
@@ -4924,7 +4926,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
}
if (curc == NUL) {
clen = 0;
- go_to_nextline = FALSE;
+ go_to_nextline = false;
}
/* swap lists */
@@ -5007,7 +5009,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
if (enc_utf8 && !ireg_icombine && utf_iscomposing(curc)) {
break;
}
- nfa_match = TRUE;
+ nfa_match = true;
copy_sub(&submatch->norm, &t->subs.norm);
if (nfa_has_zsubexpr)
copy_sub(&submatch->synt, &t->subs.synt);
@@ -5072,10 +5074,11 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
fprintf(log_fd, "Match found:\n");
log_subsexpr(m);
#endif
- nfa_match = TRUE;
- /* See comment above at "goto nextchar". */
- if (nextlist->n == 0)
+ nfa_match = true;
+ // See comment above at "goto nextchar".
+ if (nextlist->n == 0) {
clen = 0;
+ }
goto nextchar;
case NFA_START_INVISIBLE:
@@ -5092,8 +5095,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
failure_chance(t->state->out, 0),
failure_chance(t->state->out1->out, 0));
#endif
- /* Do it directly if there already is a PIM or when
- * nfa_postprocess() detected it will work better. */
+ // Do it directly if there already is a PIM or when
+ // nfa_postprocess() detected it will work better.
if (t->pim.result != NFA_PIM_UNUSED
|| t->state->c == NFA_START_INVISIBLE_FIRST
|| t->state->c == NFA_START_INVISIBLE_NEG_FIRST
@@ -5101,42 +5104,40 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
|| t->state->c == NFA_START_INVISIBLE_BEFORE_NEG_FIRST) {
int in_use = m->norm.in_use;
- /* Copy submatch info for the recursive call, opposite
- * of what happens on success below. */
+ // Copy submatch info for the recursive call, opposite
+ // of what happens on success below.
copy_sub_off(&m->norm, &t->subs.norm);
if (nfa_has_zsubexpr)
copy_sub_off(&m->synt, &t->subs.synt);
- /*
- * First try matching the invisible match, then what
- * follows.
- */
- result = recursive_regmatch(t->state, NULL, prog,
- submatch, m, &listids);
+ // First try matching the invisible match, then what
+ // follows.
+ result = recursive_regmatch(t->state, NULL, prog, submatch, m,
+ &listids);
if (result == NFA_TOO_EXPENSIVE) {
nfa_match = result;
goto theend;
}
- /* for \@! and \@<! it is a match when the result is
- * FALSE */
+ // for \@! and \@<! it is a match when the result is
+ // FALSE
if (result != (t->state->c == NFA_START_INVISIBLE_NEG
|| t->state->c == NFA_START_INVISIBLE_NEG_FIRST
|| t->state->c
== NFA_START_INVISIBLE_BEFORE_NEG
|| t->state->c
== NFA_START_INVISIBLE_BEFORE_NEG_FIRST)) {
- /* Copy submatch info from the recursive call */
+ // Copy submatch info from the recursive call
copy_sub_off(&t->subs.norm, &m->norm);
if (nfa_has_zsubexpr)
copy_sub_off(&t->subs.synt, &m->synt);
- /* If the pattern has \ze and it matched in the
- * sub pattern, use it. */
+ // If the pattern has \ze and it matched in the
+ // sub pattern, use it.
copy_ze_off(&t->subs.norm, &m->norm);
- /* t->state->out1 is the corresponding
- * END_INVISIBLE node; Add its out to the current
- * list (zero-width match). */
+ // t->state->out1 is the corresponding
+ // END_INVISIBLE node; Add its out to the current
+ // list (zero-width match).
add_here = true;
add_state = t->state->out1->out;
}
@@ -5144,12 +5145,10 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
} else {
nfa_pim_T pim;
- /*
- * First try matching what follows. Only if a match
- * is found verify the invisible match matches. Add a
- * nfa_pim_T to the following states, it contains info
- * about the invisible match.
- */
+ // First try matching what follows. Only if a match
+ // is found verify the invisible match matches. Add a
+ // nfa_pim_T to the following states, it contains info
+ // about the invisible match.
pim.state = t->state;
pim.result = NFA_PIM_TODO;
pim.subs.norm.in_use = 0;
@@ -5160,9 +5159,9 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
} else
pim.end.ptr = reginput;
- /* t->state->out1 is the corresponding END_INVISIBLE
- * node; Add its out to the current list (zero-width
- * match). */
+ // t->state->out1 is the corresponding END_INVISIBLE
+ // node; Add its out to the current list (zero-width
+ // match).
addstate_here(thislist, t->state->out1->out, &t->subs,
&pim, &listidx);
}
@@ -5176,8 +5175,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
int skip_lid = 0;
#endif
- /* There is no point in trying to match the pattern if the
- * output state is not going to be added to the list. */
+ // There is no point in trying to match the pattern if the
+ // output state is not going to be added to the list.
if (state_in_list(nextlist, t->state->out1->out, &t->subs)) {
skip = t->state->out1->out;
#ifdef REGEXP_DEBUG
@@ -5206,15 +5205,16 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
#endif
break;
}
- /* Copy submatch info to the recursive call, opposite of what
- * happens afterwards. */
+ // Copy submatch info to the recursive call, opposite of what
+ // happens afterwards.
copy_sub_off(&m->norm, &t->subs.norm);
- if (nfa_has_zsubexpr)
+ if (nfa_has_zsubexpr) {
copy_sub_off(&m->synt, &t->subs.synt);
+ }
- /* First try matching the pattern. */
- result = recursive_regmatch(t->state, NULL, prog,
- submatch, m, &listids);
+ // First try matching the pattern.
+ result = recursive_regmatch(t->state, NULL, prog, submatch, m,
+ &listids);
if (result == NFA_TOO_EXPENSIVE) {
nfa_match = result;
goto theend;
@@ -5226,36 +5226,38 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
fprintf(log_fd, "NFA_START_PATTERN matches:\n");
log_subsexpr(m);
#endif
- /* Copy submatch info from the recursive call */
+ // Copy submatch info from the recursive call
copy_sub_off(&t->subs.norm, &m->norm);
- if (nfa_has_zsubexpr)
+ if (nfa_has_zsubexpr) {
copy_sub_off(&t->subs.synt, &m->synt);
- /* Now we need to skip over the matched text and then
- * continue with what follows. */
- if (REG_MULTI)
- /* TODO: multi-line match */
+ }
+ // Now we need to skip over the matched text and then
+ // continue with what follows.
+ if (REG_MULTI) {
+ // TODO(RE): multi-line match
bytelen = m->norm.list.multi[0].end_col
- (int)(reginput - regline);
- else
+ } else {
bytelen = (int)(m->norm.list.line[0].end - reginput);
+ }
#ifdef REGEXP_DEBUG
fprintf(log_fd, "NFA_START_PATTERN length: %d\n", bytelen);
#endif
if (bytelen == 0) {
- /* empty match, output of corresponding
- * NFA_END_PATTERN/NFA_SKIP to be used at current
- * position */
+ // empty match, output of corresponding
+ // NFA_END_PATTERN/NFA_SKIP to be used at current
+ // position
add_here = true;
add_state = t->state->out1->out->out;
} else if (bytelen <= clen) {
- /* match current character, output of corresponding
- * NFA_END_PATTERN to be used at next position. */
+ // match current character, output of corresponding
+ // NFA_END_PATTERN to be used at next position.
add_state = t->state->out1->out->out;
add_off = clen;
} else {
- /* skip over the matched characters, set character
- * count in NFA_SKIP */
+ // skip over the matched characters, set character
+ // count in NFA_SKIP
add_state = t->state->out1->out;
add_off = bytelen;
add_count = bytelen - clen;
@@ -5279,23 +5281,25 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
break;
case NFA_BOW:
- result = TRUE;
+ result = true;
- if (curc == NUL)
- result = FALSE;
- else if (has_mbyte) {
+ if (curc == NUL) {
+ result = false;
+ } else if (has_mbyte) {
int this_class;
- /* Get class of current and previous char (if it exists). */
+ // Get class of current and previous char (if it exists).
this_class = mb_get_class_buf(reginput, reg_buf);
- if (this_class <= 1)
- result = FALSE;
- else if (reg_prev_class() == this_class)
- result = FALSE;
+ if (this_class <= 1) {
+ result = false;
+ } else if (reg_prev_class() == this_class) {
+ result = false;
+ }
} else if (!vim_iswordc_buf(curc, reg_buf)
|| (reginput > regline
- && vim_iswordc_buf(reginput[-1], reg_buf)))
- result = FALSE;
+ && vim_iswordc_buf(reginput[-1], reg_buf))) {
+ result = false;
+ }
if (result) {
add_here = true;
add_state = t->state->out;
@@ -5303,22 +5307,24 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
break;
case NFA_EOW:
- result = TRUE;
- if (reginput == regline)
- result = FALSE;
- else if (has_mbyte) {
+ result = true;
+ if (reginput == regline) {
+ result = false;
+ } else if (has_mbyte) {
int this_class, prev_class;
- /* Get class of current and previous char (if it exists). */
+ // Get class of current and previous char (if it exists).
this_class = mb_get_class_buf(reginput, reg_buf);
prev_class = reg_prev_class();
if (this_class == prev_class
- || prev_class == 0 || prev_class == 1)
- result = FALSE;
+ || prev_class == 0 || prev_class == 1) {
+ result = false;
+ }
} else if (!vim_iswordc_buf(reginput[-1], reg_buf)
|| (reginput[0] != NUL
- && vim_iswordc_buf(curc, reg_buf)))
- result = FALSE;
+ && vim_iswordc_buf(curc, reg_buf))) {
+ result = false;
+ }
if (result) {
add_here = true;
add_state = t->state->out;
@@ -5353,30 +5359,31 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
sta = t->state->out;
len = 0;
if (utf_iscomposing(sta->c)) {
- /* Only match composing character(s), ignore base
- * character. Used for ".{composing}" and "{composing}"
- * (no preceding character). */
+ // Only match composing character(s), ignore base
+ // character. Used for ".{composing}" and "{composing}"
+ // (no preceding character).
len += mb_char2len(mc);
}
if (ireg_icombine && len == 0) {
- /* If \Z was present, then ignore composing characters.
- * When ignoring the base character this always matches. */
- if (sta->c != curc)
+ // If \Z was present, then ignore composing characters.
+ // When ignoring the base character this always matches.
+ if (sta->c != curc) {
result = FAIL;
- else
+ } else {
result = OK;
- while (sta->c != NFA_END_COMPOSING)
+ }
+ while (sta->c != NFA_END_COMPOSING) {
sta = sta->out;
- }
- /* Check base character matches first, unless ignored. */
- else if (len > 0 || mc == sta->c) {
+ }
+ } else if (len > 0 || mc == sta->c) {
+ // Check base character matches first, unless ignored.
if (len == 0) {
len += mb_char2len(mc);
sta = sta->out;
}
- /* We don't care about the order of composing characters.
- * Get them into cchars[] first. */
+ // We don't care about the order of composing characters.
+ // Get them into cchars[] first.
while (len < clen) {
mc = mb_ptr2char(reginput + len);
cchars[ccount++] = mc;
@@ -5385,9 +5392,9 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
break;
}
- /* Check that each composing char in the pattern matches a
- * composing char in the text. We do not check if all
- * composing chars are matched. */
+ // Check that each composing char in the pattern matches a
+ // composing char in the text. We do not check if all
+ // composing chars are matched.
result = OK;
while (sta->c != NFA_END_COMPOSING) {
for (j = 0; j < ccount; ++j)
@@ -5402,7 +5409,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
} else
result = FAIL;
- end = t->state->out1; /* NFA_END_COMPOSING */
+ end = t->state->out1; // NFA_END_COMPOSING
ADD_STATE_IF_MATCH(end);
break;
}
@@ -5410,13 +5417,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
case NFA_NEWL:
if (curc == NUL && !reg_line_lbr && REG_MULTI
&& reglnum <= reg_maxline) {
- go_to_nextline = TRUE;
- /* Pass -1 for the offset, which means taking the position
- * at the start of the next line. */
+ go_to_nextline = true;
+ // Pass -1 for the offset, which means taking the position
+ // at the start of the next line.
add_state = t->state->out;
add_off = -1;
} else if (curc == '\n' && reg_line_lbr) {
- /* match \n as if it is an ordinary character */
+ // match \n as if it is an ordinary character
add_state = t->state->out;
add_off = 1;
}
@@ -5425,16 +5432,17 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
case NFA_START_COLL:
case NFA_START_NEG_COLL:
{
- /* What follows is a list of characters, until NFA_END_COLL.
- * One of them must match or none of them must match. */
+ // What follows is a list of characters, until NFA_END_COLL.
+ // One of them must match or none of them must match.
nfa_state_T *state;
int result_if_matched;
int c1, c2;
- /* Never match EOL. If it's part of the collection it is added
- * as a separate state with an OR. */
- if (curc == NUL)
+ // Never match EOL. If it's part of the collection it is added
+ // as a separate state with an OR.
+ if (curc == NUL) {
break;
+ }
state = t->state->out;
result_if_matched = (t->state->c == NFA_START_COLL);
@@ -5445,7 +5453,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
}
if (state->c == NFA_RANGE_MIN) {
c1 = state->val;
- state = state->out; /* advance to NFA_RANGE_MAX */
+ state = state->out; // advance to NFA_RANGE_MAX
c2 = state->val;
#ifdef REGEXP_DEBUG
fprintf(log_fd, "NFA_RANGE_MIN curc=%d c1=%d c2=%d\n",
@@ -5478,8 +5486,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
state = state->out;
}
if (result) {
- /* next state is in out of the NFA_END_COLL, out1 of
- * START points to the END state */
+ // next state is in out of the NFA_END_COLL, out1 of
+ // START points to the END state
add_state = t->state->out1->out;
add_off = clen;
}
@@ -5487,7 +5495,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
}
case NFA_ANY:
- /* Any char except '\0', (end of input) does not match. */
+ // Any char except '\0', (end of input) does not match.
if (curc > 0) {
add_state = t->state->out;
add_off = clen;
@@ -5506,157 +5514,155 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
add_state = t->state->out;
break;
- /*
- * Character classes like \a for alpha, \d for digit etc.
- */
- case NFA_IDENT: /* \i */
+ // Character classes like \a for alpha, \d for digit etc.
+ case NFA_IDENT: // \i
result = vim_isIDc(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_SIDENT: /* \I */
+ case NFA_SIDENT: // \I
result = !ascii_isdigit(curc) && vim_isIDc(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_KWORD: /* \k */
+ case NFA_KWORD: // \k
result = vim_iswordp_buf(reginput, reg_buf);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_SKWORD: /* \K */
+ case NFA_SKWORD: // \K
result = !ascii_isdigit(curc)
&& vim_iswordp_buf(reginput, reg_buf);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_FNAME: /* \f */
+ case NFA_FNAME: // \f
result = vim_isfilec(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_SFNAME: /* \F */
+ case NFA_SFNAME: // \F
result = !ascii_isdigit(curc) && vim_isfilec(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_PRINT: /* \p */
+ case NFA_PRINT: // \p
result = vim_isprintc(PTR2CHAR(reginput));
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_SPRINT: /* \P */
+ case NFA_SPRINT: // \P
result = !ascii_isdigit(curc) && vim_isprintc(PTR2CHAR(reginput));
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_WHITE: /* \s */
+ case NFA_WHITE: // \s
result = ascii_iswhite(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NWHITE: /* \S */
+ case NFA_NWHITE: // \S
result = curc != NUL && !ascii_iswhite(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_DIGIT: /* \d */
+ case NFA_DIGIT: // \d
result = ri_digit(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NDIGIT: /* \D */
+ case NFA_NDIGIT: // \D
result = curc != NUL && !ri_digit(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_HEX: /* \x */
+ case NFA_HEX: // \x
result = ri_hex(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NHEX: /* \X */
+ case NFA_NHEX: // \X
result = curc != NUL && !ri_hex(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_OCTAL: /* \o */
+ case NFA_OCTAL: // \o
result = ri_octal(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NOCTAL: /* \O */
+ case NFA_NOCTAL: // \O
result = curc != NUL && !ri_octal(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_WORD: /* \w */
+ case NFA_WORD: // \w
result = ri_word(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NWORD: /* \W */
+ case NFA_NWORD: // \W
result = curc != NUL && !ri_word(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_HEAD: /* \h */
+ case NFA_HEAD: // \h
result = ri_head(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NHEAD: /* \H */
+ case NFA_NHEAD: // \H
result = curc != NUL && !ri_head(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_ALPHA: /* \a */
+ case NFA_ALPHA: // \a
result = ri_alpha(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NALPHA: /* \A */
+ case NFA_NALPHA: // \A
result = curc != NUL && !ri_alpha(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_LOWER: /* \l */
+ case NFA_LOWER: // \l
result = ri_lower(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NLOWER: /* \L */
+ case NFA_NLOWER: // \L
result = curc != NUL && !ri_lower(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_UPPER: /* \u */
+ case NFA_UPPER: // \u
result = ri_upper(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NUPPER: /* \U */
+ case NFA_NUPPER: // \U
result = curc != NUL && !ri_upper(curc);
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_LOWER_IC: /* [a-z] */
+ case NFA_LOWER_IC: // [a-z]
result = ri_lower(curc) || (ireg_ic && ri_upper(curc));
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NLOWER_IC: /* [^a-z] */
+ case NFA_NLOWER_IC: // [^a-z]
result = curc != NUL
&& !(ri_lower(curc) || (ireg_ic && ri_upper(curc)));
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_UPPER_IC: /* [A-Z] */
+ case NFA_UPPER_IC: // [A-Z]
result = ri_upper(curc) || (ireg_ic && ri_lower(curc));
ADD_STATE_IF_MATCH(t->state);
break;
- case NFA_NUPPER_IC: /* ^[A-Z] */
+ case NFA_NUPPER_IC: // [^A-Z]
result = curc != NUL
&& !(ri_upper(curc) || (ireg_ic && ri_lower(curc)));
ADD_STATE_IF_MATCH(t->state);
@@ -5680,7 +5686,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
case NFA_ZREF7:
case NFA_ZREF8:
case NFA_ZREF9:
- /* \1 .. \9 \z1 .. \z9 */
+ // \1 .. \9 \z1 .. \z9
{
int subidx;
int bytelen;
@@ -5695,18 +5701,18 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
if (result) {
if (bytelen == 0) {
- /* empty match always works, output of NFA_SKIP to be
- * used next */
+ // empty match always works, output of NFA_SKIP to be
+ // used next
add_here = true;
add_state = t->state->out->out;
} else if (bytelen <= clen) {
- /* match current character, jump ahead to out of
- * NFA_SKIP */
+ // match current character, jump ahead to out of
+ // NFA_SKIP
add_state = t->state->out->out;
add_off = clen;
} else {
- /* skip over the matched characters, set character
- * count in NFA_SKIP */
+ // skip over the matched characters, set character
+ // count in NFA_SKIP
add_state = t->state->out;
add_off = bytelen;
add_count = bytelen - clen;
@@ -5715,13 +5721,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
break;
}
case NFA_SKIP:
- /* character of previous matching \1 .. \9 or \@> */
+ // character of previous matching \1 .. \9 or \@>
if (t->count - clen <= 0) {
- /* end of match, go to what follows */
+ // end of match, go to what follows
add_state = t->state->out;
add_off = clen;
} else {
- /* add state again with decremented count */
+ // add state again with decremented count
add_state = t->state;
add_off = 0;
add_count = t->count - clen;
@@ -5773,7 +5779,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
break;
}
- result = FALSE;
+ result = false;
win_T *wp = reg_win == NULL ? curwin : reg_win;
if (op == 1 && col - 1 > t->state->val && col > 100) {
long ts = wp->w_buffer->b_p_ts;
@@ -5803,9 +5809,9 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
{
pos_T *pos = getmark_buf(reg_buf, t->state->val, FALSE);
- /* Compare the mark position to the match position. */
- result = (pos != NULL /* mark doesn't exist */
- && pos->lnum > 0 /* mark isn't set in reg_buf */
+ // Compare the mark position to the match position.
+ result = (pos != NULL // mark doesn't exist
+ && pos->lnum > 0 // mark isn't set in reg_buf
&& (pos->lnum == reglnum + reg_firstlnum
? (pos->col == (colnr_T)(reginput - regline)
? t->state->c == NFA_MARK
@@ -5862,11 +5868,11 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
case NFA_ZOPEN9:
case NFA_NOPEN:
case NFA_ZSTART:
- /* These states are only added to be able to bail out when
- * they are added again, nothing is to be done. */
+ // These states are only added to be able to bail out when
+ // they are added again, nothing is to be done.
break;
- default: /* regular character */
+ default: // regular character
{
int c = t->state->c;
@@ -5888,8 +5894,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
ADD_STATE_IF_MATCH(t->state);
break;
}
-
- } /* switch (t->state->c) */
+ } // switch (t->state->c)
if (add_state != NULL) {
nfa_pim_T *pim;
@@ -5900,8 +5905,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
else
pim = &t->pim;
- /* Handle the postponed invisible match if the match might end
- * without advancing and before the end of the line. */
+ // Handle the postponed invisible match if the match might end
+ // without advancing and before the end of the line.
if (pim != NULL && (clen == 0 || match_follows(add_state, 0))) {
if (pim->result == NFA_PIM_TODO) {
#ifdef REGEXP_DEBUG
@@ -5913,15 +5918,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
result = recursive_regmatch(pim->state, pim,
prog, submatch, m, &listids);
pim->result = result ? NFA_PIM_MATCH : NFA_PIM_NOMATCH;
- /* for \@! and \@<! it is a match when the result is
- * FALSE */
+ // for \@! and \@<! it is a match when the result is
+ // FALSE
if (result != (pim->state->c == NFA_START_INVISIBLE_NEG
|| pim->state->c == NFA_START_INVISIBLE_NEG_FIRST
|| pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG
|| pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG_FIRST)) {
- /* Copy submatch info from the recursive call */
+ // Copy submatch info from the recursive call
copy_sub_off(&pim->subs.norm, &m->norm);
if (nfa_has_zsubexpr)
copy_sub_off(&pim->subs.synt, &m->synt);
@@ -5934,34 +5939,35 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
log_fd,
"Using previous recursive nfa_regmatch() result, result == %d\n",
pim->result);
- fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
+ fprintf(log_fd, "MATCH = %s\n", result ? "OK" : "FALSE");
fprintf(log_fd, "\n");
#endif
}
- /* for \@! and \@<! it is a match when result is FALSE */
+ // for \@! and \@<! it is a match when result is FALSE
if (result != (pim->state->c == NFA_START_INVISIBLE_NEG
|| pim->state->c == NFA_START_INVISIBLE_NEG_FIRST
|| pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG
|| pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG_FIRST)) {
- /* Copy submatch info from the recursive call */
+ // Copy submatch info from the recursive call
copy_sub_off(&t->subs.norm, &pim->subs.norm);
if (nfa_has_zsubexpr)
copy_sub_off(&t->subs.synt, &pim->subs.synt);
- } else
- /* look-behind match failed, don't add the state */
+ } else {
+ // look-behind match failed, don't add the state
continue;
+ }
- /* Postponed invisible match was handled, don't add it to
- * following states. */
+ // Postponed invisible match was handled, don't add it to
+ // following states.
pim = NULL;
}
- /* If "pim" points into l->t it will become invalid when
- * adding the state causes the list to be reallocated. Make a
- * local copy to avoid that. */
+ // If "pim" points into l->t it will become invalid when
+ // adding the state causes the list to be reallocated. Make a
+ // local copy to avoid that.
if (pim == &t->pim) {
copy_pim(&pim_copy, pim);
pim = &pim_copy;
@@ -5975,18 +5981,17 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
nextlist->t[nextlist->n - 1].count = add_count;
}
}
-
- } /* for (thislist = thislist; thislist->state; thislist++) */
-
- /* Look for the start of a match in the current position by adding the
- * start state to the list of states.
- * The first found match is the leftmost one, thus the order of states
- * matters!
- * Do not add the start state in recursive calls of nfa_regmatch(),
- * because recursive calls should only start in the first position.
- * Unless "nfa_endp" is not NULL, then we match the end position.
- * Also don't start a match past the first line. */
- if (nfa_match == FALSE
+ } // for (thislist = thislist; thislist->state; thislist++)
+
+ // Look for the start of a match in the current position by adding the
+ // start state to the list of states.
+ // The first found match is the leftmost one, thus the order of states
+ // matters!
+ // Do not add the start state in recursive calls of nfa_regmatch(),
+ // because recursive calls should only start in the first position.
+ // Unless "nfa_endp" is not NULL, then we match the end position.
+ // Also don't start a match past the first line.
+ if (!nfa_match
&& ((toplevel
&& reglnum == 0
&& clen != 0
@@ -6002,8 +6007,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
#ifdef REGEXP_DEBUG
fprintf(log_fd, "(---) STARTSTATE\n");
#endif
- /* Inline optimized code for addstate() if we know the state is
- * the first MOPEN. */
+ // Inline optimized code for addstate() if we know the state is
+ // the first MOPEN.
if (toplevel) {
int add = TRUE;
int c;
@@ -6012,18 +6017,19 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
if (nextlist->n == 0) {
colnr_T col = (colnr_T)(reginput - regline) + clen;
- /* Nextlist is empty, we can skip ahead to the
- * character that must appear at the start. */
- if (skip_to_start(prog->regstart, &col) == FAIL)
+ // Nextlist is empty, we can skip ahead to the
+ // character that must appear at the start.
+ if (skip_to_start(prog->regstart, &col) == FAIL) {
break;
+ }
#ifdef REGEXP_DEBUG
fprintf(log_fd, " Skipping ahead %d bytes to regstart\n",
col - ((colnr_T)(reginput - regline) + clen));
#endif
reginput = regline + col - clen;
} else {
- /* Checking if the required start character matches is
- * cheaper than adding a state that won't match. */
+ // Checking if the required start character matches is
+ // cheaper than adding a state that won't match.
c = PTR2CHAR(reginput + clen);
if (c != prog->regstart && (!ireg_ic || vim_tolower(c)
!= vim_tolower(prog->regstart))) {
@@ -6060,21 +6066,29 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
#endif
nextchar:
- /* Advance to the next character, or advance to the next line, or
- * finish. */
- if (clen != 0)
+ // Advance to the next character, or advance to the next line, or
+ // finish.
+ if (clen != 0) {
reginput += clen;
- else if (go_to_nextline || (nfa_endp != NULL && REG_MULTI
- && reglnum < nfa_endp->se_u.pos.lnum))
+ } else if (go_to_nextline || (nfa_endp != NULL && REG_MULTI
+ && reglnum < nfa_endp->se_u.pos.lnum)) {
reg_nextline();
- else
+ } else {
break;
+ }
// Allow interrupting with CTRL-C.
- fast_breakcheck();
+ line_breakcheck();
if (got_int) {
break;
}
+ // Check for timeout once every twenty times to avoid overhead.
+ if (nfa_time_limit != NULL && ++nfa_time_count == 20) {
+ nfa_time_count = 0;
+ if (profile_passed_limit(*nfa_time_limit)) {
+ break;
+ }
+ }
}
#ifdef REGEXP_DEBUG
@@ -6084,7 +6098,7 @@ nextchar:
#endif
theend:
- /* Free memory */
+ // Free memory
xfree(list[0].t);
xfree(list[1].t);
xfree(listids);
@@ -6096,11 +6110,9 @@ theend:
return nfa_match;
}
-/*
- * Try match of "prog" with at regline["col"].
- * Returns <= 0 for failure, number of lines contained in the match otherwise.
- */
-static long nfa_regtry(nfa_regprog_T *prog, colnr_T col)
+// Try match of "prog" with at regline["col"].
+// Returns <= 0 for failure, number of lines contained in the match otherwise.
+static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm)
{
int i;
regsubs_T subs, m;
@@ -6110,6 +6122,8 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col)
#endif
reginput = regline + col;
+ nfa_time_limit = tm;
+ nfa_time_count = 0;
#ifdef REGEXP_DEBUG
f = fopen(NFA_REGEXP_RUN_LOG, "a");
@@ -6134,7 +6148,7 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col)
clear_sub(&m.synt);
int result = nfa_regmatch(prog, start, &subs, &m);
- if (result == FALSE) {
+ if (!result) {
return 0;
} else if (result == NFA_TOO_EXPENSIVE) {
return result;
@@ -6207,17 +6221,16 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col)
return 1 + reglnum;
}
-/*
- * Match a regexp against a string ("line" points to the string) or multiple
- * lines ("line" is NULL, use reg_getline()).
- *
- * Returns <= 0 for failure, number of lines contained in the match otherwise.
- */
-static long
-nfa_regexec_both (
- char_u *line,
- colnr_T startcol /* column to start looking for match */
-)
+/// Match a regexp against a string ("line" points to the string) or multiple
+/// lines ("line" is NULL, use reg_getline()).
+///
+/// @param line String in which to search or NULL
+/// @param startcol Column to start looking for match
+/// @param tm Timeout limit or NULL
+///
+/// @return <= 0 if there is no match and number of lines contained in the
+/// match otherwise.
+static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm)
{
nfa_regprog_T *prog;
long retval = 0L;
@@ -6297,7 +6310,7 @@ nfa_regexec_both (
prog->state[i].lastlist[1] = 0;
}
- retval = nfa_regtry(prog, col);
+ retval = nfa_regtry(prog, col, tm);
nfa_regengine.expr = NULL;
@@ -6449,7 +6462,7 @@ nfa_regexec_nl (
ireg_ic = rmp->rm_ic;
ireg_icombine = FALSE;
ireg_maxcol = 0;
- return nfa_regexec_both(line, col);
+ return nfa_regexec_both(line, col, NULL);
}
/// Matches a regexp against multiple lines.
@@ -6500,5 +6513,5 @@ static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
ireg_icombine = FALSE;
ireg_maxcol = rmp->rmm_maxcol;
- return nfa_regexec_both(NULL, col);
+ return nfa_regexec_both(NULL, col, tm);
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index d650d56bc0..10b5b6bba4 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -387,14 +387,15 @@ void update_screen(int type)
if (wp->w_buffer->b_mod_set) {
win_T *wwp;
- /* Check if we already did this buffer. */
- for (wwp = firstwin; wwp != wp; wwp = wwp->w_next)
- if (wwp->w_buffer == wp->w_buffer)
+ // Check if we already did this buffer.
+ for (wwp = firstwin; wwp != wp; wwp = wwp->w_next) {
+ if (wwp->w_buffer == wp->w_buffer) {
break;
- if (
- wwp == wp &&
- syntax_present(wp))
+ }
+ }
+ if (wwp == wp && syntax_present(wp)) {
syn_stack_apply_changes(wp->w_buffer);
+ }
}
}
@@ -1231,16 +1232,16 @@ static void win_update(win_T *wp)
|| did_update == DID_FOLD
|| (did_update == DID_LINE
&& syntax_present(wp)
- && (
- (foldmethodIsSyntax(wp)
- && hasAnyFolding(wp)) ||
- syntax_check_changed(lnum)))
+ && ((foldmethodIsSyntax(wp)
+ && hasAnyFolding(wp))
+ || syntax_check_changed(lnum)))
// match in fixed position might need redraw
// if lines were inserted or deleted
- || (wp->w_match_head != NULL && buf->b_mod_xlines != 0)
- ))))) {
- if (lnum == mod_top)
- top_to_mod = FALSE;
+ || (wp->w_match_head != NULL
+ && buf->b_mod_xlines != 0)))))) {
+ if (lnum == mod_top) {
+ top_to_mod = false;
+ }
/*
* When at start of changed lines: May scroll following lines
@@ -2472,21 +2473,16 @@ win_line (
mb_ptr_adv(ptr);
}
- /* When:
- * - 'cuc' is set, or
- * - 'colorcolumn' is set, or
- * - 'virtualedit' is set, or
- * - the visual mode is active,
- * the end of the line may be before the start of the displayed part.
- */
- if (vcol < v && (
- wp->w_p_cuc
- || draw_color_col
- ||
- virtual_active()
- ||
- (VIsual_active && wp->w_buffer == curwin->w_buffer)
- )) {
+ // When:
+ // - 'cuc' is set, or
+ // - 'colorcolumn' is set, or
+ // - 'virtualedit' is set, or
+ // - the visual mode is active,
+ // the end of the line may be before the start of the displayed part.
+ if (vcol < v && (wp->w_p_cuc
+ || draw_color_col
+ || virtual_active()
+ || (VIsual_active && wp->w_buffer == curwin->w_buffer))) {
vcol = v;
}
@@ -3273,12 +3269,12 @@ win_line (
* contains the @Spell cluster. */
if (has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
- if (!attr_pri)
+ if (!attr_pri) {
char_attr = syntax_attr;
- if (c != 0 && (
- !has_syntax ||
- can_spell)) {
- char_u *prev_ptr, *p;
+ }
+ if (c != 0 && (!has_syntax || can_spell)) {
+ char_u *prev_ptr;
+ char_u *p;
int len;
hlf_T spell_hlf = HLF_COUNT;
if (has_mbyte) {
@@ -3607,25 +3603,22 @@ win_line (
wp->w_p_rl ? (col >= 0) :
(col < wp->w_width))) {
c = ' ';
- --ptr; /* put it back at the NUL */
- } else if ((
- diff_hlf != (hlf_T)0 ||
- line_attr != 0
- ) && (
- wp->w_p_rl ? (col >= 0) :
- (col
- - boguscols
- < wp->w_width))) {
- /* Highlight until the right side of the window */
+ ptr--; // put it back at the NUL
+ } else if ((diff_hlf != (hlf_T)0 || line_attr != 0)
+ && (wp->w_p_rl
+ ? (col >= 0)
+ : (col - boguscols < wp->w_width))) {
+ // Highlight until the right side of the window
c = ' ';
- --ptr; /* put it back at the NUL */
+ ptr--; // put it back at the NUL
- /* Remember we do the char for line highlighting. */
- ++did_line_attr;
+ // Remember we do the char for line highlighting.
+ did_line_attr++;
- /* don't do search HL for the rest of the line */
- if (line_attr != 0 && char_attr == search_attr && col > 0)
+ // don't do search HL for the rest of the line
+ if (line_attr != 0 && char_attr == search_attr && col > 0) {
char_attr = line_attr;
+ }
if (diff_hlf == HLF_TXD) {
diff_hlf = HLF_CHD;
if (attr == 0 || char_attr != attr) {
@@ -3639,8 +3632,8 @@ win_line (
}
if (wp->w_p_cole > 0
- && (wp != curwin || lnum != wp->w_cursor.lnum ||
- conceal_cursor_line(wp))
+ && (wp != curwin || lnum != wp->w_cursor.lnum
+ || conceal_cursor_line(wp))
&& ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc)
&& !(lnum_in_visual_area
&& vim_strchr(wp->w_p_cocu, 'v') == NULL)) {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index fffae1ecb2..6e2b69fff7 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -453,25 +453,24 @@ void last_pat_prog(regmmatch_T *regmatch)
--emsg_off;
}
-/*
- * lowest level search function.
- * Search for 'count'th occurrence of pattern 'pat' in direction 'dir'.
- * Start at position 'pos' and return the found position in 'pos'.
- *
- * if (options & SEARCH_MSG) == 0 don't give any messages
- * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages
- * if (options & SEARCH_MSG) == SEARCH_MSG give all messages
- * if (options & SEARCH_HIS) put search pattern in history
- * if (options & SEARCH_END) return position at end of match
- * if (options & SEARCH_START) accept match at pos itself
- * if (options & SEARCH_KEEP) keep previous search pattern
- * if (options & SEARCH_FOLD) match only once in a closed fold
- * if (options & SEARCH_PEEK) check for typed char, cancel search
- *
- * Return FAIL (zero) for failure, non-zero for success.
- * Returns the index of the first matching
- * subpattern plus one; one if there was none.
- */
+/// lowest level search function.
+/// Search for 'count'th occurrence of pattern 'pat' in direction 'dir'.
+/// Start at position 'pos' and return the found position in 'pos'.
+///
+/// if (options & SEARCH_MSG) == 0 don't give any messages
+/// if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages
+/// if (options & SEARCH_MSG) == SEARCH_MSG give all messages
+/// if (options & SEARCH_HIS) put search pattern in history
+/// if (options & SEARCH_END) return position at end of match
+/// if (options & SEARCH_START) accept match at pos itself
+/// if (options & SEARCH_KEEP) keep previous search pattern
+/// if (options & SEARCH_FOLD) match only once in a closed fold
+/// if (options & SEARCH_PEEK) check for typed char, cancel search
+/// if (options & SEARCH_COL) start at pos->col instead of zero
+///
+/// @returns FAIL (zero) for failure, non-zero for success.
+/// the index of the first matching
+/// subpattern plus one; one if there was none.
int searchit(
win_T *win, /* window to search in, can be NULL for a
buffer without a window! */
@@ -571,16 +570,14 @@ int searchit(
if (tm != NULL && profile_passed_limit(*tm))
break;
- /*
- * Look for a match somewhere in line "lnum".
- */
+ // Look for a match somewhere in line "lnum".
+ colnr_T col = at_first_line && (options & SEARCH_COL) ? pos->col : 0;
nmatched = vim_regexec_multi(&regmatch, win, buf,
- lnum, (colnr_T)0,
- tm
- );
- /* Abort searching on an error (e.g., out of stack). */
- if (called_emsg)
+ lnum, col, tm);
+ // Abort searching on an error (e.g., out of stack).
+ if (called_emsg) {
break;
+ }
if (nmatched > 0) {
/* match may actually be in another line when using \zs */
matchpos = regmatch.startpos[0];
@@ -641,9 +638,9 @@ int searchit(
break;
}
- if (ptr[matchcol] == NUL ||
- (nmatched = vim_regexec_multi(&regmatch, win, buf, lnum,
- matchcol, tm)) == 0) {
+ if (ptr[matchcol] == NUL
+ || (nmatched = vim_regexec_multi(&regmatch, win, buf, lnum,
+ matchcol, tm)) == 0) {
match_ok = false;
break;
}
@@ -881,9 +878,8 @@ static void set_vv_searchforward(void)
set_vim_var_nr(VV_SEARCHFORWARD, (long)(spats[0].off.dir == '/'));
}
-/*
- * Return the number of the first subpat that matched.
- */
+// Return the number of the first subpat that matched.
+// Return zero if none of them matched.
static int first_submatch(regmmatch_T *rp)
{
int submatch;
@@ -1031,19 +1027,18 @@ int do_search(
spats[0].off.line = FALSE;
spats[0].off.end = FALSE;
spats[0].off.off = 0;
- /*
- * Check for a line offset or a character offset.
- * For get_address (echo off) we don't check for a character
- * offset, because it is meaningless and the 's' could be a
- * substitute command.
- */
- if (*p == '+' || *p == '-' || ascii_isdigit(*p))
- spats[0].off.line = TRUE;
- else if ((options & SEARCH_OPT) &&
- (*p == 'e' || *p == 's' || *p == 'b')) {
- if (*p == 'e') /* end */
+ // Check for a line offset or a character offset.
+ // For get_address (echo off) we don't check for a character
+ // offset, because it is meaningless and the 's' could be a
+ // substitute command.
+ if (*p == '+' || *p == '-' || ascii_isdigit(*p)) {
+ spats[0].off.line = true;
+ } else if ((options & SEARCH_OPT)
+ && (*p == 'e' || *p == 's' || *p == 'b')) {
+ if (*p == 'e') { // end
spats[0].off.end = true;
- ++p;
+ }
+ p++;
}
if (ascii_isdigit(*p) || *p == '+' || *p == '-') { /* got an offset */
/* 'nr' or '+nr' or '-nr' */
@@ -1651,8 +1646,9 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
/*
* Look for matching #if, #else, #elif, or #endif
*/
- if (oap != NULL)
- oap->motion_type = MLINE; /* Linewise for this case only */
+ if (oap != NULL) {
+ oap->motion_type = kMTLineWise; // Linewise for this case only
+ }
if (initc != '#') {
ptr = skipwhite(skipwhite(linep) + 1);
if (STRNCMP(ptr, "if", 2) == 0 || STRNCMP(ptr, "el", 2) == 0)
@@ -1787,14 +1783,13 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
}
- /*
- * If FM_BLOCKSTOP given, stop at a '{' or '}' in column 0.
- */
- if (pos.col == 0 && (flags & FM_BLOCKSTOP) &&
- (linep[0] == '{' || linep[0] == '}')) {
- if (linep[0] == findc && count == 0) /* match! */
+ // If FM_BLOCKSTOP given, stop at a '{' or '}' in column 0.
+ if (pos.col == 0 && (flags & FM_BLOCKSTOP)
+ && (linep[0] == '{' || linep[0] == '}')) {
+ if (linep[0] == findc && count == 0) { // match!
return &pos;
- break; /* out of scope */
+ }
+ break; // out of scope
}
if (comment_dir) {
@@ -1963,15 +1958,15 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
if (linep[pos.col - 2] == '\'') {
pos.col -= 2;
break;
- } else if (linep[pos.col - 2] == '\\' &&
- pos.col > 2 && linep[pos.col - 3] == '\'') {
+ } else if (linep[pos.col - 2] == '\\'
+ && pos.col > 2 && linep[pos.col - 3] == '\'') {
pos.col -= 3;
break;
}
}
- } else if (linep[pos.col + 1]) { /* forward search */
- if (linep[pos.col + 1] == '\\' &&
- linep[pos.col + 2] && linep[pos.col + 3] == '\'') {
+ } else if (linep[pos.col + 1]) { // forward search
+ if (linep[pos.col + 1] == '\\'
+ && linep[pos.col + 2] && linep[pos.col + 3] == '\'') {
pos.col += 3;
break;
} else if (linep[pos.col + 2] == '\'') {
@@ -2188,30 +2183,32 @@ int findsent(int dir, long count)
* if on an empty line, skip up to a non-empty line
*/
if (gchar_pos(&pos) == NUL) {
- do
- if ((*func)(&pos) == -1)
+ do {
+ if ((*func)(&pos) == -1) {
break;
- while (gchar_pos(&pos) == NUL);
- if (dir == FORWARD)
+ }
+ } while (gchar_pos(&pos) == NUL);
+ if (dir == FORWARD) {
goto found;
- }
- /*
- * if on the start of a paragraph or a section and searching forward,
- * go to the next line
- */
- else if (dir == FORWARD && pos.col == 0 &&
- startPS(pos.lnum, NUL, FALSE)) {
- if (pos.lnum == curbuf->b_ml.ml_line_count)
+ }
+ // if on the start of a paragraph or a section and searching forward,
+ // go to the next line
+ } else if (dir == FORWARD && pos.col == 0
+ && startPS(pos.lnum, NUL, false)) {
+ if (pos.lnum == curbuf->b_ml.ml_line_count) {
return FAIL;
- ++pos.lnum;
+ }
+ pos.lnum++;
goto found;
- } else if (dir == BACKWARD)
+ } else if (dir == BACKWARD) {
decl(&pos);
+ }
- /* go back to the previous non-blank char */
- found_dot = FALSE;
- while ((c = gchar_pos(&pos)) == ' ' || c == '\t' ||
- (dir == BACKWARD && vim_strchr((char_u *)".!?)]\"'", c) != NULL)) {
+ // go back to the previous non-blank char
+ found_dot = false;
+ while ((c = gchar_pos(&pos)) == ' ' || c == '\t'
+ || (dir == BACKWARD
+ && vim_strchr((char_u *)".!?)]\"'", c) != NULL)) {
if (vim_strchr((char_u *)".!?", c) != NULL) {
/* Only skip over a '.', '!' and '?' once. */
if (found_dot)
@@ -2375,12 +2372,14 @@ int startPS(linenr_T lnum, int para, int both)
char_u *s;
s = ml_get(lnum);
- if (*s == para || *s == '\f' || (both && *s == '}'))
- return TRUE;
- if (*s == '.' && (inmacro(p_sections, s + 1) ||
- (!para && inmacro(p_para, s + 1))))
- return TRUE;
- return FALSE;
+ if (*s == para || *s == '\f' || (both && *s == '}')) {
+ return true;
+ }
+ if (*s == '.' && (inmacro(p_sections, s + 1)
+ || (!para && inmacro(p_para, s + 1)))) {
+ return true;
+ }
+ return false;
}
/*
@@ -2797,7 +2796,7 @@ current_word (
redraw_curbuf_later(INVERTED); /* update the inversion */
} else {
oap->start = start_pos;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
}
--count;
}
@@ -3032,7 +3031,7 @@ extend:
else
oap->inclusive = false;
oap->start = start_pos;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
}
return OK;
}
@@ -3156,7 +3155,7 @@ current_block (
showmode();
} else {
oap->start = start_pos;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
oap->inclusive = false;
if (sol)
incl(&curwin->w_cursor);
@@ -3403,7 +3402,7 @@ again:
showmode();
} else {
oap->start = start_pos;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
if (lt(end_pos, start_pos)) {
/* End is before the start: there is no text between tags; operate
* on an empty area. */
@@ -3568,7 +3567,7 @@ extend:
} else {
oap->start.lnum = start_lnum;
oap->start.col = 0;
- oap->motion_type = MLINE;
+ oap->motion_type = kMTLineWise;
}
curwin->w_cursor.lnum = end_lnum;
curwin->w_cursor.col = 0;
@@ -3810,7 +3809,7 @@ current_quote (
}
} else {
oap->start = curwin->w_cursor;
- oap->motion_type = MCHAR;
+ oap->motion_type = kMTCharWise;
}
/* Set end position. */
@@ -4154,19 +4153,20 @@ find_pattern_in_path (
FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname, NULL);
already_searched = FALSE;
if (new_fname != NULL) {
- /* Check whether we have already searched in this file */
+ // Check whether we have already searched in this file
for (i = 0;; i++) {
- if (i == depth + 1)
+ if (i == depth + 1) {
i = old_files;
- if (i == max_path_depth)
+ }
+ if (i == max_path_depth) {
break;
- if (path_full_compare(new_fname, files[i].name, TRUE) & kEqualFiles) {
- if (type != CHECK_PATH &&
- action == ACTION_SHOW_ALL && files[i].matched) {
- msg_putchar('\n'); /* cursor below last one */
- if (!got_int) { /* don't display if 'q'
- typed at "--more--"
- message */
+ }
+ if (path_full_compare(new_fname, files[i].name, true) & kEqualFiles) {
+ if (type != CHECK_PATH
+ && action == ACTION_SHOW_ALL && files[i].matched) {
+ msg_putchar('\n'); // cursor below last one */
+ if (!got_int) { // don't display if 'q' typed at "--more--"
+ // message
msg_home_replace_hl(new_fname);
MSG_PUTS(_(" (includes previously listed match)"));
prev_fname = NULL;
@@ -4181,15 +4181,15 @@ find_pattern_in_path (
}
if (type == CHECK_PATH && (action == ACTION_SHOW_ALL
- || (new_fname == NULL &&
- !already_searched))) {
- if (did_show)
- msg_putchar('\n'); /* cursor below last one */
- else {
- gotocmdline(TRUE); /* cursor at status line */
+ || (new_fname == NULL && !already_searched))) {
+ if (did_show) {
+ msg_putchar('\n'); // cursor below last one
+ } else {
+ gotocmdline(true); // cursor at status line
MSG_PUTS_TITLE(_("--- Included files "));
- if (action != ACTION_SHOW_ALL)
+ if (action != ACTION_SHOW_ALL) {
MSG_PUTS_TITLE(_("not found "));
+ }
MSG_PUTS_TITLE(_("in path ---\n"));
}
did_show = TRUE;
@@ -4348,16 +4348,15 @@ search_line:
&& vim_regexec(&regmatch, line, (colnr_T)(p - line))) {
matched = TRUE;
startp = regmatch.startp[0];
- /*
- * Check if the line is not a comment line (unless we are
- * looking for a define). A line starting with "# define"
- * is not considered to be a comment line.
- */
+ // Check if the line is not a comment line (unless we are
+ // looking for a define). A line starting with "# define"
+ // is not considered to be a comment line.
if (skip_comments) {
- if ((*line != '#' ||
- STRNCMP(skipwhite(line + 1), "define", 6) != 0)
- && get_leader_len(line, NULL, FALSE, TRUE))
- matched = FALSE;
+ if ((*line != '#'
+ || STRNCMP(skipwhite(line + 1), "define", 6) != 0)
+ && get_leader_len(line, NULL, false, true)) {
+ matched = false;
+ }
/*
* Also check for a "/ *" or "/ /" before the match.
diff --git a/src/nvim/search.h b/src/nvim/search.h
index 6947f79d49..d4e40cb287 100644
--- a/src/nvim/search.h
+++ b/src/nvim/search.h
@@ -15,19 +15,20 @@
#define ACTION_SHOW_ALL 4
#define ACTION_EXPAND 5
-/* Values for 'options' argument in do_search() and searchit() */
-#define SEARCH_REV 0x01 /* go in reverse of previous dir. */
-#define SEARCH_ECHO 0x02 /* echo the search command and handle options */
-#define SEARCH_MSG 0x0c /* give messages (yes, it's not 0x04) */
-#define SEARCH_NFMSG 0x08 /* give all messages except not found */
-#define SEARCH_OPT 0x10 /* interpret optional flags */
-#define SEARCH_HIS 0x20 /* put search pattern in history */
-#define SEARCH_END 0x40 /* put cursor at end of match */
-#define SEARCH_NOOF 0x80 /* don't add offset to position */
-#define SEARCH_START 0x100 /* start search without col offset */
-#define SEARCH_MARK 0x200 /* set previous context mark */
-#define SEARCH_KEEP 0x400 /* keep previous search pattern */
-#define SEARCH_PEEK 0x800 /* peek for typed char, cancel search */
+// Values for 'options' argument in do_search() and searchit()
+#define SEARCH_REV 0x01 ///< go in reverse of previous dir.
+#define SEARCH_ECHO 0x02 ///< echo the search command and handle options
+#define SEARCH_MSG 0x0c ///< give messages (yes, it's not 0x04)
+#define SEARCH_NFMSG 0x08 ///< give all messages except not found
+#define SEARCH_OPT 0x10 ///< interpret optional flags
+#define SEARCH_HIS 0x20 ///< put search pattern in history
+#define SEARCH_END 0x40 ///< put cursor at end of match
+#define SEARCH_NOOF 0x80 ///< don't add offset to position
+#define SEARCH_START 0x100 ///< start search without col offset
+#define SEARCH_MARK 0x200 ///< set previous context mark
+#define SEARCH_KEEP 0x400 ///< keep previous search pattern
+#define SEARCH_PEEK 0x800 ///< peek for typed char, cancel search
+#define SEARCH_COL 0x1000 ///< start at specified column instead of zero
/* Values for flags argument for findmatchlimit() */
#define FM_BACKWARD 0x01 /* search backwards */
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 32a02b0fb7..3192be1b3c 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -283,7 +283,7 @@ typedef struct {
} history_item;
struct reg {
char name;
- uint8_t type;
+ MotionType type;
char **contents;
size_t contents_size;
size_t width;
@@ -475,7 +475,7 @@ static const ShadaEntry sd_default_values[] = {
.additional_elements = NULL),
DEF_SDE(Register, reg,
.name = NUL,
- .type = MCHAR,
+ .type = kMTCharWise,
.contents = NULL,
.contents_size = 0,
.width = 0,
@@ -1407,9 +1407,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
break;
}
case kSDItemRegister: {
- if (cur_entry.data.reg.type != MCHAR
- && cur_entry.data.reg.type != MLINE
- && cur_entry.data.reg.type != MBLOCK) {
+ if (cur_entry.data.reg.type != kMTCharWise
+ && cur_entry.data.reg.type != kMTLineWise
+ && cur_entry.data.reg.type != kMTBlockWise) {
shada_free_shada_entry(&cur_entry);
break;
}
@@ -1882,7 +1882,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
msgpack_pack_char(spacker, entry.data.reg.name);
if (!CHECK_DEFAULT(entry, reg.type)) {
PACK_STATIC_STR(REG_KEY_TYPE);
- msgpack_pack_uint8(spacker, entry.data.reg.type);
+ msgpack_pack_uint8(spacker, (uint8_t)entry.data.reg.type);
}
if (!CHECK_DEFAULT(entry, reg.width)) {
PACK_STATIC_STR(REG_KEY_WIDTH);
@@ -2757,8 +2757,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
.reg = {
.contents = (char **) reg.y_array,
.contents_size = (size_t) reg.y_size,
- .type = (uint8_t) reg.y_type,
- .width = (size_t) (reg.y_type == MBLOCK ? reg.y_width : 0),
+ .type = reg.y_type,
+ .width = (size_t) (reg.y_type == kMTBlockWise ? reg.y_width : 0),
.additional_data = reg.additional_data,
.name = name,
}
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index fdae89b84c..0acaa9ae2b 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -319,7 +319,6 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
-#include "nvim/tempfile.h"
#include "nvim/undo.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 26f0a6c94b..41af7af55c 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -4478,12 +4478,10 @@ syn_cmd_region (
if (illegal || not_enough)
rest = NULL;
- /*
- * Must have a "start" and "end" pattern.
- */
- if (rest != NULL && (pat_ptrs[ITEM_START] == NULL ||
- pat_ptrs[ITEM_END] == NULL)) {
- not_enough = TRUE;
+ // Must have a "start" and "end" pattern.
+ if (rest != NULL && (pat_ptrs[ITEM_START] == NULL
+ || pat_ptrs[ITEM_END] == NULL)) {
+ not_enough = true;
rest = NULL;
}
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 26a89094aa..7885d467d8 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -526,19 +526,17 @@ do_tag (
taglen_advance(taglen);
MSG_PUTS_ATTR(_("file\n"), hl_attr(HLF_T));
- for (i = 0; i < num_matches && !got_int; ++i) {
+ for (i = 0; i < num_matches && !got_int; i++) {
parse_match(matches[i], &tagp);
- if (!new_tag && (
- (g_do_tagpreview != 0
- && i == ptag_entry.cur_match) ||
- (use_tagstack
- && i == tagstack[tagstackidx].cur_match)))
+ if (!new_tag && ((g_do_tagpreview != 0 && i == ptag_entry.cur_match)
+ || (use_tagstack
+ && i == tagstack[tagstackidx].cur_match))) {
*IObuff = '>';
- else
+ } else {
*IObuff = ' ';
- vim_snprintf((char *)IObuff + 1, IOSIZE - 1,
- "%2d %s ", i + 1,
- mt_names[matches[i][0] & MT_MASK]);
+ }
+ vim_snprintf((char *)IObuff + 1, IOSIZE - 1, "%2d %s ", i + 1,
+ mt_names[matches[i][0] & MT_MASK]);
msg_puts(IObuff);
if (tagp.tagkind != NULL)
msg_outtrans_len(tagp.tagkind,
@@ -1147,6 +1145,22 @@ find_tags (
int get_it_again = FALSE;
int use_cscope = (flags & TAG_CSCOPE);
int verbose = (flags & TAG_VERBOSE);
+ int save_p_ic = p_ic;
+
+ // Change the value of 'ignorecase' according to 'tagcase' for the
+ // duration of this function.
+ switch (curbuf->b_tc_flags ? curbuf->b_tc_flags : tc_flags) {
+ case TC_FOLLOWIC:
+ break;
+ case TC_IGNORE:
+ p_ic = true;
+ break;
+ case TC_MATCH:
+ p_ic = false;
+ break;
+ default:
+ assert(false);
+ }
help_save = curbuf->b_help;
orgpat.pat = pat;
@@ -1210,20 +1224,15 @@ find_tags (
for (round = 1; round <= 2; ++round) {
linear = (orgpat.headlen == 0 || !p_tbs || round == 2);
- /*
- * Try tag file names from tags option one by one.
- */
- for (first_file = TRUE;
- use_cscope ||
- get_tagfname(&tn, first_file, tag_fname) == OK;
- first_file = FALSE) {
- /*
- * A file that doesn't exist is silently ignored. Only when not a
- * single file is found, an error message is given (further on).
- */
- if (use_cscope)
- fp = NULL; /* avoid GCC warning */
- else {
+ // Try tag file names from tags option one by one.
+ for (first_file = true;
+ use_cscope || get_tagfname(&tn, first_file, tag_fname) == OK;
+ first_file = false) {
+ // A file that doesn't exist is silently ignored. Only when not a
+ // single file is found, an error message is given (further on).
+ if (use_cscope) {
+ fp = NULL; // avoid GCC warning
+ } else {
if (curbuf->b_help) {
/* Prefer help tags according to 'helplang'. Put the
* two-letter language name in help_lang[]. */
@@ -1955,6 +1964,8 @@ findtag_end:
curbuf->b_help = help_save;
xfree(saved_pat);
+ p_ic = save_p_ic;
+
return retval;
}
diff --git a/src/nvim/tempfile.c b/src/nvim/tempfile.c
deleted file mode 100644
index afe926b2ef..0000000000
--- a/src/nvim/tempfile.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "nvim/ascii.h"
-#include "nvim/memory.h"
-#include "nvim/misc1.h"
-#include "nvim/os/os.h"
-#include "nvim/os/os_defs.h"
-#include "nvim/path.h"
-#include "nvim/strings.h"
-#include "nvim/tempfile.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "tempfile.c.generated.h"
-#endif
-
-/// Name of Vim's own temp dir. Ends in a slash.
-static char_u *vim_tempdir = NULL;
-
-/// Create a directory for private use by this instance of Neovim.
-/// This is done once, and the same directory is used for all temp files.
-/// This method avoids security problems because of symlink attacks et al.
-/// It's also a bit faster, because we only need to check for an existing
-/// file when creating the directory and not for each temp file.
-static void vim_maketempdir(void)
-{
- static const char *temp_dirs[] = TEMP_DIR_NAMES;
- // Try the entries in `TEMP_DIR_NAMES` to create the temp directory.
- char_u template[TEMP_FILE_PATH_MAXLEN];
- char_u path[TEMP_FILE_PATH_MAXLEN];
- for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); ++i) {
- // Expand environment variables, leave room for "/nvimXXXXXX/999999999"
- // Skip the directory check if the expansion fails.
- expand_env((char_u *)temp_dirs[i], template, TEMP_FILE_PATH_MAXLEN - 22);
- if (template[0] == '$' || !os_isdir(template)) {
- continue;
- }
-
- add_pathsep((char *)template);
- // Concatenate with temporary directory name pattern
- STRCAT(template, "nvimXXXXXX");
-
- if (os_mkdtemp((const char *)template, (char *)path) != 0) {
- continue;
- }
-
- if (vim_settempdir((char *)path)) {
- // Successfully created and set temporary directory so stop trying.
- break;
- } else {
- // Couldn't set `vim_tempdir` to `path` so remove created directory.
- os_rmdir((char *)path);
- }
- }
-}
-
-/// Delete the temp directory and all files it contains.
-void vim_deltempdir(void)
-{
- if (vim_tempdir != NULL) {
- snprintf((char *)NameBuff, MAXPATHL, "%s*", vim_tempdir);
-
- char_u **files;
- int file_count;
-
- // Note: We cannot just do `&NameBuff` because it is a statically
- // sized array so `NameBuff == &NameBuff` according to C semantics.
- char_u *buff_list[1] = {NameBuff};
- if (gen_expand_wildcards(1, buff_list, &file_count, &files,
- EW_DIR|EW_FILE|EW_SILENT) == OK) {
- for (int i = 0; i < file_count; ++i) {
- os_remove((char *)files[i]);
- }
- FreeWild(file_count, files);
- }
- path_tail(NameBuff)[-1] = NUL;
- os_rmdir((char *)NameBuff);
-
- xfree(vim_tempdir);
- vim_tempdir = NULL;
- }
-}
-
-/// Get the name of temp directory. This directory would be created on the first
-/// call to this function.
-char_u *vim_gettempdir(void)
-{
- if (vim_tempdir == NULL) {
- vim_maketempdir();
- }
-
- return vim_tempdir;
-}
-
-/// Set Neovim own temporary directory name to `tempdir`. This directory should
-/// be already created. Expand this name to a full path and put it in
-/// `vim_tempdir`. This avoids that using `:cd` would confuse us.
-///
-/// @param tempdir must be no longer than MAXPATHL.
-///
-/// @return false if we run out of memory.
-static bool vim_settempdir(char *tempdir)
-{
- char *buf = verbose_try_malloc(MAXPATHL + 2);
- if (!buf) {
- return false;
- }
- vim_FullName(tempdir, buf, MAXPATHL, false);
- add_pathsep(buf);
- vim_tempdir = (char_u *)xstrdup(buf);
- xfree(buf);
- return true;
-}
-
-/// Return a unique name that can be used for a temp file.
-///
-/// @note The temp file is NOT created.
-///
-/// @return pointer to the temp file name or NULL if Neovim can't create
-/// temporary directory for its own temporary files.
-char_u *vim_tempname(void)
-{
- // Temp filename counter.
- static uint32_t temp_count;
-
- char_u *tempdir = vim_gettempdir();
- if (!tempdir) {
- return NULL;
- }
-
- // There is no need to check if the file exists, because we own the directory
- // and nobody else creates a file in it.
- char_u template[TEMP_FILE_PATH_MAXLEN];
- snprintf((char *)template, TEMP_FILE_PATH_MAXLEN,
- "%s%" PRIu32, tempdir, temp_count++);
- return vim_strsave(template);
-}
diff --git a/src/nvim/tempfile.h b/src/nvim/tempfile.h
deleted file mode 100644
index c030a70eeb..0000000000
--- a/src/nvim/tempfile.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef NVIM_TEMPFILE_H
-#define NVIM_TEMPFILE_H
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "tempfile.h.generated.h"
-#endif
-
-#endif // NVIM_TEMPFILE_H
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 0440272eb9..104cc47cda 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -175,7 +175,16 @@ void terminal_init(void)
for (int color_index = 0; color_index < 256; color_index++) {
VTermColor color;
- vterm_state_get_palette_color(state, color_index, &color);
+ // Some of the default 16 colors has the same color as the later
+ // 240 colors. To avoid collisions, we will use the custom colors
+ // below in non true color mode.
+ if (color_index < 16) {
+ color.red = 0;
+ color.green = 0;
+ color.blue = (uint8_t)(color_index + 1);
+ } else {
+ vterm_state_get_palette_color(state, color_index, &color);
+ }
map_put(int, int)(color_indexes,
RGB(color.red, color.green, color.blue), color_index + 1);
}
@@ -248,6 +257,15 @@ Terminal *terminal_open(TerminalOptions opts)
rv->sb_buffer = xmalloc(sizeof(ScrollbackLine *) * rv->sb_size);
if (!true_color) {
+ // Change the first 16 colors so we can easily get the correct color
+ // index from them.
+ for (int i = 0; i < 16; i++) {
+ VTermColor color;
+ color.red = 0;
+ color.green = 0;
+ color.blue = (uint8_t)(i + 1);
+ vterm_state_set_palette_color(state, i, &color);
+ }
return rv;
}
@@ -548,9 +566,9 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr,
// Since libvterm does not expose the color index used by the program, we
// use the rgb value to find the appropriate index in the cache computed by
// `terminal_init`.
- int vt_fg_idx = vt_fg != default_vt_fg ?
+ int vt_fg_idx = vt_fg != -1 ?
map_get(int, int)(color_indexes, vt_fg) : 0;
- int vt_bg_idx = vt_bg != default_vt_bg ?
+ int vt_bg_idx = vt_bg != -1 ?
map_get(int, int)(color_indexes, vt_bg) : 0;
int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0)
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 55a49122d5..82c7cd4de9 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -36,9 +36,13 @@ SCRIPTS := \
test_breakindent.out \
test_close_count.out \
test_marks.out \
- test_match_conceal.out \
-NEW_TESTS = test_viml.res
+# Tests using runtest.vim.vim.
+# Keep test_alot*.res as the last one, sort the others.
+NEW_TESTS = \
+ test_viml.res \
+ test_cursor_func.res \
+ test_alot.res
SCRIPTS_GUI := test16.out
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 1c610eab51..6601dcf52f 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -62,6 +62,7 @@ else
endif
" Locate Test_ functions and execute them.
+set nomore
redir @q
function /^Test_
redir END
diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in
index 1ce57246ee..d95052e14c 100644
--- a/src/nvim/testdir/test49.in
+++ b/src/nvim/testdir/test49.in
@@ -8,7 +8,9 @@ STARTTEST
:se nomore
:lang mess C
:so test49.vim
-GGGGGGGGGGGGGG"rp:.-,$w! test.out
+:" Go back to this file and append the results from register r.
+:buf test49.in
+G"rp:/^Results/,$w! test.out
:"
:" make valgrind happy
:redir => funclist
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
new file mode 100644
index 0000000000..1d1da94bac
--- /dev/null
+++ b/src/nvim/testdir/test_alot.vim
@@ -0,0 +1,3 @@
+" A series of tests that can run in one Vim invocation.
+" This makes testing go faster, since Vim doesn't need to restart.
+
diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim
new file mode 100644
index 0000000000..d819b7b092
--- /dev/null
+++ b/src/nvim/testdir/test_cursor_func.vim
@@ -0,0 +1,52 @@
+" Tests for cursor().
+
+func Test_wrong_arguments()
+ try
+ call cursor(1. 3)
+ " not reached
+ call assert_false(1)
+ catch
+ call assert_exception('E474:')
+ endtry
+endfunc
+
+func Test_move_cursor()
+ new
+ call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
+
+ call cursor([1, 1, 0, 1])
+ call assert_equal([1, 1, 0, 1], getcurpos()[1:])
+ call cursor([4, 3, 0, 3])
+ call assert_equal([4, 3, 0, 3], getcurpos()[1:])
+
+ call cursor(2, 2)
+ call assert_equal([2, 2, 0, 2], getcurpos()[1:])
+ " line number zero keeps the line number
+ call cursor(0, 1)
+ call assert_equal([2, 1, 0, 1], getcurpos()[1:])
+ " col number zero keeps the column
+ call cursor(3, 0)
+ call assert_equal([3, 1, 0, 1], getcurpos()[1:])
+ " below last line goes to last line
+ call cursor(9, 1)
+ call assert_equal([4, 1, 0, 1], getcurpos()[1:])
+
+ quit!
+endfunc
+
+" Very short version of what matchparen does.
+function s:Highlight_Matching_Pair()
+ let save_cursor = getcurpos()
+ call setpos('.', save_cursor)
+endfunc
+
+func Test_curswant_with_autocommand()
+ new
+ call setline(1, ['func()', '{', '}', '----'])
+ autocmd! CursorMovedI * call s:Highlight_Matching_Pair()
+ exe "normal! 3Ga\<Down>X\<Esc>"
+ call assert_equal('-X---', getline(4))
+ autocmd! CursorMovedI *
+ quit!
+endfunc
+
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index b41e4d2fba..99eb230a88 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -224,9 +224,9 @@ static void tk_getkeys(TermInput *input, bool force)
while ((result = tk_getkey(input->tk, &key, force)) == TERMKEY_RES_KEY) {
if (key.type == TERMKEY_TYPE_UNICODE && !key.modifiers) {
forward_simple_utf8(input, &key);
- } else if (key.type == TERMKEY_TYPE_UNICODE ||
- key.type == TERMKEY_TYPE_FUNCTION ||
- key.type == TERMKEY_TYPE_KEYSYM) {
+ } else if (key.type == TERMKEY_TYPE_UNICODE
+ || key.type == TERMKEY_TYPE_FUNCTION
+ || key.type == TERMKEY_TYPE_KEYSYM) {
forward_modified_utf8(input, &key);
} else if (key.type == TERMKEY_TYPE_MOUSE) {
forward_mouse_event(input, &key);
@@ -282,9 +282,9 @@ static bool handle_focus_event(TermInput *input)
static bool handle_bracketed_paste(TermInput *input)
{
- if (rbuffer_size(input->read_stream.buffer) > 5 &&
- (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6) ||
- !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
+ if (rbuffer_size(input->read_stream.buffer) > 5
+ && (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6)
+ || !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) {
bool enable = *rbuffer_get(input->read_stream.buffer, 4) == '0';
// Advance past the sequence
rbuffer_consumed(input->read_stream.buffer, 6);
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 00e2821075..e1c0407b27 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -628,8 +628,8 @@ static void tui_suspend(UI *ui)
static void tui_set_title(UI *ui, char *title)
{
TUIData *data = ui->data;
- if (!(title && unibi_get_str(data->ut, unibi_to_status_line) &&
- unibi_get_str(data->ut, unibi_from_status_line))) {
+ if (!(title && unibi_get_str(data->ut, unibi_to_status_line)
+ && unibi_get_str(data->ut, unibi_from_status_line))) {
return;
}
unibi_out(ui, unibi_to_status_line);
@@ -694,8 +694,8 @@ static void update_size(UI *ui)
}
// 2 - try from a system call(ioctl/TIOCGWINSZ on unix)
- if (data->out_isatty &&
- !uv_tty_get_winsize(&data->output_handle.tty, &width, &height)) {
+ if (data->out_isatty
+ && !uv_tty_get_winsize(&data->output_handle.tty, &width, &height)) {
goto end;
}
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 7d9b2c7c3b..f16b4264d7 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2876,9 +2876,7 @@ static char_u *u_save_line(linenr_T lnum)
/// @return true if the buffer has changed
bool bufIsChanged(buf_T *buf)
{
- return
- !bt_dontwrite(buf) &&
- (buf->b_changed || file_ff_differs(buf, true));
+ return !bt_dontwrite(buf) && (buf->b_changed || file_ff_differs(buf, true));
}
/// Check if the 'modified' flag is set, or 'ff' has changed (only need to
@@ -2888,9 +2886,8 @@ bool bufIsChanged(buf_T *buf)
/// @return true if the current buffer has changed
bool curbufIsChanged(void)
{
- return
- !bt_dontwrite(curbuf) &&
- (curbuf->b_changed || file_ff_differs(curbuf, true));
+ return (!bt_dontwrite(curbuf)
+ && (curbuf->b_changed || file_ff_differs(curbuf, true)));
}
/*
diff --git a/src/nvim/version.c b/src/nvim/version.c
index d7051647dd..b2dbfe87c8 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -69,83 +69,396 @@ static char *features[] = {
// clang-format off
static int included_patches[] = {
+ 1757,
1755,
+ 1753,
1654,
1652,
1643,
1641,
+
+ // 1600 NA
+ // 1599 NA
+ // 1598 NA
+ // 1597 NA
+ // 1596,
+ // 1595 NA
+ // 1594 NA
+ // 1593 NA
+ // 1592,
+ // 1591,
+ // 1590,
+ // 1589,
+ // 1588,
+ // 1587 NA
+ // 1586,
+ // 1585,
+ // 1584 NA
+ // 1583 NA
+ // 1582,
+
+ // 1581,
+ // 1580,
+ // 1579,
+ // 1578,
+ // 1577,
+ 1576,
+ // 1575 NA
1574,
+ // 1573,
+ // 1572 NA
+ // 1571,
1570,
+ 1569,
+ // 1568,
+ // 1567,
+ // 1566 NA
+ // 1565,
+ // 1564,
+ // 1563,
+ // 1562,
+ // 1561 NA
+ // 1560,
+ // 1559,
+ // 1558,
+ // 1557,
+ // 1556,
+ // 1555,
+ // 1554,
+ // 1553,
+ // 1552,
+ // 1551,
+ // 1550,
+ // 1549,
+ // 1548,
+ // 1547,
+ // 1546,
+ // 1545 NA
+ // 1544 NA
+ // 1543 NA
+ // 1542 NA
+ // 1541 NA
+ // 1540 NA
+ // 1539 NA
+ // 1538 NA
+ // 1537 NA
+ // 1536 NA
+ // 1535,
+ // 1534 NA
+ // 1533,
+ // 1532 NA
+ // 1531 NA
+ // 1530 NA
+ // 1529 NA
+ // 1528,
+ // 1527 NA
+ // 1526 NA
+ // 1525 NA
+ // 1524 NA
+ // 1523 NA
+ // 1522 NA
+ // 1521,
+ // 1520 NA
+ // 1519 NA
+ // 1518 NA
+ // 1517 NA
+ // 1516,
+ // 1515 NA
+ // 1514 NA
+ // 1513,
+ // 1512 NA
1511,
+ // 1510 NA
+ // 1509 NA
+ // 1508 NA
+ // 1507 NA
+ // 1506 NA
+ // 1505 NA
+ // 1504 NA
+ // 1503 NA
+ // 1502 NA
+ // 1501 NA
+ 1500,
+ // 1499,
+ // 1498 NA
+ // 1497 NA
+ // 1496 NA
+ // 1495 NA
+ // 1494,
+ // 1493 NA
+ // 1492,
+ // 1491,
+ // 1490 NA
+ // 1489 NA
+ // 1488 NA
+ // 1487 NA
+ // 1486,
+ // 1485 NA
+ // 1484 NA
+ // 1483 NA
+ // 1482 NA
+ // 1481 NA
+ // 1480,
+ // 1479,
+ // 1478,
+ // 1477,
+ // 1476 NA
+ // 1475 NA
+ // 1474 NA
+ // 1473 NA
+ // 1472 NA
+ // 1471 NA
+ // 1470 NA
+ // 1469 NA
+ // 1468,
+ // 1467 NA
+ // 1466 NA
+ // 1465 NA
+ // 1464,
+ // 1463 NA
+ // 1462 NA
+ // 1461 NA
+ // 1460 NA
+ // 1459 NA
+ // 1458 NA
+ // 1457 NA
+ // 1456,
+ // 1455 NA
+ // 1454 NA
+ // 1453 NA
+ // 1452 NA
+ // 1451 NA
+ // 1450 NA
+ // 1449 NA
+ // 1448 NA
+ // 1447 NA
+ // 1446 NA
+ // 1445 NA
+ // 1444 NA
+ // 1443 NA
+ // 1442 NA
+ // 1441 NA
+ // 1440 NA
+ // 1439 NA
+ // 1438 NA
+ // 1437 NA
+ // 1436 NA
+ // 1435 NA
+ // 1434 NA
+ // 1433 NA
+ // 1432 NA
+ // 1431 NA
+ // 1430 NA
+ // 1429 NA
+ // 1428 NA
+ // 1427 NA
+ // 1426 NA
1425,
+ // 1424 NA
+ // 1423 NA
+ // 1422 NA
+ // 1421 NA
+ // 1420 NA
+ // 1419 NA
+ // 1418 NA
+ // 1417 NA
+ // 1416 NA
+ // 1415 NA
+ // 1414 NA
+ // 1413 NA
+ // 1412 NA
+ // 1411 NA
+ 1410,
+ // 1409 NA
+ // 1408 NA
+ // 1407 NA
+ 1406,
+ 1405,
+ // 1404 NA
+ // 1403 NA
+ // 1402 NA
+ 1401,
+ // 1400 NA
+ // 1399 NA
+ // 1398 NA
+ // 1397,
+ // 1396,
+ // 1395 NA
+ // 1394,
+ // 1393 NA
+ // 1392 NA
+ // 1391 NA
+ // 1390 NA
+ // 1389 NA
+ // 1388,
+ // 1387 NA
+ // 1386 NA
+ // 1385 NA
+ // 1384,
+ // 1383 NA
+ // 1382 NA
+ // 1381 NA
+ // 1380 NA
+ // 1379 NA
+ // 1378 NA
+ // 1377 NA
+ // 1376 NA
+ // 1375 NA
+ // 1374 NA
+ // 1373 NA
+ // 1372 NA
+ // 1371 NA
+ // 1370 NA
+ // 1369 NA
+ // 1368 NA
+ // 1367 NA
1366,
+ // 1365,
+ // 1364 NA
+ // 1363 NA
+ // 1362 NA
+ // 1361 NA
+ // 1360 NA
+ // 1359 NA
+ // 1358 NA
+ // 1357 NA
+ // 1356 NA
+ // 1355 NA
+ // 1354 NA
+ // 1353 NA
+ // 1352,
+ // 1351 NA
+ // 1350 NA
+ // 1349 NA
+ // 1348 NA
+ // 1347,
+ 1346,
+ // 1345 NA
+ // 1344 NA
+ // 1343 NA
+ // 1342 NA
+ // 1341 NA
+ // 1340 NA
+ // 1339 NA
+ // 1338 NA
+ // 1337 NA
+ // 1336 NA
+ // 1335 NA
+ // 1334 NA
+ // 1333 NA
+ // 1332 NA
+ // 1331 NA
+ // 1330 NA
+ // 1329 NA
+ // 1328 NA
+ // 1327 NA
+ // 1326 NA
+ // 1325 NA
+ // 1324 NA
+ // 1323 NA
+ // 1322 NA
+ // 1321 NA
+ // 1320 NA
+ // 1319 NA
+ // 1318 NA
+ // 1317 NA
+ // 1316 NA
+ // 1315 NA
+ // 1314 NA
+ // 1313 NA
+ // 1312 NA
+ // 1311 NA
+ // 1310 NA
+ 1309,
+ // 1308 NA
+ // 1307 NA
+ // 1306 NA
+ // 1305,
1304,
+ // 1303 NA
+ // 1302 NA
+ // 1301 NA
+ // 1300 NA
+ // 1299 NA
+ // 1298 NA
+ // 1297 NA
+ 1296,
+ // 1295 NA
+ // 1294 NA
+ // 1293 NA
1292,
+ // 1291 NA
+ // 1290 NA
+ // 1289 NA
+ // 1288 NA
+ // 1287 NA
+ // 1286 NA
+ // 1285,
1284,
- // 1283
+ // 1283 NA
1282,
- // 1281
- // 1280
+ // 1281,
+ // 1280 NA
// 1279 NA
// 1278 NA
- // 1277
- // 1276
- // 1275
- // 1274
- // 1273
- // 1272
+ // 1277 NA
+ // 1276,
+ // 1275 NA
+ // 1274 NA
+ // 1273,
+ // 1272 NA
1271,
- // 1270
+ // 1270 NA
1269,
- // 1268
+ // 1268 NA
1267,
// 1266
- // 1265
- // 1264
- // 1263
- // 1262
- // 1261
- // 1260
- // 1259
- // 1258
- // 1257
- // 1256
- // 1255
- // 1254
- // 1253
- // 1252
- // 1251
- // 1250
- // 1249
- // 1248
- // 1247
- // 1246
- // 1245
- // 1244
+ // 1265 NA
+ // 1264 NA
+ // 1263 NA
+ // 1262 NA
+ // 1261 NA
+ // 1260 NA
+ // 1259,
+ // 1258 NA
+ // 1257 NA
+ // 1256 NA
+ // 1255 NA
+ // 1254 NA
+ // 1253 NA
+ // 1252 NA
+ // 1251 NA
+ // 1250 NA
+ // 1249 NA
+ // 1248 NA
+ // 1247 NA
+ // 1246 NA
+ // 1245 NA
+ // 1244 NA
// 1243 NA
- // 1242
- // 1241
- // 1240
- // 1239
- // 1238
- // 1237
- // 1236
- // 1235
- // 1234
- // 1233
- // 1232
+ // 1242 NA
+ // 1241 NA
+ // 1240 NA
+ // 1239 NA
+ // 1238 NA
+ // 1237,
+ 1236,
+ // 1235 NA
+ // 1234 NA
+ // 1233 NA
+ // 1232 NA
// 1231 NA
- // 1230
- // 1229
+ // 1230 NA
+ // 1229 NA
1228,
- // 1227
- // 1226
- // 1225
- // 1224
- // 1223
- // 1223
- // 1221
- // 1220
+ // 1227 NA
+ // 1226 NA
+ // 1225 NA
+ // 1224 NA
+ // 1223,
+ // 1222 NA
+ // 1221 NA
+ // 1220 NA
// 1219 NA
// 1218 NA
// 1217 NA
@@ -177,7 +490,7 @@ static int included_patches[] = {
// 1191 NA
// 1190 NA
// 1189 NA
- // 1188,
+ // 1188 NA
// 1187 NA
// 1186,
// 1185 NA
@@ -211,7 +524,7 @@ static int included_patches[] = {
1157,
// 1156 NA
// 1155 NA
- // 1154,
+ // 1154 NA
// 1153,
// 1152 NA
// 1151,
@@ -221,8 +534,8 @@ static int included_patches[] = {
// 1147,
// 1146 NA
// 1145 NA
- // 1144 NA
- // 1143,
+ 1144,
+ 1143,
// 1142,
1141,
// 1140,
@@ -230,8 +543,8 @@ static int included_patches[] = {
// 1138 NA
1137,
// 1136,
- // 1135 NA,
- // 1134 NA,
+ // 1135 NA
+ // 1134 NA
// 1133 NA
// 1132,
// 1131 NA
@@ -245,20 +558,20 @@ static int included_patches[] = {
// 1123,
// 1122 NA
// 1121,
- // 1120,
+ 1120,
// 1119,
- // 1118,
- // 1117,
- // 1116,
+ 1118,
+ 1117,
+ 1116,
// 1115 NA
- // 1114,
+ 1114,
1113,
1112,
// 1111,
// 1110,
// 1109 NA
// 1108,
- // 1107,
+ 1107,
// 1106 NA
1105,
// 1104 NA
@@ -272,40 +585,40 @@ static int included_patches[] = {
// 1096,
// 1095 NA
// 1094,
- // 1093,
- // 1092,
+ 1093,
+ 1092,
// 1091,
// 1090,
1089,
1088,
1087,
- // 1086,
+ 1086,
1085,
1084,
- // 1083 NA,
- // 1082 NA,
+ // 1083 NA
+ // 1082 NA
1081,
- // 1080 NA,
+ // 1080 NA
// 1079,
- // 1078 NA,
- // 1077 NA,
+ // 1078 NA
+ // 1077 NA
1076,
- // 1075,
+ 1075,
// 1074 NA,
// 1073,
1072,
// 1071,
- // 1070 NA,
- // 1069 NA,
+ // 1070 NA
+ // 1069 NA
// 1068,
- // 1067 NA,
- // 1066 NA,
+ // 1067 NA
+ // 1066 NA
1065,
// 1064,
- // 1063 NA,
- // 1062 NA,
+ // 1063 NA
+ // 1062 NA
// 1061,
- // 1060 NA,
+ // 1060 NA
// 1059,
// 1058,
// 1057,
@@ -320,54 +633,54 @@ static int included_patches[] = {
// 1048,
// 1047,
// 1046,
- // 1045 NA,
- // 1044 NA,
- // 1043 NA,
+ // 1045 NA
+ // 1044 NA
+ // 1043 NA
// 1042,
1041,
- // 1040 NA,
+ // 1040 NA
// 1039,
- // 1038 NA,
+ // 1038 NA
// 1037,
// 1036,
- // 1035,
+ 1035,
// 1034,
- // 1033 NA,
+ // 1033 NA
1032,
// 1031 NA,
1030,
1029,
- // 1028 NA,
+ // 1028 NA
1027,
- // 1026 NA,
- // 1025 NA,
- // 1024 NA,
- // 1023 NA,
- // 1022 NA,
- // 1021 NA,
- // 1020 NA,
- // 1019 NA,
+ // 1026 NA
+ // 1025 NA
+ // 1024 NA
+ // 1023 NA
+ // 1022 NA
+ // 1021 NA
+ // 1020 NA
+ // 1019 NA
// 1018,
// 1017,
- // 1016 NA,
+ // 1016 NA
// 1015,
- // 1014 NA,
+ // 1014 NA
1013,
- // 1012 NA,
- // 1011 NA,
- // 1010,
- // 1009 NA,
- // 1008 NA,
- // 1007,
- // 1006,
- // 1005,
+ // 1012 NA
+ // 1011 NA
+ // 1010 NA,
+ // 1009 NA
+ // 1008 NA
+ 1007,
+ 1006,
+ // 1005 NA,
// 1004 NA,
// 1003 NA,
// 1002 NA,
1001,
1000,
// 999 NA
- // 998,
+ 998,
// 997 NA
// 996 NA
// 995 NA
@@ -381,8 +694,8 @@ static int included_patches[] = {
// 987 NA
// 986 NA
// 985 NA
- // 984,
- // 983,
+ 984,
+ // 983 NA
// 982 NA
981,
980,
@@ -408,13 +721,13 @@ static int included_patches[] = {
// 960 NA
// 959 NA
958,
- // 957,
+ 957,
// 956 NA
955,
// 954 NA
953,
952,
- // 951,
+ 951,
950,
949,
// 948 NA
@@ -423,8 +736,8 @@ static int included_patches[] = {
945,
944,
// 943 NA
- // 942,
- // 941,
+ 942,
+ 941,
// 940 NA
939,
// 938 NA
@@ -476,14 +789,14 @@ static int included_patches[] = {
// 892 NA
891,
// 890 NA
- // 889,
+ 889,
888,
887,
// 886 NA
885,
// 884 NA
883,
- // 882,
+ 882,
881,
// 880 NA
879,
@@ -543,7 +856,7 @@ static int included_patches[] = {
825,
// 824 NA
823,
- // 822,
+ 822,
// 821 NA
820,
819,
@@ -568,7 +881,7 @@ static int included_patches[] = {
800,
799,
798,
- // 797,
+ // 797 NA
// 796 NA
795,
// 794 NA
@@ -632,7 +945,7 @@ static int included_patches[] = {
736,
// 735 NA
734,
- // 733,
+ // 733 NA
732,
// 731 NA
// 730 NA
@@ -693,7 +1006,7 @@ static int included_patches[] = {
675,
// 674 NA
673,
- // 672,
+ 672,
671,
670,
// 669 NA
@@ -752,7 +1065,7 @@ static int included_patches[] = {
616,
615,
614,
- // 613,
+ 613,
612,
// 611 NA
// 610 NA
@@ -1121,13 +1434,13 @@ static int included_patches[] = {
247,
// 246 NA
245,
- // 244,
+ // 244 NA
243,
242,
241,
240,
239,
- // 238,
+ // 238 NA
237,
236,
235,
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 623ea19e36..165a44a148 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -201,15 +201,6 @@ enum {
#define MAYBE 2 /* sometimes used for a variant on TRUE */
-/*
- * Motion types, used for operators and for yank/delete registers.
- */
-#define MCHAR 0 /* character-wise movement/register */
-#define MLINE 1 /* line-wise movement/register */
-#define MBLOCK 2 /* block-wise register */
-
-#define MAUTO 0xff /* Decide between MLINE/MCHAR */
-
#define STATUS_HEIGHT 1 /* height of a status line under a window */
#define QF_WINHEIGHT 10 /* default height for quickfix window */
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 1b8c953596..bea55c465f 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -97,7 +97,7 @@ do_window (
* don't replicate the quickfix buffer. */
if (bt_quickfix(curbuf))
goto newwindow;
- win_split((int)Prenum, 0);
+ (void)win_split((int)Prenum, 0);
break;
/* split current window in two parts, vertically */
@@ -108,7 +108,7 @@ do_window (
* don't replicate the quickfix buffer. */
if (bt_quickfix(curbuf))
goto newwindow;
- win_split((int)Prenum, WSP_VERT);
+ (void)win_split((int)Prenum, WSP_VERT);
break;
/* split current window and edit alternate file */
@@ -2948,7 +2948,7 @@ void free_tabpage(tabpage_T *tp)
unref_var_dict(tp->tp_vars);
-
+ xfree(tp->localdir); // Free tab-local working directory
xfree(tp);
}
@@ -3560,18 +3560,24 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri
curwin->w_cursor.coladd = 0;
changed_line_abv_curs(); /* assume cursor position needs updating */
- if (curwin->w_localdir != NULL) {
- /* Window has a local directory: Save current directory as global
- * directory (unless that was done already) and change to the local
- * directory. */
+ // The new directory is either the local directory of the window, of the tab
+ // or NULL.
+ char_u *new_dir = curwin->w_localdir ? curwin->w_localdir : curtab->localdir;
+
+ if (new_dir) {
+ // Window/tab has a local directory: Save current directory as global
+ // directory (unless that was done already) and change to the local
+ // directory.
if (globaldir == NULL) {
char_u cwd[MAXPATHL];
- if (os_dirname(cwd, MAXPATHL) == OK)
+ if (os_dirname(cwd, MAXPATHL) == OK) {
globaldir = vim_strsave(cwd);
+ }
+ }
+ if (os_chdir((char *)new_dir) == 0) {
+ shorten_fnames(true);
}
- if (os_chdir((char *)curwin->w_localdir) == 0)
- shorten_fnames(TRUE);
} else if (globaldir != NULL) {
/* Window doesn't have a local directory and we are not in the global
* directory: Change to the global directory. */