aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/buffer.c7
-rw-r--r--src/nvim/charset.c2
-rw-r--r--src/nvim/cursor.c5
-rw-r--r--src/nvim/digraph.c2
-rw-r--r--src/nvim/edit.c151
-rw-r--r--src/nvim/eval.c20
-rw-r--r--src/nvim/ex_cmds.c25
-rw-r--r--src/nvim/ex_docmd.c18
-rw-r--r--src/nvim/ex_getln.c38
-rw-r--r--src/nvim/farsi.c2
-rw-r--r--src/nvim/fold.c11
-rw-r--r--src/nvim/getchar.c4
-rw-r--r--src/nvim/macros.h2
-rw-r--r--src/nvim/mark.c2
-rw-r--r--src/nvim/mbyte.c6
-rw-r--r--src/nvim/mbyte.h1
-rw-r--r--src/nvim/memline.c2
-rw-r--r--src/nvim/message.c40
-rw-r--r--src/nvim/misc1.c70
-rw-r--r--src/nvim/ops.c137
-rw-r--r--src/nvim/option.c104
-rw-r--r--src/nvim/regexp.c109
-rw-r--r--src/nvim/regexp_nfa.c14
-rw-r--r--src/nvim/screen.c24
-rw-r--r--src/nvim/search.c4
-rw-r--r--src/nvim/spell.c277
-rw-r--r--src/nvim/syntax.c10
-rw-r--r--src/nvim/testdir/Makefile2
-rw-r--r--src/nvim/testdir/test_getvar.vim104
-rw-r--r--src/nvim/testdir/test_highlight.vim535
-rw-r--r--src/nvim/testdir/test_visual.vim125
-rw-r--r--src/nvim/testdir/test_window_cmd.vim90
-rw-r--r--src/nvim/testdir/view_util.vim21
-rw-r--r--src/nvim/undo.c9
-rw-r--r--src/nvim/window.c49
35 files changed, 1367 insertions, 655 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 3020c29709..71e04ec0fb 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -3220,10 +3220,11 @@ int build_stl_str_hl(
// Get the byte value now, in case we need it below. This is more
// efficient than making a copy of the line.
int byteval;
- if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr))
+ if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr)) {
byteval = 0;
- else
- byteval = (*mb_ptr2char)(line_ptr + wp->w_cursor.col);
+ } else {
+ byteval = utf_ptr2char(line_ptr + wp->w_cursor.col);
+ }
int groupdepth = 0;
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 231bff26e8..f1b3be6b46 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1379,7 +1379,7 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor,
ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
if (pos->col < (colnr_T)STRLEN(ptr)) {
- int c = (*mb_ptr2char)(ptr + pos->col);
+ int c = utf_ptr2char(ptr + pos->col);
if ((c != TAB) && vim_isprintc(c)) {
endadd = (colnr_T)(char2cells(c) - 1);
if (coladd > endadd) {
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 177f167d74..0fda941a51 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -476,9 +476,7 @@ bool leftcol_changed(void)
int gchar_cursor(void)
{
- if (has_mbyte)
- return (*mb_ptr2char)(get_cursor_pos_ptr());
- return (int)*get_cursor_pos_ptr();
+ return utf_ptr2char(get_cursor_pos_ptr());
}
/*
@@ -507,4 +505,3 @@ char_u *get_cursor_pos_ptr(void)
return ml_get_buf(curbuf, curwin->w_cursor.lnum, false) +
curwin->w_cursor.col;
}
-
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 218a3f0604..c0915224e5 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -1536,7 +1536,7 @@ static int getexactdigraph(int char1, int char2, int meta_char)
to = string_convert(&vc, buf, &len);
if (to != NULL) {
- retval = (*mb_ptr2char)(to);
+ retval = utf_ptr2char(to);
xfree(to);
}
(void)convert_setup(&vc, NULL, NULL);
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 95c903c90c..0d99aa8fb2 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -240,8 +240,8 @@ static int ins_need_undo; /* call u_save() before inserting a
char. Set when edit() is called.
after that arrow_used is used. */
-static int did_add_space = FALSE; /* auto_format() added an extra space
- under the cursor */
+static bool did_add_space = false; // auto_format() added an extra space
+ // under the cursor
static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo
// for the next left/right cursor
@@ -1766,8 +1766,8 @@ change_indent (
/* We only put back the new line up to the cursor */
new_line[curwin->w_cursor.col] = NUL;
- /* Put back original line */
- ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
+ // Put back original line
+ ml_replace(curwin->w_cursor.lnum, orig_line, false);
curwin->w_cursor.col = orig_col;
/* Backspace from cursor to start of line */
@@ -2311,24 +2311,14 @@ static void ins_compl_longest_match(compl_T *match)
p = compl_leader;
s = match->cp_str;
while (*p != NUL) {
- if (has_mbyte) {
- c1 = mb_ptr2char(p);
- c2 = mb_ptr2char(s);
- } else {
- c1 = *p;
- c2 = *s;
- }
- if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2))
- : (c1 != c2)) {
+ c1 = utf_ptr2char(p);
+ c2 = utf_ptr2char(s);
+
+ if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) : (c1 != c2)) {
break;
}
- if (has_mbyte) {
- MB_PTR_ADV(p);
- MB_PTR_ADV(s);
- } else {
- ++p;
- ++s;
- }
+ MB_PTR_ADV(p);
+ MB_PTR_ADV(s);
}
if (*p != NUL) {
@@ -5703,8 +5693,8 @@ auto_format (
pos = curwin->w_cursor;
old = get_cursor_line_ptr();
- /* may remove added space */
- check_auto_format(FALSE);
+ // may remove added space
+ check_auto_format(false);
/* Don't format in Insert mode when the cursor is on a trailing blank, the
* user might insert normal text next. Also skip formatting when "1" is
@@ -5770,12 +5760,13 @@ auto_format (
pnew = vim_strnsave(new, len + 2);
pnew[len] = ' ';
pnew[len + 1] = NUL;
- ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
- /* remove the space later */
- did_add_space = TRUE;
- } else
- /* may remove added space */
- check_auto_format(FALSE);
+ ml_replace(curwin->w_cursor.lnum, pnew, false);
+ // remove the space later
+ did_add_space = true;
+ } else {
+ // may remove added space
+ check_auto_format(false);
+ }
}
check_cursor();
@@ -5786,9 +5777,8 @@ auto_format (
* delete it now. The space must be under the cursor, just after the insert
* position.
*/
-static void
-check_auto_format (
- int end_insert /* TRUE when ending Insert mode */
+static void check_auto_format(
+ bool end_insert // true when ending Insert mode
)
{
int c = ' ';
@@ -5796,19 +5786,19 @@ check_auto_format (
if (did_add_space) {
cc = gchar_cursor();
- if (!WHITECHAR(cc))
- /* Somehow the space was removed already. */
- did_add_space = FALSE;
- else {
+ if (!WHITECHAR(cc)) {
+ // Somehow the space was removed already.
+ did_add_space = false;
+ } else {
if (!end_insert) {
inc_cursor();
c = gchar_cursor();
dec_cursor();
}
if (c != NUL) {
- /* The space is no longer at the end of the line, delete it. */
- del_char(FALSE);
- did_add_space = FALSE;
+ // The space is no longer at the end of the line, delete it.
+ del_char(false);
+ did_add_space = false;
}
}
}
@@ -6033,8 +6023,8 @@ stop_insert (
}
}
- /* If a space was inserted for auto-formatting, remove it now. */
- check_auto_format(TRUE);
+ // If a space was inserted for auto-formatting, remove it now.
+ check_auto_format(true);
/* If we just did an auto-indent, remove the white space from the end
* of the line, and put the cursor back.
@@ -6053,10 +6043,12 @@ stop_insert (
if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
--curwin->w_cursor.col;
cc = gchar_cursor();
- if (!ascii_iswhite(cc))
+ if (!ascii_iswhite(cc)) {
break;
- if (del_char(TRUE) == FAIL)
- break; /* should not happen */
+ }
+ if (del_char(true) == FAIL) {
+ break; // should not happen
+ }
}
if (curwin->w_cursor.lnum != tpos.lnum)
curwin->w_cursor = tpos;
@@ -6198,12 +6190,10 @@ int oneright(void)
/* Adjust for multi-wide char (excluding TAB) */
ptr = get_cursor_pos_ptr();
- coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(
- (*mb_ptr2char)(ptr)
- ))
- ? ptr2cells(ptr) : 1));
- curwin->w_set_curswant = TRUE;
- /* Return OK if the cursor moved, FAIL otherwise (at window edge). */
+ coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))) ?
+ ptr2cells(ptr) : 1));
+ curwin->w_set_curswant = true;
+ // Return OK if the cursor moved, FAIL otherwise (at window edge).
return (prevpos.col != curwin->w_cursor.col
|| prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL;
}
@@ -6258,10 +6248,10 @@ int oneleft(void)
/* Adjust for multi-wide char (not a TAB) */
ptr = get_cursor_pos_ptr();
- if (*ptr != TAB && vim_isprintc(
- (*mb_ptr2char)(ptr)
- ) && ptr2cells(ptr) > 1)
+ if (*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))
+ && ptr2cells(ptr) > 1) {
curwin->w_cursor.coladd = 0;
+ }
}
curwin->w_set_curswant = TRUE;
@@ -6710,8 +6700,8 @@ static void replace_do_bs(int limit_col)
* text aligned. */
curwin->w_cursor.col += ins_len;
while (vcol > orig_vcols && gchar_cursor() == ' ') {
- del_char(FALSE);
- ++orig_vcols;
+ del_char(false);
+ orig_vcols++;
}
curwin->w_cursor.col -= ins_len;
}
@@ -7453,13 +7443,15 @@ static void ins_shift(int c, int lastc)
*/
if (c == Ctrl_D && (lastc == '0' || lastc == '^')
&& curwin->w_cursor.col > 0) {
- --curwin->w_cursor.col;
- (void)del_char(FALSE); /* delete the '^' or '0' */
- /* In Replace mode, restore the characters that '^' or '0' replaced. */
- if (State & REPLACE_FLAG)
+ curwin->w_cursor.col--;
+ (void)del_char(false); // delete the '^' or '0'
+ // In Replace mode, restore the characters that '^' or '0' replaced.
+ if (State & REPLACE_FLAG) {
replace_pop_ins();
- if (lastc == '^')
- old_indent = get_indent(); /* remember curr. indent */
+ }
+ if (lastc == '^') {
+ old_indent = get_indent(); // remember curr. indent
+ }
change_indent(INDENT_SET, 0, TRUE, 0, TRUE);
} else
change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE);
@@ -7475,17 +7467,23 @@ static void ins_shift(int c, int lastc)
static void ins_del(void)
{
- int temp;
-
- if (stop_arrow() == FAIL)
+ if (stop_arrow() == FAIL) {
return;
- if (gchar_cursor() == NUL) { /* delete newline */
- temp = curwin->w_cursor.col;
+ }
+ if (gchar_cursor() == NUL) { // delete newline
+ const int temp = curwin->w_cursor.col;
if (!can_bs(BS_EOL) // only if "eol" included
|| do_join(2, false, true, false, false) == FAIL) {
vim_beep(BO_BS);
} else {
curwin->w_cursor.col = temp;
+ // Adjust orig_line_count in case more lines have been deleted than
+ // have been added. That makes sure, that open_line() later
+ // can access all buffer lines correctly
+ if (State & VREPLACE_FLAG
+ && orig_line_count > curbuf->b_ml.ml_line_count) {
+ orig_line_count = curbuf->b_ml.ml_line_count;
+ }
}
} else if (del_char(false) == FAIL) { // delete char under cursor
vim_beep(BO_BS);
@@ -7511,8 +7509,9 @@ static void ins_bs_one(colnr_T *vcolp)
if (curwin->w_cursor.lnum != Insstart.lnum
|| curwin->w_cursor.col >= Insstart.col)
replace_do_bs(-1);
- } else
- (void)del_char(FALSE);
+ } else {
+ (void)del_char(false);
+ }
}
/// Handle Backspace, delete-word and delete-line in Insert mode.
@@ -7776,16 +7775,16 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
else {
const bool l_enc_utf8 = enc_utf8;
const int l_p_deco = p_deco;
- if (l_enc_utf8 && l_p_deco)
+ if (l_enc_utf8 && l_p_deco) {
(void)utfc_ptr2char(get_cursor_pos_ptr(), cpc);
- (void)del_char(FALSE);
- /*
- * If there are combining characters and 'delcombine' is set
- * move the cursor back. Don't back up before the base
- * character.
- */
- if (l_enc_utf8 && l_p_deco && cpc[0] != NUL)
+ }
+ (void)del_char(false);
+ // If there are combining characters and 'delcombine' is set
+ // move the cursor back. Don't back up before the base
+ // character.
+ if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) {
inc_cursor();
+ }
if (revins_chars) {
revins_chars--;
revins_legal++;
@@ -8496,7 +8495,7 @@ int ins_copychar(linenr_T lnum)
if ((colnr_T)temp > curwin->w_virtcol)
ptr = prev_ptr;
- c = (*mb_ptr2char)(ptr);
+ c = utf_ptr2char(ptr);
if (c == NUL) {
vim_beep(BO_COPY);
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 3abc39e7bf..9765b04922 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -10210,32 +10210,34 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *oldcurwin;
- tabpage_T *tp, *oldtabpage;
- dictitem_T *v;
+ tabpage_T *oldtabpage;
bool done = false;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
const char *const varname = tv_get_string_chk(&argvars[1]);
- tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
+ tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
if (tp != NULL && varname != NULL) {
// Set tp to be our tabpage, temporarily. Also set the window to the
// first window in the tabpage, otherwise the window is not valid.
- win_T *window = tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin;
+ win_T *const window = tp == curtab || tp->tp_firstwin == NULL
+ ? firstwin
+ : tp->tp_firstwin;
if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
// look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary.
- v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
- varname, strlen(varname), false);
+ const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
+ varname, strlen(varname),
+ false);
if (v != NULL) {
tv_copy(&v->di_tv, rettv);
done = true;
}
}
- /* restore previous notion of curwin */
- restore_win(oldcurwin, oldtabpage, TRUE);
+ // restore previous notion of curwin
+ restore_win(oldcurwin, oldtabpage, true);
}
if (!done && argvars[2].v_type != VAR_UNKNOWN) {
@@ -15896,7 +15898,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
while (charidx >= 0 && byteidx < len) {
if (charidx == 0) {
- rettv->vval.v_number = mb_ptr2char((const char_u *)str + byteidx);
+ rettv->vval.v_number = utf_ptr2char((const char_u *)str + byteidx);
break;
}
charidx--;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 4ef51b72b7..1420a9aae4 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -716,11 +716,13 @@ void ex_retab(exarg_T *eap)
memmove(new_line + start_col + len,
ptr + col, (size_t)(old_len - col + 1));
ptr = new_line + start_col;
- for (col = 0; col < len; col++)
+ for (col = 0; col < len; col++) {
ptr[col] = (col < num_tabs) ? '\t' : ' ';
- ml_replace(lnum, new_line, FALSE);
- if (first_line == 0)
+ }
+ ml_replace(lnum, new_line, false);
+ if (first_line == 0) {
first_line = lnum;
+ }
last_line = lnum;
ptr = new_line;
col = start_col + len;
@@ -1598,6 +1600,7 @@ void ex_file(exarg_T *eap)
// print full file name if :cd used
fileinfo(false, false, eap->forceit);
}
+ redraw_tabline = true;
}
/*
@@ -3624,7 +3627,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
// before the cursor.
len_change = (int)STRLEN(new_line) - (int)STRLEN(orig_line);
curwin->w_cursor.col += len_change;
- ml_replace(lnum, new_line, FALSE);
+ ml_replace(lnum, new_line, false);
}
search_match_lines = regmatch.endpos[0].lnum
@@ -3666,9 +3669,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
msg_col = 0;
gotocmdline(TRUE);
- /* restore the line */
- if (orig_line != NULL)
- ml_replace(lnum, orig_line, FALSE);
+ // restore the line
+ if (orig_line != NULL) {
+ ml_replace(lnum, orig_line, false);
+ }
}
need_wait_return = FALSE; /* no hit-return prompt */
@@ -3925,9 +3929,10 @@ skip:
prev_matchcol = (colnr_T)STRLEN(sub_firstline)
- prev_matchcol;
- if (u_savesub(lnum) != OK)
+ if (u_savesub(lnum) != OK) {
break;
- ml_replace(lnum, new_start, TRUE);
+ }
+ ml_replace(lnum, new_start, true);
if (nmatch_tl > 0) {
/*
@@ -5641,7 +5646,7 @@ void ex_sign(exarg_T *eap)
// Count cells and check for non-printable chars
cells = 0;
for (s = arg; s < p; s += (*mb_ptr2len)(s)) {
- if (!vim_isprintc((*mb_ptr2char)(s))) {
+ if (!vim_isprintc(utf_ptr2char(s))) {
break;
}
cells += (*mb_ptr2cells)(s);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 0ab0178d24..3d3d02fd71 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2899,11 +2899,7 @@ const char * set_one_cmd_context(
xp->xp_pattern = skipwhite((const char_u *)arg);
p = (const char *)xp->xp_pattern;
while (*p != NUL) {
- if (has_mbyte) {
- c = mb_ptr2char((const char_u *)p);
- } else {
- c = (uint8_t)(*p);
- }
+ c = utf_ptr2char((const char_u *)p);
if (c == '\\' && p[1] != NUL) {
p++;
} else if (c == '`') {
@@ -2921,19 +2917,11 @@ const char * set_one_cmd_context(
|| ascii_iswhite(c)) {
len = 0; /* avoid getting stuck when space is in 'isfname' */
while (*p != NUL) {
- if (has_mbyte) {
- c = mb_ptr2char((const char_u *)p);
- } else {
- c = *p;
- }
+ c = utf_ptr2char((const char_u *)p);
if (c == '`' || vim_isfilec_or_wc(c)) {
break;
}
- if (has_mbyte) {
- len = (size_t)(*mb_ptr2len)((const char_u *)p);
- } else {
- len = 1;
- }
+ len = (size_t)utfc_ptr2len((const char_u *)p);
MB_PTR_ADV(p);
}
if (in_quote) {
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index ee616ae955..1810056a4a 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -3327,16 +3327,11 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
/* Locate start of last word in the cmd buffer. */
for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) {
- if (has_mbyte) {
- len = (*mb_head_off)(ccline.cmdbuff, w - 1) + 1;
- if (!vim_iswordc(mb_ptr2char(w - len)))
- break;
- w -= len;
- } else {
- if (!vim_iswordc(w[-1]))
- break;
- --w;
+ len = utf_head_off(ccline.cmdbuff, w - 1) + 1;
+ if (!vim_iswordc(utf_ptr2char(w - len))) {
+ break;
}
+ w -= len;
}
len = (int)((ccline.cmdbuff + ccline.cmdpos) - w);
if (p_ic ? STRNICMP(w, arg, len) == 0 : STRNCMP(w, arg, len) == 0)
@@ -3837,24 +3832,13 @@ ExpandOne (
// Find longest common part
if (mode == WILD_LONGEST && xp->xp_numfiles > 0) {
- size_t len;
- size_t mb_len = 1;
- int c0;
- int ci;
+ size_t len = 0;
- for (len = 0; xp->xp_files[0][len]; len += mb_len) {
- if (has_mbyte) {
- mb_len = (* mb_ptr2len)(&xp->xp_files[0][len]);
- c0 = (* mb_ptr2char)(&xp->xp_files[0][len]);
- } else {
- c0 = xp->xp_files[0][len];
- }
- for (i = 1; i < xp->xp_numfiles; ++i) {
- if (has_mbyte) {
- ci =(* mb_ptr2char)(&xp->xp_files[i][len]);
- } else {
- ci = xp->xp_files[i][len];
- }
+ for (size_t mb_len; xp->xp_files[0][len]; len += mb_len) {
+ mb_len = utfc_ptr2len(&xp->xp_files[0][len]);
+ int c0 = utf_ptr2char(&xp->xp_files[0][len]);
+ for (i = 1; i < xp->xp_numfiles; i++) {
+ int ci = utf_ptr2char(&xp->xp_files[i][len]);
if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES
|| xp->xp_context == EXPAND_FILES
@@ -6100,7 +6084,7 @@ static int open_cmdwin(void)
/* Replace the empty last line with the current command-line and put the
* cursor there. */
- ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, TRUE);
+ ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, true);
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
curwin->w_cursor.col = ccline.cmdpos;
changed_line_abv_curs();
diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c
index 6de84fbf4d..9862c50ab9 100644
--- a/src/nvim/farsi.c
+++ b/src/nvim/farsi.c
@@ -1081,7 +1081,7 @@ int fkmap(int c)
if (gchar_cursor() == _LAM) {
chg_l_toXor_X();
- del_char(FALSE);
+ del_char(false);
AppendCharToRedobuff(K_BS);
if (!p_ri) {
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 1ed34ef124..b00c45413a 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -1687,7 +1687,7 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen)
assert(p >= line);
memcpy(newline, line, (size_t)(p - line));
STRCPY(newline + (p - line), p + len);
- ml_replace(lnum, newline, FALSE);
+ ml_replace(lnum, newline, false);
}
break;
}
@@ -1763,12 +1763,13 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume,
if (text != NULL) {
/* Replace unprintable characters, if there are any. But
* replace a TAB with a space. */
- for (p = text; *p != NUL; ++p) {
- int len;
+ for (p = text; *p != NUL; p++) {
+ int len = utfc_ptr2len(p);
- if (has_mbyte && (len = (*mb_ptr2len)(p)) > 1) {
- if (!vim_isprintc((*mb_ptr2char)(p)))
+ if (len > 1) {
+ if (!vim_isprintc(utf_ptr2char(p))) {
break;
+ }
p += len - 1;
} else if (*p == TAB)
*p = ' ';
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index e20c75cf7b..b57e1f6558 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -701,7 +701,7 @@ static int read_redo(int init, int old_redo)
buf[i] = (char_u)c;
if (i == n - 1) { // last byte of a character
if (n != 1) {
- c = (*mb_ptr2char)(buf);
+ c = utf_ptr2char(buf);
}
break;
}
@@ -1486,7 +1486,7 @@ int vgetc(void)
}
}
no_mapping--;
- c = (*mb_ptr2char)(buf);
+ c = utf_ptr2char(buf);
}
break;
diff --git a/src/nvim/macros.h b/src/nvim/macros.h
index 7eb58bea2a..b02af723b4 100644
--- a/src/nvim/macros.h
+++ b/src/nvim/macros.h
@@ -126,7 +126,7 @@
# define MB_CHARLEN(p) mb_charlen(p)
# define MB_CHAR2LEN(c) mb_char2len(c)
-# define PTR2CHAR(p) mb_ptr2char(p)
+# define PTR2CHAR(p) utf_ptr2char(p)
# define RESET_BINDING(wp) (wp)->w_p_scb = FALSE; (wp)->w_p_crb = FALSE
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 49e60b5166..b9c91de2a8 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -1470,7 +1470,7 @@ void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
// double-wide character.
if (lp->coladd == 1
&& p[lp->col] != TAB
- && vim_isprintc((*mb_ptr2char)(p + lp->col))
+ && vim_isprintc(utf_ptr2char(p + lp->col))
&& ptr2cells(p + lp->col) > 1) {
lp->coladd = 0;
}
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 65a1a8246c..7c196831ba 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -674,7 +674,7 @@ int mb_ptr2char_adv(const char_u **const pp)
{
int c;
- c = (*mb_ptr2char)(*pp);
+ c = utf_ptr2char(*pp);
*pp += (*mb_ptr2len)(*pp);
return c;
}
@@ -687,7 +687,7 @@ int mb_cptr2char_adv(const char_u **pp)
{
int c;
- c = (*mb_ptr2char)(*pp);
+ c = utf_ptr2char(*pp);
*pp += utf_ptr2len(*pp);
return c;
}
@@ -1714,7 +1714,7 @@ void mb_check_adjust_col(void *win_)
// Reset `coladd` when the cursor would be on the right half of a
// double-wide character.
if (win->w_cursor.coladd == 1 && p[win->w_cursor.col] != TAB
- && vim_isprintc((*mb_ptr2char)(p + win->w_cursor.col))
+ && vim_isprintc(utf_ptr2char(p + win->w_cursor.col))
&& ptr2cells(p + win->w_cursor.col) > 1) {
win->w_cursor.coladd = 0;
}
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index 99aadcacad..a21c08c7fe 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -54,7 +54,6 @@ enum { MAX_MCO = 6 };
#define mb_ptr2cells_len utf_ptr2cells_len
#define mb_char2cells utf_char2cells
#define mb_off2cells utf_off2cells
-#define mb_ptr2char utf_ptr2char
#define mb_head_off utf_head_off
/// Flags for vimconv_T
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 84ceaf0973..9a1e61d40b 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -2378,7 +2378,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, int message)
)
set_keep_msg((char_u *)_(no_lines_msg), 0);
- i = ml_replace((linenr_T)1, (char_u *)"", TRUE);
+ i = ml_replace((linenr_T)1, (char_u *)"", true);
buf->b_ml.ml_flags |= ML_EMPTY;
return i;
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 46fc9115b4..947cd0735e 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1219,7 +1219,7 @@ int msg_outtrans_len_attr(char_u *msgstr, int len, int attr)
// Don't include composing chars after the end.
mb_l = utfc_ptr2len_len((char_u *)str, len + 1);
if (mb_l > 1) {
- c = (*mb_ptr2char)((char_u *)str);
+ c = utf_ptr2char((char_u *)str);
if (vim_isprintc(c)) {
// Printable multi-byte char: count the cells.
retval += (*mb_ptr2cells)((char_u *)str);
@@ -1480,7 +1480,7 @@ void msg_prt_line(char_u *s, int list)
col += (*mb_ptr2cells)(s);
char buf[MB_MAXBYTES + 1];
if (lcs_nbsp != NUL && list
- && (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) {
+ && (utf_ptr2char(s) == 160 || utf_ptr2char(s) == 0x202f)) {
mb_char2bytes(lcs_nbsp, (char_u *)buf);
buf[(*mb_ptr2len)((char_u *)buf)] = NUL;
} else {
@@ -2866,14 +2866,12 @@ do_dialog (
// Make the character lowercase, as chars in "hotkeys" are.
c = mb_tolower(c);
retval = 1;
- for (i = 0; hotkeys[i]; ++i) {
- if (has_mbyte) {
- if ((*mb_ptr2char)(hotkeys + i) == c)
- break;
- i += (*mb_ptr2len)(hotkeys + i) - 1;
- } else if (hotkeys[i] == c)
+ for (i = 0; hotkeys[i]; i++) {
+ if (utf_ptr2char(hotkeys + i) == c) {
break;
- ++retval;
+ }
+ i += utfc_ptr2len(hotkeys + i) - 1;
+ retval++;
}
if (hotkeys[i])
break;
@@ -2905,25 +2903,13 @@ copy_char (
int lowercase /* make character lower case */
)
{
- int len;
- int c;
-
- if (has_mbyte) {
- if (lowercase) {
- c = mb_tolower((*mb_ptr2char)(from));
- return (*mb_char2bytes)(c, to);
- } else {
- len = (*mb_ptr2len)(from);
- memmove(to, from, (size_t)len);
- return len;
- }
- } else {
- if (lowercase)
- *to = (char_u)TOLOWER_LOC(*from);
- else
- *to = *from;
- return 1;
+ if (lowercase) {
+ int c = mb_tolower(utf_ptr2char(from));
+ return utf_char2bytes(c, to);
}
+ int len = utfc_ptr2len(from);
+ memmove(to, from, (size_t)len);
+ return len;
}
#define HAS_HOTKEY_LEN 30
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index d2ecb9a74b..84d8c995a6 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -701,13 +701,12 @@ open_line (
replace_push(NUL); /* end of extra blanks */
if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) {
while ((*p_extra == ' ' || *p_extra == '\t')
- && (!enc_utf8
- || !utf_iscomposing(utf_ptr2char(p_extra + 1)))
- ) {
- if (REPLACE_NORMAL(State))
+ && !utf_iscomposing(utf_ptr2char(p_extra + 1))) {
+ if (REPLACE_NORMAL(State)) {
replace_push(*p_extra);
- ++p_extra;
- ++less_cols_off;
+ }
+ p_extra++;
+ less_cols_off++;
}
}
if (*p_extra != NUL) {
@@ -772,7 +771,7 @@ open_line (
(void)u_save_cursor(); /* errors are ignored! */
vr_lines_changed++;
}
- ml_replace(curwin->w_cursor.lnum, p_extra, TRUE);
+ ml_replace(curwin->w_cursor.lnum, p_extra, true);
changed_bytes(curwin->w_cursor.lnum, 0);
curwin->w_cursor.lnum--;
did_append = FALSE;
@@ -832,12 +831,13 @@ open_line (
if (dir == FORWARD) {
if (trunc_line || (State & INSERT)) {
- /* truncate current line at cursor */
+ // truncate current line at cursor
saved_line[curwin->w_cursor.col] = NUL;
- /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */
- if (trunc_line && !(flags & OPENLINE_KEEPTRAIL))
+ // Remove trailing white space, unless OPENLINE_KEEPTRAIL used.
+ if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) {
truncate_spaces(saved_line);
- ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
+ }
+ ml_replace(curwin->w_cursor.lnum, saved_line, false);
saved_line = NULL;
if (did_append) {
changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
@@ -913,8 +913,8 @@ open_line (
/* Put new line in p_extra */
p_extra = vim_strsave(get_cursor_line_ptr());
- /* Put back original line */
- ml_replace(curwin->w_cursor.lnum, next_line, FALSE);
+ // Put back original line
+ ml_replace(curwin->w_cursor.lnum, next_line, false);
/* Insert new stuff into line again */
curwin->w_cursor.col = 0;
@@ -1498,8 +1498,8 @@ void ins_char_bytes(char_u *buf, size_t charlen)
p[i] = ' ';
}
- /* Replace the line in the buffer. */
- ml_replace(lnum, newp, FALSE);
+ // Replace the line in the buffer.
+ ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying
changed_bytes(lnum, (colnr_T)col);
@@ -1512,7 +1512,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
&& msg_silent == 0
&& !ins_compl_active()
) {
- showmatch(mb_ptr2char(buf));
+ showmatch(utf_ptr2char(buf));
}
if (!p_ri || (State & REPLACE_FLAG)) {
@@ -1549,19 +1549,17 @@ void ins_str(char_u *s)
memmove(newp, oldp, (size_t)col);
memmove(newp + col, s, (size_t)newlen);
memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1));
- ml_replace(lnum, newp, FALSE);
+ ml_replace(lnum, newp, false);
changed_bytes(lnum, col);
curwin->w_cursor.col += newlen;
}
-/*
- * Delete one character under the cursor.
- * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
- * Caller must have prepared for undo.
- *
- * return FAIL for failure, OK otherwise
- */
-int del_char(int fixpos)
+// Delete one character under the cursor.
+// If "fixpos" is true, don't leave the cursor on the NUL after the line.
+// Caller must have prepared for undo.
+//
+// return FAIL for failure, OK otherwise
+int del_char(bool fixpos)
{
if (has_mbyte) {
/* Make sure the cursor is at the start of a character. */
@@ -1667,8 +1665,9 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
memmove(newp, oldp, (size_t)col);
}
memmove(newp + col, oldp + col + count, (size_t)movelen);
- if (!was_alloced)
- ml_replace(lnum, newp, FALSE);
+ if (!was_alloced) {
+ ml_replace(lnum, newp, false);
+ }
/* mark the buffer as changed and prepare for displaying */
changed_bytes(lnum, curwin->w_cursor.col);
@@ -1749,11 +1748,7 @@ del_lines (
int gchar_pos(pos_T *pos)
{
- char_u *ptr = ml_get_pos(pos);
-
- if (has_mbyte)
- return (*mb_ptr2char)(ptr);
- return (int)*ptr;
+ return utf_ptr2char(ml_get_pos(pos));
}
/*
@@ -2389,12 +2384,12 @@ int get_keystroke(void)
}
break;
}
- if (has_mbyte) {
- if (MB_BYTE2LEN(n) > len)
- continue; /* more bytes to get */
- buf[len >= buflen ? buflen - 1 : len] = NUL;
- n = (*mb_ptr2char)(buf);
+ if (MB_BYTE2LEN(n) > len) {
+ // more bytes to get.
+ continue;
}
+ buf[len >= buflen ? buflen - 1 : len] = NUL;
+ n = utf_ptr2char(buf);
#ifdef UNIX
if (n == intr_char)
n = ESC;
@@ -2840,4 +2835,3 @@ int goto_im(void)
{
return p_im && stuff_empty() && typebuf_typed();
}
-
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 4fb1a1ea9d..7defde731a 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -310,30 +310,32 @@ void shift_line(
*/
static void shift_block(oparg_T *oap, int amount)
{
- int left = (oap->op_type == OP_LSHIFT);
- int oldstate = State;
- int total;
- char_u *newp, *oldp;
- int oldcol = curwin->w_cursor.col;
- int p_sw = get_sw_value(curbuf);
- int p_ts = (int)curbuf->b_p_ts;
+ const bool left = (oap->op_type == OP_LSHIFT);
+ const int oldstate = State;
+ char_u *newp;
+ const int oldcol = curwin->w_cursor.col;
+ const int p_sw = get_sw_value(curbuf);
+ const int p_ts = (int)curbuf->b_p_ts;
struct block_def bd;
int incr;
- colnr_T ws_vcol;
int i = 0, j = 0;
- int len;
- int old_p_ri = p_ri;
+ const int old_p_ri = p_ri;
p_ri = 0; /* don't want revins in indent */
- State = INSERT; /* don't want REPLACE for State */
- block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
- if (bd.is_short)
+ State = INSERT; // don't want REPLACE for State
+ block_prep(oap, &bd, curwin->w_cursor.lnum, true);
+ if (bd.is_short) {
return;
+ }
+
+ // total is number of screen columns to be inserted/removed
+ int total = (int)((unsigned)amount * (unsigned)p_sw);
+ if ((total / p_sw) != amount) {
+ return; // multiplication overflow
+ }
- /* total is number of screen columns to be inserted/removed */
- total = amount * p_sw;
- oldp = get_cursor_line_ptr();
+ char_u *const oldp = get_cursor_line_ptr();
if (!left) {
/*
@@ -342,8 +344,8 @@ static void shift_block(oparg_T *oap, int amount)
* 3. Divvy into TABs & spp
* 4. Construct new string
*/
- total += bd.pre_whitesp; /* all virtual WS up to & incl a split TAB */
- ws_vcol = bd.start_vcol - bd.pre_whitesp;
+ total += bd.pre_whitesp; // all virtual WS up to & incl a split TAB
+ colnr_T ws_vcol = bd.start_vcol - bd.pre_whitesp;
if (bd.startspaces) {
if (has_mbyte) {
if ((*mb_ptr2len)(bd.textstart) == 1) {
@@ -372,8 +374,8 @@ static void shift_block(oparg_T *oap, int amount)
j = total;
/* if we're splitting a TAB, allow for it */
bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
- len = (int)STRLEN(bd.textstart) + 1;
- newp = (char_u *) xmalloc((size_t)(bd.textcol + i + j + len));
+ const int len = (int)STRLEN(bd.textstart) + 1;
+ newp = (char_u *)xmalloc((size_t)(bd.textcol + i + j + len));
memset(newp, NUL, (size_t)(bd.textcol + i + j + len));
memmove(newp, oldp, (size_t)bd.textcol);
memset(newp + bd.textcol, TAB, (size_t)i);
@@ -390,10 +392,7 @@ static void shift_block(oparg_T *oap, int amount)
size_t fill; // nr of spaces that replace a TAB
size_t new_line_len; // the length of the line after the
// block shift
- colnr_T block_space_width;
- colnr_T shift_amount;
char_u *non_white = bd.textstart;
- colnr_T non_white_col;
/*
* Firstly, let's find the first non-whitespace character that is
@@ -410,19 +409,20 @@ static void shift_block(oparg_T *oap, int amount)
MB_PTR_ADV(non_white);
}
- /* The character's column is in "bd.start_vcol". */
- non_white_col = bd.start_vcol;
+ // The character's column is in "bd.start_vcol".
+ colnr_T non_white_col = bd.start_vcol;
while (ascii_iswhite(*non_white)) {
incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col);
non_white_col += incr;
}
- block_space_width = non_white_col - oap->start_vcol;
- /* We will shift by "total" or "block_space_width", whichever is less.
- */
- shift_amount = (block_space_width < total ? block_space_width : total);
+ const colnr_T block_space_width = non_white_col - oap->start_vcol;
+ // We will shift by "total" or "block_space_width", whichever is less.
+ const colnr_T shift_amount = block_space_width < total
+ ? block_space_width
+ : total;
// The column to which we will shift the text.
destination_col = non_white_col - shift_amount;
@@ -454,7 +454,7 @@ static void shift_block(oparg_T *oap, int amount)
fill = (size_t)(destination_col - verbatim_copy_width);
assert(verbatim_copy_end - oldp >= 0);
- size_t verbatim_diff = (size_t)(verbatim_copy_end - oldp);
+ const size_t verbatim_diff = (size_t)(verbatim_copy_end - oldp);
// The replacement line will consist of:
// - the beginning of the original line up to "verbatim_copy_end",
// - "fill" number of spaces,
@@ -466,8 +466,8 @@ static void shift_block(oparg_T *oap, int amount)
memset(newp + verbatim_diff, ' ', fill);
STRMOVE(newp + verbatim_diff + fill, non_white);
}
- /* replace the line */
- ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+ // replace the line
+ ml_replace(curwin->w_cursor.lnum, newp, false);
changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol);
State = oldstate;
curwin->w_cursor.col = oldcol;
@@ -561,7 +561,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
offset += count;
STRMOVE(newp + offset, oldp);
- ml_replace(lnum, newp, FALSE);
+ ml_replace(lnum, newp, false);
if (lnum == oap->end.lnum) {
/* Set "']" mark to the end of the block instead of the end of
@@ -1427,10 +1427,11 @@ int op_delete(oparg_T *oap)
return FAIL;
}
- for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum) {
- block_prep(oap, &bd, lnum, TRUE);
- if (bd.textlen == 0) /* nothing to delete */
+ for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; lnum++) {
+ block_prep(oap, &bd, lnum, true);
+ if (bd.textlen == 0) { // nothing to delete
continue;
+ }
/* Adjust cursor position for tab replaced by spaces and 'lbr'. */
if (lnum == curwin->w_cursor.lnum) {
@@ -1656,11 +1657,12 @@ int op_replace(oparg_T *oap, int c)
*/
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 */
- block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
- if (bd.textlen == 0 && (!virtual_op || bd.is_MAX))
- continue; /* nothing to replace */
+ for (; curwin->w_cursor.lnum <= oap->end.lnum; curwin->w_cursor.lnum++) {
+ curwin->w_cursor.col = 0; // make sure cursor position is valid
+ block_prep(oap, &bd, curwin->w_cursor.lnum, true);
+ if (bd.textlen == 0 && (!virtual_op || bd.is_MAX)) {
+ continue; // nothing to replace
+ }
/* n == number of extra chars required
* If we split a TAB, it may be replaced by several characters.
@@ -1747,8 +1749,8 @@ int op_replace(oparg_T *oap, int c)
after_p = (char_u *)xmalloc(after_p_len);
memmove(after_p, oldp, after_p_len);
}
- /* replace the line */
- ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+ // replace the line
+ ml_replace(curwin->w_cursor.lnum, newp, false);
if (after_p != NULL) {
ml_append(curwin->w_cursor.lnum++, after_p, (int)after_p_len, false);
appended_lines_mark(curwin->w_cursor.lnum, 1L);
@@ -1852,7 +1854,7 @@ void op_tilde(oparg_T *oap)
for (; pos.lnum <= oap->end.lnum; pos.lnum++) {
int one_change;
- block_prep(oap, &bd, pos.lnum, FALSE);
+ block_prep(oap, &bd, pos.lnum, false);
pos.col = bd.textcol;
one_change = swapchars(oap->op_type, &pos, bd.textlen);
did_change |= one_change;
@@ -1956,7 +1958,7 @@ int swapchar(int op_type, pos_T *pos)
/* Special handling of German sharp s: change to "SS". */
curwin->w_cursor = *pos;
- del_char(FALSE);
+ del_char(false);
ins_char('S');
ins_char('S');
curwin->w_cursor = sp;
@@ -2030,8 +2032,8 @@ void op_insert(oparg_T *oap, long count1)
--curwin->w_cursor.col;
ve_flags = old_ve_flags;
}
- /* Get the info about the block before entering the text */
- block_prep(oap, &bd, oap->start.lnum, TRUE);
+ // Get the info about the block before entering the text
+ block_prep(oap, &bd, oap->start.lnum, true);
firstline = ml_get(oap->start.lnum) + bd.textcol;
if (oap->op_type == OP_APPEND)
firstline += bd.textlen;
@@ -2119,7 +2121,7 @@ void op_insert(oparg_T *oap, long count1)
* tabs. Get the starting column again and correct the length.
* Don't do this when "$" used, end-of-line will have changed.
*/
- block_prep(oap, &bd2, oap->start.lnum, TRUE);
+ block_prep(oap, &bd2, oap->start.lnum, true);
if (!bd.is_MAX || bd2.textlen < bd.textlen) {
if (oap->op_type == OP_APPEND) {
pre_textlen += bd2.textlen - bd.textlen;
@@ -2239,7 +2241,7 @@ int op_change(oparg_T *oap)
STRLCPY(ins_text, firstline + bd.textcol, ins_len + 1);
for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum;
linenr++) {
- block_prep(oap, &bd, linenr, TRUE);
+ block_prep(oap, &bd, linenr, true);
if (!bd.is_short || virtual_op) {
pos_T vpos;
@@ -2263,7 +2265,7 @@ int op_change(oparg_T *oap)
offset += ins_len;
oldp += bd.textcol;
STRMOVE(newp + offset, oldp);
- ml_replace(linenr, newp, FALSE);
+ ml_replace(linenr, newp, false);
}
}
check_cursor();
@@ -3117,10 +3119,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
ptr += yanklen;
}
STRMOVE(ptr, oldp + col);
- ml_replace(lnum, newp, FALSE);
- /* Place cursor on last putted char. */
+ ml_replace(lnum, newp, false);
+ // Place cursor on last putted char.
if (lnum == curwin->w_cursor.lnum) {
- /* make sure curwin->w_virtcol is updated */
+ // make sure curwin->w_virtcol is updated
changed_cline_bef_curs();
curwin->w_cursor.col += (colnr_T)(totlen - 1);
}
@@ -3164,7 +3166,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
memmove(newp, oldp, (size_t)col);
/* append to first line */
memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
- ml_replace(lnum, newp, FALSE);
+ ml_replace(lnum, newp, false);
curwin->w_cursor.lnum = lnum;
i = 1;
@@ -3620,9 +3622,9 @@ int do_join(size_t count,
curr = skipwhite(curr);
if (*curr != ')' && currsize != 0 && endcurr1 != TAB
&& (!has_format_option(FO_MBYTE_JOIN)
- || (mb_ptr2char(curr) < 0x100 && endcurr1 < 0x100))
+ || (utf_ptr2char(curr) < 0x100 && endcurr1 < 0x100))
&& (!has_format_option(FO_MBYTE_JOIN2)
- || mb_ptr2char(curr) < 0x100 || endcurr1 < 0x100)
+ || utf_ptr2char(curr) < 0x100 || endcurr1 < 0x100)
) {
/* don't add a space if the line is ending in a space */
if (endcurr1 == ' ')
@@ -3639,18 +3641,12 @@ int do_join(size_t count,
sumsize += currsize + spaces[t];
endcurr1 = endcurr2 = NUL;
if (insert_space && currsize > 0) {
- if (has_mbyte) {
- cend = curr + currsize;
+ cend = curr + currsize;
+ MB_PTR_BACK(curr, cend);
+ endcurr1 = utf_ptr2char(cend);
+ if (cend > curr) {
MB_PTR_BACK(curr, cend);
- endcurr1 = (*mb_ptr2char)(cend);
- if (cend > curr) {
- MB_PTR_BACK(curr, cend);
- endcurr2 = (*mb_ptr2char)(cend);
- }
- } else {
- endcurr1 = *(curr + currsize - 1);
- if (currsize > 1)
- endcurr2 = *(curr + currsize - 2);
+ endcurr2 = utf_ptr2char(cend);
}
}
line_breakcheck();
@@ -3693,7 +3689,7 @@ int do_join(size_t count,
curr = skipwhite(curr);
currsize = (int)STRLEN(curr);
}
- ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+ ml_replace(curwin->w_cursor.lnum, newp, false);
if (setmark) {
// Set the '] mark.
@@ -4245,7 +4241,8 @@ int paragraph_start(linenr_T lnum)
* - start/endspaces is the number of columns of the first/last yanked char
* that are to be yanked.
*/
-static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int is_del)
+static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum,
+ bool is_del)
{
int incr = 0;
char_u *pend;
@@ -5382,7 +5379,7 @@ void cursor_pos_info(dict_T *dict)
switch (l_VIsual_mode) {
case Ctrl_V:
virtual_op = virtual_active();
- block_prep(&oparg, &bd, lnum, 0);
+ block_prep(&oparg, &bd, lnum, false);
virtual_op = kNone;
s = bd.textstart;
len = (long)bd.textlen;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 50c172b580..8e2264c6a7 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2703,7 +2703,7 @@ did_set_string_option (
if (*p != NUL)
x2 = *p++;
if (*p != NUL) {
- x3 = mb_ptr2char(p);
+ x3 = utf_ptr2char(p);
p += mb_ptr2len(p);
}
if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
@@ -6406,22 +6406,25 @@ static void langmap_set(void)
++p;
break;
}
- if (p[0] == '\\' && p[1] != NUL)
- ++p;
- from = (*mb_ptr2char)(p);
+ if (p[0] == '\\' && p[1] != NUL) {
+ p++;
+ }
+ from = utf_ptr2char(p);
to = NUL;
if (p2 == NULL) {
MB_PTR_ADV(p);
if (p[0] != ',') {
- if (p[0] == '\\')
- ++p;
- to = (*mb_ptr2char)(p);
+ if (p[0] == '\\') {
+ p++;
+ }
+ to = utf_ptr2char(p);
}
} else {
if (p2[0] != ',') {
- if (p2[0] == '\\')
- ++p2;
- to = (*mb_ptr2char)(p2);
+ if (p2[0] == '\\') {
+ p2++;
+ }
+ to = utf_ptr2char(p2);
}
}
if (to == NUL) {
@@ -6846,66 +6849,37 @@ int get_sts_value(void)
*/
void find_mps_values(int *initc, int *findc, int *backwards, int switchit)
{
- char_u *ptr;
+ char_u *ptr = curbuf->b_p_mps;
- ptr = curbuf->b_p_mps;
while (*ptr != NUL) {
- if (has_mbyte) {
- char_u *prev;
-
- if (mb_ptr2char(ptr) == *initc) {
- if (switchit) {
- *findc = *initc;
- *initc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
- *backwards = TRUE;
- } else {
- *findc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
- *backwards = FALSE;
- }
- return;
- }
- prev = ptr;
- ptr += mb_ptr2len(ptr) + 1;
- if (mb_ptr2char(ptr) == *initc) {
- if (switchit) {
- *findc = *initc;
- *initc = mb_ptr2char(prev);
- *backwards = FALSE;
- } else {
- *findc = mb_ptr2char(prev);
- *backwards = TRUE;
- }
- return;
- }
- ptr += mb_ptr2len(ptr);
- } else {
- if (*ptr == *initc) {
- if (switchit) {
- *backwards = TRUE;
- *findc = *initc;
- *initc = ptr[2];
- } else {
- *backwards = FALSE;
- *findc = ptr[2];
- }
- return;
+ if (utf_ptr2char(ptr) == *initc) {
+ if (switchit) {
+ *findc = *initc;
+ *initc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1);
+ *backwards = true;
+ } else {
+ *findc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1);
+ *backwards = false;
}
- ptr += 2;
- if (*ptr == *initc) {
- if (switchit) {
- *backwards = FALSE;
- *findc = *initc;
- *initc = ptr[-2];
- } else {
- *backwards = TRUE;
- *findc = ptr[-2];
- }
- return;
+ return;
+ }
+ char_u *prev = ptr;
+ ptr += utfc_ptr2len(ptr) + 1;
+ if (utf_ptr2char(ptr) == *initc) {
+ if (switchit) {
+ *findc = *initc;
+ *initc = utf_ptr2char(prev);
+ *backwards = false;
+ } else {
+ *findc = utf_ptr2char(prev);
+ *backwards = true;
}
- ++ptr;
+ return;
+ }
+ ptr += utfc_ptr2len(ptr);
+ if (*ptr == ',') {
+ ptr++;
}
- if (*ptr == ',')
- ++ptr;
}
}
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index d76da62c6d..be6c43493b 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -772,13 +772,9 @@ static int get_equi_class(char_u **pp)
char_u *p = *pp;
if (p[1] == '=') {
- if (has_mbyte)
- l = (*mb_ptr2len)(p + 2);
+ l = (*mb_ptr2len)(p + 2);
if (p[l + 2] == '=' && p[l + 3] == ']') {
- if (has_mbyte)
- c = mb_ptr2char(p + 2);
- else
- c = p[2];
+ c = utf_ptr2char(p + 2);
*pp += l + 4;
return c;
}
@@ -1107,13 +1103,9 @@ static int get_coll_element(char_u **pp)
char_u *p = *pp;
if (p[0] != NUL && p[1] == '.') {
- if (has_mbyte)
- l = (*mb_ptr2len)(p + 2);
+ l = utfc_ptr2len(p + 2);
if (p[l + 2] == '.' && p[l + 3] == ']') {
- if (has_mbyte)
- c = mb_ptr2char(p + 2);
- else
- c = p[2];
+ c = utf_ptr2char(p + 2);
*pp += l + 4;
return c;
}
@@ -1299,10 +1291,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
}
if (OP(scan) == EXACTLY) {
- if (has_mbyte)
- r->regstart = (*mb_ptr2char)(OPERAND(scan));
- else
- r->regstart = *OPERAND(scan);
+ r->regstart = utf_ptr2char(OPERAND(scan));
} else if (OP(scan) == BOW
|| OP(scan) == EOW
|| OP(scan) == NOTHING
@@ -1310,10 +1299,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
|| OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE) {
char_u *regnext_scan = regnext(scan);
if (OP(regnext_scan) == EXACTLY) {
- if (has_mbyte)
- r->regstart = (*mb_ptr2char)(OPERAND(regnext_scan));
- else
- r->regstart = *OPERAND(regnext_scan);
+ r->regstart = utf_ptr2char(OPERAND(regnext_scan));
}
}
@@ -2412,20 +2398,16 @@ collection:
break;
}
} else {
- if (has_mbyte) {
- int len;
-
- /* produce a multibyte character, including any
- * following composing characters */
- startc = mb_ptr2char(regparse);
- len = (*mb_ptr2len)(regparse);
- if (enc_utf8 && utf_char2len(startc) != len)
- startc = -1; /* composing chars */
- while (--len >= 0)
- regc(*regparse++);
- } else {
- startc = *regparse++;
- regc(startc);
+ // produce a multibyte character, including any
+ // following composing characters.
+ startc = utf_ptr2char(regparse);
+ int len = utfc_ptr2len(regparse);
+ if (utf_char2len(startc) != len) {
+ // composing chars
+ startc = -1;
+ }
+ while (--len >= 0) {
+ regc(*regparse++);
}
}
}
@@ -2906,17 +2888,13 @@ static int peekchr(void)
* Next character can never be (made) magic?
* Then backslashing it won't do anything.
*/
- if (has_mbyte)
- curchr = (*mb_ptr2char)(regparse + 1);
- else
- curchr = c;
+ curchr = utf_ptr2char(regparse + 1);
}
break;
}
default:
- if (has_mbyte)
- curchr = (*mb_ptr2char)(regparse);
+ curchr = utf_ptr2char(regparse);
}
return curchr;
@@ -3466,12 +3444,7 @@ static long bt_regexec_both(char_u *line,
/* If there is a "must appear" string, look for it. */
if (prog->regmust != NULL) {
- int c;
-
- if (has_mbyte)
- c = (*mb_ptr2char)(prog->regmust);
- else
- c = *prog->regmust;
+ int c = utf_ptr2char(prog->regmust);
s = line + col;
// This is used very often, esp. for ":global". Use two versions of
@@ -3502,16 +3475,11 @@ static long bt_regexec_both(char_u *line,
/* Simplest case: Anchored match need be tried only once. */
if (prog->reganch) {
- int c;
-
- if (has_mbyte)
- c = (*mb_ptr2char)(regline + col);
- else
- c = regline[col];
+ int c = utf_ptr2char(regline + col);
if (prog->regstart == NUL
|| prog->regstart == c
|| (rex.reg_ic
- && (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
+ && (utf_fold(prog->regstart) == utf_fold(c)
|| (c < 255 && prog->regstart < 255
&& mb_tolower(prog->regstart) == mb_tolower(c))))) {
retval = regtry(prog, col);
@@ -3858,12 +3826,10 @@ regmatch (
} else if (rex.reg_line_lbr && WITH_NL(op) && *reginput == '\n') {
ADVANCE_REGINPUT();
} else {
- if (WITH_NL(op))
+ if (WITH_NL(op)) {
op -= ADD_NL;
- if (has_mbyte)
- c = (*mb_ptr2char)(reginput);
- else
- c = *reginput;
+ }
+ c = utf_ptr2char(reginput);
switch (op) {
case BOL:
if (reginput != regline)
@@ -5473,8 +5439,8 @@ do_class:
}
} else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) {
scan++;
- } else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) {
- if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval) {
+ } else if ((len = utfc_ptr2len(scan)) > 1) {
+ if ((cstrchr(opnd, utf_ptr2char(scan)) == NULL) == testval) {
break;
}
scan += len;
@@ -6782,18 +6748,18 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
}
c = *src++;
}
- } else if (has_mbyte)
- c = mb_ptr2char(src - 1);
-
- /* Write to buffer, if copy is set. */
- if (func_one != (fptr_T)NULL)
- /* Turbo C complains without the typecast */
+ } else {
+ c = utf_ptr2char(src - 1);
+ }
+ // Write to buffer, if copy is set.
+ if (func_one != NULL) {
func_one = (fptr_T)(func_one(&cc, c));
- else if (func_all != (fptr_T)NULL)
- /* Turbo C complains without the typecast */
+ } else if (func_all != NULL) {
func_all = (fptr_T)(func_all(&cc, c));
- else /* just copy */
+ } else {
+ // just copy
cc = c;
+ }
if (has_mbyte) {
int totlen = mb_ptr2len(src - 1);
@@ -6878,10 +6844,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
}
dst += 2;
} else {
- if (has_mbyte)
- c = mb_ptr2char(s);
- else
- c = *s;
+ c = utf_ptr2char(s);
if (func_one != (fptr_T)NULL)
/* Turbo C complains without the typecast */
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 2eb0ca9313..deef3042d2 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -5030,16 +5030,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
* Run for each character.
*/
for (;; ) {
- int curc;
- int clen;
-
- if (has_mbyte) {
- curc = (*mb_ptr2char)(reginput);
- clen = (*mb_ptr2len)(reginput);
- } else {
- curc = *reginput;
- clen = 1;
- }
+ int curc = utf_ptr2char(reginput);
+ int clen = utfc_ptr2len(reginput);
if (curc == NUL) {
clen = 0;
go_to_nextline = false;
@@ -5501,7 +5493,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
// We don't care about the order of composing characters.
// Get them into cchars[] first.
while (len < clen) {
- mc = mb_ptr2char(reginput + len);
+ mc = utf_ptr2char(reginput + len);
cchars[ccount++] = mc;
len += mb_char2len(mc);
if (ccount == MAX_MCO)
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 8e7a84c6b1..f7fdc6060d 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -2197,7 +2197,7 @@ win_line (
match_T *shl; // points to search_hl or a match
int shl_flag; // flag to indicate whether search_hl
// has been processed or not
- int prevcol_hl_flag; // flag to indicate whether prevcol
+ bool prevcol_hl_flag; // flag to indicate whether prevcol
// equals startcol of search_hl or one
// of the matches
int prev_c = 0; // previous Arabic character
@@ -3026,6 +3026,12 @@ win_line (
if (shl != &search_hl && cur != NULL)
cur = cur->next;
}
+ // Only highlight one character after the last column.
+ if (*ptr == NUL
+ && (did_line_attr >= 1
+ || (wp->w_p_list && lcs_eol_one == -1))) {
+ search_attr = 0;
+ }
}
if (diff_hlf != (hlf_T)0) {
@@ -3674,7 +3680,9 @@ win_line (
// don't do search HL for the rest of the line
if ((line_attr_lowprio || line_attr)
- && char_attr == search_attr && col > 0) {
+ && char_attr == search_attr
+ && (did_line_attr > 1
+ || (wp->w_p_list && lcs_eol > 0))) {
char_attr = line_attr;
}
if (diff_hlf == HLF_TXD) {
@@ -3833,9 +3841,12 @@ win_line (
|| lnum == VIsual.lnum
|| lnum == curwin->w_cursor.lnum)
&& c == NUL)
- /* highlight 'hlsearch' match at end of line */
- || (prevcol_hl_flag == TRUE && did_line_attr <= 1)
- )) {
+ // highlight 'hlsearch' match at end of line
+ || (prevcol_hl_flag
+ && !(wp->w_p_cul && lnum == wp->w_cursor.lnum
+ && !(wp == curwin && VIsual_active))
+ && diff_hlf == (hlf_T)0
+ && did_line_attr <= 1))) {
int n = 0;
if (wp->w_p_rl) {
@@ -5805,7 +5816,8 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
// TODO(bfredl): The relevant caller should do this
if (row == Rows - 1) { // overwritten the command line
redraw_cmdline = true;
- if (c1 == ' ' && c2 == ' ') {
+ if (start_col == 0 && end_col == Columns
+ && c1 == ' ' && c2 == ' ' && attr == 0) {
clear_cmdline = false; // command line has been cleared
}
if (start_col == 0) {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 472b98a501..95929f0eb4 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -1120,8 +1120,8 @@ int do_search(
msgbuf = xmalloc(STRLEN(p) + 40);
{
msgbuf[0] = dirc;
- if (enc_utf8 && utf_iscomposing(utf_ptr2char(p))) {
- /* Use a space to draw the composing char on. */
+ if (utf_iscomposing(utf_ptr2char(p))) {
+ // Use a space to draw the composing char on.
msgbuf[1] = ' ';
STRCPY(msgbuf + 2, p);
} else
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index cb03257878..1cb679245b 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1956,7 +1956,7 @@ static int count_syllables(slang_T *slang, char_u *word)
skip = false;
} else {
// No recognized syllable item, at least a syllable char then?
- c = mb_ptr2char(p);
+ c = utf_ptr2char(p);
len = (*mb_ptr2len)(p);
if (vim_strchr(slang->sl_syllable, c) == NULL)
skip = false; // No, search for next syllable
@@ -2271,7 +2271,7 @@ static void use_midword(slang_T *lp, win_T *wp)
int c, l, n;
char_u *bp;
- c = mb_ptr2char(p);
+ c = utf_ptr2char(p);
l = (*mb_ptr2len)(p);
if (c < 256 && l <= 2)
wp->w_s->b_spell_ismw[c] = true;
@@ -2597,16 +2597,18 @@ static bool spell_iswordp(char_u *p, win_T *wp)
if (wp->w_s->b_spell_ismw[*p])
s = p + 1; // skip a mid-word character
} else {
- c = mb_ptr2char(p);
+ c = utf_ptr2char(p);
if (c < 256 ? wp->w_s->b_spell_ismw[c]
: (wp->w_s->b_spell_ismw_mb != NULL
- && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL))
+ && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL)) {
s = p + l;
+ }
}
- c = mb_ptr2char(s);
- if (c > 255)
+ c = utf_ptr2char(s);
+ if (c > 255) {
return spell_mb_isword_class(mb_get_class(s), wp);
+ }
return spelltab.st_isw[c];
}
@@ -2617,16 +2619,11 @@ static bool spell_iswordp(char_u *p, win_T *wp)
// Unlike spell_iswordp() this doesn't check for "midword" characters.
bool spell_iswordp_nmw(const char_u *p, win_T *wp)
{
- int c;
-
- if (has_mbyte) {
- c = mb_ptr2char(p);
- if (c > 255) {
- return spell_mb_isword_class(mb_get_class(p), wp);
- }
- return spelltab.st_isw[c];
+ int c = utf_ptr2char(p);
+ if (c > 255) {
+ return spell_mb_isword_class(mb_get_class(p), wp);
}
- return spelltab.st_isw[*p];
+ return spelltab.st_isw[c];
}
// Returns true if word class indicates a word character.
@@ -2944,7 +2941,7 @@ void spell_suggest(int count)
memmove(p, line, c);
STRCPY(p + c, stp->st_word);
STRCAT(p, sug.su_badptr + stp->st_orglen);
- ml_replace(curwin->w_cursor.lnum, p, FALSE);
+ ml_replace(curwin->w_cursor.lnum, p, false);
curwin->w_cursor.col = c;
// For redo we use a change-word command.
@@ -3062,7 +3059,7 @@ void ex_spellrepall(exarg_T *eap)
memmove(p, line, curwin->w_cursor.col);
STRCPY(p + curwin->w_cursor.col, repl_to);
STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from));
- ml_replace(curwin->w_cursor.lnum, p, FALSE);
+ ml_replace(curwin->w_cursor.lnum, p, false);
changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
if (curwin->w_cursor.lnum != prev_lnum) {
@@ -4300,14 +4297,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
&& utf_iscomposing(utf_ptr2char(fword
+ sp->ts_fcharstart))) {
sp->ts_score -= SCORE_SUBST - SCORE_SUBCOMP;
- } else if (!soundfold
- && slang->sl_has_map
- && similar_chars(slang,
- mb_ptr2char(tword
- + sp->ts_twordlen
- - sp->ts_tcharlen),
- mb_ptr2char(fword
- + sp->ts_fcharstart))) {
+ } else if (
+ !soundfold
+ && slang->sl_has_map
+ && similar_chars(
+ slang,
+ utf_ptr2char(tword + sp->ts_twordlen - sp->ts_tcharlen),
+ utf_ptr2char(fword + sp->ts_fcharstart))) {
// For a similar character adjust score from
// SCORE_SUBST to SCORE_SIMILAR.
sp->ts_score -= SCORE_SUBST - SCORE_SIMILAR;
@@ -4315,8 +4311,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
} else if (sp->ts_isdiff == DIFF_INSERT
&& sp->ts_twordlen > sp->ts_tcharlen) {
p = tword + sp->ts_twordlen - sp->ts_tcharlen;
- c = mb_ptr2char(p);
- if (enc_utf8 && utf_iscomposing(c)) {
+ c = utf_ptr2char(p);
+ if (utf_iscomposing(c)) {
// Inserting a composing char doesn't
// count that much.
sp->ts_score -= SCORE_INS - SCORE_INSCOMP;
@@ -4327,7 +4323,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// tree (might seem illogical but does
// give better scores).
MB_PTR_BACK(tword, p);
- if (c == mb_ptr2char(p)) {
+ if (c == utf_ptr2char(p)) {
sp->ts_score -= SCORE_INS - SCORE_INSDUP;
}
}
@@ -4388,19 +4384,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// score if the same character is following "nn" -> "n". It's
// a bit illogical for soundfold tree but it does give better
// results.
- if (has_mbyte) {
- c = mb_ptr2char(fword + sp->ts_fidx);
- stack[depth].ts_fidx += MB_PTR2LEN(fword + sp->ts_fidx);
- if (enc_utf8 && utf_iscomposing(c)) {
- stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
- } else if (c == mb_ptr2char(fword + stack[depth].ts_fidx)) {
- stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
- }
- } else {
- ++stack[depth].ts_fidx;
- if (fword[sp->ts_fidx] == fword[sp->ts_fidx + 1])
- stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
+ c = utf_ptr2char(fword + sp->ts_fidx);
+ stack[depth].ts_fidx += MB_PTR2LEN(fword + sp->ts_fidx);
+ if (utf_iscomposing(c)) {
+ stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
+ } else if (c == utf_ptr2char(fword + stack[depth].ts_fidx)) {
+ stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP;
}
+
break;
}
// FALLTHROUGH
@@ -4515,22 +4506,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
break;
}
- if (has_mbyte) {
- n = MB_CPTR2LEN(p);
- c = mb_ptr2char(p);
- if (p[n] == NUL)
- c2 = NUL;
- else if (!soundfold && !spell_iswordp(p + n, curwin))
- c2 = c; // don't swap non-word char
- else
- c2 = mb_ptr2char(p + n);
+ n = MB_CPTR2LEN(p);
+ c = utf_ptr2char(p);
+ if (p[n] == NUL) {
+ c2 = NUL;
+ } else if (!soundfold && !spell_iswordp(p + n, curwin)) {
+ c2 = c; // don't swap non-word char
} else {
- if (p[1] == NUL)
- c2 = NUL;
- else if (!soundfold && !spell_iswordp(p + 1, curwin))
- c2 = c; // don't swap non-word char
- else
- c2 = p[1];
+ c2 = utf_ptr2char(p + n);
}
// When the second character is NUL we can't swap.
@@ -4550,9 +4533,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (c2 != NUL && TRY_DEEPER(su, stack, depth, SCORE_SWAP)) {
go_deeper(stack, depth, SCORE_SWAP);
#ifdef DEBUG_TRIEWALK
- sprintf(changename[depth], "%.*s-%s: swap %c and %c",
- sp->ts_twordlen, tword, fword + sp->ts_fidx,
- c, c2);
+ snprintf(changename[depth], sizeof(changename[0]),
+ "%.*s-%s: swap %c and %c",
+ sp->ts_twordlen, tword, fword + sp->ts_fidx,
+ c, c2);
#endif
PROF_STORE(sp->ts_state)
sp->ts_state = STATE_UNSWAP;
@@ -4576,38 +4560,25 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
case STATE_UNSWAP:
// Undo the STATE_SWAP swap: "21" -> "12".
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- n = MB_PTR2LEN(p);
- c = mb_ptr2char(p + n);
- memmove(p + MB_PTR2LEN(p + n), p, n);
- mb_char2bytes(c, p);
- } else {
- c = *p;
- *p = p[1];
- p[1] = c;
- }
+ n = MB_PTR2LEN(p);
+ c = utf_ptr2char(p + n);
+ memmove(p + MB_PTR2LEN(p + n), p, n);
+ mb_char2bytes(c, p);
+
// FALLTHROUGH
case STATE_SWAP3:
// Swap two bytes, skipping one: "123" -> "321". We change
// "fword" here, it's changed back afterwards at STATE_UNSWAP3.
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- n = MB_CPTR2LEN(p);
- c = mb_ptr2char(p);
- fl = MB_CPTR2LEN(p + n);
- c2 = mb_ptr2char(p + n);
- if (!soundfold && !spell_iswordp(p + n + fl, curwin))
- c3 = c; // don't swap non-word char
- else
- c3 = mb_ptr2char(p + n + fl);
+ n = MB_CPTR2LEN(p);
+ c = utf_ptr2char(p);
+ fl = MB_CPTR2LEN(p + n);
+ c2 = utf_ptr2char(p + n);
+ if (!soundfold && !spell_iswordp(p + n + fl, curwin)) {
+ c3 = c; // don't swap non-word char
} else {
- c = *p;
- c2 = p[1];
- if (!soundfold && !spell_iswordp(p + 2, curwin))
- c3 = c; // don't swap non-word char
- else
- c3 = p[2];
+ c3 = utf_ptr2char(p + n + fl);
}
// When characters are identical: "121" then SWAP3 result is
@@ -4651,22 +4622,15 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
case STATE_UNSWAP3:
// Undo STATE_SWAP3: "321" -> "123"
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- n = MB_PTR2LEN(p);
- c2 = mb_ptr2char(p + n);
- fl = MB_PTR2LEN(p + n);
- c = mb_ptr2char(p + n + fl);
- tl = MB_PTR2LEN(p + n + fl);
- memmove(p + fl + tl, p, n);
- mb_char2bytes(c, p);
- mb_char2bytes(c2, p + tl);
- p = p + tl;
- } else {
- c = *p;
- *p = p[2];
- p[2] = c;
- ++p;
- }
+ n = MB_PTR2LEN(p);
+ c2 = utf_ptr2char(p + n);
+ fl = MB_PTR2LEN(p + n);
+ c = utf_ptr2char(p + n + fl);
+ tl = MB_PTR2LEN(p + n + fl);
+ memmove(p + fl + tl, p, n);
+ mb_char2bytes(c, p);
+ mb_char2bytes(c2, p + tl);
+ p = p + tl;
if (!soundfold && !spell_iswordp(p, curwin)) {
// Middle char is not a word char, skip the rotate. First and
@@ -4690,21 +4654,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_state = STATE_UNROT3L;
++depth;
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- n = MB_CPTR2LEN(p);
- c = mb_ptr2char(p);
- fl = MB_CPTR2LEN(p + n);
- fl += MB_CPTR2LEN(p + n + fl);
- memmove(p, p + n, fl);
- mb_char2bytes(c, p + fl);
- stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
- } else {
- c = *p;
- *p = p[1];
- p[1] = p[2];
- p[2] = c;
- stack[depth].ts_fidxtry = sp->ts_fidx + 3;
- }
+ n = MB_CPTR2LEN(p);
+ c = utf_ptr2char(p);
+ fl = MB_CPTR2LEN(p + n);
+ fl += MB_CPTR2LEN(p + n + fl);
+ memmove(p, p + n, fl);
+ utf_char2bytes(c, p + fl);
+ stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
} else {
PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
@@ -4714,19 +4670,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
case STATE_UNROT3L:
// Undo ROT3L: "231" -> "123"
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- n = MB_PTR2LEN(p);
- n += MB_PTR2LEN(p + n);
- c = mb_ptr2char(p + n);
- tl = MB_PTR2LEN(p + n);
- memmove(p + tl, p, n);
- mb_char2bytes(c, p);
- } else {
- c = p[2];
- p[2] = p[1];
- p[1] = *p;
- *p = c;
- }
+ n = MB_PTR2LEN(p);
+ n += MB_PTR2LEN(p + n);
+ c = utf_ptr2char(p + n);
+ tl = MB_PTR2LEN(p + n);
+ memmove(p + tl, p, n);
+ mb_char2bytes(c, p);
// Rotate three bytes right: "123" -> "312". We change "fword"
// here, it's changed back afterwards at STATE_UNROT3R.
@@ -4742,21 +4691,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_state = STATE_UNROT3R;
++depth;
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- n = MB_CPTR2LEN(p);
- n += MB_CPTR2LEN(p + n);
- c = mb_ptr2char(p + n);
- tl = MB_CPTR2LEN(p + n);
- memmove(p + tl, p, n);
- mb_char2bytes(c, p);
- stack[depth].ts_fidxtry = sp->ts_fidx + n + tl;
- } else {
- c = p[2];
- p[2] = p[1];
- p[1] = *p;
- *p = c;
- stack[depth].ts_fidxtry = sp->ts_fidx + 3;
- }
+ n = MB_CPTR2LEN(p);
+ n += MB_CPTR2LEN(p + n);
+ c = utf_ptr2char(p + n);
+ tl = MB_CPTR2LEN(p + n);
+ memmove(p + tl, p, n);
+ mb_char2bytes(c, p);
+ stack[depth].ts_fidxtry = sp->ts_fidx + n + tl;
} else {
PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
@@ -4766,19 +4707,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
case STATE_UNROT3R:
// Undo ROT3R: "312" -> "123"
p = fword + sp->ts_fidx;
- if (has_mbyte) {
- c = mb_ptr2char(p);
- tl = MB_PTR2LEN(p);
- n = MB_PTR2LEN(p + tl);
- n += MB_PTR2LEN(p + tl + n);
- memmove(p, p + tl, n);
- mb_char2bytes(c, p + n);
- } else {
- c = *p;
- *p = p[1];
- p[1] = p[2];
- p[2] = c;
- }
+ c = utf_ptr2char(p);
+ tl = MB_PTR2LEN(p);
+ n = MB_PTR2LEN(p + tl);
+ n += MB_PTR2LEN(p + tl + n);
+ memmove(p, p + tl, n);
+ mb_char2bytes(c, p + n);
+
// FALLTHROUGH
case STATE_REP_INI:
@@ -5604,25 +5539,29 @@ static bool similar_chars(slang_T *slang, int c1, int c2)
if (c1 >= 256) {
buf[mb_char2bytes(c1, buf)] = 0;
hi = hash_find(&slang->sl_map_hash, buf);
- if (HASHITEM_EMPTY(hi))
+ if (HASHITEM_EMPTY(hi)) {
m1 = 0;
- else
- m1 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
- } else
+ } else {
+ m1 = utf_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
+ }
+ } else {
m1 = slang->sl_map_array[c1];
- if (m1 == 0)
+ }
+ if (m1 == 0) {
return false;
-
+ }
if (c2 >= 256) {
buf[mb_char2bytes(c2, buf)] = 0;
hi = hash_find(&slang->sl_map_hash, buf);
- if (HASHITEM_EMPTY(hi))
+ if (HASHITEM_EMPTY(hi)) {
m2 = 0;
- else
- m2 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
- } else
+ } else {
+ m2 = utf_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1);
+ }
+ } else {
m2 = slang->sl_map_array[c2];
+ }
return m1 == m2;
}
@@ -5659,11 +5598,9 @@ add_suggestion (
break;
MB_PTR_BACK(goodword, pgood);
MB_PTR_BACK(su->su_badptr, pbad);
- if (has_mbyte) {
- if (mb_ptr2char(pgood) != mb_ptr2char(pbad))
- break;
- } else if (*pgood != *pbad)
+ if (utf_ptr2char(pgood) != utf_ptr2char(pbad)) {
break;
+ }
}
if (badlen == 0 && goodlen == 0)
@@ -7608,5 +7545,3 @@ int expand_spelling(linenr_T lnum, char_u *pat, char_u ***matchp)
*matchp = ga.ga_data;
return ga.ga_len;
}
-
-
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index bd590f53c0..d7c23742ba 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -4101,13 +4101,9 @@ get_syn_options(
return NULL;
}
} else if (flagtab[fidx].argtype == 11 && arg[5] == '=') {
- /* cchar=? */
- if (has_mbyte) {
- *conceal_char = mb_ptr2char(arg + 6);
- arg += mb_ptr2len(arg + 6) - 1;
- } else {
- *conceal_char = arg[6];
- }
+ // cchar=?
+ *conceal_char = utf_ptr2char(arg + 6);
+ arg += mb_ptr2len(arg + 6) - 1;
if (!vim_isprintc_strict(*conceal_char)) {
EMSG(_("E844: invalid cchar value"));
return NULL;
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 0379235ec0..361db47fc7 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -60,12 +60,14 @@ NEW_TESTS ?= \
test_fnameescape.res \
test_fold.res \
test_ga.res \
+ test_getvar.res \
test_glob2regpat.res \
test_gf.res \
test_gn.res \
test_hardcopy.res \
test_help_tagjump.res \
test_hide.res \
+ test_highlight.res \
test_history.res \
test_hlsearch.res \
test_increment.res \
diff --git a/src/nvim/testdir/test_getvar.vim b/src/nvim/testdir/test_getvar.vim
new file mode 100644
index 0000000000..d6b6b69aa8
--- /dev/null
+++ b/src/nvim/testdir/test_getvar.vim
@@ -0,0 +1,104 @@
+" Tests for getwinvar(), gettabvar() and gettabwinvar().
+func Test_var()
+ " Use strings to test for memory leaks. First, check that in an empty
+ " window, gettabvar() returns the correct value
+ let t:testvar='abcd'
+ call assert_equal('abcd', gettabvar(1, 'testvar'))
+ call assert_equal('abcd', gettabvar(1, 'testvar'))
+
+ " test for getwinvar()
+ let w:var_str = "Dance"
+ let def_str = "Chance"
+ call assert_equal('Dance', getwinvar(1, 'var_str'))
+ call assert_equal('Dance', getwinvar(1, 'var_str', def_str))
+ call assert_equal({'var_str': 'Dance'}, getwinvar(1, ''))
+ call assert_equal({'var_str': 'Dance'}, getwinvar(1, '', def_str))
+ unlet w:var_str
+ call assert_equal('Chance', getwinvar(1, 'var_str', def_str))
+ call assert_equal({}, getwinvar(1, ''))
+ call assert_equal({}, getwinvar(1, '', def_str))
+ call assert_equal('', getwinvar(9, ''))
+ call assert_equal('Chance', getwinvar(9, '', def_str))
+ call assert_equal(0, getwinvar(1, '&nu'))
+ call assert_equal(0, getwinvar(1, '&nu', 1))
+ unlet def_str
+
+ " test for gettabvar()
+ tabnew
+ tabnew
+ let t:var_list = [1, 2, 3]
+ let t:other = 777
+ let def_list = [4, 5, 6, 7]
+ tabrewind
+ call assert_equal([1, 2, 3], gettabvar(3, 'var_list'))
+ call assert_equal([1, 2, 3], gettabvar(3, 'var_list', def_list))
+ call assert_equal({'var_list': [1, 2, 3], 'other': 777}, gettabvar(3, ''))
+ call assert_equal({'var_list': [1, 2, 3], 'other': 777},
+ \ gettabvar(3, '', def_list))
+
+ tablast
+ unlet t:var_list
+ tabrewind
+ call assert_equal([4, 5, 6, 7], gettabvar(3, 'var_list', def_list))
+ call assert_equal('', gettabvar(9, ''))
+ call assert_equal([4, 5, 6, 7], gettabvar(9, '', def_list))
+ call assert_equal('', gettabvar(3, '&nu'))
+ call assert_equal([4, 5, 6, 7], gettabvar(3, '&nu', def_list))
+ unlet def_list
+ tabonly
+
+ " test for gettabwinvar()
+ tabnew
+ tabnew
+ tabprev
+ split
+ split
+ wincmd w
+ vert split
+ wincmd w
+ let w:var_dict = {'dict': 'tabwin'}
+ let def_dict = {'dict2': 'newval'}
+ wincmd b
+ tabrewind
+ call assert_equal({'dict': 'tabwin'}, gettabwinvar(2, 3, 'var_dict'))
+ call assert_equal({'dict': 'tabwin'},
+ \ gettabwinvar(2, 3, 'var_dict', def_dict))
+ call assert_equal({'var_dict': {'dict': 'tabwin'}}, gettabwinvar(2, 3, ''))
+ call assert_equal({'var_dict': {'dict': 'tabwin'}},
+ \ gettabwinvar(2, 3, '', def_dict))
+
+ tabnext
+ 3wincmd w
+ unlet w:var_dict
+ tabrewind
+ call assert_equal({'dict2': 'newval'},
+ \ gettabwinvar(2, 3, 'var_dict', def_dict))
+ call assert_equal({}, gettabwinvar(2, 3, ''))
+ call assert_equal({}, gettabwinvar(2, 3, '', def_dict))
+ call assert_equal("", gettabwinvar(2, 9, ''))
+ call assert_equal({'dict2': 'newval'}, gettabwinvar(2, 9, '', def_dict))
+ call assert_equal('', gettabwinvar(9, 3, ''))
+ call assert_equal({'dict2': 'newval'}, gettabwinvar(9, 3, '', def_dict))
+
+ unlet def_dict
+
+ call assert_equal('', gettabwinvar(2, 3, '&nux'))
+ call assert_equal(1, gettabwinvar(2, 3, '&nux', 1))
+ tabonly
+endfunc
+
+" It was discovered that "gettabvar()" would fail if called from within the
+" tabline when the user closed a window. This test confirms the fix.
+func Test_gettabvar_in_tabline()
+ let t:var_str = 'value'
+
+ set tabline=%{assert_equal('value',gettabvar(1,'var_str'))}
+ set showtabline=2
+
+ " Simulate the user opening a split (which becomes window #1) and then
+ " closing the split, which triggers the redrawing of the tabline.
+ leftabove split
+ redrawstatus!
+ close
+ redrawstatus!
+endfunc
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
new file mode 100644
index 0000000000..33df79581c
--- /dev/null
+++ b/src/nvim/testdir/test_highlight.vim
@@ -0,0 +1,535 @@
+" Tests for ":highlight" and highlighting.
+
+source view_util.vim
+
+func Test_highlight()
+ " basic test if ":highlight" doesn't crash
+ highlight
+ hi Search
+
+ " test setting colors.
+ " test clearing one color and all doesn't generate error or warning
+ silent! hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan
+ silent! hi Group2 term= cterm=
+ hi Group3 term=underline cterm=bold
+
+ let res = split(execute("hi NewGroup"), "\n")[0]
+ " filter ctermfg and ctermbg, the numbers depend on the terminal
+ let res = substitute(res, 'ctermfg=\d*', 'ctermfg=2', '')
+ let res = substitute(res, 'ctermbg=\d*', 'ctermbg=3', '')
+ call assert_equal("NewGroup xxx cterm=italic ctermfg=2 ctermbg=3",
+ \ res)
+ call assert_equal("Group2 xxx cleared",
+ \ split(execute("hi Group2"), "\n")[0])
+ call assert_equal("Group3 xxx cterm=bold",
+ \ split(execute("hi Group3"), "\n")[0])
+
+ hi clear NewGroup
+ call assert_equal("NewGroup xxx cleared",
+ \ split(execute("hi NewGroup"), "\n")[0])
+ call assert_equal("Group2 xxx cleared",
+ \ split(execute("hi Group2"), "\n")[0])
+ hi Group2 NONE
+ call assert_equal("Group2 xxx cleared",
+ \ split(execute("hi Group2"), "\n")[0])
+ hi clear
+ call assert_equal("Group3 xxx cleared",
+ \ split(execute("hi Group3"), "\n")[0])
+ call assert_fails("hi Crash term='asdf", "E475:")
+endfunc
+
+function! HighlightArgs(name)
+ return 'hi ' . substitute(split(execute('hi ' . a:name), '\n')[0], '\<xxx\>', '', '')
+endfunction
+
+function! IsColorable()
+ return has('gui_running') || str2nr(&t_Co) >= 8
+endfunction
+
+function! HiCursorLine()
+ let hiCursorLine = HighlightArgs('CursorLine')
+ if has('gui_running')
+ let guibg = matchstr(hiCursorLine, 'guibg=\w\+')
+ let hi_ul = 'hi CursorLine gui=underline guibg=NONE'
+ let hi_bg = 'hi CursorLine gui=NONE ' . guibg
+ else
+ let hi_ul = 'hi CursorLine cterm=underline ctermbg=NONE'
+ let hi_bg = 'hi CursorLine cterm=NONE ctermbg=Gray'
+ endif
+ return [hiCursorLine, hi_ul, hi_bg]
+endfunction
+
+function! Check_lcs_eol_attrs(attrs, row, col)
+ let save_lcs = &lcs
+ set list
+
+ call assert_equal(a:attrs, ScreenAttrs(a:row, a:col)[0])
+
+ set nolist
+ let &lcs = save_lcs
+endfunction
+
+func Test_highlight_eol_with_cursorline()
+ let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine()
+
+ call NewWindow('topleft 5', 20)
+ call setline(1, 'abcd')
+ call matchadd('Search', '\n')
+
+ " expected:
+ " 'abcd '
+ " ^^^^ ^^^^^ no highlight
+ " ^ 'Search' highlight
+ let attrs0 = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs0[0]], 4), attrs0[0:3])
+ call assert_equal(repeat([attrs0[0]], 5), attrs0[5:9])
+ call assert_notequal(attrs0[0], attrs0[4])
+
+ setlocal cursorline
+
+ " underline
+ exe hi_ul
+
+ " expected:
+ " 'abcd '
+ " ^^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^^^^^ underline
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[0]], 4), attrs[0:3])
+ call assert_equal([attrs[4]] + repeat([attrs[5]], 5), attrs[4:9])
+ call assert_notequal(attrs[0], attrs[4])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[4], attrs[4])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ " expected:
+ " 'abcd '
+ " ^^^^ bg-color of 'CursorLine'
+ " ^ 'Search' highlight
+ " ^^^^^ bg-color of 'CursorLine'
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[0]], 4), attrs[0:3])
+ call assert_equal(repeat([attrs[5]], 5), attrs[5:9])
+ call assert_equal(attrs0[4], attrs[4])
+ call assert_notequal(attrs[0], attrs[4])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[5], attrs[5])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+ endif
+
+ call CloseWindow()
+ exe hiCursorLine
+endfunc
+
+func Test_highlight_eol_with_cursorline_vertsplit()
+ if !has('vertsplit')
+ return
+ endif
+
+ let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine()
+
+ call NewWindow('topleft 5', 5)
+ call setline(1, 'abcd')
+ call matchadd('Search', '\n')
+
+ let expected = "abcd |abcd "
+ let actual = ScreenLines(1, 15)[0]
+ call assert_equal(expected, actual)
+
+ " expected:
+ " 'abcd |abcd '
+ " ^^^^ ^^^^^^^^^ no highlight
+ " ^ 'Search' highlight
+ " ^ 'VertSplit' highlight
+ let attrs0 = ScreenAttrs(1, 15)[0]
+ call assert_equal(repeat([attrs0[0]], 4), attrs0[0:3])
+ call assert_equal(repeat([attrs0[0]], 9), attrs0[6:14])
+ call assert_notequal(attrs0[0], attrs0[4])
+ call assert_notequal(attrs0[0], attrs0[5])
+ call assert_notequal(attrs0[4], attrs0[5])
+
+ setlocal cursorline
+
+ " expected:
+ " 'abcd |abcd '
+ " ^^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^ 'VertSplit' highlight
+ " ^^^^^^^^^ no highlight
+
+ " underline
+ exe hi_ul
+
+ let actual = ScreenLines(1, 15)[0]
+ call assert_equal(expected, actual)
+
+ let attrs = ScreenAttrs(1, 15)[0]
+ call assert_equal(repeat([attrs[0]], 4), attrs[0:3])
+ call assert_equal(repeat([attrs[6]], 9), attrs[6:14])
+ call assert_equal(attrs0[5:14], attrs[5:14])
+ call assert_notequal(attrs[0], attrs[4])
+ call assert_notequal(attrs[0], attrs[5])
+ call assert_notequal(attrs[0], attrs[6])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs[5], attrs[6])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[4], attrs[4])
+ call Check_lcs_eol_attrs(attrs, 1, 15)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ let actual = ScreenLines(1, 15)[0]
+ call assert_equal(expected, actual)
+
+ let attrs = ScreenAttrs(1, 15)[0]
+ call assert_equal(repeat([attrs[0]], 4), attrs[0:3])
+ call assert_equal(repeat([attrs[6]], 9), attrs[6:14])
+ call assert_equal(attrs0[5:14], attrs[5:14])
+ call assert_notequal(attrs[0], attrs[4])
+ call assert_notequal(attrs[0], attrs[5])
+ call assert_notequal(attrs[0], attrs[6])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs[5], attrs[6])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_equal(attrs0[4], attrs[4])
+ call Check_lcs_eol_attrs(attrs, 1, 15)
+ endif
+
+ call CloseWindow()
+ exe hiCursorLine
+endfunc
+
+func Test_highlight_eol_with_cursorline_rightleft()
+ if !has('rightleft')
+ return
+ endif
+
+ let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine()
+
+ call NewWindow('topleft 5', 10)
+ setlocal rightleft
+ call setline(1, 'abcd')
+ call matchadd('Search', '\n')
+ let attrs0 = ScreenAttrs(1, 10)[0]
+
+ setlocal cursorline
+
+ " underline
+ exe hi_ul
+
+ " expected:
+ " ' dcba'
+ " ^^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^^^^^ underline
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[9]], 4), attrs[6:9])
+ call assert_equal(repeat([attrs[4]], 5) + [attrs[5]], attrs[0:5])
+ call assert_notequal(attrs[9], attrs[5])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs0[9], attrs[9])
+ call assert_notequal(attrs0[5], attrs[5])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ " expected:
+ " ' dcba'
+ " ^^^^ bg-color of 'CursorLine'
+ " ^ 'Search' highlight
+ " ^^^^^ bg-color of 'CursorLine'
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[9]], 4), attrs[6:9])
+ call assert_equal(repeat([attrs[4]], 5), attrs[0:4])
+ call assert_equal(attrs0[5], attrs[5])
+ call assert_notequal(attrs[9], attrs[5])
+ call assert_notequal(attrs[5], attrs[4])
+ call assert_notequal(attrs0[9], attrs[9])
+ call assert_notequal(attrs0[4], attrs[4])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+ endif
+
+ call CloseWindow()
+ exe hiCursorLine
+endfunc
+
+func Test_highlight_eol_with_cursorline_linewrap()
+ let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine()
+
+ call NewWindow('topleft 5', 10)
+ call setline(1, [repeat('a', 51) . 'bcd', ''])
+ call matchadd('Search', '\n')
+
+ setlocal wrap
+ normal! gg$
+ let attrs0 = ScreenAttrs(5, 10)[0]
+ setlocal cursorline
+
+ " underline
+ exe hi_ul
+
+ " expected:
+ " 'abcd '
+ " ^^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^^^^^ underline
+ let attrs = ScreenAttrs(5, 10)[0]
+ call assert_equal(repeat([attrs[0]], 4), attrs[0:3])
+ call assert_equal([attrs[4]] + repeat([attrs[5]], 5), attrs[4:9])
+ call assert_notequal(attrs[0], attrs[4])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[4], attrs[4])
+ call Check_lcs_eol_attrs(attrs, 5, 10)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ " expected:
+ " 'abcd '
+ " ^^^^ bg-color of 'CursorLine'
+ " ^ 'Search' highlight
+ " ^^^^^ bg-color of 'CursorLine'
+ let attrs = ScreenAttrs(5, 10)[0]
+ call assert_equal(repeat([attrs[0]], 4), attrs[0:3])
+ call assert_equal(repeat([attrs[5]], 5), attrs[5:9])
+ call assert_equal(attrs0[4], attrs[4])
+ call assert_notequal(attrs[0], attrs[4])
+ call assert_notequal(attrs[4], attrs[5])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[5], attrs[5])
+ call Check_lcs_eol_attrs(attrs, 5, 10)
+ endif
+
+ setlocal nocursorline nowrap
+ normal! gg$
+ let attrs0 = ScreenAttrs(1, 10)[0]
+ setlocal cursorline
+
+ " underline
+ exe hi_ul
+
+ " expected:
+ " 'aaabcd '
+ " ^^^^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^^^ underline
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[0]], 6), attrs[0:5])
+ call assert_equal([attrs[6]] + repeat([attrs[7]], 3), attrs[6:9])
+ call assert_notequal(attrs[0], attrs[6])
+ call assert_notequal(attrs[6], attrs[7])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[6], attrs[6])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ " expected:
+ " 'aaabcd '
+ " ^^^^^^ bg-color of 'CursorLine'
+ " ^ 'Search' highlight
+ " ^^^ bg-color of 'CursorLine'
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[0]], 6), attrs[0:5])
+ call assert_equal(repeat([attrs[7]], 3), attrs[7:9])
+ call assert_equal(attrs0[6], attrs[6])
+ call assert_notequal(attrs[0], attrs[6])
+ call assert_notequal(attrs[6], attrs[7])
+ call assert_notequal(attrs0[0], attrs[0])
+ call assert_notequal(attrs0[7], attrs[7])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+ endif
+
+ call CloseWindow()
+ exe hiCursorLine
+endfunc
+
+func Test_highlight_eol_with_cursorline_sign()
+ if !has('signs')
+ return
+ endif
+
+ let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine()
+
+ call NewWindow('topleft 5', 10)
+ call setline(1, 'abcd')
+ call matchadd('Search', '\n')
+
+ sign define Sign text=>>
+ exe 'sign place 1 line=1 name=Sign buffer=' . bufnr('')
+ let attrs0 = ScreenAttrs(1, 10)[0]
+ setlocal cursorline
+
+ " underline
+ exe hi_ul
+
+ " expected:
+ " '>>abcd '
+ " ^^ sign
+ " ^^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^^^ underline
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[2]], 4), attrs[2:5])
+ call assert_equal([attrs[6]] + repeat([attrs[7]], 3), attrs[6:9])
+ call assert_notequal(attrs[2], attrs[6])
+ call assert_notequal(attrs[6], attrs[7])
+ call assert_notequal(attrs0[2], attrs[2])
+ call assert_notequal(attrs0[6], attrs[6])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ " expected:
+ " '>>abcd '
+ " ^^ sign
+ " ^^^^ bg-color of 'CursorLine'
+ " ^ 'Search' highlight
+ " ^^^ bg-color of 'CursorLine'
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[2]], 4), attrs[2:5])
+ call assert_equal(repeat([attrs[7]], 3), attrs[7:9])
+ call assert_equal(attrs0[6], attrs[6])
+ call assert_notequal(attrs[2], attrs[6])
+ call assert_notequal(attrs[6], attrs[7])
+ call assert_notequal(attrs0[2], attrs[2])
+ call assert_notequal(attrs0[7], attrs[7])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+ endif
+
+ sign unplace 1
+ call CloseWindow()
+ exe hiCursorLine
+endfunc
+
+func Test_highlight_eol_with_cursorline_breakindent()
+ if !has('linebreak')
+ return
+ endif
+
+ let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine()
+
+ call NewWindow('topleft 5', 10)
+ setlocal breakindent breakindentopt=min:0,shift:1 showbreak=>
+ call setline(1, ' ' . repeat('a', 9) . 'bcd')
+ call matchadd('Search', '\n')
+ let attrs0 = ScreenAttrs(2, 10)[0]
+ setlocal cursorline
+
+ " underline
+ exe hi_ul
+
+ " expected:
+ " ' >bcd '
+ " ^^^ breakindent and showbreak
+ " ^^^ underline
+ " ^ 'Search' highlight with underline
+ " ^^^ underline
+ let attrs = ScreenAttrs(2, 10)[0]
+ call assert_equal(repeat([attrs[0]], 2), attrs[0:1])
+ call assert_equal(repeat([attrs[3]], 3), attrs[3:5])
+ call assert_equal([attrs[6]] + repeat([attrs[7]], 3), attrs[6:9])
+ call assert_equal(attrs0[0], attrs[0])
+ call assert_notequal(attrs[0], attrs[2])
+ call assert_notequal(attrs[2], attrs[3])
+ call assert_notequal(attrs[3], attrs[6])
+ call assert_notequal(attrs[6], attrs[7])
+ call assert_notequal(attrs0[2], attrs[2])
+ call assert_notequal(attrs0[3], attrs[3])
+ call assert_notequal(attrs0[6], attrs[6])
+ call Check_lcs_eol_attrs(attrs, 2, 10)
+
+ if IsColorable()
+ " bg-color
+ exe hi_bg
+
+ " expected:
+ " ' >bcd '
+ " ^^^ breakindent and showbreak
+ " ^^^ bg-color of 'CursorLine'
+ " ^ 'Search' highlight
+ " ^^^ bg-color of 'CursorLine'
+ let attrs = ScreenAttrs(2, 10)[0]
+ call assert_equal(repeat([attrs[0]], 2), attrs[0:1])
+ call assert_equal(repeat([attrs[3]], 3), attrs[3:5])
+ call assert_equal(repeat([attrs[7]], 3), attrs[7:9])
+ call assert_equal(attrs0[0], attrs[0])
+ call assert_equal(attrs0[6], attrs[6])
+ call assert_notequal(attrs[0], attrs[2])
+ call assert_notequal(attrs[2], attrs[3])
+ call assert_notequal(attrs[3], attrs[6])
+ call assert_notequal(attrs[6], attrs[7])
+ call assert_notequal(attrs0[2], attrs[2])
+ call assert_notequal(attrs0[3], attrs[3])
+ call assert_notequal(attrs0[7], attrs[7])
+ call Check_lcs_eol_attrs(attrs, 2, 10)
+ endif
+
+ call CloseWindow()
+ set showbreak=
+ exe hiCursorLine
+endfunc
+
+func Test_highlight_eol_on_diff()
+ call setline(1, ['abcd', ''])
+ call matchadd('Search', '\n')
+ let attrs0 = ScreenAttrs(1, 10)[0]
+
+ diffthis
+ botright new
+ diffthis
+
+ " expected:
+ " ' abcd '
+ " ^^ sign
+ " ^^^^ ^^^ 'DiffAdd' highlight
+ " ^ 'Search' highlight
+ let attrs = ScreenAttrs(1, 10)[0]
+ call assert_equal(repeat([attrs[0]], 2), attrs[0:1])
+ call assert_equal(repeat([attrs[2]], 4), attrs[2:5])
+ call assert_equal(repeat([attrs[2]], 3), attrs[7:9])
+ call assert_equal(attrs0[4], attrs[6])
+ call assert_notequal(attrs[0], attrs[2])
+ call assert_notequal(attrs[0], attrs[6])
+ call assert_notequal(attrs[2], attrs[6])
+ call Check_lcs_eol_attrs(attrs, 1, 10)
+
+ bwipe!
+ diffoff
+endfunc
+
+func Test_termguicolors()
+ if !exists('+termguicolors')
+ return
+ endif
+ if has('vtp') && !has('vcon')
+ " Win32: 'guicolors' doesn't work without virtual console.
+ call assert_fails('set termguicolors', 'E954:')
+ return
+ endif
+
+ " Basic test that setting 'termguicolors' works with one color.
+ set termguicolors
+ redraw
+ set t_Co=1
+ redraw
+ set t_Co=0
+ redraw
+endfunc
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 0f2e7e493e..756a455ebd 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -17,6 +17,14 @@ func Test_block_shift_multibyte()
q!
endfunc
+func Test_block_shift_overflow()
+ " This used to cause a multiplication overflow followed by a crash.
+ new
+ normal ii
+ exe "normal \<C-V>876543210>"
+ q!
+endfunc
+
func Test_Visual_ctrl_o()
new
call setline(1, ['one', 'two', 'three'])
@@ -118,9 +126,34 @@ func Test_blockwise_visual()
enew!
endfunc
+" Test swapping corners in blockwise visual mode with o and O
+func Test_blockwise_visual_o_O()
+ enew!
+
+ exe "norm! 10i.\<Esc>Y4P3lj\<C-V>4l2jr "
+ exe "norm! gvO\<Esc>ra"
+ exe "norm! gvO\<Esc>rb"
+ exe "norm! gvo\<C-c>rc"
+ exe "norm! gvO\<C-c>rd"
+
+ call assert_equal(['..........',
+ \ '...c d..',
+ \ '... ..',
+ \ '...a b..',
+ \ '..........'], getline(1, '$'))
+
+ enew!
+endfun
+
" Test Virtual replace mode.
func Test_virtual_replace()
throw 'skipped: TODO: '
+ if exists('&t_kD')
+ let save_t_kD = &t_kD
+ endif
+ if exists('&t_kb')
+ let save_t_kb = &t_kb
+ endif
exe "set t_kD=\<C-V>x7f t_kb=\<C-V>x08"
enew!
exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz"
@@ -151,4 +184,96 @@ func Test_virtual_replace()
call assert_equal(['AB......CDEFGHI.Jkl',
\ 'AB IJKLMNO QRst'], getline(12, 13))
enew!
+ set noai bs&vim
+ if exists('save_t_kD')
+ let &t_kD = save_t_kD
+ endif
+ if exists('save_t_kb')
+ let &t_kb = save_t_kb
+ endif
+endfunc
+
+" Test Virtual replace mode.
+func Test_virtual_replace2()
+ enew!
+ set bs=2
+ exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz"
+ call cursor(1,1)
+ " Test 1: Test that del deletes the newline
+ exe "normal gR0\<del> 1\nA\nBCDEFGHIJ\n\tKL\nMNO\nPQR"
+ call assert_equal(['0 1',
+ \ 'A',
+ \ 'BCDEFGHIJ',
+ \ ' KL',
+ \ 'MNO',
+ \ 'PQR',
+ \ ], getline(1, 6))
+ " Test 2:
+ " a newline is not deleted, if no newline has been added in virtual replace mode
+ %d_
+ call setline(1, ['abcd', 'efgh', 'ijkl'])
+ call cursor(2,1)
+ exe "norm! gR1234\<cr>5\<bs>\<bs>\<bs>"
+ call assert_equal(['abcd',
+ \ '123h',
+ \ 'ijkl'], getline(1, '$'))
+ " Test 3:
+ " a newline is deleted, if a newline has been inserted before in virtual replace mode
+ %d_
+ call setline(1, ['abcd', 'efgh', 'ijkl'])
+ call cursor(2,1)
+ exe "norm! gR1234\<cr>\<cr>56\<bs>\<bs>\<bs>"
+ call assert_equal(['abcd',
+ \ '1234',
+ \ 'ijkl'], getline(1, '$'))
+ " Test 4:
+ " delete add a newline, delete it, add it again and check undo
+ %d_
+ call setline(1, ['abcd', 'efgh', 'ijkl'])
+ call cursor(2,1)
+ " break undo sequence explicitly
+ let &ul = &ul
+ exe "norm! gR1234\<cr>\<bs>\<del>56\<cr>"
+ let &ul = &ul
+ call assert_equal(['abcd',
+ \ '123456',
+ \ ''], getline(1, '$'))
+ norm! u
+ call assert_equal(['abcd',
+ \ 'efgh',
+ \ 'ijkl'], getline(1, '$'))
+ " clean up
+ %d_
+ set bs&vim
+endfunc
+
+" Test for Visual mode not being reset causing E315 error.
+func TriggerTheProblem()
+ " At this point there is no visual selection because :call reset it.
+ " Let's restore the selection:
+ normal gv
+ '<,'>del _
+ try
+ exe "normal \<Esc>"
+ catch /^Vim\%((\a\+)\)\=:E315/
+ echom 'Snap! E315 error!'
+ let g:msg = 'Snap! E315 error!'
+ endtry
+endfunc
+
+func Test_visual_mode_reset()
+ set belloff=all
+ enew
+ let g:msg = "Everything's fine."
+ enew
+ setl buftype=nofile
+ call append(line('$'), 'Delete this line.')
+
+ " NOTE: this has to be done by a call to a function because executing :del
+ " the ex-way will require the colon operator which resets the visual mode
+ " thus preventing the problem:
+ exe "normal! GV:call TriggerTheProblem()\<CR>"
+ call assert_equal("Everything's fine.", g:msg)
+
+ set belloff&
endfunc
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index 139d29a48b..ad60c8d3c7 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -17,7 +17,7 @@ func Test_window_cmd_ls0_with_split()
endfunc
func Test_window_cmd_cmdwin_with_vsp()
- let efmt='Expected 0 but got %d (in ls=%d, %s window)'
+ let efmt = 'Expected 0 but got %d (in ls=%d, %s window)'
for v in range(0, 2)
exec "set ls=" . v
vsplit
@@ -417,4 +417,92 @@ func Test_window_newtab()
endfunc
+" Tests for adjusting window and contents
+func GetScreenStr(row)
+ let str = ""
+ for c in range(1,3)
+ let str .= nr2char(screenchar(a:row, c))
+ endfor
+ return str
+endfunc
+
+func Test_window_contents()
+ enew! | only | new
+ call setline(1, range(1,256))
+
+ exe "norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+"
+ redraw
+ let s3 = GetScreenStr(1)
+ wincmd p
+ call assert_equal(1, line("w0"))
+ call assert_equal('1 ', s3)
+
+ exe "norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+"
+ redraw
+ let s3 = GetScreenStr(1)
+ wincmd p
+ call assert_equal(50, line("w0"))
+ call assert_equal('50 ', s3)
+
+ exe "norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+"
+ redraw
+ let s3 = GetScreenStr(1)
+ wincmd p
+ call assert_equal(59, line("w0"))
+ call assert_equal('59 ', s3)
+
+ bwipeout!
+ call test_garbagecollect_now()
+endfunc
+
+func Test_access_freed_mem()
+ " This was accessing freed memory
+ au * 0 vs xxx
+ arg 0
+ argadd
+ all
+ all
+ au!
+ bwipe xxx
+endfunc
+
+func Test_visual_cleared_after_window_split()
+ new | only!
+ let smd_save = &showmode
+ set showmode
+ let ls_save = &laststatus
+ set laststatus=1
+ call setline(1, ['a', 'b', 'c', 'd', ''])
+ norm! G
+ exe "norm! kkvk"
+ redraw
+ exe "norm! \<C-W>v"
+ redraw
+ " check if '-- VISUAL --' disappeared from command line
+ let columns = range(1, &columns)
+ let cmdlinechars = map(columns, 'nr2char(screenchar(&lines, v:val))')
+ let cmdline = join(cmdlinechars, '')
+ let cmdline_ltrim = substitute(cmdline, '^\s*', "", "")
+ let mode_shown = substitute(cmdline_ltrim, '\s*$', "", "")
+ call assert_equal('', mode_shown)
+ let &showmode = smd_save
+ let &laststatus = ls_save
+ bwipe!
+endfunc
+
+func Test_winrestcmd()
+ 2split
+ 3vsplit
+ let a = winrestcmd()
+ call assert_equal(2, winheight(0))
+ call assert_equal(3, winwidth(0))
+ wincmd =
+ call assert_notequal(2, winheight(0))
+ call assert_notequal(3, winwidth(0))
+ exe a
+ call assert_equal(2, winheight(0))
+ call assert_equal(3, winwidth(0))
+ only
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/view_util.vim b/src/nvim/testdir/view_util.vim
index eb92630761..29ea073f97 100644
--- a/src/nvim/testdir/view_util.vim
+++ b/src/nvim/testdir/view_util.vim
@@ -1,5 +1,10 @@
" Functions about view shared by several tests
+" Only load this script once.
+if exists('*ScreenLines')
+ finish
+endif
+
" ScreenLines(lnum, width) or
" ScreenLines([start, end], width)
function! ScreenLines(lnum, width) abort
@@ -18,6 +23,22 @@ function! ScreenLines(lnum, width) abort
return lines
endfunction
+function! ScreenAttrs(lnum, width) abort
+ redraw!
+ if type(a:lnum) == v:t_list
+ let start = a:lnum[0]
+ let end = a:lnum[1]
+ else
+ let start = a:lnum
+ let end = a:lnum
+ endif
+ let attrs = []
+ for l in range(start, end)
+ let attrs += [map(range(1, a:width), 'screenattr(l, v:val)')]
+ endfor
+ return attrs
+endfunction
+
function! NewWindow(height, width) abort
exe a:height . 'new'
exe a:width . 'vsp'
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 2055b4879e..f4eb50b3b5 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2233,10 +2233,11 @@ static void u_undoredo(int undo, bool do_buf_event)
* If the file is empty, there is an empty line 1 that we
* should get rid of, by replacing it with the new line
*/
- if (empty_buffer && lnum == 0)
- ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
- else
+ if (empty_buffer && lnum == 0) {
+ ml_replace((linenr_T)1, uep->ue_array[i], true);
+ } else {
ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
+ }
xfree(uep->ue_array[i]);
}
xfree((char_u *)uep->ue_array);
@@ -2902,7 +2903,7 @@ void u_undoline(void)
curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
return;
oldp = u_save_line(curbuf->b_u_line_lnum);
- ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
+ ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
changed_bytes(curbuf->b_u_line_lnum, 0);
xfree(curbuf->b_u_line_ptr);
curbuf->b_u_line_ptr = oldp;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 7582c837c8..8239061a0c 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2296,6 +2296,9 @@ winframe_remove (
if (frp2->fr_win != NULL)
frp2->fr_win->w_frame = frp2->fr_parent;
frp = frp2->fr_parent;
+ if (topframe->fr_child == frp2) {
+ topframe->fr_child = frp;
+ }
xfree(frp2);
frp2 = frp->fr_parent;
@@ -2317,6 +2320,9 @@ winframe_remove (
break;
}
}
+ if (topframe->fr_child == frp) {
+ topframe->fr_child = frp2;
+ }
xfree(frp);
}
}
@@ -2959,7 +2965,6 @@ static int win_alloc_firstwin(win_T *oldwin)
topframe = curwin->w_frame;
topframe->fr_width = Columns;
topframe->fr_height = Rows - p_ch;
- topframe->fr_win = curwin;
return OK;
}
@@ -3970,18 +3975,20 @@ win_remove (
tabpage_T *tp /* tab page "win" is in, NULL for current */
)
{
- if (wp->w_prev != NULL)
+ if (wp->w_prev != NULL) {
wp->w_prev->w_next = wp->w_next;
- else if (tp == NULL)
- firstwin = wp->w_next;
- else
+ } else if (tp == NULL) {
+ firstwin = curtab->tp_firstwin = wp->w_next;
+ } else {
tp->tp_firstwin = wp->w_next;
- if (wp->w_next != NULL)
+ }
+ if (wp->w_next != NULL) {
wp->w_next->w_prev = wp->w_prev;
- else if (tp == NULL)
- lastwin = wp->w_prev;
- else
+ } else if (tp == NULL) {
+ lastwin = curtab->tp_lastwin = wp->w_prev;
+ } else {
tp->tp_lastwin = wp->w_prev;
+ }
}
/*
@@ -4015,12 +4022,18 @@ static void frame_insert(frame_T *before, frame_T *frp)
*/
static void frame_remove(frame_T *frp)
{
- if (frp->fr_prev != NULL)
+ if (frp->fr_prev != NULL) {
frp->fr_prev->fr_next = frp->fr_next;
- else
+ } else {
frp->fr_parent->fr_child = frp->fr_next;
- if (frp->fr_next != NULL)
+ // special case: topframe->fr_child == frp
+ if (topframe->fr_child == frp) {
+ topframe->fr_child = frp->fr_next;
+ }
+ }
+ if (frp->fr_next != NULL) {
frp->fr_next->fr_prev = frp->fr_prev;
+ }
}
@@ -5489,12 +5502,10 @@ int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage
return OK;
}
-/*
- * Restore current tabpage and window saved by switch_win(), if still valid.
- * When "no_display" is TRUE the display won't be affected, no redraw is
- * triggered.
- */
-void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display)
+// Restore current tabpage and window saved by switch_win(), if still valid.
+// When "no_display" is true the display won't be affected, no redraw is
+// triggered.
+void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
{
if (save_curtab != NULL && valid_tabpage(save_curtab)) {
if (no_display) {
@@ -5609,7 +5620,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
m->match.rmm_maxcol = 0;
m->conceal_char = 0;
if (conceal_char != NULL) {
- m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char);
+ m->conceal_char = utf_ptr2char((const char_u *)conceal_char);
}
// Set up position matches