aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui/tui.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/tui/tui.c')
-rw-r--r--src/nvim/tui/tui.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index a1f56d2695..57a2b896f7 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -57,14 +57,17 @@ typedef struct {
bool busy;
HlAttrs attrs, print_attrs;
Cell **screen;
+ int showing_mode;
struct {
int enable_mouse, disable_mouse;
int enable_bracketed_paste, disable_bracketed_paste;
- int enter_insert_mode, exit_insert_mode;
+ int enter_insert_mode, enter_replace_mode, exit_insert_mode;
int set_rgb_foreground, set_rgb_background;
} unibi_ext;
} TUIData;
+static bool volatile got_winch = false;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/tui.c.generated.h"
#endif
@@ -98,11 +101,13 @@ UI *tui_start(void)
data->can_use_terminal_scroll = true;
data->bufpos = 0;
data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE;
+ data->showing_mode = 0;
data->unibi_ext.enable_mouse = -1;
data->unibi_ext.disable_mouse = -1;
data->unibi_ext.enable_bracketed_paste = -1;
data->unibi_ext.disable_bracketed_paste = -1;
data->unibi_ext.enter_insert_mode = -1;
+ data->unibi_ext.enter_replace_mode = -1;
data->unibi_ext.exit_insert_mode = -1;
// write output to stderr if stdout is not a tty
@@ -148,8 +153,7 @@ UI *tui_start(void)
ui->busy_stop = tui_busy_stop;
ui->mouse_on = tui_mouse_on;
ui->mouse_off = tui_mouse_off;
- ui->insert_mode = tui_insert_mode;
- ui->normal_mode = tui_normal_mode;
+ ui->mode_change = tui_mode_change;
ui->set_scroll_region = tui_set_scroll_region;
ui->scroll = tui_scroll;
ui->highlight_set = tui_highlight_set;
@@ -178,7 +182,7 @@ static void tui_stop(UI *ui)
// Destroy input stuff
term_input_destroy(data->input);
// Destroy output stuff
- tui_normal_mode(ui);
+ tui_mode_change(ui, NORMAL);
tui_mouse_off(ui);
unibi_out(ui, unibi_exit_attribute_mode);
// cursor should be set to normal before exiting alternate screen
@@ -201,23 +205,14 @@ static void tui_stop(UI *ui)
xfree(ui);
}
-static void try_resize(Event ev)
+static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
{
- UI *ui = ev.data;
+ got_winch = true;
+ UI *ui = data;
update_size(ui);
ui_refresh();
}
-static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
-{
- // Queue the event because resizing can result in recursive event_poll calls
- // FIXME(blueyed): TUI does not resize properly when not deferred. Why? #2322
- loop_push_event(&loop, (Event) {
- .data = data,
- .handler = try_resize
- }, true);
-}
-
static bool attrs_differ(HlAttrs a1, HlAttrs a2)
{
return a1.foreground != a2.foreground || a1.background != a2.background
@@ -352,10 +347,13 @@ static void tui_resize(UI *ui, int width, int height)
data->scroll_region.right = width - 1;
data->row = data->col = 0;
- // try to resize the terminal window
- char r[16]; // enough for 9999x9999
- snprintf(r, sizeof(r), "\x1b[8;%d;%dt", height, width);
- out(ui, r, strlen(r));
+ if (!got_winch) { // Try to resize the terminal window.
+ char r[16]; // enough for 9999x9999
+ snprintf(r, sizeof(r), "\x1b[8;%d;%dt", height, width);
+ out(ui, r, strlen(r));
+ } else { // Already handled the SIGWINCH signal; avoid double-resize.
+ got_winch = false;
+ }
}
static void tui_clear(UI *ui)
@@ -404,16 +402,25 @@ static void tui_mouse_off(UI *ui)
data->mouse_enabled = false;
}
-static void tui_insert_mode(UI *ui)
+static void tui_mode_change(UI *ui, int mode)
{
TUIData *data = ui->data;
- unibi_out(ui, data->unibi_ext.enter_insert_mode);
-}
-static void tui_normal_mode(UI *ui)
-{
- TUIData *data = ui->data;
- unibi_out(ui, data->unibi_ext.exit_insert_mode);
+ if (mode == INSERT) {
+ if (data->showing_mode != INSERT) {
+ unibi_out(ui, data->unibi_ext.enter_insert_mode);
+ }
+ } else if (mode == REPLACE) {
+ if (data->showing_mode != REPLACE) {
+ unibi_out(ui, data->unibi_ext.enter_replace_mode);
+ }
+ } else {
+ assert(mode == NORMAL);
+ if (data->showing_mode != NORMAL) {
+ unibi_out(ui, data->unibi_ext.exit_insert_mode);
+ }
+ }
+ data->showing_mode = mode;
}
static void tui_set_scroll_region(UI *ui, int top, int bot, int left,
@@ -798,18 +805,25 @@ static void fix_terminfo(TUIData *data)
#define TMUX_WRAP(seq) (inside_tmux ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq)
// Support changing cursor shape on some popular terminals.
const char *term_prog = os_getenv("TERM_PROGRAM");
+ const char *vte_version = os_getenv("VTE_VERSION");
- if ((term_prog && !strcmp(term_prog, "iTerm.app"))
- || os_getenv("ITERM_SESSION_ID") != NULL) {
- // iterm
+ if ((term_prog && !strcmp(term_prog, "Konsole"))
+ || os_getenv("KONSOLE_DBUS_SESSION") != NULL) {
+ // Konsole uses a proprietary escape code to set the cursor shape
+ // and does not suppport DECSCUSR.
data->unibi_ext.enter_insert_mode = (int)unibi_add_ext_str(ut, NULL,
TMUX_WRAP("\x1b]50;CursorShape=1;BlinkingCursorEnabled=1\x07"));
+ data->unibi_ext.enter_replace_mode = (int)unibi_add_ext_str(ut, NULL,
+ TMUX_WRAP("\x1b]50;CursorShape=2;BlinkingCursorEnabled=1\x07"));
data->unibi_ext.exit_insert_mode = (int)unibi_add_ext_str(ut, NULL,
TMUX_WRAP("\x1b]50;CursorShape=0;BlinkingCursorEnabled=0\x07"));
- } else {
- // xterm-like sequences for blinking bar and solid block
+ } else if (!vte_version || atoi(vte_version) >= 3900) {
+ // Assume that the terminal supports DECSCUSR unless it is an
+ // old VTE based terminal
data->unibi_ext.enter_insert_mode = (int)unibi_add_ext_str(ut, NULL,
TMUX_WRAP("\x1b[5 q"));
+ data->unibi_ext.enter_replace_mode = (int)unibi_add_ext_str(ut, NULL,
+ TMUX_WRAP("\x1b[3 q"));
data->unibi_ext.exit_insert_mode = (int)unibi_add_ext_str(ut, NULL,
TMUX_WRAP("\x1b[2 q"));
}