diff --git a/screen.c b/screen.c index 0b1047ab..2d770abb 100644 --- a/screen.c +++ b/screen.c @@ -81,7 +81,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->titles = NULL; s->path = NULL; - s->cstyle = 0; + s->cstyle = SCREEN_CURSOR_DEFAULT; s->ccolour = xstrdup(""); s->tabs = NULL; s->sel = NULL; @@ -156,9 +156,35 @@ screen_reset_tabs(struct screen *s) void screen_set_cursor_style(struct screen *s, u_int style) { - if (style <= 6) { - s->cstyle = style; + switch (style) + { + case 0: + s->cstyle = SCREEN_CURSOR_DEFAULT; + break; + case 1: + s->cstyle = SCREEN_CURSOR_BLOCK; + s->mode |= MODE_BLINKING; + break; + case 2: + s->cstyle = SCREEN_CURSOR_BLOCK; s->mode &= ~MODE_BLINKING; + break; + case 3: + s->cstyle = SCREEN_CURSOR_UNDERLINE; + s->mode |= MODE_BLINKING; + break; + case 4: + s->cstyle = SCREEN_CURSOR_UNDERLINE; + s->mode &= ~MODE_BLINKING; + break; + case 5: + s->cstyle = SCREEN_CURSOR_BAR; + s->mode |= MODE_BLINKING; + break; + case 6: + s->cstyle = SCREEN_CURSOR_BAR; + s->mode &= ~MODE_BLINKING; + break; } } diff --git a/tmux.h b/tmux.h index 508fddd3..96d829fb 100644 --- a/tmux.h +++ b/tmux.h @@ -794,6 +794,14 @@ struct style { enum style_default_type default_type; }; +/* Cursor style. */ +enum screen_cursor_style { + SCREEN_CURSOR_DEFAULT, + SCREEN_CURSOR_BLOCK, + SCREEN_CURSOR_UNDERLINE, + SCREEN_CURSOR_BAR +}; + /* Virtual screen. */ struct screen_sel; struct screen_titles; @@ -807,8 +815,8 @@ struct screen { u_int cx; /* cursor x */ u_int cy; /* cursor y */ - u_int cstyle; /* cursor style */ - char *ccolour; /* cursor colour string */ + enum screen_cursor_style cstyle; /* cursor style */ + char *ccolour; /* cursor colour */ u_int rupper; /* scroll region top */ u_int rlower; /* scroll region bottom */ @@ -1296,7 +1304,7 @@ struct tty { u_int cx; u_int cy; - u_int cstyle; + enum screen_cursor_style cstyle; char *ccolour; int oflag; diff --git a/tty.c b/tty.c index e8a8cbaa..367f54d5 100644 --- a/tty.c +++ b/tty.c @@ -98,7 +98,7 @@ tty_init(struct tty *tty, struct client *c) memset(tty, 0, sizeof *tty); tty->client = c; - tty->cstyle = 0; + tty->cstyle = SCREEN_CURSOR_DEFAULT; tty->ccolour = xstrdup(""); if (tcgetattr(c->fd, &tty->tio) != 0) @@ -392,10 +392,10 @@ tty_stop_tty(struct tty *tty) tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); - if (tty_term_has(tty->term, TTYC_SS) && tty->cstyle != 0) { + if (tty->cstyle != SCREEN_CURSOR_DEFAULT) { if (tty_term_has(tty->term, TTYC_SE)) tty_raw(tty, tty_term_string(tty->term, TTYC_SE)); - else + else if (tty_term_has(tty->term, TTYC_SS)) tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0)); } if (tty->mode & MODE_BRACKETPASTE) @@ -657,11 +657,9 @@ tty_force_cursor_colour(struct tty *tty, const char *ccolour) void tty_update_mode(struct tty *tty, int mode, struct screen *s) { - struct client *c = tty->client; - int changed; - - if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0) - tty_force_cursor_colour(tty, s->ccolour); + struct client *c = tty->client; + int changed; + enum screen_cursor_style cstyle = tty->cstyle; if (tty->flags & TTY_NOCURSOR) mode &= ~MODE_CURSOR; @@ -670,38 +668,83 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) if (changed != 0) log_debug("%s: update mode %x to %x", c->name, tty->mode, mode); - /* - * The cursor blinking flag can be reset by setting the cursor style, so - * set the style first. - */ - if (s != NULL && tty->cstyle != s->cstyle) { - if (tty_term_has(tty->term, TTYC_SS)) { - if (s->cstyle == 0 && tty_term_has(tty->term, TTYC_SE)) - tty_putcode(tty, TTYC_SE); - else - tty_putcode1(tty, TTYC_SS, s->cstyle); - } - tty->cstyle = s->cstyle; - changed |= (MODE_CURSOR|MODE_BLINKING); + if (s != NULL) { + if (strcmp(s->ccolour, tty->ccolour) != 0) + tty_force_cursor_colour(tty, s->ccolour); + cstyle = s->cstyle; } - - /* - * Cursor invisible (RM ?25) overrides cursor blinking (SM ?12 or RM - * 34), and we need to be careful not send cnorm after cvvis since it - * can undo it. - */ - if (changed & (MODE_CURSOR|MODE_BLINKING)) { - log_debug("%s: cursor %s, %sblinking", __func__, - (mode & MODE_CURSOR) ? "on" : "off", - (mode & MODE_BLINKING) ? "" : "not "); - if (~mode & MODE_CURSOR) + if (~mode & MODE_CURSOR) { + /* Cursor now off - set as invisible. */ + if (changed & MODE_CURSOR) tty_putcode(tty, TTYC_CIVIS); - else if (mode & MODE_BLINKING) { - tty_putcode(tty, TTYC_CNORM); - if (tty_term_has(tty->term, TTYC_CVVIS)) + } else if ((changed & (MODE_CURSOR|MODE_BLINKING)) || + cstyle != tty->cstyle) { + /* + * Cursor now on, blinking flag changed or style changed. Start + * by setting the cursor to normal. + */ + tty_putcode(tty, TTYC_CNORM); + switch (cstyle) { + case SCREEN_CURSOR_DEFAULT: + /* + * If the old style wasn't default, then reset it to + * default. + */ + if (tty->cstyle != SCREEN_CURSOR_DEFAULT) { + if (tty_term_has(tty->term, TTYC_SE)) + tty_putcode(tty, TTYC_SE); + else + tty_putcode1(tty, TTYC_SS, 0); + } + + /* Set the cursor as very visible if necessary. */ + if (mode & MODE_BLINKING) tty_putcode(tty, TTYC_CVVIS); - } else - tty_putcode(tty, TTYC_CNORM); + break; + case SCREEN_CURSOR_BLOCK: + /* + * Set style to either block blinking (1) or steady (2) + * if supported, otherwise just check the blinking + * flag. + */ + if (tty_term_has(tty->term, TTYC_SS)) { + if (mode & MODE_BLINKING) + tty_putcode1(tty, TTYC_SS, 1); + else + tty_putcode1(tty, TTYC_SS, 2); + } else if (mode & MODE_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_UNDERLINE: + /* + * Set style to either underline blinking (3) or steady + * (4) if supported, otherwise just check the blinking + * flag. + */ + if (tty_term_has(tty->term, TTYC_SS)) { + if (mode & MODE_BLINKING) + tty_putcode1(tty, TTYC_SS, 3); + else + tty_putcode1(tty, TTYC_SS, 4); + } else if (mode & MODE_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_BAR: + /* + * Set style to either bar blinking (5) or steady (6) + * if supported, otherwise just check the blinking + * flag. + */ + if (tty_term_has(tty->term, TTYC_SS)) { + if (mode & MODE_BLINKING) + tty_putcode1(tty, TTYC_SS, 5); + else + tty_putcode1(tty, TTYC_SS, 6); + } else if (mode & MODE_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + } + tty->cstyle = cstyle; } if ((changed & ALL_MOUSE_MODES) &&