aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/eval.c31
-rw-r--r--src/nvim/fileio.c8
-rw-r--r--src/nvim/globals.h8
-rw-r--r--src/nvim/screen.c82
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test63.in23
-rw-r--r--src/nvim/testdir/test63.ok2
-rw-r--r--src/nvim/testdir/test_changelist.in22
-rw-r--r--src/nvim/testdir/test_changelist.ok1
-rw-r--r--src/nvim/version.c10
-rw-r--r--src/nvim/window.c10
12 files changed, 149 insertions, 51 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 4eff8df9f5..83cddb85bf 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -318,7 +318,7 @@ close_buffer (
} else if (buf->b_p_bh[0] == 'u') /* 'bufhidden' == "unload" */
unload_buf = true;
- if (win != NULL) {
+ if (win_valid(win)) {
/* Set b_last_cursor when closing the last window for the buffer.
* Remember the last cursor position and window options of the buffer.
* This used to be only for the current window, but then options like
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 28f16d0e92..0ae96365b2 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -13461,15 +13461,36 @@ static int item_compare(const void *s1, const void *s2)
{
sortItem_T *si1, *si2;
char_u *p1, *p2;
- char_u *tofree1, *tofree2;
+ char_u *tofree1 = NULL, *tofree2 = NULL;
int res;
char_u numbuf1[NUMBUFLEN];
char_u numbuf2[NUMBUFLEN];
si1 = (sortItem_T *)s1;
si2 = (sortItem_T *)s2;
- p1 = tv2string(&si1->item->li_tv, &tofree1, numbuf1, 0);
- p2 = tv2string(&si2->item->li_tv, &tofree2, numbuf2, 0);
+ typval_T *tv1 = &si1->item->li_tv;
+ typval_T *tv2 = &si2->item->li_tv;
+ // tv2string() puts quotes around a string and allocates memory. Don't do
+ // that for string variables. Use a single quote when comparing with a
+ // non-string to do what the docs promise.
+ if (tv1->v_type == VAR_STRING) {
+ if (tv2->v_type != VAR_STRING || item_compare_numeric) {
+ p1 = (char_u *)"'";
+ } else {
+ p1 = tv1->vval.v_string;
+ }
+ } else {
+ p1 = tv2string(tv1, &tofree1, numbuf1, 0);
+ }
+ if (tv2->v_type == VAR_STRING) {
+ if (tv1->v_type != VAR_STRING || item_compare_numeric) {
+ p2 = (char_u *)"'";
+ } else {
+ p2 = tv2->vval.v_string;
+ }
+ } else {
+ p2 = tv2string(tv2, &tofree2, numbuf2, 0);
+ }
if (p1 == NULL)
p1 = (char_u *)"";
if (p2 == NULL)
@@ -13487,8 +13508,8 @@ static int item_compare(const void *s1, const void *s2)
res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1;
}
- // When the result would be zero, compare the pointers themselves. Makes
- // the sort stable.
+ // When the result would be zero, compare the item indexes. Makes the
+ // sort stable.
if (res == 0 && !item_compare_keep_zero) {
res = si1->idx > si2->idx ? 1 : -1;
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index ec91949def..fbce4428db 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -6750,7 +6750,8 @@ apply_autocmds_group (
--nesting; /* see matching increment above */
// When stopping to execute autocommands, restore the search patterns and
- // the redo buffer. Free buffers in the au_pending_free_buf list.
+ // the redo buffer. Free any buffers in the au_pending_free_buf list and
+ // free any windows in the au_pending_free_win list.
if (!autocmd_busy) {
restore_search_patterns();
restoreRedobuff();
@@ -6760,6 +6761,11 @@ apply_autocmds_group (
free(au_pending_free_buf);
au_pending_free_buf = b;
}
+ while (au_pending_free_win != NULL) {
+ win_T *w = au_pending_free_win->w_next;
+ free(au_pending_free_win);
+ au_pending_free_win = w;
+ }
}
/*
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 465a48e5b2..2025295c11 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -468,10 +468,12 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
* which one is preferred, au_new_curbuf is set to it */
EXTERN buf_T *au_new_curbuf INIT(= NULL);
-// When deleting the buffer and autocmd_busy is TRUE, do not free the buffer
-// but link it in the list starting with au_pending_free_buf, using b_next.
-// Free the buffer when autocmd_busy is set to FALSE.
+// When deleting a buffer/window and autocmd_busy is TRUE, do not free the
+// buffer/window. but link it in the list starting with
+// au_pending_free_buf/ap_pending_free_win, using b_next/w_next.
+// Free the buffer/window when autocmd_busy is being set to FALSE.
EXTERN buf_T *au_pending_free_buf INIT(= NULL);
+EXTERN win_T *au_pending_free_win INIT(= NULL);
/*
* Mouse coordinates, set by check_termcode()
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index e882935e39..c46b5fa48c 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -346,7 +346,7 @@ int redraw_asap(int type)
* Note that when also inserting/deleting lines w_redraw_top and w_redraw_bot
* may become invalid and the whole window will have to be redrawn.
*/
-void
+void
redrawWinline (
linenr_T lnum,
int invalid /* window line height is invalid now */
@@ -2114,7 +2114,7 @@ static void copy_text_attr(int off, char_u *buf, int len, int attr)
* Fill the foldcolumn at "p" for window "wp".
* Only to be called when 'foldcolumn' > 0.
*/
-static void
+static void
fill_foldcolumn (
char_u *p,
win_T *wp,
@@ -2166,7 +2166,7 @@ fill_foldcolumn (
*
* Return the number of last row the line occupies.
*/
-static int
+static int
win_line (
win_T *wp,
linenr_T lnum,
@@ -2655,8 +2655,8 @@ win_line (
}
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
- // Need to get the line again, a multi-line regexp may have made it
- // invalid.
+ // Need to get the line again, a multi-line regexp may have made it
+ // invalid.
line = ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + v;
@@ -2672,7 +2672,7 @@ win_line (
} else {
shl->endcol = MAXCOL;
}
- // Highlight one character for an empty match.
+ // Highlight one character for an empty match.
if (shl->startcol == shl->endcol) {
if (has_mbyte && line[shl->endcol] != NUL) {
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
@@ -2680,7 +2680,7 @@ win_line (
++shl->endcol;
}
}
- if ((long)shl->startcol < v) { // match at leftcol
+ if ((long)shl->startcol < v) { // match at leftcol
shl->attr_cur = shl->attr;
search_attr = shl->attr;
}
@@ -2830,9 +2830,12 @@ win_line (
if (wp->w_p_bri && n_extra == 0 && row != startrow && filler_lines == 0) {
char_attr = 0; // was: hl_attr(HLF_AT);
- if (diff_hlf != (hlf_T)0)
+ if (diff_hlf != (hlf_T)0) {
char_attr = hl_attr(diff_hlf);
-
+ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
+ char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL));
+ }
+ }
p_extra = NULL;
c_extra = ' ';
n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, FALSE));
@@ -2869,8 +2872,9 @@ win_line (
if (tocol == vcol)
tocol += n_extra;
/* combine 'showbreak' with 'cursorline' */
- if (wp->w_p_cul && lnum == wp->w_cursor.lnum)
- char_attr = hl_combine_attr(char_attr, HLF_CLN);
+ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
+ char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL));
+ }
}
}
@@ -2948,7 +2952,7 @@ win_line (
&& v >= (long)shl->startcol
&& v < (long)shl->endcol) {
shl->attr_cur = shl->attr;
- } else if (v >= (long)shl->endcol) {
+ } else if (v >= (long)shl->endcol && shl->lnum == lnum) {
shl->attr_cur = 0;
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
@@ -3016,6 +3020,9 @@ win_line (
&& n_extra == 0)
diff_hlf = HLF_CHD; /* changed line */
line_attr = hl_attr(diff_hlf);
+ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
+ line_attr = hl_combine_attr(line_attr, hl_attr(HLF_CUL));
+ }
}
/* Decide which of the highlight attributes to use. */
@@ -3620,8 +3627,12 @@ win_line (
char_attr = line_attr;
if (diff_hlf == HLF_TXD) {
diff_hlf = HLF_CHD;
- if (attr == 0 || char_attr != attr)
+ if (attr == 0 || char_attr != attr) {
char_attr = hl_attr(diff_hlf);
+ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
+ char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL));
+ }
+ }
}
}
}
@@ -4676,7 +4687,7 @@ static int skip_status_match_char(expand_T *xp, char_u *s)
*
* If inversion is possible we use it. Else '=' characters are used.
*/
-void
+void
win_redr_status_matches (
expand_T *xp,
int num_matches,
@@ -4962,7 +4973,7 @@ void win_redr_status(win_T *wp)
fillchar = fillchar_status(&attr, wp == curwin);
else
fillchar = fillchar_vsep(&attr);
- screen_putchar(fillchar, wp->w_winrow + wp->w_height,
+ screen_putchar(fillchar, wp->w_winrow + wp->w_height,
W_ENDCOL(wp), attr);
}
busy = FALSE;
@@ -5024,7 +5035,7 @@ int stl_connected(win_T *wp)
/*
* Get the value to show for the language mappings, active 'keymap'.
*/
-int
+int
get_keymap_str (
win_T *wp,
char_u *buf, /* buffer for the result */
@@ -5068,7 +5079,7 @@ get_keymap_str (
* Redraw the status line or ruler of window "wp".
* When "wp" is NULL redraw the tab pages line from 'tabline'.
*/
-static void
+static void
win_redr_custom (
win_T *wp,
int draw_ruler /* TRUE or FALSE */
@@ -5606,7 +5617,7 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
if (cur != NULL) {
cur->pos.cur = 0;
}
- bool pos_inprogress = true; // mark that a position match search is
+ bool pos_inprogress = true; // mark that a position match search is
// in progress
n = 0;
while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
@@ -5637,7 +5648,7 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
* shl->lnum is zero.
* Careful: Any pointers for buffer lines will become invalid.
*/
-static void
+static void
next_search_hl (
win_T *win,
match_T *shl, /* points to search_hl or a match */
@@ -5705,9 +5716,9 @@ next_search_hl (
if (shl->rm.regprog != NULL) {
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, &(shl->tm));
if (called_emsg || got_int) {
- // Error while handling regexp: stop using this regexp.
+ // Error while handling regexp: stop using this regexp.
if (shl == &search_hl) {
- // don't free regprog in the match list, it's a copy
+ // don't free regprog in the match list, it's a copy
vim_regfree(shl->rm.regprog);
SET_NO_HLSEARCH(TRUE);
}
@@ -5735,11 +5746,11 @@ next_search_hl (
static int
next_search_hl_pos(
- match_T *shl, // points to a match
+ match_T *shl, // points to a match
linenr_T lnum,
- posmatch_T *posmatch, // match positions
+ posmatch_T *posmatch, // match positions
colnr_T mincol // minimal column for a match
-)
+)
{
int i;
int bot = -1;
@@ -5754,8 +5765,8 @@ next_search_hl_pos(
}
if (posmatch->pos[i].lnum == lnum) {
if (shl->lnum == lnum) {
- // partially sort positions by column numbers
- // on the same line
+ // partially sort positions by column numbers
+ // on the same line
if (posmatch->pos[i].col < posmatch->pos[bot].col) {
llpos_T tmp = posmatch->pos[i];
@@ -5772,7 +5783,7 @@ next_search_hl_pos(
if (shl->lnum == lnum) {
colnr_T start = posmatch->pos[bot].col == 0
? 0: posmatch->pos[bot].col - 1;
- colnr_T end = posmatch->pos[bot].col == 0
+ colnr_T end = posmatch->pos[bot].col == 0
? MAXCOL : start + posmatch->pos[bot].len;
shl->rm.startpos[0].lnum = 0;
@@ -7091,7 +7102,7 @@ static void win_rest_invalid(win_T *wp)
*
* return FAIL for failure, OK for success.
*/
-int
+int
screen_ins_lines (
int off,
int row,
@@ -7264,7 +7275,7 @@ screen_ins_lines (
*
* Return OK for success, FAIL if the lines are not deleted.
*/
-int
+int
screen_del_lines (
int off,
int row,
@@ -7630,7 +7641,7 @@ void unshowmode(int force)
static void draw_tabline(void)
{
int tabcount = 0;
- int tabwidth;
+ int tabwidth = 0;
int col = 0;
int scol = 0;
int attr;
@@ -7676,9 +7687,13 @@ static void draw_tabline(void)
++tabcount;
}
- tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
- if (tabwidth < 6)
+ if (tabcount > 0) {
+ tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
+ }
+
+ if (tabwidth < 6) {
tabwidth = 6;
+ }
attr = attr_nosel;
tabcount = 0;
@@ -7720,8 +7735,7 @@ static void draw_tabline(void)
if (col + len >= Columns - 3)
break;
screen_puts_len(NameBuff, len, 0, col,
- hl_combine_attr(attr, hl_attr(HLF_T))
- );
+ hl_combine_attr(attr, hl_attr(HLF_T)));
col += len;
}
if (modified)
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 81dc49e800..9f04f880b5 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -33,6 +33,7 @@ SCRIPTS := test_autoformat_join.out \
test106.out test107.out \
test_options.out \
test_listlbr.out test_listlbr_utf8.out \
+ test_changelist.out \
test_breakindent.out \
test_insertcount.out
diff --git a/src/nvim/testdir/test63.in b/src/nvim/testdir/test63.in
index ea66ee6dea..ff05afbf81 100644
--- a/src/nvim/testdir/test63.in
+++ b/src/nvim/testdir/test63.in
@@ -3,6 +3,7 @@ Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
STARTTEST
:so small.vim
+:set encoding=utf8
:" --- Check that "matcharg()" returns the correct group and pattern if a match
:" --- is defined.
:let @r = "*** Test 1: "
@@ -164,7 +165,27 @@ STARTTEST
:if v1 != v5 && v6 == v1 && v8 == v5 && v10 == v5 && v11 == v1
: let @r .= "OK\n"
:else
-: let @r .= "FAILED\n"
+: let @r .= "FAILED: " . v5 . "/" . v6 . "/" . v8 . "/" . v10 . "/" . v11 . "\n"
+:endif
+:call clearmatches()
+:"
+:call setline(1, 'abcdΣabcdef')
+:call matchaddpos("MyGroup1", [[1, 4, 2], [1, 9, 2]])
+:1
+:redraw!
+:let v1 = screenattr(1, 1)
+:let v4 = screenattr(1, 4)
+:let v5 = screenattr(1, 5)
+:let v6 = screenattr(1, 6)
+:let v7 = screenattr(1, 7)
+:let v8 = screenattr(1, 8)
+:let v9 = screenattr(1, 9)
+:let v10 = screenattr(1, 10)
+:let @r .= string(getmatches())."\n"
+:if v1 != v4 && v5 == v4 && v6 == v1 && v7 == v1 && v8 == v4 && v9 == v4 && v10 == v1
+: let @r .= "OK\n"
+:else
+: let @r .= "FAILED: " . v4 . "/" . v5 . "/" . v6 . "/" . v7 . "/" . v8 . "/" . v9 . "/" . v10 . "\n"
:endif
:call clearmatches()
G"rp
diff --git a/src/nvim/testdir/test63.ok b/src/nvim/testdir/test63.ok
index f804b693ac..5d619395b7 100644
--- a/src/nvim/testdir/test63.ok
+++ b/src/nvim/testdir/test63.ok
@@ -12,3 +12,5 @@ Results of test63:
*** Test 11:
[{'group': 'MyGroup1', 'id': 3, 'priority': 10, 'pos1': [1, 5, 1], 'pos2': [1, 8, 3]}]
OK
+[{'group': 'MyGroup1', 'id': 11, 'priority': 10, 'pos1': [1, 4, 2], 'pos2': [1, 9, 2]}]
+OK
diff --git a/src/nvim/testdir/test_changelist.in b/src/nvim/testdir/test_changelist.in
new file mode 100644
index 0000000000..6c7c4306c3
--- /dev/null
+++ b/src/nvim/testdir/test_changelist.in
@@ -0,0 +1,22 @@
+Test changelist position after splitting window
+Set 'undolevels' to make changelist for sourced file
+
+STARTTEST
+:so small.vim
+Gkylp:set ul=100
+Gylp:set ul=100
+gg
+:vsplit
+:try
+: normal g;
+: normal ggVGcpass
+:catch
+: normal ggVGcfail
+:finally
+: %w! test.out
+:endtry
+:qa!
+ENDTEST
+
+1
+2
diff --git a/src/nvim/testdir/test_changelist.ok b/src/nvim/testdir/test_changelist.ok
new file mode 100644
index 0000000000..2ae28399f5
--- /dev/null
+++ b/src/nvim/testdir/test_changelist.ok
@@ -0,0 +1 @@
+pass
diff --git a/src/nvim/version.c b/src/nvim/version.c
index cc1d5abc3f..1482ec4a5a 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -230,13 +230,13 @@ static int included_patches[] = {
//414,
//413 NA
//412 NA
- //411,
+ 411,
410,
//409 NA
//408,
407,
//406,
- //405,
+ 405,
//404 NA
//403 NA
//402,
@@ -250,12 +250,12 @@ static int included_patches[] = {
//394,
//393,
392,
- //391,
+ 391,
//390,
//389,
388,
387,
- //386,
+ 386,
//385,
//384 NA
383,
@@ -321,7 +321,7 @@ static int included_patches[] = {
323,
//322 NA
//321 NA
- //320,
+ 320,
//319 NA
318,
317,
diff --git a/src/nvim/window.c b/src/nvim/window.c
index fbb283899b..4f94284186 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -950,6 +950,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
p_wh = size;
}
+ // Keep same changelist position in new window.
+ wp->w_changelistidx = oldwin->w_changelistidx;
+
/*
* make the new window the current window
*/
@@ -3694,7 +3697,12 @@ win_free (
if (wp != aucmd_win)
win_remove(wp, tp);
- free(wp);
+ if (autocmd_busy) {
+ wp->w_next = au_pending_free_win;
+ au_pending_free_win = wp;
+ } else {
+ free(wp);
+ }
unblock_autocmds();
}