diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2020-05-16 15:01:32 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2020-05-16 15:01:32 +0000 |
commit | e0d5e2766c2dde6fe92876de0e45419382fe76c3 (patch) | |
tree | 5577fce3911e0671a1ab85b07ff96d9b58fcc854 /usr.bin | |
parent | 77b52d0eb703bbd2aa29920c8b3ce2774accf8f4 (diff) |
Drop having a separate type for style options and make them all strings,
which allows formats to be expanded. Any styles without a '#{' are still
validated when they are set but any with a '#{' are not. Formats are not
expanded usefully in many cases yet, that will be changed later.
To make this work, a few other changes:
- set-option -a with a style option automatically appends a ",".
- OSC 10 and 11 don't set the window-style option anymore, instead the
fg and bg are stored in the pane struct and act as the defaults that
can be overridden by window-style.
- status-fg and -bg now override status-style instead of trying to keep
them in sync.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/cmd-rename-window.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-resize-pane.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-respawn-pane.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-select-pane.c | 34 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-set-option.c | 59 | ||||
-rw-r--r-- | usr.bin/tmux/input.c | 31 | ||||
-rw-r--r-- | usr.bin/tmux/menu.c | 5 | ||||
-rw-r--r-- | usr.bin/tmux/mode-tree.c | 4 | ||||
-rw-r--r-- | usr.bin/tmux/names.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/options-table.c | 96 | ||||
-rw-r--r-- | usr.bin/tmux/options.c | 100 | ||||
-rw-r--r-- | usr.bin/tmux/screen-redraw.c | 433 | ||||
-rw-r--r-- | usr.bin/tmux/status.c | 18 | ||||
-rw-r--r-- | usr.bin/tmux/style.c | 36 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 33 | ||||
-rw-r--r-- | usr.bin/tmux/tty.c | 18 | ||||
-rw-r--r-- | usr.bin/tmux/window-copy.c | 6 | ||||
-rw-r--r-- | usr.bin/tmux/window.c | 7 |
18 files changed, 528 insertions, 364 deletions
diff --git a/usr.bin/tmux/cmd-rename-window.c b/usr.bin/tmux/cmd-rename-window.c index f5f527181f9..a369f241e60 100644 --- a/usr.bin/tmux/cmd-rename-window.c +++ b/usr.bin/tmux/cmd-rename-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-rename-window.c,v 1.25 2020/04/13 20:51:57 nicm Exp $ */ +/* $OpenBSD: cmd-rename-window.c,v 1.26 2020/05/16 15:01:30 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -54,6 +54,7 @@ cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item) window_set_name(wl->window, newname); options_set_number(wl->window->options, "automatic-rename", 0); + server_redraw_window_borders(wl->window); server_status_window(wl->window); free(newname); diff --git a/usr.bin/tmux/cmd-resize-pane.c b/usr.bin/tmux/cmd-resize-pane.c index cbc761d093b..7aede4da29d 100644 --- a/usr.bin/tmux/cmd-resize-pane.c +++ b/usr.bin/tmux/cmd-resize-pane.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-resize-pane.c,v 1.46 2020/04/13 14:46:04 nicm Exp $ */ +/* $OpenBSD: cmd-resize-pane.c,v 1.47 2020/05/16 15:01:30 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -91,7 +91,6 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item) else window_zoom(wp); server_redraw_window(w); - server_status_window(w); return (CMD_RETURN_NORMAL); } server_unzoom_window(w); diff --git a/usr.bin/tmux/cmd-respawn-pane.c b/usr.bin/tmux/cmd-respawn-pane.c index ba0fa01a9a1..73616b953aa 100644 --- a/usr.bin/tmux/cmd-respawn-pane.c +++ b/usr.bin/tmux/cmd-respawn-pane.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-respawn-pane.c,v 1.32 2020/04/13 10:59:58 nicm Exp $ */ +/* $OpenBSD: cmd-respawn-pane.c,v 1.33 2020/05/16 15:01:30 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -90,6 +90,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item) } wp->flags |= PANE_REDRAW; + server_redraw_window_borders(wp->window); server_status_window(wp->window); environ_free(sc.environ); diff --git a/usr.bin/tmux/cmd-select-pane.c b/usr.bin/tmux/cmd-select-pane.c index 3d72092d3d6..a767e28e791 100644 --- a/usr.bin/tmux/cmd-select-pane.c +++ b/usr.bin/tmux/cmd-select-pane.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-select-pane.c,v 1.59 2020/04/13 20:51:57 nicm Exp $ */ +/* $OpenBSD: cmd-select-pane.c,v 1.60 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -91,9 +91,9 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) struct window *w = wl->window; struct session *s = target->s; struct window_pane *wp = target->wp, *lastwp, *markedwp; + struct options *oo = wp->options; char *title; const char *style; - struct style *sy; struct options_entry *o; if (entry == &cmd_last_pane_entry || args_has(args, 'l')) { @@ -147,22 +147,18 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (args_has(args, 'P') || args_has(args, 'g')) { - if ((style = args_get(args, 'P')) != NULL) { - o = options_set_style(wp->options, "window-style", 0, - style); - if (o == NULL) { - cmdq_error(item, "bad style: %s", style); - return (CMD_RETURN_ERROR); - } - options_set_style(wp->options, "window-active-style", 0, - style); - wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); - } - if (args_has(args, 'g')) { - sy = options_get_style(wp->options, "window-style"); - cmdq_print(item, "%s", style_tostring(sy)); + style = args_get(args, 'P'); + if (style != NULL) { + o = options_set_string(oo, "window-style", 0, "%s", style); + if (o == NULL) { + cmdq_error(item, "bad style: %s", style); + return (CMD_RETURN_ERROR); } + options_set_string(oo, "window-active-style", 0, "%s", style); + wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); + } + if (args_has(args, 'g')) { + cmdq_print(item, "%s", options_get_string(oo, "window-style")); return (CMD_RETURN_NORMAL); } @@ -197,8 +193,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) if (args_has(args, 'T')) { title = format_single_from_target(item, args_get(args, 'T')); - if (screen_set_title(&wp->base, title)) + if (screen_set_title(&wp->base, title)) { + server_redraw_window_borders(wp->window); server_status_window(wp->window); + } free(title); return (CMD_RETURN_NORMAL); } diff --git a/usr.bin/tmux/cmd-set-option.c b/usr.bin/tmux/cmd-set-option.c index 3f867ad34c1..69f1a3c55c2 100644 --- a/usr.bin/tmux/cmd-set-option.c +++ b/usr.bin/tmux/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-set-option.c,v 1.133 2020/04/13 20:54:15 nicm Exp $ */ +/* $OpenBSD: cmd-set-option.c,v 1.134 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -93,7 +93,6 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) char *name, *argument, *value = NULL, *cause; int window, idx, already, error, ambiguous; int scope; - struct style *sy; window = (cmd_get_entry(self) == &cmd_set_window_option_entry); @@ -232,16 +231,6 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) tty_keys_build(&loop->tty); } } - if (strcmp(name, "status-fg") == 0 || strcmp(name, "status-bg") == 0) { - sy = options_get_style(oo, "status-style"); - sy->gc.fg = options_get_number(oo, "status-fg"); - sy->gc.bg = options_get_number(oo, "status-bg"); - } - if (strcmp(name, "status-style") == 0) { - sy = options_get_style(oo, "status-style"); - options_set_number(oo, "status-fg", sy->gc.fg); - options_set_number(oo, "status-bg", sy->gc.bg); - } if (strcmp(name, "status") == 0 || strcmp(name, "status-interval") == 0) status_timer_start_all(); @@ -283,16 +272,38 @@ fail: } static int +cmd_set_option_check_string(const struct options_table_entry *oe, + const char *value, char **cause) +{ + struct style sy; + + if (strcmp(oe->name, "default-shell") == 0 && !checkshell(value)) { + xasprintf(cause, "not a suitable shell: %s", value); + return (-1); + } + if (oe->pattern != NULL && fnmatch(oe->pattern, value, 0) != 0) { + xasprintf(cause, "value is invalid: %s", value); + return (-1); + } + if ((oe->flags & OPTIONS_TABLE_IS_STYLE) && + strstr(value, "#{") == NULL && + style_parse(&sy, &grid_default_cell, value) != 0) { + xasprintf(cause, "invalid style: %s", value); + return (-1); + } + return (0); +} + +static int cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo, struct options_entry *parent, const char *value) { const struct options_table_entry *oe; struct args *args = cmd_get_args(self); int append = args_has(args, 'a'); - struct options_entry *o; long long number; const char *errstr, *new; - char *old; + char *old, *cause; key_code key; oe = options_table_entry(parent); @@ -308,17 +319,12 @@ cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo, old = xstrdup(options_get_string(oo, oe->name)); options_set_string(oo, oe->name, append, "%s", value); new = options_get_string(oo, oe->name); - if (strcmp(oe->name, "default-shell") == 0 && - !checkshell(new)) { - options_set_string(oo, oe->name, 0, "%s", old); - free(old); - cmdq_error(item, "not a suitable shell: %s", value); - return (-1); - } - if (oe->pattern != NULL && fnmatch(oe->pattern, new, 0) != 0) { + if (cmd_set_option_check_string(oe, new, &cause) != 0) { + cmdq_error(item, "%s", cause); + free(cause); + options_set_string(oo, oe->name, 0, "%s", old); free(old); - cmdq_error(item, "value is invalid: %s", value); return (-1); } free(old); @@ -350,13 +356,6 @@ cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo, return (cmd_set_option_flag(item, oe, oo, value)); case OPTIONS_TABLE_CHOICE: return (cmd_set_option_choice(item, oe, oo, value)); - case OPTIONS_TABLE_STYLE: - o = options_set_style(oo, oe->name, append, value); - if (o == NULL) { - cmdq_error(item, "bad style: %s", value); - return (-1); - } - return (0); case OPTIONS_TABLE_COMMAND: break; } diff --git a/usr.bin/tmux/input.c b/usr.bin/tmux/input.c index b9e1d694137..5ee5eafe211 100644 --- a/usr.bin/tmux/input.c +++ b/usr.bin/tmux/input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.175 2020/05/16 14:16:25 nicm Exp $ */ +/* $OpenBSD: input.c,v 1.176 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -1861,8 +1861,10 @@ input_csi_dispatch_winops(struct input_ctx *ictx) case 0: case 2: screen_pop_title(sctx->s); - if (wp != NULL) + if (wp != NULL) { + server_redraw_window_borders(wp->window); server_status_window(wp->window); + } break; } break; @@ -2253,8 +2255,10 @@ input_exit_osc(struct input_ctx *ictx) switch (option) { case 0: case 2: - if (screen_set_title(sctx->s, p) && wp != NULL) - server_status_window(ictx->wp->window); + if (screen_set_title(sctx->s, p) && wp != NULL) { + server_redraw_window_borders(wp->window); + server_status_window(wp->window); + } break; case 4: input_osc_4(ictx, p); @@ -2262,8 +2266,10 @@ input_exit_osc(struct input_ctx *ictx) case 7: if (utf8_isvalid(p)) { screen_set_path(sctx->s, p); - if (wp != NULL) + if (wp != NULL) { + server_redraw_window_borders(wp->window); server_status_window(wp->window); + } } break; case 10: @@ -2314,8 +2320,10 @@ input_exit_apc(struct input_ctx *ictx) return; log_debug("%s: \"%s\"", __func__, ictx->input_buf); - if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL) + if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL) { + server_redraw_window_borders(wp->window); server_status_window(wp->window); + } } /* Rename string started. */ @@ -2355,6 +2363,7 @@ input_exit_rename(struct input_ctx *ictx) } window_set_name(wp->window, ictx->input_buf); options_set_number(wp->window->options, "automatic-rename", 0); + server_redraw_window_borders(wp->window); server_status_window(wp->window); } @@ -2486,7 +2495,6 @@ input_osc_10(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; u_int r, g, b; - char tmp[16]; if (wp == NULL) return; @@ -2495,9 +2503,7 @@ input_osc_10(struct input_ctx *ictx, const char *p) if (!input_osc_parse_colour(p, &r, &g, &b)) goto bad; - xsnprintf(tmp, sizeof tmp, "fg=#%02x%02x%02x", r, g, b); - options_set_style(wp->options, "window-style", 1, tmp); - options_set_style(wp->options, "window-active-style", 1, tmp); + wp->fg = colour_join_rgb(r, g, b); wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); return; @@ -2512,7 +2518,6 @@ input_osc_11(struct input_ctx *ictx, const char *p) { struct window_pane *wp = ictx->wp; u_int r, g, b; - char tmp[16]; if (wp == NULL) return; @@ -2521,9 +2526,7 @@ input_osc_11(struct input_ctx *ictx, const char *p) if (!input_osc_parse_colour(p, &r, &g, &b)) goto bad; - xsnprintf(tmp, sizeof tmp, "bg=#%02x%02x%02x", r, g, b); - options_set_style(wp->options, "window-style", 1, tmp); - options_set_style(wp->options, "window-active-style", 1, tmp); + wp->bg = colour_join_rgb(r, g, b); wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED); return; diff --git a/usr.bin/tmux/menu.c b/usr.bin/tmux/menu.c index 3922261b8d4..01f61d23172 100644 --- a/usr.bin/tmux/menu.c +++ b/usr.bin/tmux/menu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: menu.c,v 1.24 2020/05/16 14:53:23 nicm Exp $ */ +/* $OpenBSD: menu.c,v 1.25 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -151,8 +151,7 @@ menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) u_int i, px = md->px, py = md->py; struct grid_cell gc; - memcpy(&gc, &grid_default_cell, sizeof gc); - style_apply(&gc, c->session->curw->window->options, "mode-style"); + style_apply(&gc, c->session->curw->window->options, "mode-style", NULL); screen_write_start(&ctx, NULL, s); screen_write_clearscreen(&ctx, 8); diff --git a/usr.bin/tmux/mode-tree.c b/usr.bin/tmux/mode-tree.c index 9df226438d6..e87c3653d42 100644 --- a/usr.bin/tmux/mode-tree.c +++ b/usr.bin/tmux/mode-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mode-tree.c,v 1.41 2020/04/22 21:01:28 nicm Exp $ */ +/* $OpenBSD: mode-tree.c,v 1.42 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -557,7 +557,7 @@ mode_tree_draw(struct mode_tree_data *mtd) memcpy(&gc0, &grid_default_cell, sizeof gc0); memcpy(&gc, &grid_default_cell, sizeof gc); - style_apply(&gc, oo, "mode-style"); + style_apply(&gc, oo, "mode-style", NULL); w = mtd->width; h = mtd->height; diff --git a/usr.bin/tmux/names.c b/usr.bin/tmux/names.c index 6e897a28aa4..60b0f314a1d 100644 --- a/usr.bin/tmux/names.c +++ b/usr.bin/tmux/names.c @@ -1,4 +1,4 @@ -/* $OpenBSD: names.c,v 1.41 2017/07/21 12:58:02 nicm Exp $ */ +/* $OpenBSD: names.c,v 1.42 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -96,6 +96,7 @@ check_window_name(struct window *w) if (strcmp(name, w->name) != 0) { log_debug("@%u new name %s (was %s)", w->id, name, w->name); window_set_name(w, name); + server_redraw_window_borders(w); server_status_window(w); } else log_debug("@%u name not changed (still %s)", w->id, w->name); diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c index cd2238351e6..b4a0a7a7e05 100644 --- a/usr.bin/tmux/options-table.c +++ b/usr.bin/tmux/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.122 2020/05/16 14:46:14 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.123 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -401,15 +401,19 @@ const struct options_table_entry options_table[] = { }, { .name = "message-command-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, - .default_str = "bg=black,fg=yellow" + .default_str = "bg=black,fg=yellow", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "message-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, - .default_str = "bg=yellow,fg=black" + .default_str = "bg=yellow,fg=black", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "mouse", @@ -473,13 +477,13 @@ const struct options_table_entry options_table[] = { { .name = "status-bg", .type = OPTIONS_TABLE_COLOUR, .scope = OPTIONS_TABLE_SESSION, - .default_num = 2, + .default_num = 8, }, { .name = "status-fg", .type = OPTIONS_TABLE_COLOUR, .scope = OPTIONS_TABLE_SESSION, - .default_num = 0, + .default_num = 8, }, { .name = "status-format", @@ -526,9 +530,11 @@ const struct options_table_entry options_table[] = { }, { .name = "status-left-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "status-position", @@ -555,15 +561,19 @@ const struct options_table_entry options_table[] = { }, { .name = "status-right-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "status-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SESSION, - .default_str = "bg=green,fg=black" + .default_str = "bg=green,fg=black", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "update-environment", @@ -666,9 +676,11 @@ const struct options_table_entry options_table[] = { }, { .name = "mode-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "bg=yellow,fg=black" + .default_str = "bg=yellow,fg=black", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "monitor-activity", @@ -704,9 +716,11 @@ const struct options_table_entry options_table[] = { }, { .name = "pane-active-border-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "fg=green" + .default_str = "#{?pane_in_mode,fg=yellow,#{?synchronize-panes,fg=red,fg=green}}", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "pane-base-index", @@ -732,9 +746,11 @@ const struct options_table_entry options_table[] = { }, { .name = "pane-border-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "remain-on-exit", @@ -750,9 +766,11 @@ const struct options_table_entry options_table[] = { }, { .name = "window-active-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "window-size", @@ -763,21 +781,27 @@ const struct options_table_entry options_table[] = { }, { .name = "window-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "window-status-activity-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "reverse" + .default_str = "reverse", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "window-status-bell-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "reverse" + .default_str = "reverse", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "window-status-current-format", @@ -787,9 +811,11 @@ const struct options_table_entry options_table[] = { }, { .name = "window-status-current-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "window-status-format", @@ -799,9 +825,11 @@ const struct options_table_entry options_table[] = { }, { .name = "window-status-last-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "window-status-separator", @@ -811,9 +839,11 @@ const struct options_table_entry options_table[] = { }, { .name = "window-status-style", - .type = OPTIONS_TABLE_STYLE, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "default" + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = "," }, { .name = "wrap-search", diff --git a/usr.bin/tmux/options.c b/usr.bin/tmux/options.c index aaccaa126bd..58c5337898c 100644 --- a/usr.bin/tmux/options.c +++ b/usr.bin/tmux/options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options.c,v 1.55 2019/12/03 10:47:22 nicm Exp $ */ +/* $OpenBSD: options.c,v 1.56 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -53,6 +53,9 @@ struct options_entry { const struct options_table_entry *tableentry; union options_value value; + int cached; + struct style style; + RB_ENTRY(options_entry) entry; }; @@ -73,9 +76,6 @@ static struct options_entry *options_add(struct options *, const char *); (o)->tableentry->type == OPTIONS_TABLE_COLOUR || \ (o)->tableentry->type == OPTIONS_TABLE_FLAG || \ (o)->tableentry->type == OPTIONS_TABLE_CHOICE)) -#define OPTIONS_IS_STYLE(o) \ - ((o)->tableentry != NULL && \ - (o)->tableentry->type == OPTIONS_TABLE_STYLE) #define OPTIONS_IS_COMMAND(o) \ ((o)->tableentry != NULL && \ (o)->tableentry->type == OPTIONS_TABLE_COMMAND) @@ -123,8 +123,6 @@ options_value_tostring(struct options_entry *o, union options_value *ov, if (OPTIONS_IS_COMMAND(o)) return (cmd_list_print(ov->cmdlist, 0)); - if (OPTIONS_IS_STYLE(o)) - return (xstrdup(style_tostring(&ov->style))); if (OPTIONS_IS_NUMBER(o)) { switch (o->tableentry->type) { case OPTIONS_TABLE_NUMBER: @@ -146,7 +144,6 @@ options_value_tostring(struct options_entry *o, union options_value *ov, s = xstrdup(o->tableentry->choices[ov->number]); break; case OPTIONS_TABLE_STRING: - case OPTIONS_TABLE_STYLE: case OPTIONS_TABLE_COMMAND: fatalx("not a number option type"); } @@ -258,10 +255,6 @@ options_default(struct options *oo, const struct options_table_entry *oe) case OPTIONS_TABLE_STRING: ov->string = xstrdup(oe->default_str); break; - case OPTIONS_TABLE_STYLE: - style_set(&ov->style, &grid_default_cell); - style_parse(&ov->style, &grid_default_cell, oe->default_str); - break; default: ov->number = oe->default_num; break; @@ -653,25 +646,13 @@ options_get_number(struct options *oo, const char *name) return (o->value.number); } -struct style * -options_get_style(struct options *oo, const char *name) -{ - struct options_entry *o; - - o = options_get(oo, name); - if (o == NULL) - fatalx("missing option %s", name); - if (!OPTIONS_IS_STYLE(o)) - fatalx("option %s is not a style", name); - return (&o->value.style); -} - struct options_entry * options_set_string(struct options *oo, const char *name, int append, const char *fmt, ...) { struct options_entry *o; va_list ap; + const char *separator = ""; char *s, *value; va_start(ap, fmt); @@ -680,7 +661,12 @@ options_set_string(struct options *oo, const char *name, int append, o = options_get_only(oo, name); if (o != NULL && append && OPTIONS_IS_STRING(o)) { - xasprintf(&value, "%s%s", o->value.string, s); + if (*name != '@') { + separator = o->tableentry->separator; + if (separator == NULL) + separator = ""; + } + xasprintf(&value, "%s%s%s", o->value.string, separator, s); free(s); } else value = s; @@ -696,6 +682,7 @@ options_set_string(struct options *oo, const char *name, int append, fatalx("option %s is not a string", name); free(o->value.string); o->value.string = value; + o->cached = 0; return (o); } @@ -720,35 +707,6 @@ options_set_number(struct options *oo, const char *name, long long value) return (o); } -struct options_entry * -options_set_style(struct options *oo, const char *name, int append, - const char *value) -{ - struct options_entry *o; - struct style sy; - - if (*name == '@') - fatalx("user option %s must be a string", name); - - o = options_get_only(oo, name); - if (o != NULL && append && OPTIONS_IS_STYLE(o)) - style_copy(&sy, &o->value.style); - else - style_set(&sy, &grid_default_cell); - if (style_parse(&sy, &grid_default_cell, value) == -1) - return (NULL); - if (o == NULL) { - o = options_default(oo, options_parent_table_entry(oo, name)); - if (o == NULL) - return (NULL); - } - - if (!OPTIONS_IS_STYLE(o)) - fatalx("option %s is not a style", name); - style_copy(&o->value.style, &sy); - return (o); -} - int options_scope_from_name(struct args *args, int window, const char *name, struct cmd_find_state *fs, struct options **oo, @@ -874,3 +832,37 @@ options_scope_from_flags(struct args *args, int window, return (OPTIONS_TABLE_SESSION); } } + +struct style * +options_string_to_style(struct options *oo, const char *name, + struct format_tree *ft) +{ + struct options_entry *o; + const char *s; + char *expanded; + + o = options_get(oo, name); + if (o == NULL || !OPTIONS_IS_STRING(o)) + return (NULL); + + if (o->cached) + return (&o->style); + s = o->value.string; + log_debug("%s: %s is '%s'", __func__, name, s); + + style_set(&o->style, &grid_default_cell); + o->cached = (strstr(s, "#{") == NULL); + + if (ft != NULL && !o->cached) { + expanded = format_expand(ft, s); + if (style_parse(&o->style, &grid_default_cell, expanded) != 0) { + free(expanded); + return (NULL); + } + free(expanded); + } else { + if (style_parse(&o->style, &grid_default_cell, s) != 0) + return (NULL); + } + return (&o->style); +} diff --git a/usr.bin/tmux/screen-redraw.c b/usr.bin/tmux/screen-redraw.c index c6242b927a1..9dcfa91769d 100644 --- a/usr.bin/tmux/screen-redraw.c +++ b/usr.bin/tmux/screen-redraw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-redraw.c,v 1.74 2020/05/16 14:42:06 nicm Exp $ */ +/* $OpenBSD: screen-redraw.c,v 1.75 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -45,54 +45,197 @@ static void screen_redraw_draw_pane(struct screen_redraw_ctx *, #define CELL_BORDERS " xqlkmjwvtun~" -/* Check if cell is on the border of a particular pane. */ +const struct grid_cell screen_redraw_border_cell = { + { { ' ' }, 0, 1, 1 }, GRID_ATTR_CHARSET, 0, 8, 8, 0 +}; + +enum screen_redraw_border_type { + SCREEN_REDRAW_OUTSIDE, + SCREEN_REDRAW_INSIDE, + SCREEN_REDRAW_BORDER +}; + +/* Return if window has only two panes. */ static int -screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py) +screen_redraw_two_panes(struct window *w, int direction) { - /* Inside pane. */ - if (px >= wp->xoff && px < wp->xoff + wp->sx && - py >= wp->yoff && py < wp->yoff + wp->sy) + struct window_pane *wp; + + wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); + if (wp == NULL) + return (0); /* one pane */ + if (TAILQ_NEXT(wp, entry) != NULL) + return (0); /* more than two panes */ + if (direction == 0 && wp->xoff == 0) + return (0); + if (direction == 1 && wp->yoff == 0) return (0); + return (1); +} + +/* Check if cell is on the border of a pane. */ +static enum screen_redraw_border_type +screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py, + int pane_status) +{ + u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy; + + /* Inside pane. */ + if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey) + return (SCREEN_REDRAW_INSIDE); /* Left/right borders. */ - if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= wp->yoff + wp->sy) { - if (wp->xoff != 0 && px == wp->xoff - 1) - return (1); - if (px == wp->xoff + wp->sx) - return (2); + if (pane_status == PANE_STATUS_OFF) { + if (screen_redraw_two_panes(wp->window, 0)) { + if (wp->xoff == 0 && px == wp->sx && py <= wp->sy / 2) + return (SCREEN_REDRAW_BORDER); + if (wp->xoff != 0 && + px == wp->xoff - 1 && + py > wp->sy / 2) + return (SCREEN_REDRAW_BORDER); + } else { + if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) { + if (wp->xoff != 0 && px == wp->xoff - 1) + return (SCREEN_REDRAW_BORDER); + if (px == ex) + return (SCREEN_REDRAW_BORDER); + } + } + } else { + if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) { + if (wp->xoff != 0 && px == wp->xoff - 1) + return (SCREEN_REDRAW_BORDER); + if (px == ex) + return (SCREEN_REDRAW_BORDER); + } } /* Top/bottom borders. */ - if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= wp->xoff + wp->sx) { - if (wp->yoff != 0 && py == wp->yoff - 1) - return (3); - if (py == wp->yoff + wp->sy) - return (4); + if (pane_status == PANE_STATUS_OFF) { + if (screen_redraw_two_panes(wp->window, 1)) { + if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2) + return (SCREEN_REDRAW_BORDER); + if (wp->yoff != 0 && + py == wp->yoff - 1 && + px > wp->sx / 2) + return (SCREEN_REDRAW_BORDER); + } else { + if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { + if (wp->yoff != 0 && py == wp->yoff - 1) + return (SCREEN_REDRAW_BORDER); + if (py == ey) + return (SCREEN_REDRAW_BORDER); + } + } + } else if (pane_status == PANE_STATUS_TOP) { + if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { + if (wp->yoff != 0 && py == wp->yoff - 1) + return (SCREEN_REDRAW_BORDER); + } + } else { + if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { + if (py == ey) + return (SCREEN_REDRAW_BORDER); + } } /* Outside pane. */ - return (-1); + return (SCREEN_REDRAW_OUTSIDE); } -/* Check if a cell is on the pane border. */ +/* Check if a cell is on a border. */ static int -screen_redraw_cell_border(struct client *c, u_int px, u_int py) +screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status) { struct window *w = c->session->curw->window; struct window_pane *wp; - int retval; + + /* Outside the window? */ + if (px > w->sx || py > w->sy) + return (0); + + /* On the window border? */ + if (px == w->sx || py == w->sy) + return (1); /* Check all the panes. */ TAILQ_FOREACH(wp, &w->panes, entry) { if (!window_pane_visible(wp)) continue; - if ((retval = screen_redraw_cell_border1(wp, px, py)) != -1) - return (!!retval); + switch (screen_redraw_pane_border(wp, px, py, pane_status)) { + case SCREEN_REDRAW_INSIDE: + return (0); + case SCREEN_REDRAW_BORDER: + return (1); + case SCREEN_REDRAW_OUTSIDE: + break; + } } return (0); } +/* Work out type of border cell from surrounding cells. */ +static int +screen_redraw_type_of_cell(struct client *c, u_int px, u_int py, + int pane_status) +{ + struct window *w = c->session->curw->window; + u_int sx = w->sx, sy = w->sy; + int borders = 0; + + /* + * Construct a bitmask of whether the cells to the left (bit 4), right, + * top, and bottom (bit 1) of this cell are borders. + */ + if (px == 0 || screen_redraw_cell_border(c, px - 1, py, pane_status)) + borders |= 8; + if (px <= sx && screen_redraw_cell_border(c, px + 1, py, pane_status)) + borders |= 4; + if (pane_status == PANE_STATUS_TOP) { + if (py != 0 && + screen_redraw_cell_border(c, px, py - 1, pane_status)) + borders |= 2; + } else { + if (py == 0 || + screen_redraw_cell_border(c, px, py - 1, pane_status)) + borders |= 2; + } + if (py <= sy && screen_redraw_cell_border(c, px, py + 1, pane_status)) + borders |= 1; + + /* + * Figure out what kind of border this cell is. Only one bit set + * doesn't make sense (can't have a border cell with no others + * connected). + */ + switch (borders) { + case 15: /* 1111, left right top bottom */ + return (CELL_JOIN); + case 14: /* 1110, left right top */ + return (CELL_BOTTOMJOIN); + case 13: /* 1101, left right bottom */ + return (CELL_TOPJOIN); + case 12: /* 1100, left right */ + return (CELL_TOPBOTTOM); + case 11: /* 1011, left top bottom */ + return (CELL_RIGHTJOIN); + case 10: /* 1010, left top */ + return (CELL_BOTTOMRIGHT); + case 9: /* 1001, left bottom */ + return (CELL_TOPRIGHT); + case 7: /* 0111, right top bottom */ + return (CELL_LEFTJOIN); + case 6: /* 0110, right top */ + return (CELL_BOTTOMLEFT); + case 5: /* 0101, right bottom */ + return (CELL_TOPLEFT); + case 3: /* 0011, top bottom */ + return (CELL_LEFTRIGHT); + } + return (CELL_OUTSIDE); +} + /* Check if cell inside a pane. */ static int screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, @@ -100,18 +243,21 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, { struct window *w = c->session->curw->window; struct window_pane *wp; - int borders; + int border; u_int right, line; *wpp = NULL; if (px > w->sx || py > w->sy) return (CELL_OUTSIDE); + if (px == w->sx || py == w->sy) /* window border */ + return (screen_redraw_type_of_cell(c, px, py, pane_status)); if (pane_status != PANE_STATUS_OFF) { - TAILQ_FOREACH(wp, &w->panes, entry) { + wp = w->active; + do { if (!window_pane_visible(wp)) - continue; + goto next1; if (pane_status == PANE_STATUS_TOP) line = wp->yoff - 1; @@ -121,129 +267,51 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, if (py == line && px >= wp->xoff + 2 && px <= right) return (CELL_INSIDE); - } + + next1: + wp = TAILQ_NEXT(wp, entry); + if (wp == NULL) + wp = TAILQ_FIRST(&w->panes); + } while (wp != w->active); } - TAILQ_FOREACH(wp, &w->panes, entry) { + wp = w->active; + do { if (!window_pane_visible(wp)) - continue; + goto next2; *wpp = wp; - /* If outside the pane and its border, skip it. */ - if ((wp->xoff != 0 && px < wp->xoff - 1) || - px > wp->xoff + wp->sx || - (wp->yoff != 0 && py < wp->yoff - 1) || - py > wp->yoff + wp->sy) - continue; - - /* If definitely inside, return so. */ - if (!screen_redraw_cell_border(c, px, py)) - return (CELL_INSIDE); - /* - * Construct a bitmask of whether the cells to the left (bit - * 4), right, top, and bottom (bit 1) of this cell are borders. + * If definitely inside, return. If not on border, skip. + * Otherwise work out the cell. */ - borders = 0; - if (px == 0 || screen_redraw_cell_border(c, px - 1, py)) - borders |= 8; - if (px <= w->sx && screen_redraw_cell_border(c, px + 1, py)) - borders |= 4; - if (pane_status == PANE_STATUS_TOP) { - if (py != 0 && screen_redraw_cell_border(c, px, py - 1)) - borders |= 2; - } else { - if (py == 0 || screen_redraw_cell_border(c, px, py - 1)) - borders |= 2; - } - if (py <= w->sy && screen_redraw_cell_border(c, px, py + 1)) - borders |= 1; + border = screen_redraw_pane_border(wp, px, py, pane_status); + if (border == SCREEN_REDRAW_INSIDE) + return (CELL_INSIDE); + if (border == SCREEN_REDRAW_OUTSIDE) + goto next2; + return (screen_redraw_type_of_cell(c, px, py, pane_status)); - /* - * Figure out what kind of border this cell is. Only one bit - * set doesn't make sense (can't have a border cell with no - * others connected). - */ - switch (borders) { - case 15: /* 1111, left right top bottom */ - return (CELL_JOIN); - case 14: /* 1110, left right top */ - return (CELL_BOTTOMJOIN); - case 13: /* 1101, left right bottom */ - return (CELL_TOPJOIN); - case 12: /* 1100, left right */ - return (CELL_TOPBOTTOM); - case 11: /* 1011, left top bottom */ - return (CELL_RIGHTJOIN); - case 10: /* 1010, left top */ - return (CELL_BOTTOMRIGHT); - case 9: /* 1001, left bottom */ - return (CELL_TOPRIGHT); - case 7: /* 0111, right top bottom */ - return (CELL_LEFTJOIN); - case 6: /* 0110, right top */ - return (CELL_BOTTOMLEFT); - case 5: /* 0101, right bottom */ - return (CELL_TOPLEFT); - case 3: /* 0011, top bottom */ - return (CELL_LEFTRIGHT); - } - } + next2: + wp = TAILQ_NEXT(wp, entry); + if (wp == NULL) + wp = TAILQ_FIRST(&w->panes); + } while (wp != w->active); return (CELL_OUTSIDE); } /* Check if the border of a particular pane. */ static int -screen_redraw_check_is(u_int px, u_int py, int type, int pane_status, - struct window *w, struct window_pane *wantwp, struct window_pane *wp) +screen_redraw_check_is(u_int px, u_int py, int pane_status, + struct window_pane *wp) { - int border; - - /* Is this off the active pane border? */ - border = screen_redraw_cell_border1(wantwp, px, py); - if (border == 0 || border == -1) - return (0); - if (pane_status == PANE_STATUS_TOP && border == 4) - return (0); - if (pane_status == PANE_STATUS_BOTTOM && border == 3) - return (0); - - /* If there are more than two panes, that's enough. */ - if (window_count_panes(w) != 2) - return (1); + enum screen_redraw_border_type border; - /* Else if the cell is not a border cell, forget it. */ - if (wp == NULL || (type == CELL_OUTSIDE || type == CELL_INSIDE)) + border = screen_redraw_pane_border(wp, px, py, pane_status); + if (border == SCREEN_REDRAW_BORDER) return (1); - - /* With status lines mark the entire line. */ - if (pane_status != PANE_STATUS_OFF) - return (1); - - /* Check if the pane covers the whole width. */ - if (wp->xoff == 0 && wp->sx == w->sx) { - /* This can either be the top pane or the bottom pane. */ - if (wp->yoff == 0) { /* top pane */ - if (wp == wantwp) - return (px <= wp->sx / 2); - return (px > wp->sx / 2); - } - return (0); - } - - /* Check if the pane covers the whole height. */ - if (wp->yoff == 0 && wp->sy == w->sy) { - /* This can either be the left pane or the right pane. */ - if (wp->xoff == 0) { /* left pane */ - if (wp == wantwp) - return (py <= wp->sy / 2); - return (py > wp->sy / 2); - } - return (0); - } - - return (1); + return (0); } /* Update pane status. */ @@ -259,16 +327,15 @@ screen_redraw_make_pane_status(struct client *c, struct window *w, struct screen_write_ctx ctx; struct screen old; + ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS); + format_defaults(ft, c, c->session, c->session->curw, wp); + if (wp == w->active) - style_apply(&gc, w->options, "pane-active-border-style"); + style_apply(&gc, w->options, "pane-active-border-style", ft); else - style_apply(&gc, w->options, "pane-border-style"); - + style_apply(&gc, w->options, "pane-border-style", ft); fmt = options_get_string(w->options, "pane-border-format"); - ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS); - format_defaults(ft, c, NULL, NULL, wp); - expanded = format_expand_time(ft, fmt); if (wp->sx < 4) wp->status_size = width = 0; @@ -482,39 +549,73 @@ screen_redraw_pane(struct client *c, struct window_pane *wp) tty_reset(&c->tty); } +/* Get border cell style. */ +static const struct grid_cell * +screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x, + u_int y, struct window_pane *wp) +{ + struct client *c = ctx->c; + struct session *s = c->session; + struct window *w = s->curw->window; + struct options *oo = w->options; + struct grid_cell *gc; + struct format_tree *ft; + + if (wp->border_gc_set) + return (&wp->border_gc); + wp->border_gc_set = 1; + + ft = format_create_defaults(NULL, c, s, s->curw, wp); + gc = &wp->border_gc; + + if (screen_redraw_check_is(x, y, ctx->pane_status, w->active)) { + style_apply(gc, oo, "pane-active-border-style", ft); + gc->attr |= GRID_ATTR_CHARSET; + } else { + style_apply(gc, oo, "pane-border-style", ft); + gc->attr |= GRID_ATTR_CHARSET; + } + + format_free(ft); + return (gc); +} + /* Draw a border cell. */ static void -screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j, - struct grid_cell *m_active_gc, struct grid_cell *active_gc, - struct grid_cell *m_other_gc, struct grid_cell *other_gc) +screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) { struct client *c = ctx->c; struct session *s = c->session; - struct window *w = s->curw->window; struct tty *tty = &c->tty; struct window_pane *wp; - struct window_pane *active = w->active; - struct window_pane *marked = marked_pane.wp; u_int type, x = ctx->ox + i, y = ctx->oy + j; - int flag, pane_status = ctx->pane_status; + int pane_status = ctx->pane_status; + const struct grid_cell *gc; + struct grid_cell copy; if (c->overlay_check != NULL && !c->overlay_check(c, x, y)) return; + type = screen_redraw_check_cell(c, x, y, pane_status, &wp); if (type == CELL_INSIDE) return; - flag = screen_redraw_check_is(x, y, type, pane_status, w, active, wp); - if (server_is_marked(s, s->curw, marked_pane.wp) && - screen_redraw_check_is(x, y, type, pane_status, w, marked, wp)) { - if (flag) - tty_attributes(tty, m_active_gc, NULL); - else - tty_attributes(tty, m_other_gc, NULL); - } else if (flag) - tty_attributes(tty, active_gc, NULL); - else - tty_attributes(tty, other_gc, NULL); + if (wp == NULL) + gc = &screen_redraw_border_cell; + else { + gc = screen_redraw_draw_borders_style(ctx, x, y, wp); + if (gc == NULL) + return; + + if (server_is_marked(s, s->curw, marked_pane.wp) && + screen_redraw_check_is(x, y, pane_status, marked_pane.wp)) { + memcpy(©, gc, sizeof copy); + copy.attr ^= GRID_ATTR_REVERSE; + gc = © + } + } + + tty_attributes(tty, gc, NULL); if (ctx->statustop) tty_cursor(tty, i, ctx->statuslines + j); else @@ -529,27 +630,17 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx) struct client *c = ctx->c; struct session *s = c->session; struct window *w = s->curw->window; - struct tty *tty = &c->tty; - struct options *oo = w->options; - struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc; + struct window_pane *wp; u_int i, j; log_debug("%s: %s @%u", __func__, c->name, w->id); - style_apply(&other_gc, oo, "pane-border-style"); - style_apply(&active_gc, oo, "pane-active-border-style"); - active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET; - - memcpy(&m_other_gc, &other_gc, sizeof m_other_gc); - m_other_gc.attr ^= GRID_ATTR_REVERSE; - memcpy(&m_active_gc, &active_gc, sizeof m_active_gc); - m_active_gc.attr ^= GRID_ATTR_REVERSE; + TAILQ_FOREACH(wp, &w->panes, entry) + wp->border_gc_set = 0; - for (j = 0; j < tty->sy - ctx->statuslines; j++) { - for (i = 0; i < tty->sx; i++) { - screen_redraw_draw_borders_cell(ctx, i, j, - &m_active_gc, &active_gc, &m_other_gc, &other_gc); - } + for (j = 0; j < c->tty.sy - ctx->statuslines; j++) { + for (i = 0; i < c->tty.sx; i++) + screen_redraw_draw_borders_cell(ctx, i, j); } } diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c index 6715d0f1944..027d5e8cf8e 100644 --- a/usr.bin/tmux/status.c +++ b/usr.bin/tmux/status.c @@ -1,4 +1,4 @@ -/* $OpenBSD: status.c,v 1.202 2020/03/12 09:49:43 nicm Exp $ */ +/* $OpenBSD: status.c,v 1.203 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -321,7 +321,7 @@ status_redraw(struct client *c) struct screen_write_ctx ctx; struct grid_cell gc; u_int lines, i, n, width = c->tty.sx; - int flags, force = 0, changed = 0; + int flags, force = 0, changed = 0, fg, bg; struct options_entry *o; union options_value *ov; struct format_tree *ft; @@ -339,7 +339,13 @@ status_redraw(struct client *c) return (1); /* Set up default colour. */ - style_apply(&gc, s->options, "status-style"); + style_apply(&gc, s->options, "status-style", NULL); + fg = options_get_number(s->options, "status-fg"); + if (fg != 8) + gc.fg = fg; + bg = options_get_number(s->options, "status-bg"); + if (bg != 8) + gc.bg = bg; if (!grid_cells_equal(&gc, &sl->style)) { force = 1; memcpy(&sl->style, &gc, sizeof sl->style); @@ -490,7 +496,7 @@ status_message_redraw(struct client *c) if (len > c->tty.sx) len = c->tty.sx; - style_apply(&gc, s->options, "message-style"); + style_apply(&gc, s->options, "message-style", NULL); screen_write_start(&ctx, NULL, sl->active); screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); @@ -633,9 +639,9 @@ status_prompt_redraw(struct client *c) screen_init(sl->active, c->tty.sx, lines, 0); if (c->prompt_mode == PROMPT_COMMAND) - style_apply(&gc, s->options, "message-command-style"); + style_apply(&gc, s->options, "message-command-style", NULL); else - style_apply(&gc, s->options, "message-style"); + style_apply(&gc, s->options, "message-style", NULL); memcpy(&cursorgc, &gc, sizeof cursorgc); cursorgc.attr ^= GRID_ATTR_REVERSE; diff --git a/usr.bin/tmux/style.c b/usr.bin/tmux/style.c index 36cb44c48ff..e2f28ffab0d 100644 --- a/usr.bin/tmux/style.c +++ b/usr.bin/tmux/style.c @@ -1,4 +1,4 @@ -/* $OpenBSD: style.c,v 1.26 2020/05/16 14:53:23 nicm Exp $ */ +/* $OpenBSD: style.c,v 1.27 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -260,17 +260,37 @@ style_tostring(struct style *sy) return (s); } -/* Apply a style. */ +/* Apply a style on top of the given style. */ void -style_apply(struct grid_cell *gc, struct options *oo, const char *name) +style_add(struct grid_cell *gc, struct options *oo, const char *name, + struct format_tree *ft) { - struct style *sy; + struct style *sy; + struct format_tree *ft0 = NULL; - memcpy(gc, &grid_default_cell, sizeof *gc); - sy = options_get_style(oo, name); - gc->fg = sy->gc.fg; - gc->bg = sy->gc.bg; + if (ft == NULL) + ft = ft0 = format_create(NULL, NULL, 0, FORMAT_NOJOBS); + + sy = options_string_to_style(oo, name, ft); + if (sy == NULL) + sy = &style_default; + if (sy->gc.fg != 8) + gc->fg = sy->gc.fg; + if (sy->gc.bg != 8) + gc->bg = sy->gc.bg; gc->attr |= sy->gc.attr; + + if (ft0 != NULL) + format_free(ft0); +} + +/* Apply a style on top of the default style. */ +void +style_apply(struct grid_cell *gc, struct options *oo, const char *name, + struct format_tree *ft) +{ + memcpy(gc, &grid_default_cell, sizeof *gc); + style_add(gc, oo, name, ft); } /* Initialize style from cell. */ diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 7aaaf3c622b..e9905511d33 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1024 2020/05/16 14:53:23 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1025 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -896,6 +896,9 @@ struct window_pane { u_int xoff; u_int yoff; + int fg; + int bg; + int flags; #define PANE_REDRAW 0x1 #define PANE_DROP 0x2 @@ -950,6 +953,9 @@ struct window_pane { size_t written; size_t skipped; + int border_gc_set; + struct grid_cell border_gc; + TAILQ_ENTRY(window_pane) entry; RB_ENTRY(window_pane) tree_entry; }; @@ -1662,7 +1668,6 @@ enum options_table_type { OPTIONS_TABLE_COLOUR, OPTIONS_TABLE_FLAG, OPTIONS_TABLE_CHOICE, - OPTIONS_TABLE_STYLE, OPTIONS_TABLE_COMMAND }; @@ -1674,12 +1679,13 @@ enum options_table_type { #define OPTIONS_TABLE_IS_ARRAY 0x1 #define OPTIONS_TABLE_IS_HOOK 0x2 +#define OPTIONS_TABLE_IS_STYLE 0x4 struct options_table_entry { const char *name; enum options_table_type type; int scope; - int flags; + int flags; u_int minimum; u_int maximum; @@ -1718,7 +1724,7 @@ struct spawn_context { const char *name; char **argv; int argc; - struct environ *environ; + struct environ *environ; int idx; const char *cwd; @@ -1898,18 +1904,17 @@ struct options_entry *options_match_get(struct options *, const char *, int *, int, int *); const char *options_get_string(struct options *, const char *); long long options_get_number(struct options *, const char *); -struct style *options_get_style(struct options *, const char *); struct options_entry * printflike(4, 5) options_set_string(struct options *, const char *, int, const char *, ...); struct options_entry *options_set_number(struct options *, const char *, long long); -struct options_entry *options_set_style(struct options *, const char *, int, - const char *); int options_scope_from_name(struct args *, int, const char *, struct cmd_find_state *, struct options **, char **); int options_scope_from_flags(struct args *, int, struct cmd_find_state *, struct options **, char **); +struct style *options_string_to_style(struct options *, const char *, + struct format_tree *); /* options-table.c */ extern const struct options_table_entry options_table[]; @@ -2136,7 +2141,7 @@ enum cmd_retval cmd_attach_session(struct cmdq_item *, const char *, int, int, int, const char *, int); /* cmd-parse.c */ -void cmd_parse_empty(struct cmd_parse_input *); +void cmd_parse_empty(struct cmd_parse_input *); struct cmd_parse_result *cmd_parse_from_file(FILE *, struct cmd_parse_input *); struct cmd_parse_result *cmd_parse_from_string(const char *, struct cmd_parse_input *); @@ -2227,8 +2232,8 @@ void file_fire_done(struct client_file *); void file_fire_read(struct client_file *); int file_can_print(struct client *); void printflike(2, 3) file_print(struct client *, const char *, ...); -void file_vprint(struct client *, const char *, va_list); -void file_print_buffer(struct client *, void *, size_t); +void file_vprint(struct client *, const char *, va_list); +void file_print_buffer(struct client *, void *, size_t); void printflike(2, 3) file_error(struct client *, const char *, ...); void file_write(struct client *, const char *, int, const void *, size_t, client_file_cb, void *); @@ -2726,7 +2731,7 @@ struct session *session_find_by_id_str(const char *); struct session *session_find_by_id(u_int); struct session *session_create(const char *, const char *, const char *, struct environ *, struct options *, struct termios *); -void session_destroy(struct session *, int, const char *); +void session_destroy(struct session *, int, const char *); void session_add_ref(struct session *, const char *); void session_remove_ref(struct session *, const char *); char *session_check_name(const char *); @@ -2795,7 +2800,7 @@ struct menu *menu_create(const char *); void menu_add_items(struct menu *, const struct menu_item *, struct cmdq_item *, struct client *, struct cmd_find_state *); -void menu_add_item(struct menu *, const struct menu_item *, +void menu_add_item(struct menu *, const struct menu_item *, struct cmdq_item *, struct client *, struct cmd_find_state *); void menu_free(struct menu *); @@ -2818,8 +2823,10 @@ int popup_display(int, struct cmdq_item *, u_int, u_int, u_int, int style_parse(struct style *,const struct grid_cell *, const char *); const char *style_tostring(struct style *); +void style_add(struct grid_cell *, struct options *, + const char *, struct format_tree *); void style_apply(struct grid_cell *, struct options *, - const char *); + const char *, struct format_tree *); void style_set(struct style *, const struct grid_cell *); void style_copy(struct style *, struct style *); diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index 6c3735fd86b..c96d1131fe6 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.370 2020/05/16 14:53:23 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.371 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -2687,6 +2687,14 @@ tty_try_colour(struct tty *tty, int colour, const char *type) } static void +tty_window_default_style(struct grid_cell *gc, struct window_pane *wp) +{ + memcpy(gc, &grid_default_cell, sizeof *gc); + gc->fg = wp->fg; + gc->bg = wp->bg; +} + +static void tty_default_colours(struct grid_cell *gc, struct window_pane *wp) { struct options *oo = wp->options; @@ -2694,8 +2702,12 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) if (wp->flags & PANE_STYLECHANGED) { wp->flags &= ~PANE_STYLECHANGED; - style_apply(&wp->cached_active_gc, oo, "window-active-style"); - style_apply(&wp->cached_gc, oo, "window-style"); + + tty_window_default_style(&wp->cached_active_gc, wp); + style_add(&wp->cached_active_gc, oo, "window-active-style", + NULL); + tty_window_default_style(&wp->cached_gc, wp); + style_add(&wp->cached_gc, oo, "window-style", NULL); } if (gc->fg == 8) { diff --git a/usr.bin/tmux/window-copy.c b/usr.bin/tmux/window-copy.c index 96b8e3c0f0d..b3af78aeec3 100644 --- a/usr.bin/tmux/window-copy.c +++ b/usr.bin/tmux/window-copy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-copy.c,v 1.280 2020/05/16 14:22:51 nicm Exp $ */ +/* $OpenBSD: window-copy.c,v 1.281 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -3004,7 +3004,7 @@ window_copy_write_line(struct window_mode_entry *wme, size_t size = 0; u_int hsize = screen_hsize(data->backing); - style_apply(&gc, oo, "mode-style"); + style_apply(&gc, oo, "mode-style", NULL); gc.flags |= GRID_FLAG_NOPALETTE; if (py == 0 && s->rupper < s->rlower && !data->hide_position) { @@ -3311,7 +3311,7 @@ window_copy_set_selection(struct window_mode_entry *wme, int may_redraw, } /* Set colours and selection. */ - style_apply(&gc, oo, "mode-style"); + style_apply(&gc, oo, "mode-style", NULL); gc.flags |= GRID_FLAG_NOPALETTE; screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag, data->modekeys, &gc); diff --git a/usr.bin/tmux/window.c b/usr.bin/tmux/window.c index 2e4506ab8eb..43fa4d93072 100644 --- a/usr.bin/tmux/window.c +++ b/usr.bin/tmux/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.258 2020/05/16 14:53:23 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.259 2020/05/16 15:01:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -865,6 +865,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->fd = -1; wp->event = NULL; + wp->fg = 8; + wp->bg = 8; + TAILQ_INIT(&wp->modes); wp->layout_cell = NULL; @@ -1096,6 +1099,7 @@ window_pane_set_mode(struct window_pane *wp, struct window_pane *swp, wp->screen = wme->screen; wp->flags |= (PANE_REDRAW|PANE_CHANGED); + server_redraw_window_borders(wp->window); server_status_window(wp->window); notify_pane("pane-mode-changed", wp); @@ -1127,6 +1131,7 @@ window_pane_reset_mode(struct window_pane *wp) } wp->flags |= (PANE_REDRAW|PANE_CHANGED); + server_redraw_window_borders(wp->window); server_status_window(wp->window); notify_pane("pane-mode-changed", wp); } |