aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/win_config.c18
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/eval/vars.c11
-rw-r--r--src/nvim/fold.c2
-rw-r--r--src/nvim/generators/gen_options.lua17
-rw-r--r--src/nvim/getchar.c8
-rw-r--r--src/nvim/lua/treesitter.c7
-rw-r--r--src/nvim/option.c65
-rw-r--r--src/nvim/option_defs.h6
-rw-r--r--src/nvim/optionstr.c10
-rw-r--r--src/nvim/terminal.c45
-rw-r--r--src/nvim/vterm/screen.c12
-rw-r--r--src/nvim/vterm/state.c19
-rw-r--r--src/nvim/vterm/vterm_defs.h3
-rw-r--r--src/nvim/vterm/vterm_internal_defs.h1
-rw-r--r--src/nvim/window.c6
-rw-r--r--src/nvim/winfloat.c9
17 files changed, 135 insertions, 106 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 45c9e3f56c..225189a3f9 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -101,10 +101,12 @@
/// @param config Map defining the window configuration. Keys:
/// - relative: Sets the window layout to "floating", placed at (row,col)
/// coordinates relative to:
-/// - "editor" The global editor grid
-/// - "win" Window given by the `win` field, or current window.
-/// - "cursor" Cursor position in current window.
-/// - "mouse" Mouse position
+/// - "cursor" Cursor position in current window.
+/// - "editor" The global editor grid.
+/// - "laststatus" 'laststatus' if present, or last row.
+/// - "mouse" Mouse position.
+/// - "tabline" Tabline if present, or first row.
+/// - "win" Window given by the `win` field, or current window.
/// - win: |window-ID| window to split, or relative window when creating a
/// float (relative="win").
/// - anchor: Decides which corner of the float to place at (row,col):
@@ -699,7 +701,9 @@ Dict(win_config) nvim_win_get_config(Window window, Arena *arena, Error *err)
FUNC_API_SINCE(6)
{
/// Keep in sync with FloatRelative in buffer_defs.h
- static const char *const float_relative_str[] = { "editor", "win", "cursor", "mouse" };
+ static const char *const float_relative_str[] = {
+ "editor", "win", "cursor", "mouse", "tabline", "laststatus"
+ };
/// Keep in sync with WinSplit in buffer_defs.h
static const char *const win_split_str[] = { "left", "right", "above", "below" };
@@ -805,6 +809,10 @@ static bool parse_float_relative(String relative, FloatRelative *out)
*out = kFloatRelativeCursor;
} else if (striequal(str, "mouse")) {
*out = kFloatRelativeMouse;
+ } else if (striequal(str, "tabline")) {
+ *out = kFloatRelativeTabline;
+ } else if (striequal(str, "laststatus")) {
+ *out = kFloatRelativeLaststatus;
} else {
return false;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 3fe44beab9..bffb29578f 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -900,6 +900,8 @@ typedef enum {
kFloatRelativeWindow = 1,
kFloatRelativeCursor = 2,
kFloatRelativeMouse = 3,
+ kFloatRelativeTabline = 4,
+ kFloatRelativeLaststatus = 5,
} FloatRelative;
/// Keep in sync with win_split_str[] in nvim_win_get_config() (api/win_config.c)
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index b9b5a055fb..012d23b567 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -843,11 +843,10 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const,
goto theend;
}
- // Don't assume current and new values are of the same type in order to future-proof the code for
- // when an option can have multiple types.
- const bool is_num = ((curval.type == kOptValTypeNumber || curval.type == kOptValTypeBoolean)
- && (newval.type == kOptValTypeNumber || newval.type == kOptValTypeBoolean));
- const bool is_string = curval.type == kOptValTypeString && newval.type == kOptValTypeString;
+ // Current value and new value must have the same type.
+ assert(curval.type == newval.type);
+ const bool is_num = curval.type == kOptValTypeNumber || curval.type == kOptValTypeBoolean;
+ const bool is_string = curval.type == kOptValTypeString;
if (op != NULL && *op != '=') {
if (!hidden && is_num) { // number or bool
@@ -1900,8 +1899,6 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off)
///
/// @return Typval converted to OptVal. Must be freed by caller.
/// Returns NIL_OPTVAL for invalid option name.
-///
-/// TODO(famiu): Refactor this to support multitype options.
static OptVal tv_to_optval(typval_T *tv, OptIndex opt_idx, const char *option, bool *error)
{
OptVal value = NIL_OPTVAL;
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index c9699cb161..b59933d600 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -1658,7 +1658,7 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char *marker, size_t marker
if (*cms != NUL) {
// Also delete 'commentstring' if it matches.
char *cms2 = strstr(cms, "%s");
- if (p - line >= cms2 - cms
+ if (cms2 != NULL && p - line >= cms2 - cms
&& strncmp(p - (cms2 - cms), cms, (size_t)(cms2 - cms)) == 0
&& strncmp(p + len, cms2 + 2, strlen(cms2 + 2)) == 0) {
p -= cms2 - cms;
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index c79683dc00..0298381ece 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -314,21 +314,6 @@ end
--- @param o vim.option_meta
--- @return string
-local function get_type_flags(o)
- local opt_types = (type(o.type) == 'table') and o.type or { o.type }
- local type_flags = '0'
- assert(type(opt_types) == 'table')
-
- for _, opt_type in ipairs(opt_types) do
- assert(type(opt_type) == 'string')
- type_flags = ('%s | (1 << %s)'):format(type_flags, opt_type_enum(opt_type))
- end
-
- return type_flags
-end
-
---- @param o vim.option_meta
---- @return string
local function get_scope_flags(o)
local scope_flags = '0'
@@ -427,8 +412,8 @@ local function dump_option(i, o)
if o.abbreviation then
w(' .shortname=' .. cstr(o.abbreviation))
end
+ w(' .type=' .. opt_type_enum(o.type))
w(' .flags=' .. get_flags(o))
- w(' .type_flags=' .. get_type_flags(o))
w(' .scope_flags=' .. get_scope_flags(o))
w(' .scope_idx=' .. get_scope_idx(o))
if o.enable_if then
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 60aa1055c3..6cf4556a9f 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1518,9 +1518,11 @@ int merge_modifiers(int c_arg, int *modifiers)
if (*modifiers & MOD_MASK_CTRL) {
if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) {
- c &= 0x1f;
- if (c == NUL) {
- c = K_ZERO;
+ if (!(State & MODE_TERMINAL) || !(c == 'I' || c == 'J' || c == 'M' || c == '[')) {
+ c &= 0x1f;
+ if (c == NUL) {
+ c = K_ZERO;
+ }
}
} else if (c == '6') {
// CTRL-6 is equivalent to CTRL-^
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 9bd2baad27..3493384a8f 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -128,9 +128,9 @@ static const TSLanguage *load_language_from_object(lua_State *L, const char *pat
{
uv_lib_t lib;
if (uv_dlopen(path, &lib)) {
+ xstrlcpy(IObuff, uv_dlerror(&lib), sizeof(IObuff));
uv_dlclose(&lib);
- luaL_error(L, "Failed to load parser for language '%s': uv_dlopen: %s",
- lang_name, uv_dlerror(&lib));
+ luaL_error(L, "Failed to load parser for language '%s': uv_dlopen: %s", lang_name, IObuff);
}
char symbol_buf[128];
@@ -138,8 +138,9 @@ static const TSLanguage *load_language_from_object(lua_State *L, const char *pat
TSLanguage *(*lang_parser)(void);
if (uv_dlsym(&lib, symbol_buf, (void **)&lang_parser)) {
+ xstrlcpy(IObuff, uv_dlerror(&lib), sizeof(IObuff));
uv_dlclose(&lib);
- luaL_error(L, "Failed to load parser: uv_dlsym: %s", uv_dlerror(&lib));
+ luaL_error(L, "Failed to load parser: uv_dlsym: %s", IObuff);
}
TSLanguage *lang = lang_parser();
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 551ea0be20..593ac62172 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -3121,17 +3121,10 @@ bool optval_equal(OptVal o1, OptVal o2)
UNREACHABLE;
}
-/// Get type of option. Does not support multitype options.
+/// Get type of option.
static OptValType option_get_type(const OptIndex opt_idx)
{
- assert(!option_is_multitype(opt_idx));
-
- // If the option only supports a single type, it means that the index of the option's type flag
- // corresponds to the value of the type enum. So get the index of the type flag using xctz() and
- // use that as the option's type.
- OptValType type = xctz(options[opt_idx].type_flags);
- assert(type > kOptValTypeNil && type < kOptValTypeSize);
- return type;
+ return options[opt_idx].type;
}
/// Create OptVal from var pointer.
@@ -3149,11 +3142,6 @@ OptVal optval_from_varp(OptIndex opt_idx, void *varp)
return BOOLEAN_OPTVAL(curbufIsChanged());
}
- if (option_is_multitype(opt_idx)) {
- // Multitype options are stored as OptVal.
- return *(OptVal *)varp;
- }
-
OptValType type = option_get_type(opt_idx);
switch (type) {
@@ -3264,33 +3252,6 @@ OptVal object_as_optval(Object o, bool *error)
UNREACHABLE;
}
-/// Get an allocated string containing a list of valid types for an option.
-/// For options with a singular type, it returns the name of the type. For options with multiple
-/// possible types, it returns a slash separated list of types. For example, if an option can be a
-/// number, boolean or string, the function returns "number/boolean/string"
-static char *option_get_valid_types(OptIndex opt_idx)
-{
- StringBuilder str = KV_INITIAL_VALUE;
- kv_resize(str, 32);
-
- // Iterate through every valid option value type and check if the option supports that type
- for (OptValType type = 0; type < kOptValTypeSize; type++) {
- if (option_has_type(opt_idx, type)) {
- const char *typename = optval_type_get_name(type);
-
- if (str.size == 0) {
- kv_concat(str, typename);
- } else {
- kv_printf(str, "/%s", typename);
- }
- }
- }
-
- // Ensure that the string is NUL-terminated.
- kv_push(str, NUL);
- return str.items;
-}
-
/// Check if option is hidden.
///
/// @param opt_idx Option index in options[] table.
@@ -3303,25 +3264,10 @@ bool is_option_hidden(OptIndex opt_idx)
&& options[opt_idx].var == &options[opt_idx].def_val.data;
}
-/// Check if option is multitype (supports multiple types).
-static bool option_is_multitype(OptIndex opt_idx)
-{
- const OptTypeFlags type_flags = get_option(opt_idx)->type_flags;
- assert(type_flags != 0);
- return !is_power_of_two(type_flags);
-}
-
/// Check if option supports a specific type.
bool option_has_type(OptIndex opt_idx, OptValType type)
{
- // Ensure that type flags variable can hold all types.
- STATIC_ASSERT(kOptValTypeSize <= sizeof(OptTypeFlags) * 8,
- "Option type_flags cannot fit all option types");
- // Ensure that the type is valid before accessing type_flags.
- assert(type > kOptValTypeNil && type < kOptValTypeSize);
- // Bitshift 1 by the value of type to get the type's corresponding flag, and check if it's set in
- // the type_flags bit field.
- return get_option(opt_idx)->type_flags & (1 << type);
+ return options[opt_idx].type == type;
}
/// Check if option supports a specific scope.
@@ -3658,11 +3604,10 @@ static const char *validate_option_value(const OptIndex opt_idx, OptVal *newval,
}
} else if (!option_has_type(opt_idx, newval->type)) {
char *rep = optval_to_cstr(*newval);
- char *valid_types = option_get_valid_types(opt_idx);
+ const char *type_str = optval_type_get_name(opt->type);
snprintf(errbuf, IOSIZE, _("Invalid value for option '%s': expected %s, got %s %s"),
- opt->fullname, valid_types, optval_type_get_name(newval->type), rep);
+ opt->fullname, type_str, optval_type_get_name(newval->type), rep);
xfree(rep);
- xfree(valid_types);
errmsg = errbuf;
} else if (newval->type == kOptValTypeNumber) {
// Validate and bound check num option values.
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 832e03148a..2b51547004 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -54,9 +54,6 @@ typedef enum {
kOptValTypeNumber,
kOptValTypeString,
} OptValType;
-/// Always update this whenever a new option type is added.
-#define kOptValTypeSize (kOptValTypeString + 1)
-typedef uint32_t OptTypeFlags;
/// Scopes that an option can support.
typedef enum {
@@ -99,7 +96,6 @@ typedef struct {
int os_flags;
/// Old value of the option.
- /// TODO(famiu): Convert `os_oldval` and `os_newval` to `OptVal` to accommodate multitype options.
OptValData os_oldval;
/// New value of the option.
OptValData os_newval;
@@ -173,7 +169,7 @@ typedef struct {
char *fullname; ///< full option name
char *shortname; ///< permissible abbreviation
uint32_t flags; ///< see above
- OptTypeFlags type_flags; ///< option type flags, see OptValType
+ OptValType type; ///< option type
OptScopeFlags scope_flags; ///< option scope flags, see OptScope
void *var; ///< global option: pointer to variable;
///< window-local option: NULL;
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index eac9ea02e0..93871905db 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -44,6 +44,7 @@
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
#include "nvim/strings.h"
+#include "nvim/terminal.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -532,6 +533,15 @@ const char *did_set_background(optset_T *args)
check_string_option(&p_bg);
init_highlight(false, false);
}
+
+ // Notify all terminal buffers that the background color changed so they can
+ // send a theme update notification
+ FOR_ALL_BUFFERS(buf) {
+ if (buf->terminal) {
+ terminal_notify_theme(buf->terminal, dark);
+ }
+ }
+
return NULL;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index d7ed709906..2ad5ac49ca 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -179,6 +179,8 @@ struct terminal {
StringBuilder *send; ///< When there is a pending TermRequest autocommand, block and store input.
} pending;
+ bool theme_updates; ///< Send a theme update notification when 'bg' changes
+
bool color_set[16];
char *selection_buffer; /// libvterm selection buffer
@@ -193,6 +195,7 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
.movecursor = term_movecursor,
.settermprop = term_settermprop,
.bell = term_bell,
+ .theme = term_theme,
.sb_pushline = term_sb_push, // Called before a line goes offscreen.
.sb_popline = term_sb_pop,
};
@@ -1011,7 +1014,7 @@ static void terminal_send_key(Terminal *term, int c)
c = Ctrl_AT;
}
- VTermKey key = convert_key(c, &mod);
+ VTermKey key = convert_key(&c, &mod);
if (key) {
vterm_keyboard_key(term->vt, key, mod);
@@ -1141,6 +1144,20 @@ bool terminal_running(const Terminal *term)
return !term->closed;
}
+void terminal_notify_theme(Terminal *term, bool dark)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if (!term->theme_updates) {
+ return;
+ }
+
+ char buf[10];
+ ssize_t ret = snprintf(buf, sizeof(buf), "\x1b[997;%cn", dark ? '1' : '2');
+ assert(ret > 0);
+ assert((size_t)ret <= sizeof(buf));
+ terminal_send(term, buf, (size_t)ret);
+}
+
static void terminal_focus(const Terminal *term, bool focus)
FUNC_ATTR_NONNULL_ALL
{
@@ -1259,6 +1276,10 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
invalidate_terminal(term, -1, -1);
break;
+ case VTERM_PROP_THEMEUPDATES:
+ term->theme_updates = val->boolean;
+ break;
+
default:
return 0;
}
@@ -1273,6 +1294,14 @@ static int term_bell(void *data)
return 1;
}
+/// Called when the terminal wants to query the system theme.
+static int term_theme(bool *dark, void *data)
+ FUNC_ATTR_NONNULL_ALL
+{
+ *dark = (*p_bg == 'd');
+ return 1;
+}
+
/// Scrollback push handler: called just before a line goes offscreen (and libvterm will forget it),
/// giving us a chance to store it.
///
@@ -1415,19 +1444,23 @@ static int term_selection_set(VTermSelectionMask mask, VTermStringFragment frag,
// }}}
// input handling {{{
-static void convert_modifiers(int key, VTermModifier *statep)
+static void convert_modifiers(int *key, VTermModifier *statep)
{
if (mod_mask & MOD_MASK_SHIFT) {
*statep |= VTERM_MOD_SHIFT;
}
if (mod_mask & MOD_MASK_CTRL) {
*statep |= VTERM_MOD_CTRL;
+ if (!(mod_mask & MOD_MASK_SHIFT) && *key >= 'A' && *key <= 'Z') {
+ // vterm interprets CTRL+A as SHIFT+CTRL, change to CTRL+a
+ *key += ('a' - 'A');
+ }
}
if (mod_mask & MOD_MASK_ALT) {
*statep |= VTERM_MOD_ALT;
}
- switch (key) {
+ switch (*key) {
case K_S_TAB:
case K_S_UP:
case K_S_DOWN:
@@ -1459,11 +1492,11 @@ static void convert_modifiers(int key, VTermModifier *statep)
}
}
-static VTermKey convert_key(int key, VTermModifier *statep)
+static VTermKey convert_key(int *key, VTermModifier *statep)
{
convert_modifiers(key, statep);
- switch (key) {
+ switch (*key) {
case K_BS:
return VTERM_KEY_BACKSPACE;
case K_S_TAB:
@@ -1791,7 +1824,7 @@ static bool send_mouse_event(Terminal *term, int c)
}
VTermModifier mod = VTERM_MOD_NONE;
- convert_modifiers(c, &mod);
+ convert_modifiers(&c, &mod);
mouse_action(term, button, row, col - offset, pressed, mod);
return false;
}
diff --git a/src/nvim/vterm/screen.c b/src/nvim/vterm/screen.c
index c91c6fb84f..45bd5e2a27 100644
--- a/src/nvim/vterm/screen.c
+++ b/src/nvim/vterm/screen.c
@@ -784,6 +784,17 @@ static int resize(int new_rows, int new_cols, VTermStateFields *fields, void *us
return 1;
}
+static int theme(bool *dark, void *user)
+{
+ VTermScreen *screen = user;
+
+ if (screen->callbacks && screen->callbacks->theme) {
+ return (*screen->callbacks->theme)(dark, screen->cbdata);
+ }
+
+ return 1;
+}
+
static int setlineinfo(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo,
void *user)
{
@@ -838,6 +849,7 @@ static VTermStateCallbacks state_cbs = {
.settermprop = &settermprop,
.bell = &bell,
.resize = &resize,
+ .theme = &theme,
.setlineinfo = &setlineinfo,
.sb_clear = &sb_clear,
};
diff --git a/src/nvim/vterm/state.c b/src/nvim/vterm/state.c
index 9e787acd9b..4ad07377de 100644
--- a/src/nvim/vterm/state.c
+++ b/src/nvim/vterm/state.c
@@ -819,6 +819,10 @@ static void set_dec_mode(VTermState *state, int num, int val)
state->mode.bracketpaste = (unsigned)val;
break;
+ case 2031:
+ settermprop_bool(state, VTERM_PROP_THEMEUPDATES, val);
+ break;
+
default:
DEBUG_LOG("libvterm: Unknown DEC mode %d\n", num);
return;
@@ -894,6 +898,10 @@ static void request_dec_mode(VTermState *state, int num)
reply = state->mode.bracketpaste;
break;
+ case 2031:
+ reply = state->mode.theme_updates;
+ break;
+
default:
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?%d;%d$y", num, 0);
return;
@@ -1387,6 +1395,7 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
{
char *qmark = (leader_byte == '?') ? "?" : "";
+ bool dark = false;
switch (val) {
case 0:
@@ -1403,6 +1412,13 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%s%d;%dR", qmark, state->pos.row + 1,
state->pos.col + 1);
break;
+ case 996:
+ if (state->callbacks && state->callbacks->theme) {
+ if (state->callbacks->theme(&dark, state->cbdata)) {
+ vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?997;%cn", dark ? '1' : '2');
+ }
+ }
+ break;
}
}
break;
@@ -2268,6 +2284,9 @@ int vterm_state_set_termprop(VTermState *state, VTermProp prop, VTermValue *val)
case VTERM_PROP_FOCUSREPORT:
state->mode.report_focus = (unsigned)val->boolean;
return 1;
+ case VTERM_PROP_THEMEUPDATES:
+ state->mode.theme_updates = (unsigned)val->boolean;
+ return 1;
case VTERM_N_PROPS:
return 0;
diff --git a/src/nvim/vterm/vterm_defs.h b/src/nvim/vterm/vterm_defs.h
index d0a8ba8814..9aa933bef0 100644
--- a/src/nvim/vterm/vterm_defs.h
+++ b/src/nvim/vterm/vterm_defs.h
@@ -86,6 +86,7 @@ typedef enum {
VTERM_PROP_CURSORSHAPE, // number
VTERM_PROP_MOUSE, // number
VTERM_PROP_FOCUSREPORT, // bool
+ VTERM_PROP_THEMEUPDATES, // bool
VTERM_N_PROPS,
} VTermProp;
@@ -111,6 +112,7 @@ typedef struct {
int (*settermprop)(VTermProp prop, VTermValue *val, void *user);
int (*bell)(void *user);
int (*resize)(int rows, int cols, void *user);
+ int (*theme)(bool *dark, void *user);
int (*sb_pushline)(int cols, const VTermScreenCell *cells, void *user);
int (*sb_popline)(int cols, VTermScreenCell *cells, void *user);
int (*sb_clear)(void *user);
@@ -263,6 +265,7 @@ typedef struct {
int (*settermprop)(VTermProp prop, VTermValue *val, void *user);
int (*bell)(void *user);
int (*resize)(int rows, int cols, VTermStateFields *fields, void *user);
+ int (*theme)(bool *dark, void *user);
int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo,
void *user);
int (*sb_clear)(void *user);
diff --git a/src/nvim/vterm/vterm_internal_defs.h b/src/nvim/vterm/vterm_internal_defs.h
index 770f862ce3..d4d59867bf 100644
--- a/src/nvim/vterm/vterm_internal_defs.h
+++ b/src/nvim/vterm/vterm_internal_defs.h
@@ -119,6 +119,7 @@ struct VTermState {
unsigned leftrightmargin:1;
unsigned bracketpaste:1;
unsigned report_focus:1;
+ unsigned theme_updates:1;
} mode;
VTermEncodingInstance encoding[4], encoding_utf8;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 68f45ec5ba..1c0d8c1027 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -835,6 +835,10 @@ void ui_ext_win_position(win_T *wp, bool validate)
col += tcol - 1;
}
}
+ } else if (c.relative == kFloatRelativeLaststatus) {
+ row += Rows - (int)p_ch - last_stl_height(false);
+ } else if (c.relative == kFloatRelativeTabline) {
+ row += tabline_height();
}
bool resort = wp->w_grid_alloc.comp_index != 0
@@ -1066,6 +1070,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
return NULL;
}
need_status = STATUS_HEIGHT;
+ win_float_anchor_laststatus();
}
bool do_equal = false;
@@ -6803,6 +6808,7 @@ void last_status(bool morewin)
{
// Don't make a difference between horizontal or vertical split.
last_status_rec(topframe, last_stl_height(morewin) > 0, global_stl_height() > 0);
+ win_float_anchor_laststatus();
}
// Remove status line from window, replacing it with a horizontal separator if needed.
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
index 3e791e2beb..d11b965dfc 100644
--- a/src/nvim/winfloat.c
+++ b/src/nvim/winfloat.c
@@ -307,6 +307,15 @@ void win_check_anchored_floats(win_T *win)
}
}
+void win_float_anchor_laststatus(void)
+{
+ FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
+ if (win->w_config.relative == kFloatRelativeLaststatus) {
+ win->w_pos_changed = true;
+ }
+ }
+}
+
void win_reconfig_floats(void)
{
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {