diff options
Diffstat (limited to 'src/nvim/tui/tui.c')
| -rw-r--r-- | src/nvim/tui/tui.c | 46 |
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) |