diff options
-rw-r--r-- | src/nvim/tui/tui.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index d017db3651..931f2738ab 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -39,8 +39,8 @@ #include "nvim/syntax.h" #include "nvim/macros.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. +// Space reserved in two output buffers to make the cursor normal or invisible +// when flushing. No existing terminal will require 32 bytes to do that. #define CNORM_COMMAND_MAX_SIZE 32 #define OUTBUF_SIZE 0xffff @@ -73,7 +73,10 @@ typedef struct { bool stop; unibi_var_t params[9]; char buf[OUTBUF_SIZE]; - size_t bufpos, bufsize; + size_t bufpos; + char norm[CNORM_COMMAND_MAX_SIZE]; + char invis[CNORM_COMMAND_MAX_SIZE]; + size_t normlen, invislen; TermInput input; uv_loop_t write_loop; unibi_term *ut; @@ -155,12 +158,20 @@ UI *tui_start(void) return ui_bridge_attach(ui, tui_main, tui_scheduler); } +static size_t unibi_pre_fmt_str(TUIData *data, unsigned int unibi_index, char * buf, size_t len) +{ + const char *str = unibi_get_str(data->ut, unibi_index); + if (!str) { + return 0U; + } + return unibi_run(str, data->params, buf, len); +} + static void terminfo_start(UI *ui) { TUIData *data = ui->data; data->scroll_region_is_full_screen = true; data->bufpos = 0; - data->bufsize = sizeof(data->buf) - CNORM_COMMAND_MAX_SIZE; data->default_attr = false; data->showing_mode = SHAPE_IDX_N; data->unibi_ext.enable_mouse = -1; @@ -205,6 +216,8 @@ static void terminfo_start(UI *ui) data->immediate_wrap_after_last_column = terminfo_is_term_family(term, "cygwin") || terminfo_is_term_family(term, "interix"); + data->normlen = unibi_pre_fmt_str(data, unibi_cursor_normal, data->norm, sizeof data->norm); + data->invislen = unibi_pre_fmt_str(data, unibi_cursor_invisible, data->invis, sizeof data->invis); // Set 't_Co' from the result of unibilium & fix_terminfo. t_colors = unibi_get_num(data->ut, unibi_max_colors); // Enter alternate screen and clear @@ -1183,7 +1196,7 @@ static void out(void *ctx, const char *str, size_t len) { UI *ui = ctx; TUIData *data = ui->data; - size_t available = data->bufsize - data->bufpos; + size_t available = sizeof(data->buf) - data->bufpos; if (len > available) { flush_buf(ui, false); @@ -1613,28 +1626,37 @@ static void augment_terminfo(TUIData *data, const char *term, static void flush_buf(UI *ui, bool toggle_cursor) { uv_write_t req; - uv_buf_t buf; + uv_buf_t bufs[3]; + uv_buf_t *bufp = bufs; TUIData *data = ui->data; + if (data->bufpos <= 0) { + return; + } + if (toggle_cursor && !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; + // not busy and cursor is visible, write a "cursor invisible" command + // before writing the buffer. + bufp->base = data->invis; + bufp->len = data->invislen; + bufp++; } - buf.base = data->buf; - buf.len = data->bufpos; - uv_write(&req, STRUCT_CAST(uv_stream_t, &data->output_handle), &buf, 1, NULL); - uv_run(&data->write_loop, UV_RUN_DEFAULT); - data->bufpos = 0; + bufp->base = data->buf; + bufp->len = data->bufpos; + bufp++; if (toggle_cursor && !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); + // not busy and the cursor is invisible. Write a "cursor normal" command + // after writing the buffer. + bufp->base = data->norm; + bufp->len = data->normlen; + bufp++; } + + uv_write(&req, STRUCT_CAST(uv_stream_t, &data->output_handle), bufs, (unsigned)(bufp - bufs), NULL); + uv_run(&data->write_loop, UV_RUN_DEFAULT); + data->bufpos = 0; } #if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 |