Merge #8744 from janlazo/vim-8.0.0890

This commit is contained in:
Justin M. Keyes
2018-08-08 02:22:34 +02:00
committed by GitHub
19 changed files with 1099 additions and 179 deletions

View File

@@ -240,8 +240,8 @@ static int ins_need_undo; /* call u_save() before inserting a
char. Set when edit() is called. char. Set when edit() is called.
after that arrow_used is used. */ after that arrow_used is used. */
static int did_add_space = FALSE; /* auto_format() added an extra space static bool did_add_space = false; // auto_format() added an extra space
under the cursor */ // under the cursor
static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo
// for the next left/right cursor // for the next left/right cursor
@@ -1766,8 +1766,8 @@ change_indent (
/* We only put back the new line up to the cursor */ /* We only put back the new line up to the cursor */
new_line[curwin->w_cursor.col] = NUL; new_line[curwin->w_cursor.col] = NUL;
/* Put back original line */ // Put back original line
ml_replace(curwin->w_cursor.lnum, orig_line, FALSE); ml_replace(curwin->w_cursor.lnum, orig_line, false);
curwin->w_cursor.col = orig_col; curwin->w_cursor.col = orig_col;
/* Backspace from cursor to start of line */ /* Backspace from cursor to start of line */
@@ -5693,8 +5693,8 @@ auto_format (
pos = curwin->w_cursor; pos = curwin->w_cursor;
old = get_cursor_line_ptr(); old = get_cursor_line_ptr();
/* may remove added space */ // may remove added space
check_auto_format(FALSE); check_auto_format(false);
/* Don't format in Insert mode when the cursor is on a trailing blank, the /* 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 * user might insert normal text next. Also skip formatting when "1" is
@@ -5760,12 +5760,13 @@ auto_format (
pnew = vim_strnsave(new, len + 2); pnew = vim_strnsave(new, len + 2);
pnew[len] = ' '; pnew[len] = ' ';
pnew[len + 1] = NUL; pnew[len + 1] = NUL;
ml_replace(curwin->w_cursor.lnum, pnew, FALSE); ml_replace(curwin->w_cursor.lnum, pnew, false);
/* remove the space later */ // remove the space later
did_add_space = TRUE; did_add_space = true;
} else } else {
/* may remove added space */ // may remove added space
check_auto_format(FALSE); check_auto_format(false);
}
} }
check_cursor(); check_cursor();
@@ -5776,9 +5777,8 @@ auto_format (
* delete it now. The space must be under the cursor, just after the insert * delete it now. The space must be under the cursor, just after the insert
* position. * position.
*/ */
static void static void check_auto_format(
check_auto_format ( bool end_insert // true when ending Insert mode
int end_insert /* TRUE when ending Insert mode */
) )
{ {
int c = ' '; int c = ' ';
@@ -5786,19 +5786,19 @@ check_auto_format (
if (did_add_space) { if (did_add_space) {
cc = gchar_cursor(); cc = gchar_cursor();
if (!WHITECHAR(cc)) if (!WHITECHAR(cc)) {
/* Somehow the space was removed already. */ // Somehow the space was removed already.
did_add_space = FALSE; did_add_space = false;
else { } else {
if (!end_insert) { if (!end_insert) {
inc_cursor(); inc_cursor();
c = gchar_cursor(); c = gchar_cursor();
dec_cursor(); dec_cursor();
} }
if (c != NUL) { if (c != NUL) {
/* The space is no longer at the end of the line, delete it. */ // The space is no longer at the end of the line, delete it.
del_char(FALSE); del_char(false);
did_add_space = FALSE; did_add_space = false;
} }
} }
} }
@@ -6023,8 +6023,8 @@ stop_insert (
} }
} }
/* If a space was inserted for auto-formatting, remove it now. */ // If a space was inserted for auto-formatting, remove it now.
check_auto_format(TRUE); check_auto_format(true);
/* If we just did an auto-indent, remove the white space from the end /* If we just did an auto-indent, remove the white space from the end
* of the line, and put the cursor back. * of the line, and put the cursor back.
@@ -6043,10 +6043,12 @@ stop_insert (
if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
--curwin->w_cursor.col; --curwin->w_cursor.col;
cc = gchar_cursor(); cc = gchar_cursor();
if (!ascii_iswhite(cc)) if (!ascii_iswhite(cc)) {
break; 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) if (curwin->w_cursor.lnum != tpos.lnum)
curwin->w_cursor = tpos; curwin->w_cursor = tpos;
@@ -6698,8 +6700,8 @@ static void replace_do_bs(int limit_col)
* text aligned. */ * text aligned. */
curwin->w_cursor.col += ins_len; curwin->w_cursor.col += ins_len;
while (vcol > orig_vcols && gchar_cursor() == ' ') { while (vcol > orig_vcols && gchar_cursor() == ' ') {
del_char(FALSE); del_char(false);
++orig_vcols; orig_vcols++;
} }
curwin->w_cursor.col -= ins_len; curwin->w_cursor.col -= ins_len;
} }
@@ -7441,13 +7443,15 @@ static void ins_shift(int c, int lastc)
*/ */
if (c == Ctrl_D && (lastc == '0' || lastc == '^') if (c == Ctrl_D && (lastc == '0' || lastc == '^')
&& curwin->w_cursor.col > 0) { && curwin->w_cursor.col > 0) {
--curwin->w_cursor.col; curwin->w_cursor.col--;
(void)del_char(FALSE); /* delete the '^' or '0' */ (void)del_char(false); // delete the '^' or '0'
/* In Replace mode, restore the characters that '^' or '0' replaced. */ // In Replace mode, restore the characters that '^' or '0' replaced.
if (State & REPLACE_FLAG) if (State & REPLACE_FLAG) {
replace_pop_ins(); 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); change_indent(INDENT_SET, 0, TRUE, 0, TRUE);
} else } else
change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE);
@@ -7463,17 +7467,23 @@ static void ins_shift(int c, int lastc)
static void ins_del(void) static void ins_del(void)
{ {
int temp; if (stop_arrow() == FAIL) {
if (stop_arrow() == FAIL)
return; 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 if (!can_bs(BS_EOL) // only if "eol" included
|| do_join(2, false, true, false, false) == FAIL) { || do_join(2, false, true, false, false) == FAIL) {
vim_beep(BO_BS); vim_beep(BO_BS);
} else { } else {
curwin->w_cursor.col = temp; 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 } else if (del_char(false) == FAIL) { // delete char under cursor
vim_beep(BO_BS); vim_beep(BO_BS);
@@ -7499,8 +7509,9 @@ static void ins_bs_one(colnr_T *vcolp)
if (curwin->w_cursor.lnum != Insstart.lnum if (curwin->w_cursor.lnum != Insstart.lnum
|| curwin->w_cursor.col >= Insstart.col) || curwin->w_cursor.col >= Insstart.col)
replace_do_bs(-1); replace_do_bs(-1);
} else } else {
(void)del_char(FALSE); (void)del_char(false);
}
} }
/// Handle Backspace, delete-word and delete-line in Insert mode. /// Handle Backspace, delete-word and delete-line in Insert mode.
@@ -7764,16 +7775,16 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
else { else {
const bool l_enc_utf8 = enc_utf8; const bool l_enc_utf8 = enc_utf8;
const int l_p_deco = p_deco; 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)utfc_ptr2char(get_cursor_pos_ptr(), cpc);
(void)del_char(FALSE); }
/* (void)del_char(false);
* If there are combining characters and 'delcombine' is set // If there are combining characters and 'delcombine' is set
* move the cursor back. Don't back up before the base // move the cursor back. Don't back up before the base
* character. // character.
*/ if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) {
if (l_enc_utf8 && l_p_deco && cpc[0] != NUL)
inc_cursor(); inc_cursor();
}
if (revins_chars) { if (revins_chars) {
revins_chars--; revins_chars--;
revins_legal++; revins_legal++;

View File

@@ -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) static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
win_T *oldcurwin; win_T *oldcurwin;
tabpage_T *tp, *oldtabpage; tabpage_T *oldtabpage;
dictitem_T *v;
bool done = false; bool done = false;
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
const char *const varname = tv_get_string_chk(&argvars[1]); 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) { if (tp != NULL && varname != NULL) {
// Set tp to be our tabpage, temporarily. Also set the window to the // Set tp to be our tabpage, temporarily. Also set the window to the
// first window in the tabpage, otherwise the window is not valid. // 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) { if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
// look up the variable // look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary. // Let gettabvar({nr}, "") return the "t:" dictionary.
v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
varname, strlen(varname), false); varname, strlen(varname),
false);
if (v != NULL) { if (v != NULL) {
tv_copy(&v->di_tv, rettv); tv_copy(&v->di_tv, rettv);
done = true; done = true;
} }
} }
/* restore previous notion of curwin */ // restore previous notion of curwin
restore_win(oldcurwin, oldtabpage, TRUE); restore_win(oldcurwin, oldtabpage, true);
} }
if (!done && argvars[2].v_type != VAR_UNKNOWN) { if (!done && argvars[2].v_type != VAR_UNKNOWN) {

View File

@@ -716,11 +716,13 @@ void ex_retab(exarg_T *eap)
memmove(new_line + start_col + len, memmove(new_line + start_col + len,
ptr + col, (size_t)(old_len - col + 1)); ptr + col, (size_t)(old_len - col + 1));
ptr = new_line + start_col; ptr = new_line + start_col;
for (col = 0; col < len; col++) for (col = 0; col < len; col++) {
ptr[col] = (col < num_tabs) ? '\t' : ' '; 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; first_line = lnum;
}
last_line = lnum; last_line = lnum;
ptr = new_line; ptr = new_line;
col = start_col + len; col = start_col + len;
@@ -1598,6 +1600,7 @@ void ex_file(exarg_T *eap)
// print full file name if :cd used // print full file name if :cd used
fileinfo(false, false, eap->forceit); 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. // before the cursor.
len_change = (int)STRLEN(new_line) - (int)STRLEN(orig_line); len_change = (int)STRLEN(new_line) - (int)STRLEN(orig_line);
curwin->w_cursor.col += len_change; 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 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; msg_col = 0;
gotocmdline(TRUE); gotocmdline(TRUE);
/* restore the line */ // restore the line
if (orig_line != NULL) if (orig_line != NULL) {
ml_replace(lnum, orig_line, FALSE); ml_replace(lnum, orig_line, false);
}
} }
need_wait_return = FALSE; /* no hit-return prompt */ need_wait_return = FALSE; /* no hit-return prompt */
@@ -3925,9 +3929,10 @@ skip:
prev_matchcol = (colnr_T)STRLEN(sub_firstline) prev_matchcol = (colnr_T)STRLEN(sub_firstline)
- prev_matchcol; - prev_matchcol;
if (u_savesub(lnum) != OK) if (u_savesub(lnum) != OK) {
break; break;
ml_replace(lnum, new_start, TRUE); }
ml_replace(lnum, new_start, true);
if (nmatch_tl > 0) { if (nmatch_tl > 0) {
/* /*

View File

@@ -6084,7 +6084,7 @@ static int open_cmdwin(void)
/* Replace the empty last line with the current command-line and put the /* Replace the empty last line with the current command-line and put the
* cursor there. */ * 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.lnum = curbuf->b_ml.ml_line_count;
curwin->w_cursor.col = ccline.cmdpos; curwin->w_cursor.col = ccline.cmdpos;
changed_line_abv_curs(); changed_line_abv_curs();

View File

@@ -1081,7 +1081,7 @@ int fkmap(int c)
if (gchar_cursor() == _LAM) { if (gchar_cursor() == _LAM) {
chg_l_toXor_X(); chg_l_toXor_X();
del_char(FALSE); del_char(false);
AppendCharToRedobuff(K_BS); AppendCharToRedobuff(K_BS);
if (!p_ri) { if (!p_ri) {

View File

@@ -1687,7 +1687,7 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen)
assert(p >= line); assert(p >= line);
memcpy(newline, line, (size_t)(p - line)); memcpy(newline, line, (size_t)(p - line));
STRCPY(newline + (p - line), p + len); STRCPY(newline + (p - line), p + len);
ml_replace(lnum, newline, FALSE); ml_replace(lnum, newline, false);
} }
break; break;
} }

View File

@@ -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); 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; buf->b_ml.ml_flags |= ML_EMPTY;
return i; return i;

