patch 8.0.0918: cannot get terminal window cursor shape or attributes
Problem: Cannot get terminal window cursor shape or attributes.
Solution: Support cursor shape, attributes and color.
diff --git a/src/terminal.c b/src/terminal.c
index e8727ee..fe1d5da 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -36,9 +36,7 @@
* that buffer, attributes come from the scrollback buffer tl_scrollback.
*
* TODO:
- * - support different cursor shapes, colors and attributes
- * - make term_getcursor() return type (none/block/bar/underline) and
- * attributes (color, blink, etc.)
+ * - cursor shape/color/blink in the GUI
* - Make argument list work on MS-Windows. #1954
* - MS-Windows: no redraw for 'updatetime' #1915
* - To set BS correctly, check get_stty(); Pass the fd of the pty.
@@ -143,6 +141,9 @@
VTermPos tl_cursor_pos;
int tl_cursor_visible;
+ int tl_cursor_blink;
+ int tl_cursor_shape; /* 1: block, 2: underline, 3: bar */
+ char_u *tl_cursor_color; /* NULL or allocated */
int tl_using_altscreen;
};
@@ -155,6 +156,8 @@
*/
static term_T *first_term = NULL;
+/* Terminal active in terminal_loop(). */
+static term_T *in_terminal_loop = NULL;
#define MAX_ROW 999999 /* used for tl_dirty_row_end to update all rows */
#define KEY_BUF_LEN 200
@@ -256,6 +259,7 @@
return;
term->tl_dirty_row_end = MAX_ROW;
term->tl_cursor_visible = TRUE;
+ term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
term->tl_finish = opt->jo_term_finish;
ga_init2(&term->tl_scrollback, sizeof(sb_line_T), 300);
@@ -517,6 +521,7 @@
vim_free(term->tl_title);
vim_free(term->tl_status_text);
vim_free(term->tl_opencmd);
+ vim_free(term->tl_cursor_color);
vim_free(term);
buf->b_term = NULL;
}
@@ -1158,6 +1163,35 @@
}
}
+static int did_change_cursor = FALSE;
+
+ static void
+may_set_cursor_props(term_T *term)
+{
+ if (in_terminal_loop == term)
+ {
+ if (term->tl_cursor_color != NULL)
+ term_cursor_color(term->tl_cursor_color);
+ else
+ term_cursor_color((char_u *)"");
+ /* do both blink and shape+blink, in case setting shape does not work */
+ term_cursor_blink(term->tl_cursor_blink);
+ term_cursor_shape(term->tl_cursor_shape, term->tl_cursor_blink);
+ }
+}
+
+ static void
+may_restore_cursor_props(void)
+{
+ if (did_change_cursor)
+ {
+ did_change_cursor = FALSE;
+ ui_cursor_shape_forced(TRUE);
+ term_cursor_color((char_u *)"");
+ term_cursor_blink(FALSE);
+ }
+}
+
/*
* Returns TRUE if the current window contains a terminal and we are sending
* keys to the job.
@@ -1185,10 +1219,14 @@
{
int c;
int termkey = 0;
+ int ret;
+
+ in_terminal_loop = curbuf->b_term;
if (*curwin->w_p_tk != NUL)
termkey = string_to_key(curwin->w_p_tk, TRUE);
position_cursor(curwin, &curbuf->b_term->tl_cursor_pos);
+ may_set_cursor_props(curbuf->b_term);
for (;;)
{
@@ -1235,7 +1273,8 @@
{
/* CTRL-\ CTRL-N : go to Terminal-Normal mode. */
term_enter_normal_mode();
- return FAIL;
+ ret = FAIL;
+ goto theend;
}
/* Send both keys to the terminal. */
send_keys_to_term(curbuf->b_term, prev_c, TRUE);
@@ -1249,7 +1288,8 @@
{
/* CTRL-W N : go to Terminal-Normal mode. */
term_enter_normal_mode();
- return FAIL;
+ ret = FAIL;
+ goto theend;
}
else if (c == '"')
{
@@ -1260,13 +1300,22 @@
{
stuffcharReadbuff(Ctrl_W);
stuffcharReadbuff(c);
- return OK;
+ ret = OK;
+ goto theend;
}
}
if (send_keys_to_term(curbuf->b_term, c, TRUE) != OK)
- return OK;
+ {
+ ret = OK;
+ goto theend;
+ }
}
- return FAIL;
+ ret = FAIL;
+
+theend:
+ in_terminal_loop = NULL;
+ may_restore_cursor_props();
+ return ret;
}
/*
@@ -1303,7 +1352,7 @@
static void
may_toggle_cursor(term_T *term)
{
- if (curbuf == term->tl_buffer)
+ if (in_terminal_loop == term)
{
if (term->tl_cursor_visible)
cursor_on();
@@ -1385,6 +1434,22 @@
out_flush();
break;
+ case VTERM_PROP_CURSORBLINK:
+ term->tl_cursor_blink = value->boolean;
+ may_set_cursor_props(term);
+ break;
+
+ case VTERM_PROP_CURSORSHAPE:
+ term->tl_cursor_shape = value->number;
+ may_set_cursor_props(term);
+ break;
+
+ case VTERM_PROP_CURSORCOLOR:
+ vim_free(term->tl_cursor_color);
+ term->tl_cursor_color = vim_strsave((char_u *)value->string);
+ may_set_cursor_props(term);
+ break;
+
case VTERM_PROP_ALTSCREEN:
/* TODO: do anything else? */
term->tl_using_altscreen = value->boolean;
@@ -2076,17 +2141,30 @@
f_term_getcursor(typval_T *argvars, typval_T *rettv)
{
buf_T *buf = term_get_buf(argvars);
+ term_T *term;
list_T *l;
+ dict_T *d;
if (rettv_list_alloc(rettv) == FAIL)
return;
if (buf == NULL)
return;
+ term = buf->b_term;
l = rettv->vval.v_list;
- list_append_number(l, buf->b_term->tl_cursor_pos.row + 1);
- list_append_number(l, buf->b_term->tl_cursor_pos.col + 1);
- list_append_number(l, buf->b_term->tl_cursor_visible);
+ list_append_number(l, term->tl_cursor_pos.row + 1);
+ list_append_number(l, term->tl_cursor_pos.col + 1);
+
+ d = dict_alloc();
+ if (d != NULL)
+ {
+ dict_add_nr_str(d, "visible", term->tl_cursor_visible, NULL);
+ dict_add_nr_str(d, "blink", term->tl_cursor_blink, NULL);
+ dict_add_nr_str(d, "shape", term->tl_cursor_shape, NULL);
+ dict_add_nr_str(d, "color", 0L, term->tl_cursor_color == NULL
+ ? (char_u *)"" : term->tl_cursor_color);
+ list_append_dict(l, d);
+ }
}
/*