diff options
Diffstat (limited to 'src/nvim/terminal.c')
-rw-r--r-- | src/nvim/terminal.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 08fcefaa88..46f141492b 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -120,6 +120,10 @@ struct terminal { // window height has increased) and must be deleted from the terminal buffer int sb_pending; + char *title; // VTermStringFragment buffer + size_t title_len; // number of rows pushed to sb_buffer + size_t title_size; // sb_buffer size + // buf_T instance that acts as a "drawing surface" for libvterm // we can't store a direct reference to the buffer because the // refresh_timer_cb may be called after the buffer was freed, and there's @@ -230,7 +234,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts) set_option_value("wrap", false, NULL, OPT_LOCAL); set_option_value("list", false, NULL, OPT_LOCAL); if (buf->b_ffname != NULL) { - buf_set_term_title(buf, buf->b_ffname); + buf_set_term_title(buf, buf->b_ffname, strlen(buf->b_ffname)); } RESET_BINDING(curwin); // Reset cursor in current window. @@ -418,15 +422,15 @@ bool terminal_enter(void) // placed at end of buffer to "follow" output. #11072 handle_T save_curwin = curwin->handle; bool save_w_p_cul = curwin->w_p_cul; - char_u *save_w_p_culopt = NULL; + char *save_w_p_culopt = NULL; char_u save_w_p_culopt_flags = curwin->w_p_culopt_flags; int save_w_p_cuc = curwin->w_p_cuc; long save_w_p_so = curwin->w_p_so; long save_w_p_siso = curwin->w_p_siso; if (curwin->w_p_cul && curwin->w_p_culopt_flags & CULOPT_NBR) { - if (STRCMP(curwin->w_p_culopt, "number")) { + if (strcmp(curwin->w_p_culopt, "number")) { save_w_p_culopt = curwin->w_p_culopt; - curwin->w_p_culopt = (char_u *)xstrdup("number"); + curwin->w_p_culopt = xstrdup("number"); } curwin->w_p_culopt_flags = CULOPT_NBR; } else { @@ -636,6 +640,7 @@ void terminal_destroy(Terminal **termpp) xfree(term->sb_buffer[i]); } xfree(term->sb_buffer); + xfree(term->title); vterm_free(term->vt); xfree(term); *termpp = NULL; // coverity[dead-store] @@ -858,13 +863,13 @@ static int term_movecursor(VTermPos new, VTermPos old, int visible, void *data) return 1; } -static void buf_set_term_title(buf_T *buf, char *title) +static void buf_set_term_title(buf_T *buf, const char *title, size_t len) FUNC_ATTR_NONNULL_ALL { Error err = ERROR_INIT; dict_set_var(buf->b_vars, STATIC_CSTR_AS_STRING("term_title"), - STRING_OBJ(cstr_as_string(title)), + STRING_OBJ(((String){ .data = (char *)title, .size = len })), false, false, &err); @@ -887,7 +892,34 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) case VTERM_PROP_TITLE: { buf_T *buf = handle_get_buffer(term->buf_handle); - buf_set_term_title(buf, val->string); +#if VTERM_VERSION_MAJOR > 0 || (VTERM_VERSION_MAJOR == 0 && VTERM_VERSION_MINOR >= 2) + VTermStringFragment frag = val->string; + + if (frag.initial && frag.final) { + buf_set_term_title(buf, frag.str, frag.len); + break; + } + + if (frag.initial) { + term->title_len = 0; + term->title_size = MAX(frag.len, 1024); + term->title = xmalloc(sizeof(char *) * term->title_size); + } else if (term->title_len + frag.len > term->title_size) { + term->title_size *= 2; + term->title = xrealloc(term->title, sizeof(char *) * term->title_size); + } + + memcpy(term->title + term->title_len, frag.str, frag.len); + term->title_len += frag.len; + + if (frag.final) { + buf_set_term_title(buf, term->title, term->title_len); + xfree(term->title); + term->title = NULL; + } +#else + buf_set_term_title(buf, val->string, strlen(val->string)); +#endif break; } @@ -1375,7 +1407,7 @@ static bool send_mouse_event(Terminal *term, int c) curwin->w_redr_status = true; curwin = save_curwin; curbuf = curwin->w_buffer; - redraw_later(mouse_win, NOT_VALID); + redraw_later(mouse_win, UPD_NOT_VALID); invalidate_terminal(term, -1, -1); // Only need to exit focus if the scrolled window is the terminal window return mouse_win == curwin; |