View File

@@ -771,7 +771,7 @@ open_line (
(void)u_save_cursor(); /* errors are ignored! */ (void)u_save_cursor(); /* errors are ignored! */
vr_lines_changed++; 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); changed_bytes(curwin->w_cursor.lnum, 0);
curwin->w_cursor.lnum--; curwin->w_cursor.lnum--;
did_append = FALSE; did_append = FALSE;
@@ -831,12 +831,13 @@ open_line (
if (dir == FORWARD) { if (dir == FORWARD) {
if (trunc_line || (State & INSERT)) { if (trunc_line || (State & INSERT)) {
/* truncate current line at cursor */ // truncate current line at cursor
saved_line[curwin->w_cursor.col] = NUL; saved_line[curwin->w_cursor.col] = NUL;
/* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */ // Remove trailing white space, unless OPENLINE_KEEPTRAIL used.
if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) {
truncate_spaces(saved_line); 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; saved_line = NULL;
if (did_append) { if (did_append) {
changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
@@ -912,8 +913,8 @@ open_line (
/* Put new line in p_extra */ /* Put new line in p_extra */
p_extra = vim_strsave(get_cursor_line_ptr()); p_extra = vim_strsave(get_cursor_line_ptr());
/* Put back original line */ // Put back original line
ml_replace(curwin->w_cursor.lnum, next_line, FALSE); ml_replace(curwin->w_cursor.lnum, next_line, false);
/* Insert new stuff into line again */ /* Insert new stuff into line again */
curwin->w_cursor.col = 0; curwin->w_cursor.col = 0;
@@ -1497,8 +1498,8 @@ void ins_char_bytes(char_u *buf, size_t charlen)
p[i] = ' '; p[i] = ' ';
} }
/* Replace the line in the buffer. */ // Replace the line in the buffer.
ml_replace(lnum, newp, FALSE); ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying // mark the buffer as changed and prepare for displaying
changed_bytes(lnum, (colnr_T)col); changed_bytes(lnum, (colnr_T)col);
@@ -1548,19 +1549,17 @@ void ins_str(char_u *s)
memmove(newp, oldp, (size_t)col); memmove(newp, oldp, (size_t)col);
memmove(newp + col, s, (size_t)newlen); memmove(newp + col, s, (size_t)newlen);
memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1)); 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); changed_bytes(lnum, col);
curwin->w_cursor.col += newlen; curwin->w_cursor.col += newlen;
} }
/* // Delete one character under the cursor.
* Delete one character under the cursor. // If "fixpos" is true, don't leave the cursor on the NUL after the line.
* If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. // Caller must have prepared for undo.
* Caller must have prepared for undo. //
* // return FAIL for failure, OK otherwise
* return FAIL for failure, OK otherwise int del_char(bool fixpos)
*/
int del_char(int fixpos)
{ {
if (has_mbyte) { if (has_mbyte) {
/* Make sure the cursor is at the start of a character. */ /* Make sure the cursor is at the start of a character. */
@@ -1666,8 +1665,9 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
memmove(newp, oldp, (size_t)col); memmove(newp, oldp, (size_t)col);
} }
memmove(newp + col, oldp + col + count, (size_t)movelen); memmove(newp + col, oldp + col + count, (size_t)movelen);
if (!was_alloced) if (!was_alloced) {
ml_replace(lnum, newp, FALSE); ml_replace(lnum, newp, false);
}
/* mark the buffer as changed and prepare for displaying */ /* mark the buffer as changed and prepare for displaying */
changed_bytes(lnum, curwin->w_cursor.col); changed_bytes(lnum, curwin->w_cursor.col);

View File

@@ -310,30 +310,32 @@ void shift_line(
*/ */
static void shift_block(oparg_T *oap, int amount) static void shift_block(oparg_T *oap, int amount)
{ {
int left = (oap->op_type == OP_LSHIFT); const bool left = (oap->op_type == OP_LSHIFT);
int oldstate = State; const int oldstate = State;
int total; char_u *newp;
char_u *newp, *oldp; const int oldcol = curwin->w_cursor.col;
int oldcol = curwin->w_cursor.col; const int p_sw = get_sw_value(curbuf);
int p_sw = get_sw_value(curbuf); const int p_ts = (int)curbuf->b_p_ts;
int p_ts = (int)curbuf->b_p_ts;
struct block_def bd; struct block_def bd;
int incr; int incr;
colnr_T ws_vcol;
int i = 0, j = 0; int i = 0, j = 0;
int len; const int old_p_ri = p_ri;
int old_p_ri = p_ri;
p_ri = 0; /* don't want revins in indent */ p_ri = 0; /* don't want revins in indent */
State = INSERT; /* don't want REPLACE for State */ State = INSERT; // don't want REPLACE for State
block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE); block_prep(oap, &bd, curwin->w_cursor.lnum, true);
if (bd.is_short) if (bd.is_short) {
return; return;
}
/* total is number of screen columns to be inserted/removed */ // total is number of screen columns to be inserted/removed
total = amount * p_sw; int total = (int)((unsigned)amount * (unsigned)p_sw);
oldp = get_cursor_line_ptr(); if ((total / p_sw) != amount) {
return; // multiplication overflow
}
char_u *const oldp = get_cursor_line_ptr();
if (!left) { if (!left) {
/* /*
@@ -342,8 +344,8 @@ static void shift_block(oparg_T *oap, int amount)
* 3. Divvy into TABs & spp * 3. Divvy into TABs & spp
* 4. Construct new string * 4. Construct new string
*/ */
total += bd.pre_whitesp; /* all virtual WS up to & incl a split TAB */ total += bd.pre_whitesp; // all virtual WS up to & incl a split TAB
ws_vcol = bd.start_vcol - bd.pre_whitesp; colnr_T ws_vcol = bd.start_vcol - bd.pre_whitesp;
if (bd.startspaces) { if (bd.startspaces) {
if (has_mbyte) { if (has_mbyte) {
if ((*mb_ptr2len)(bd.textstart) == 1) { if ((*mb_ptr2len)(bd.textstart) == 1) {
@@ -372,8 +374,8 @@ static void shift_block(oparg_T *oap, int amount)
j = total; j = total;
/* if we're splitting a TAB, allow for it */ /* if we're splitting a TAB, allow for it */
bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
len = (int)STRLEN(bd.textstart) + 1; const int len = (int)STRLEN(bd.textstart) + 1;
newp = (char_u *) xmalloc((size_t)(bd.textcol + i + j + len)); newp = (char_u *)xmalloc((size_t)(bd.textcol + i + j + len));
memset(newp, NUL, (size_t)(bd.textcol + i + j + len)); memset(newp, NUL, (size_t)(bd.textcol + i + j + len));
memmove(newp, oldp, (size_t)bd.textcol); memmove(newp, oldp, (size_t)bd.textcol);
memset(newp + bd.textcol, TAB, (size_t)i); 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 fill; // nr of spaces that replace a TAB
size_t new_line_len; // the length of the line after the size_t new_line_len; // the length of the line after the
// block shift // block shift
colnr_T block_space_width;
colnr_T shift_amount;
char_u *non_white = bd.textstart; char_u *non_white = bd.textstart;
colnr_T non_white_col;
/* /*
* Firstly, let's find the first non-whitespace character that is * 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); MB_PTR_ADV(non_white);
} }
/* The character's column is in "bd.start_vcol". */ // The character's column is in "bd.start_vcol".
non_white_col = bd.start_vcol; colnr_T non_white_col = bd.start_vcol;
while (ascii_iswhite(*non_white)) { while (ascii_iswhite(*non_white)) {
incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col); incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col);
non_white_col += incr; 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. // The column to which we will shift the text.
destination_col = non_white_col - shift_amount; 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); fill = (size_t)(destination_col - verbatim_copy_width);
assert(verbatim_copy_end - oldp >= 0); 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 replacement line will consist of:
// - the beginning of the original line up to "verbatim_copy_end", // - the beginning of the original line up to "verbatim_copy_end",
// - "fill" number of spaces, // - "fill" number of spaces,
@@ -466,8 +466,8 @@ static void shift_block(oparg_T *oap, int amount)
memset(newp + verbatim_diff, ' ', fill); memset(newp + verbatim_diff, ' ', fill);
STRMOVE(newp + verbatim_diff + fill, non_white); STRMOVE(newp + verbatim_diff + fill, non_white);
} }
/* replace the line */ // replace the line
ml_replace(curwin->w_cursor.lnum, newp, FALSE); ml_replace(curwin->w_cursor.lnum, newp, false);
changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol); changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol);
State = oldstate; State = oldstate;
curwin->w_cursor.col = oldcol; 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; offset += count;
STRMOVE(newp + offset, oldp); STRMOVE(newp + offset, oldp);
ml_replace(lnum, newp, FALSE); ml_replace(lnum, newp, false);
if (lnum == oap->end.lnum) { if (lnum == oap->end.lnum) {
/* Set "']" mark to the end of the block instead of the end of /* 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; return FAIL;
} }
for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum) { for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; lnum++) {
block_prep(oap, &bd, lnum, TRUE); block_prep(oap, &bd, lnum, true);
if (bd.textlen == 0) /* nothing to delete */ if (bd.textlen == 0) { // nothing to delete
continue; continue;
}
/* Adjust cursor position for tab replaced by spaces and 'lbr'. */ /* Adjust cursor position for tab replaced by spaces and 'lbr'. */
if (lnum == curwin->w_cursor.lnum) { if (lnum == curwin->w_cursor.lnum) {
@@ -1656,11 +1657,12 @@ int op_replace(oparg_T *oap, int c)
*/ */
if (oap->motion_type == kMTBlockWise) { if (oap->motion_type == kMTBlockWise) {
bd.is_MAX = (curwin->w_curswant == MAXCOL); bd.is_MAX = (curwin->w_curswant == MAXCOL);
for (; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) { for (; curwin->w_cursor.lnum <= oap->end.lnum; curwin->w_cursor.lnum++) {
curwin->w_cursor.col = 0; /* make sure cursor position is valid */ curwin->w_cursor.col = 0; // make sure cursor position is valid
block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE); block_prep(oap, &bd, curwin->w_cursor.lnum, true);
if (bd.textlen == 0 && (!virtual_op || bd.is_MAX)) if (bd.textlen == 0 && (!virtual_op || bd.is_MAX)) {
continue; /* nothing to replace */ continue; // nothing to replace
}
/* n == number of extra chars required /* n == number of extra chars required
* If we split a TAB, it may be replaced by several characters. * 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); after_p = (char_u *)xmalloc(after_p_len);
memmove(after_p, oldp, after_p_len); memmove(after_p, oldp, after_p_len);
} }
/* replace the line */ // replace the line
ml_replace(curwin->w_cursor.lnum, newp, FALSE); ml_replace(curwin->w_cursor.lnum, newp, false);
if (after_p != NULL) { if (after_p != NULL) {
ml_append(curwin->w_cursor.lnum++, after_p, (int)after_p_len, false); ml_append(curwin->w_cursor.lnum++, after_p, (int)after_p_len, false);
appended_lines_mark(curwin->w_cursor.lnum, 1L); 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++) { for (; pos.lnum <= oap->end.lnum; pos.lnum++) {
int one_change; int one_change;
block_prep(oap, &bd, pos.lnum, FALSE); block_prep(oap, &bd, pos.lnum, false);
pos.col = bd.textcol; pos.col = bd.textcol;
one_change = swapchars(oap->op_type, &pos, bd.textlen); one_change = swapchars(oap->op_type, &pos, bd.textlen);
did_change |= one_change; 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". */ /* Special handling of German sharp s: change to "SS". */
curwin->w_cursor = *pos; curwin->w_cursor = *pos;
del_char(FALSE); del_char(false);
ins_char('S'); ins_char('S');
ins_char('S'); ins_char('S');
curwin->w_cursor = sp; curwin->w_cursor = sp;
@@ -2030,8 +2032,8 @@ void op_insert(oparg_T *oap, long count1)
--curwin->w_cursor.col; --curwin->w_cursor.col;
ve_flags = old_ve_flags; ve_flags = old_ve_flags;
} }
/* Get the info about the block before entering the text */ // Get the info about the block before entering the text
block_prep(oap, &bd, oap->start.lnum, TRUE); block_prep(oap, &bd, oap->start.lnum, true);
firstline = ml_get(oap->start.lnum) + bd.textcol; firstline = ml_get(oap->start.lnum) + bd.textcol;
if (oap->op_type == OP_APPEND) if (oap->op_type == OP_APPEND)
firstline += bd.textlen; 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. * tabs. Get the starting column again and correct the length.
* Don't do this when "$" used, end-of-line will have changed. * 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 (!bd.is_MAX || bd2.textlen < bd.textlen) {
if (oap->op_type == OP_APPEND) { if (oap->op_type == OP_APPEND) {
pre_textlen += bd2.textlen - bd.textlen; 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); STRLCPY(ins_text, firstline + bd.textcol, ins_len + 1);
for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum;
linenr++) { linenr++) {
block_prep(oap, &bd, linenr, TRUE); block_prep(oap, &bd, linenr, true);
if (!bd.is_short || virtual_op) { if (!bd.is_short || virtual_op) {
pos_T vpos; pos_T vpos;
@@ -2263,7 +2265,7 @@ int op_change(oparg_T *oap)
offset += ins_len; offset += ins_len;
oldp += bd.textcol; oldp += bd.textcol;
STRMOVE(newp + offset, oldp); STRMOVE(newp + offset, oldp);
ml_replace(linenr, newp, FALSE); ml_replace(linenr, newp, false);
} }
} }
check_cursor(); check_cursor();
@@ -3117,10 +3119,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
ptr += yanklen; ptr += yanklen;
} }
STRMOVE(ptr, oldp + col); STRMOVE(ptr, oldp + col);
ml_replace(lnum, newp, FALSE); ml_replace(lnum, newp, false);
/* Place cursor on last putted char. */ // Place cursor on last putted char.
if (lnum == curwin->w_cursor.lnum) { if (lnum == curwin->w_cursor.lnum) {
/* make sure curwin->w_virtcol is updated */ // make sure curwin->w_virtcol is updated
changed_cline_bef_curs(); changed_cline_bef_curs();
curwin->w_cursor.col += (colnr_T)(totlen - 1); 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); memmove(newp, oldp, (size_t)col);
/* append to first line */ /* append to first line */
memmove(newp + col, y_array[0], (size_t)(yanklen + 1)); 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; curwin->w_cursor.lnum = lnum;
i = 1; i = 1;
@@ -3687,7 +3689,7 @@ int do_join(size_t count,
curr = skipwhite(curr); curr = skipwhite(curr);
currsize = (int)STRLEN(curr); currsize = (int)STRLEN(curr);
} }
ml_replace(curwin->w_cursor.lnum, newp, FALSE); ml_replace(curwin->w_cursor.lnum, newp, false);
if (setmark) { if (setmark) {
// Set the '] mark. // Set the '] mark.
@@ -4239,7 +4241,8 @@ int paragraph_start(linenr_T lnum)
* - start/endspaces is the number of columns of the first/last yanked char * - start/endspaces is the number of columns of the first/last yanked char
* that are to be yanked. * 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; int incr = 0;
char_u *pend; char_u *pend;
@@ -5376,7 +5379,7 @@ void cursor_pos_info(dict_T *dict)
switch (l_VIsual_mode) { switch (l_VIsual_mode) {
case Ctrl_V: case Ctrl_V:
virtual_op = virtual_active(); virtual_op = virtual_active();
block_prep(&oparg, &bd, lnum, 0); block_prep(&oparg, &bd, lnum, false);
virtual_op = kNone; virtual_op = kNone;
s = bd.textstart; s = bd.textstart;
len = (long)bd.textlen; len = (long)bd.textlen;

View File

@@ -2197,7 +2197,7 @@ win_line (
match_T *shl; // points to search_hl or a match match_T *shl; // points to search_hl or a match
int shl_flag; // flag to indicate whether search_hl int shl_flag; // flag to indicate whether search_hl
// has been processed or not // 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 // equals startcol of search_hl or one
// of the matches // of the matches
int prev_c = 0; // previous Arabic character int prev_c = 0; // previous Arabic character
@@ -3026,6 +3026,12 @@ win_line (
if (shl != &search_hl && cur != NULL) if (shl != &search_hl && cur != NULL)
cur = cur->next; 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) { if (diff_hlf != (hlf_T)0) {
@@ -3674,7 +3680,9 @@ win_line (
// don't do search HL for the rest of the line // don't do search HL for the rest of the line
if ((line_attr_lowprio || line_attr) 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; char_attr = line_attr;
} }
if (diff_hlf == HLF_TXD) { if (diff_hlf == HLF_TXD) {
@@ -3833,9 +3841,12 @@ win_line (
|| lnum == VIsual.lnum || lnum == VIsual.lnum
|| lnum == curwin->w_cursor.lnum) || lnum == curwin->w_cursor.lnum)
&& c == NUL) && c == NUL)
/* highlight 'hlsearch' match at end of line */ // highlight 'hlsearch' match at end of line
|| (prevcol_hl_flag == TRUE && did_line_attr <= 1) || (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; int n = 0;
if (wp->w_p_rl) { 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 // TODO(bfredl): The relevant caller should do this
if (row == Rows - 1) { // overwritten the command line if (row == Rows - 1) { // overwritten the command line
redraw_cmdline = true; 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 clear_cmdline = false; // command line has been cleared
} }
if (start_col == 0) { if (start_col == 0) {

View File

@@ -2941,7 +2941,7 @@ void spell_suggest(int count)
memmove(p, line, c); memmove(p, line, c);
STRCPY(p + c, stp->st_word); STRCPY(p + c, stp->st_word);
STRCAT(p, sug.su_badptr + stp->st_orglen); 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; curwin->w_cursor.col = c;
// For redo we use a change-word command. // For redo we use a change-word command.
@@ -3059,7 +3059,7 @@ void ex_spellrepall(exarg_T *eap)
memmove(p, line, curwin->w_cursor.col); memmove(p, line, curwin->w_cursor.col);
STRCPY(p + curwin->w_cursor.col, repl_to); STRCPY(p + curwin->w_cursor.col, repl_to);
STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from)); 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); changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
if (curwin->w_cursor.lnum != prev_lnum) { if (curwin->w_cursor.lnum != prev_lnum) {

View File

@@ -60,12 +60,14 @@ NEW_TESTS ?= \
test_fnameescape.res \ test_fnameescape.res \
test_fold.res \ test_fold.res \
test_ga.res \ test_ga.res \
test_getvar.res \
test_glob2regpat.res \ test_glob2regpat.res \
test_gf.res \ test_gf.res \
test_gn.res \ test_gn.res \
test_hardcopy.res \ test_hardcopy.res \
test_help_tagjump.res \ test_help_tagjump.res \
test_hide.res \ test_hide.res \
test_highlight.res \
test_history.res \ test_history.res \
test_hlsearch.res \ test_hlsearch.res \
test_increment.res \ test_increment.res \

View File

@@ -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

View File

@@ -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

View File

@@ -17,6 +17,14 @@ func Test_block_shift_multibyte()
q! q!
endfunc 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() func Test_Visual_ctrl_o()
new new
call setline(1, ['one', 'two', 'three']) call setline(1, ['one', 'two', 'three'])
@@ -118,9 +126,34 @@ func Test_blockwise_visual()
enew! enew!
endfunc 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. " Test Virtual replace mode.
func Test_virtual_replace() func Test_virtual_replace()
throw 'skipped: TODO: ' 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" exe "set t_kD=\<C-V>x7f t_kb=\<C-V>x08"
enew! enew!
exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz" 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', call assert_equal(['AB......CDEFGHI.Jkl',
\ 'AB IJKLMNO QRst'], getline(12, 13)) \ 'AB IJKLMNO QRst'], getline(12, 13))
enew! 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 endfunc

View File

@@ -17,7 +17,7 @@ func Test_window_cmd_ls0_with_split()
endfunc endfunc
func Test_window_cmd_cmdwin_with_vsp() 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) for v in range(0, 2)
exec "set ls=" . v exec "set ls=" . v
vsplit vsplit
@@ -417,4 +417,92 @@ func Test_window_newtab()
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1,5 +1,10 @@
" Functions about view shared by several tests " Functions about view shared by several tests
" Only load this script once.
if exists('*ScreenLines')
finish
endif
" ScreenLines(lnum, width) or " ScreenLines(lnum, width) or
" ScreenLines([start, end], width) " ScreenLines([start, end], width)
function! ScreenLines(lnum, width) abort function! ScreenLines(lnum, width) abort
@@ -18,6 +23,22 @@ function! ScreenLines(lnum, width) abort
return lines return lines
endfunction 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 function! NewWindow(height, width) abort
exe a:height . 'new' exe a:height . 'new'
exe a:width . 'vsp' exe a:width . 'vsp'

View File

@@ -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 * If the file is empty, there is an empty line 1 that we
* should get rid of, by replacing it with the new line * should get rid of, by replacing it with the new line
*/ */
if (empty_buffer && lnum == 0) if (empty_buffer && lnum == 0) {
ml_replace((linenr_T)1, uep->ue_array[i], TRUE); ml_replace((linenr_T)1, uep->ue_array[i], true);
else } else {
ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE); ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
}
xfree(uep->ue_array[i]); xfree(uep->ue_array[i]);
} }
xfree((char_u *)uep->ue_array); 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) curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
return; return;
oldp = u_save_line(curbuf->b_u_line_lnum); 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); changed_bytes(curbuf->b_u_line_lnum, 0);
xfree(curbuf->b_u_line_ptr); xfree(curbuf->b_u_line_ptr);
curbuf->b_u_line_ptr = oldp; curbuf->b_u_line_ptr = oldp;

View File

@@ -2296,6 +2296,9 @@ winframe_remove (
if (frp2->fr_win != NULL) if (frp2->fr_win != NULL)
frp2->fr_win->w_frame = frp2->fr_parent; frp2->fr_win->w_frame = frp2->fr_parent;
frp = frp2->fr_parent; frp = frp2->fr_parent;
if (topframe->fr_child == frp2) {
topframe->fr_child = frp;
}
xfree(frp2); xfree(frp2);
frp2 = frp->fr_parent; frp2 = frp->fr_parent;
@@ -2317,6 +2320,9 @@ winframe_remove (
break; break;
} }
} }
if (topframe->fr_child == frp) {
topframe->fr_child = frp2;
}
xfree(frp); xfree(frp);
} }
} }
@@ -2959,7 +2965,6 @@ static int win_alloc_firstwin(win_T *oldwin)
topframe = curwin->w_frame; topframe = curwin->w_frame;
topframe->fr_width = Columns; topframe->fr_width = Columns;
topframe->fr_height = Rows - p_ch; topframe->fr_height = Rows - p_ch;
topframe->fr_win = curwin;
return OK; return OK;
} }
@@ -3970,18 +3975,20 @@ win_remove (
tabpage_T *tp /* tab page "win" is in, NULL for current */ 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; wp->w_prev->w_next = wp->w_next;
else if (tp == NULL) } else if (tp == NULL) {
firstwin = wp->w_next; firstwin = curtab->tp_firstwin = wp->w_next;
else } else {
tp->tp_firstwin = wp->w_next; tp->tp_firstwin = wp->w_next;
if (wp->w_next != NULL) }
if (wp->w_next != NULL) {
wp->w_next->w_prev = wp->w_prev; wp->w_next->w_prev = wp->w_prev;
else if (tp == NULL) } else if (tp == NULL) {
lastwin = wp->w_prev; lastwin = curtab->tp_lastwin = wp->w_prev;
else } else {
tp->tp_lastwin = wp->w_prev; 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) 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; frp->fr_prev->fr_next = frp->fr_next;
else } else {
frp->fr_parent->fr_child = frp->fr_next; 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; 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; return OK;
} }
/* // Restore current tabpage and window saved by switch_win(), if still valid.
* 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
* When "no_display" is TRUE the display won't be affected, no redraw is // triggered.
* triggered. void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
*/
void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display)
{ {
if (save_curtab != NULL && valid_tabpage(save_curtab)) { if (save_curtab != NULL && valid_tabpage(save_curtab)) {
if (no_display) { if (no_display) {