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.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index b95a22d48b..4736e7a8ba 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -16,6 +16,11 @@
#include "nvim/os/event.h"
#include "nvim/tui/tui.h"
+// Space reserved in the output buffer to restore the cursor to normal when
+// flushing. No existing terminal will require 32 bytes to do that.
+#define CNORM_COMMAND_MAX_SIZE 32
+#define OUTBUF_SIZE 0xffff
+
typedef struct term_input TermInput;
#include "term_input.inl"
@@ -31,8 +36,8 @@ typedef struct {
typedef struct {
unibi_var_t params[9];
- char buf[0xffff];
- size_t bufpos;
+ char buf[OUTBUF_SIZE];
+ size_t bufpos, bufsize;
TermInput *input;
uv_loop_t *write_loop;
unibi_term *ut;
@@ -45,6 +50,7 @@ typedef struct {
int out_fd;
int old_height;
bool can_use_terminal_scroll;
+ bool busy;
HlAttrs attrs, print_attrs;
Cell **screen;
struct {
@@ -86,6 +92,7 @@ void tui_start(void)
data->fg = data->bg = -1;
data->can_use_terminal_scroll = true;
data->bufpos = 0;
+ data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE;
data->unibi_ext.enable_mouse = -1;
data->unibi_ext.disable_mouse = -1;
data->unibi_ext.enable_bracketed_paste = -1;
@@ -134,8 +141,8 @@ void tui_start(void)
ui->clear = tui_clear;
ui->eol_clear = tui_eol_clear;
ui->cursor_goto = tui_cursor_goto;
- ui->cursor_on = tui_cursor_on;
- ui->cursor_off = tui_cursor_off;
+ ui->busy_start = tui_busy_start;
+ ui->busy_stop = tui_busy_stop;
ui->mouse_on = tui_mouse_on;
ui->mouse_off = tui_mouse_off;
ui->insert_mode = tui_insert_mode;
@@ -169,6 +176,7 @@ static void tui_stop(UI *ui)
tui_normal_mode(ui);
tui_mouse_off(ui);
unibi_out(ui, unibi_exit_attribute_mode);
+ // cursor should be set to normal before exiting alternate screen
unibi_out(ui, unibi_cursor_normal);
unibi_out(ui, unibi_exit_ca_mode);
// Disable bracketed paste
@@ -342,14 +350,14 @@ static void tui_cursor_goto(UI *ui, int row, int col)
unibi_goto(ui, row, col);
}
-static void tui_cursor_on(UI *ui)
+static void tui_busy_start(UI *ui)
{
- unibi_out(ui, unibi_cursor_normal);
+ ((TUIData *)ui->data)->busy = true;
}
-static void tui_cursor_off(UI *ui)
+static void tui_busy_stop(UI *ui)
{
- unibi_out(ui, unibi_cursor_invisible);
+ ((TUIData *)ui->data)->busy = false;
}
static void tui_mouse_on(UI *ui)
@@ -527,6 +535,7 @@ static void tui_flush(UI *ui)
}
unibi_goto(ui, data->row, data->col);
+
flush_buf(ui);
}
@@ -657,7 +666,7 @@ static void out(void *ctx, const char *str, size_t len)
{
UI *ui = ctx;
TUIData *data = ui->data;
- size_t available = sizeof(data->buf) - data->bufpos;
+ size_t available = data->bufsize - data->bufpos;
if (len > available) {
flush_buf(ui);
@@ -781,14 +790,29 @@ end:
static void flush_buf(UI *ui)
{
- static uv_write_t req;
- static uv_buf_t buf;
+ uv_write_t req;
+ uv_buf_t buf;
TUIData *data = ui->data;
+
+ if (!data->busy) {
+ // not busy and the cursor is invisible(see below). Append a "cursor
+ // normal" command to the end of the buffer.
+ data->bufsize += CNORM_COMMAND_MAX_SIZE;
+ unibi_out(ui, unibi_cursor_normal);
+ data->bufsize -= CNORM_COMMAND_MAX_SIZE;
+ }
+
buf.base = data->buf;
buf.len = data->bufpos;
uv_write(&req, (uv_stream_t *)&data->output_handle, &buf, 1, NULL);
uv_run(data->write_loop, UV_RUN_DEFAULT);
data->bufpos = 0;
+
+ if (!data->busy) {
+ // not busy and cursor is visible(see above), append a "cursor invisible"
+ // command to the beginning of the buffer for the next flush
+ unibi_out(ui, unibi_cursor_invisible);
+ }
}
static void destroy_screen(TUIData *data)