aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_cmds2.c3
-rw-r--r--src/nvim/globals.h16
-rw-r--r--src/nvim/mouse.c71
-rw-r--r--src/nvim/normal.c4
-rw-r--r--src/nvim/screen.c10
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_options.vim42
-rw-r--r--src/nvim/testdir/test_statusline.vim16
-rw-r--r--src/nvim/undo.c114
-rw-r--r--src/nvim/window.c12
10 files changed, 239 insertions, 50 deletions
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index c24ecde096..c4c18c4324 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -3024,6 +3024,7 @@ void scriptnames_slash_adjust(void)
# endif
/// Get a pointer to a script name. Used for ":verbose set".
+/// Message appended to "Last set from "
char_u *get_scriptname(LastSet last_set, bool *should_free)
{
*should_free = false;
@@ -3039,6 +3040,8 @@ char_u *get_scriptname(LastSet last_set, bool *should_free)
return (char_u *)_("environment variable");
case SID_ERROR:
return (char_u *)_("error handler");
+ case SID_WINLAYOUT:
+ return (char_u *)_("changed window size");
case SID_LUA:
return (char_u *)_("Lua");
case SID_API_CLIENT:
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 22f06941aa..7b8e809de7 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -180,6 +180,11 @@ EXTERN int compl_cont_status INIT(= 0);
# define CONT_LOCAL 32 // for ctrl_x_mode 0, ^X^P/^X^N do a local
// expansion, (eg use complete=.)
+EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
+EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
+EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode
+EXTERN hlf_T edit_submode_highl; // highl. method for extra info
+
// state for putting characters in the message area
EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left
EXTERN int msg_col;
@@ -328,9 +333,10 @@ EXTERN int garbage_collect_at_exit INIT(= false);
#define SID_ENV -4 // for sourcing environment variable
#define SID_ERROR -5 // option was reset because of an error
#define SID_NONE -6 // don't set scriptID
-#define SID_LUA -7 // for Lua scripts/chunks
-#define SID_API_CLIENT -8 // for API clients
-#define SID_STR -9 // for sourcing a string
+#define SID_WINLAYOUT -7 // changing window size
+#define SID_LUA -8 // for Lua scripts/chunks
+#define SID_API_CLIENT -9 // for API clients
+#define SID_STR -10 // for sourcing a string
// Script CTX being sourced or was sourced to define the current function.
EXTERN sctx_T current_sctx INIT(= { 0 COMMA 0 COMMA 0 });
@@ -639,10 +645,6 @@ EXTERN int arrow_used; // Normally false, set to true after
// to call u_sync()
EXTERN bool ins_at_eol INIT(= false); // put cursor after eol when
// restarting edit after CTRL-O
-EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode
-EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode
-EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode
-EXTERN hlf_T edit_submode_highl; // highl. method for extra info
EXTERN int no_abbr INIT(= true); // true when no abbreviations loaded
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index ff471ea978..f28658aa29 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -72,9 +72,7 @@ int jump_to_mouse(int flags,
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
- int mouse_char;
int fdc = 0;
- ScreenGrid *gp = &default_grid;
mouse_past_bottom = false;
mouse_past_eol = false;
@@ -303,25 +301,6 @@ retnomove:
}
}
- // Remember the character under the mouse, might be one of foldclose or
- // foldopen fillchars in the fold column.
- if (ui_has(kUIMultigrid)) {
- gp = &curwin->w_grid;
- }
- if (row >= 0 && row < Rows && col >= 0 && col <= Columns
- && gp->chars != NULL) {
- mouse_char = utf_ptr2char(gp->chars[gp->line_offset[row]
- + (unsigned)col]);
- } else {
- mouse_char = ' ';
- }
-
- // Check for position outside of the fold column.
- if (curwin->w_p_rl ? col < curwin->w_width_inner - fdc :
- col >= fdc + (cmdwin_type == 0 ? 0 : 1)) {
- mouse_char = ' ';
- }
-
// compute the position in the buffer line from the posn on the screen
if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum)) {
mouse_past_bottom = true;
@@ -362,11 +341,7 @@ retnomove:
count |= CURSOR_MOVED; // Cursor has moved
}
- if (mouse_char == curwin->w_p_fcs_chars.foldclosed) {
- count |= MOUSE_FOLD_OPEN;
- } else if (mouse_char != ' ') {
- count |= MOUSE_FOLD_CLOSE;
- }
+ count |= mouse_check_fold();
return count;
}
@@ -738,3 +713,47 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
return col + nudge;
}
+
+// Check clicked cell is foldcolumn
+int mouse_check_fold(void)
+{
+ int grid = mouse_grid;
+ int row = mouse_row;
+ int col = mouse_col;
+ int mouse_char = ' ';
+
+ win_T *wp;
+
+ wp = mouse_find_win(&grid, &row, &col);
+
+ if (wp && mouse_row >= 0 && mouse_row < Rows
+ && mouse_col >= 0 && mouse_col <= Columns) {
+ int multigrid = ui_has(kUIMultigrid);
+ ScreenGrid *gp = multigrid ? &wp->w_grid : &default_grid;
+ int fdc = win_fdccol_count(wp);
+
+ row = multigrid && mouse_grid == 0 ? row : mouse_row;
+ col = multigrid && mouse_grid == 0 ? col : mouse_col;
+
+ // Remember the character under the mouse, might be one of foldclose or
+ // foldopen fillchars in the fold column.
+ if (gp->chars != NULL) {
+ mouse_char = utf_ptr2char(gp->chars[gp->line_offset[row]
+ + (unsigned)col]);
+ }
+
+ // Check for position outside of the fold column.
+ if (wp->w_p_rl ? col < wp->w_width_inner - fdc :
+ col >= fdc + (cmdwin_type == 0 ? 0 : 1)) {
+ mouse_char = ' ';
+ }
+ }
+
+ if (mouse_char == wp->w_p_fcs_chars.foldclosed) {
+ return MOUSE_FOLD_OPEN;
+ } else if (mouse_char != ' ') {
+ return MOUSE_FOLD_CLOSE;
+ }
+
+ return 0;
+}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index d5c92bc3e6..4d8b11f832 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -2404,8 +2404,8 @@ do_mouse (
start_visual.lnum = 0;
- /* Check for clicking in the tab page line. */
- if (mouse_row == 0 && firstwin->w_winrow > 0) {
+ // Check for clicking in the tab page line.
+ if (mouse_grid <= 1 && mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
move_tab_to_mouse();
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index dd28c6fb35..20e3cc0a2e 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -7152,11 +7152,13 @@ static void win_redr_ruler(win_T *wp, int always)
if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
return;
- /* Don't draw the ruler while doing insert-completion, it might overwrite
- * the (long) mode message. */
- if (wp == lastwin && lastwin->w_status_height == 0)
- if (edit_submode != NULL)
+ // Don't draw the ruler while doing insert-completion, it might overwrite
+ // the (long) mode message.
+ if (wp == lastwin && lastwin->w_status_height == 0) {
+ if (edit_submode != NULL) {
return;
+ }
+ }
if (*p_ruf) {
int save_called_emsg = called_emsg;
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index 4f056abdc0..daf3c9c110 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -37,7 +37,6 @@ source test_recover.vim
source test_scroll_opt.vim
source test_sort.vim
source test_sha256.vim
-source test_statusline.vim
source test_suspend.vim
source test_syn_attr.vim
source test_tabline.vim
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 5a10c9baa6..1202b842fd 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -1,5 +1,7 @@
" Test for options
+source check.vim
+
func Test_whichwrap()
set whichwrap=b,s
call assert_equal('b,s', &whichwrap)
@@ -604,6 +606,27 @@ func Test_opt_boolean()
set number&
endfunc
+func Test_opt_winminheight_term()
+ " See test/functional/legacy/options_spec.lua
+ CheckRunVimInTerminal
+
+ " The tabline should be taken into account.
+ let lines =<< trim END
+ set wmh=0 stal=2
+ below sp | wincmd _
+ below sp | wincmd _
+ below sp | wincmd _
+ below sp
+ END
+ call writefile(lines, 'Xwinminheight')
+ let buf = RunVimInTerminal('-S Xwinminheight', #{rows: 11})
+ call term_sendkeys(buf, ":set wmh=1\n")
+ call WaitForAssert({-> assert_match('E36: Not enough room', term_getline(buf, 11))})
+
+ call StopVimInTerminal(buf)
+ call delete('Xwinminheight')
+endfunc
+
" Test for setting option value containing spaces with isfname+=32
func Test_isfname_with_options()
set isfname+=32
@@ -613,4 +636,23 @@ func Test_isfname_with_options()
setlocal keywordprg&
endfunc
+" Test that resetting laststatus does change scroll option
+func Test_opt_reset_scroll()
+ " See test/functional/legacy/options_spec.lua
+ CheckRunVimInTerminal
+ let vimrc =<< trim [CODE]
+ set scroll=2
+ set laststatus=2
+ [CODE]
+ call writefile(vimrc, 'Xscroll')
+ let buf = RunVimInTerminal('-S Xscroll', {'rows': 16, 'cols': 45})
+ call term_sendkeys(buf, ":verbose set scroll?\n")
+ call WaitForAssert({-> assert_match('Last set.*window size', term_getline(buf, 15))})
+ call assert_match('^\s*scroll=7$', term_getline(buf, 14))
+ call StopVimInTerminal(buf)
+
+ " clean up
+ call delete('Xscroll')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim
index 4e38f7ebd8..ce2ef4dcd8 100644
--- a/src/nvim/testdir/test_statusline.vim
+++ b/src/nvim/testdir/test_statusline.vim
@@ -1,12 +1,12 @@
" Test 'statusline'
"
" Not tested yet:
-" %a
" %N
" %T
" %X
source view_util.vim
+source check.vim
source term_util.vim
func s:get_statusline()
@@ -61,7 +61,19 @@ func Test_statusline_will_be_disabled_with_error()
endfunc
func Test_statusline()
- new Xstatusline
+ CheckFeature quickfix
+
+ " %a: Argument list ({current} of {max})
+ set statusline=%a
+ call assert_match('^\s*$', s:get_statusline())
+ arglocal a1 a2
+ rewind
+ call assert_match('^ (1 of 2)\s*$', s:get_statusline())
+ next
+ call assert_match('^ (2 of 2)\s*$', s:get_statusline())
+ e Xstatusline
+ call assert_match('^ ((2) of 2)\s*$', s:get_statusline())
+
only
set laststatus=2
set splitbelow
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 8c2ae3bc35..f52850f6f3 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -594,13 +594,20 @@ int u_savecommon(linenr_T top, linenr_T bot, linenr_T newbot, int reload)
}
-# define UF_START_MAGIC "Vim\237UnDo\345" /* magic at start of undofile */
+// magic at start of undofile
+# define UF_START_MAGIC "Vim\237UnDo\345"
# define UF_START_MAGIC_LEN 9
-# define UF_HEADER_MAGIC 0x5fd0 /* magic at start of header */
-# define UF_HEADER_END_MAGIC 0xe7aa /* magic after last header */
-# define UF_ENTRY_MAGIC 0xf518 /* magic at start of entry */
-# define UF_ENTRY_END_MAGIC 0x3581 /* magic after last entry */
-# define UF_VERSION 2 /* 2-byte undofile version number */
+// magic at start of header
+# define UF_HEADER_MAGIC 0x5fd0
+// magic after last header
+# define UF_HEADER_END_MAGIC 0xe7aa
+// magic at start of entry
+# define UF_ENTRY_MAGIC 0xf518
+// magic after last entry
+# define UF_ENTRY_END_MAGIC 0x3581
+
+// 2-byte undofile version number
+# define UF_VERSION 3
/* extra fields for header */
# define UF_LAST_SAVE_NR 1
@@ -847,6 +854,15 @@ static bool serialize_uhp(bufinfo_T *bi, u_header_T *uhp)
}
}
undo_write_bytes(bi, (uintmax_t)UF_ENTRY_END_MAGIC, 2);
+
+ // Write all extmark undo objects
+ for (size_t i = 0; i < kv_size(uhp->uh_extmark); i++) {
+ if (!serialize_extmark(bi, kv_A(uhp->uh_extmark, i))) {
+ return false;
+ }
+ }
+ undo_write_bytes(bi, (uintmax_t)UF_ENTRY_END_MAGIC, 2);
+
return true;
}
@@ -928,9 +944,95 @@ static u_header_T *unserialize_uhp(bufinfo_T *bi,
return NULL;
}
+ // Unserialize all extmark undo information
+ ExtmarkUndoObject *extup;
+ kv_init(uhp->uh_extmark);
+
+ while ((c = undo_read_2c(bi)) == UF_ENTRY_MAGIC) {
+ bool error = false;
+ extup = unserialize_extmark(bi, &error, file_name);
+ if (error) {
+ kv_destroy(uhp->uh_extmark);
+ xfree(extup);
+ return NULL;
+ }
+ kv_push(uhp->uh_extmark, *extup);
+ xfree(extup);
+ }
+ if (c != UF_ENTRY_END_MAGIC) {
+ corruption_error("entry end", file_name);
+ u_free_uhp(uhp);
+ return NULL;
+ }
+
return uhp;
}
+static bool serialize_extmark(bufinfo_T *bi, ExtmarkUndoObject extup)
+{
+ if (extup.type == kExtmarkSplice) {
+ undo_write_bytes(bi, (uintmax_t)UF_ENTRY_MAGIC, 2);
+ undo_write_bytes(bi, (uintmax_t)extup.type, 4);
+ if (!undo_write(bi, (uint8_t *)&(extup.data.splice),
+ sizeof(ExtmarkSplice))) {
+ return false;
+ }
+ } else if (extup.type == kExtmarkMove) {
+ undo_write_bytes(bi, (uintmax_t)UF_ENTRY_MAGIC, 2);
+ undo_write_bytes(bi, (uintmax_t)extup.type, 4);
+ if (!undo_write(bi, (uint8_t *)&(extup.data.move), sizeof(ExtmarkMove))) {
+ return false;
+ }
+ }
+ // Note: We do not serialize ExtmarkSavePos information, since
+ // buffer marktrees are not retained when closing/reopening a file
+ return true;
+}
+
+static ExtmarkUndoObject *unserialize_extmark(bufinfo_T *bi, bool *error,
+ const char *filename)
+{
+ UndoObjectType type;
+ uint8_t *buf = NULL;
+ size_t n_elems;
+
+ ExtmarkUndoObject *extup = xmalloc(sizeof(ExtmarkUndoObject));
+
+ type = (UndoObjectType)undo_read_4c(bi);
+ extup->type = type;
+ if (type == kExtmarkSplice) {
+ n_elems = (size_t)sizeof(ExtmarkSplice) / sizeof(uint8_t);
+ buf = xcalloc(sizeof(uint8_t), n_elems);
+ if (!undo_read(bi, buf, n_elems)) {
+ goto error;
+ }
+ extup->data.splice = *(ExtmarkSplice *)buf;
+ } else if (type == kExtmarkMove) {
+ n_elems = (size_t)sizeof(ExtmarkMove) / sizeof(uint8_t);
+ buf = xcalloc(sizeof(uint8_t), n_elems);
+ if (!undo_read(bi, buf, n_elems)) {
+ goto error;
+ }
+ extup->data.move = *(ExtmarkMove *)buf;
+ } else {
+ goto error;
+ }
+
+ if (buf) {
+ xfree(buf);
+ }
+
+ return extup;
+
+error:
+ xfree(extup);
+ if (buf) {
+ xfree(buf);
+ }
+ *error = true;
+ return NULL;
+}
+
/// Serializes "uep".
///
/// @param bi The buffer information
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 00f49724b6..0f717a2f90 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5501,7 +5501,7 @@ void win_setminheight(void)
// loop until there is a 'winminheight' that is possible
while (p_wmh > 0) {
- const int room = Rows - p_ch;
+ const int room = Rows - p_ch - tabline_height();
const int needed = frame_minheight(topframe, NULL);
if (room >= needed) {
break;
@@ -5960,9 +5960,17 @@ void win_new_width(win_T *wp, int width)
void win_comp_scroll(win_T *wp)
{
+ const long old_w_p_scr = wp->w_p_scr;
+
wp->w_p_scr = wp->w_height / 2;
- if (wp->w_p_scr == 0)
+ if (wp->w_p_scr == 0) {
wp->w_p_scr = 1;
+ }
+ if (wp->w_p_scr != old_w_p_scr) {
+ // Used by "verbose set scroll".
+ wp->w_p_script_ctx[WV_SCROLL].script_ctx.sc_sid = SID_WINLAYOUT;
+ wp->w_p_script_ctx[WV_SCROLL].script_ctx.sc_lnum = 0;
+ }
}
/*