diff --git a/cmd-send-keys.c b/cmd-send-keys.c index 44b796ba..47fa1caa 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -202,6 +202,12 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) wp->flags |= (PANE_STYLECHANGED|PANE_REDRAW); } + if (count == 0) { + for (; np != 0; np--) + cmd_send_keys_inject_key(item, NULL, event->key); + return (CMD_RETURN_NORMAL); + } + for (; np != 0; np--) { for (i = 0; i < count; i++) { after = cmd_send_keys_inject_string(item, after, args, diff --git a/format.c b/format.c index 178102cc..e6d5dac9 100644 --- a/format.c +++ b/format.c @@ -3327,7 +3327,7 @@ format_find(struct format_tree *ft, const char *key, int modifiers, fte = format_table_get(key); if (fte != NULL) { value = fte->cb(ft); - if (fte->type == FORMAT_TABLE_TIME) + if (fte->type == FORMAT_TABLE_TIME && value != NULL) t = ((struct timeval *)value)->tv_sec; else found = value; diff --git a/input.c b/input.c index 7a320c56..8a16281c 100644 --- a/input.c +++ b/input.c @@ -1646,7 +1646,7 @@ input_csi_dispatch_rm(struct input_ctx *ictx) screen_write_mode_clear(sctx, MODE_INSERT); break; case 34: - screen_write_mode_set(sctx, MODE_BLINKING); + screen_write_mode_set(sctx, MODE_CURSOR_VERY_VISIBLE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); @@ -1682,7 +1682,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx) screen_write_mode_clear(sctx, MODE_WRAP); break; case 12: - screen_write_mode_clear(sctx, MODE_BLINKING); + screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING); break; case 25: /* TCEM */ screen_write_mode_clear(sctx, MODE_CURSOR); @@ -1734,7 +1734,7 @@ input_csi_dispatch_sm(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_INSERT); break; case 34: - screen_write_mode_clear(sctx, MODE_BLINKING); + screen_write_mode_clear(sctx, MODE_CURSOR_VERY_VISIBLE); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); @@ -1771,7 +1771,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_WRAP); break; case 12: - screen_write_mode_set(sctx, MODE_BLINKING); + screen_write_mode_set(sctx, MODE_CURSOR_BLINKING); break; case 25: /* TCEM */ screen_write_mode_set(sctx, MODE_CURSOR); diff --git a/screen.c b/screen.c index 514c740e..3837c8f5 100644 --- a/screen.c +++ b/screen.c @@ -162,27 +162,27 @@ screen_set_cursor_style(struct screen *s, u_int style) break; case 1: s->cstyle = SCREEN_CURSOR_BLOCK; - s->mode |= MODE_BLINKING; + s->mode |= MODE_CURSOR_BLINKING; break; case 2: s->cstyle = SCREEN_CURSOR_BLOCK; - s->mode &= ~MODE_BLINKING; + s->mode &= ~MODE_CURSOR_BLINKING; break; case 3: s->cstyle = SCREEN_CURSOR_UNDERLINE; - s->mode |= MODE_BLINKING; + s->mode |= MODE_CURSOR_BLINKING; break; case 4: s->cstyle = SCREEN_CURSOR_UNDERLINE; - s->mode &= ~MODE_BLINKING; + s->mode &= ~MODE_CURSOR_BLINKING; break; case 5: s->cstyle = SCREEN_CURSOR_BAR; - s->mode |= MODE_BLINKING; + s->mode |= MODE_CURSOR_BLINKING; break; case 6: s->cstyle = SCREEN_CURSOR_BAR; - s->mode &= ~MODE_BLINKING; + s->mode &= ~MODE_CURSOR_BLINKING; break; } } @@ -679,8 +679,10 @@ screen_mode_to_string(int mode) strlcat(tmp, "MOUSE_STANDARD,", sizeof tmp); if (mode & MODE_MOUSE_BUTTON) strlcat(tmp, "MOUSE_BUTTON,", sizeof tmp); - if (mode & MODE_BLINKING) - strlcat(tmp, "BLINKING,", sizeof tmp); + if (mode & MODE_CURSOR_BLINKING) + strlcat(tmp, "CURSOR_BLINKING,", sizeof tmp); + if (mode & MODE_CURSOR_VERY_VISIBLE) + strlcat(tmp, "CURSOR_VERY_VISIBLE,", sizeof tmp); if (mode & MODE_MOUSE_UTF8) strlcat(tmp, "UTF8,", sizeof tmp); if (mode & MODE_MOUSE_SGR) diff --git a/tmux.1 b/tmux.1 index b8e96984..2f032c76 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3123,6 +3123,7 @@ or to send; if the string is not recognised as a key, it is sent as a series of characters. All arguments are sent sequentially from first to last. +If no keys are given and the command is bound to a key, then that key is used. .Pp The .Fl l diff --git a/tmux.h b/tmux.h index 74ea3517..1e5722db 100644 --- a/tmux.h +++ b/tmux.h @@ -521,7 +521,7 @@ enum tty_code_code { #define MODE_WRAP 0x10 #define MODE_MOUSE_STANDARD 0x20 #define MODE_MOUSE_BUTTON 0x40 -#define MODE_BLINKING 0x80 +#define MODE_CURSOR_BLINKING 0x80 #define MODE_MOUSE_UTF8 0x100 #define MODE_MOUSE_SGR 0x200 #define MODE_BRACKETPASTE 0x400 @@ -530,10 +530,12 @@ enum tty_code_code { #define MODE_ORIGIN 0x2000 #define MODE_CRLF 0x4000 #define MODE_KEXTENDED 0x8000 +#define MODE_CURSOR_VERY_VISIBLE 0x10000 #define ALL_MODES 0xffffff #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) #define MOTION_MOUSE_MODES (MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) +#define CURSOR_MODES (MODE_CURSOR|MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE) /* A single UTF-8 character. */ typedef u_int utf8_char; diff --git a/tty.c b/tty.c index ba58aa2b..e4800ec2 100644 --- a/tty.c +++ b/tty.c @@ -314,7 +314,7 @@ tty_start_tty(struct tty *tty) tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; if (tcsetattr(c->fd, TCSANOW, &tio) == 0) - tcflush(c->fd, TCIOFLUSH); + tcflush(c->fd, TCOFLUSH); tty_putcode(tty, TTYC_SMCUP); @@ -658,12 +658,83 @@ tty_force_cursor_colour(struct tty *tty, const char *ccolour) tty->ccolour = xstrdup(ccolour); } +static void +tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) +{ + enum screen_cursor_style cstyle; + + /* Set cursor colour if changed. */ + if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0) + tty_force_cursor_colour(tty, s->ccolour); + + /* If cursor is off, set as invisible. */ + if (~mode & MODE_CURSOR) { + if (changed & MODE_CURSOR) + tty_putcode(tty, TTYC_CIVIS); + return; + } + + /* Check if blinking or very visible flag changed or style changed. */ + if (s == NULL) + cstyle = tty->cstyle; + else + cstyle = s->cstyle; + if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle) + return; + + /* + * Set cursor style. If an explicit style has been set with DECSCUSR, + * set it if supported, otherwise send cvvis for blinking styles. + * + * If no style, has been set (SCREEN_CURSOR_DEFAULT), then send cvvis + * if either the blinking or very visible flags are set. + */ + tty_putcode(tty, TTYC_CNORM); + switch (cstyle) { + case SCREEN_CURSOR_DEFAULT: + if (tty_term_has(tty->term, TTYC_SE)) + tty_putcode(tty, TTYC_SE); + else + tty_putcode1(tty, TTYC_SS, 0); + if (mode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_BLOCK: + if (tty_term_has(tty->term, TTYC_SS)) { + if (mode & MODE_CURSOR_BLINKING) + tty_putcode1(tty, TTYC_SS, 1); + else + tty_putcode1(tty, TTYC_SS, 2); + } else if (mode & MODE_CURSOR_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_UNDERLINE: + if (tty_term_has(tty->term, TTYC_SS)) { + if (mode & MODE_CURSOR_BLINKING) + tty_putcode1(tty, TTYC_SS, 3); + else + tty_putcode1(tty, TTYC_SS, 4); + } else if (mode & MODE_CURSOR_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + case SCREEN_CURSOR_BAR: + if (tty_term_has(tty->term, TTYC_SS)) { + if (mode & MODE_CURSOR_BLINKING) + tty_putcode1(tty, TTYC_SS, 5); + else + tty_putcode1(tty, TTYC_SS, 6); + } else if (mode & MODE_CURSOR_BLINKING) + tty_putcode(tty, TTYC_CVVIS); + break; + } + tty->cstyle = cstyle; + } + void tty_update_mode(struct tty *tty, int mode, struct screen *s) { - struct client *c = tty->client; - int changed; - enum screen_cursor_style cstyle = tty->cstyle; + struct client *c = tty->client; + int changed; if (tty->flags & TTY_NOCURSOR) mode &= ~MODE_CURSOR; @@ -676,85 +747,7 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) screen_mode_to_string(mode)); } - if (s != NULL) { - if (strcmp(s->ccolour, tty->ccolour) != 0) - tty_force_cursor_colour(tty, s->ccolour); - cstyle = s->cstyle; - } - if (~mode & MODE_CURSOR) { - /* Cursor now off - set as invisible. */ - if (changed & MODE_CURSOR) - tty_putcode(tty, TTYC_CIVIS); - } 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); - 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; - } - + tty_update_cursor(tty, mode, changed, s); if ((changed & ALL_MOUSE_MODES) && tty_term_has(tty->term, TTYC_KMOUS)) { /*