From f1828921dfed4b7f2ba38b8c4a370b42965c404c Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 23 Feb 2014 00:53:06 +0000 Subject: [PATCH 01/24] Change terminal-overrides to a server option (now that we have them), it doesn't make much sense as a session option. --- cmd-attach-session.c | 2 +- cmd-new-session.c | 2 +- options-table.c | 16 +++++----- server-client.c | 8 ++--- tmux.1 | 72 ++++++++++++++++++++++---------------------- tmux.h | 6 ++-- tty-term.c | 7 +++-- tty.c | 4 +-- 8 files changed, 58 insertions(+), 59 deletions(-) diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 6fb83d20..94f01e4c 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -132,7 +132,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, server_redraw_client(cmdq->client); s->curw->flags &= ~WINLINK_ALERTFLAGS; } else { - if (server_client_open(cmdq->client, s, &cause) != 0) { + if (server_client_open(cmdq->client, &cause) != 0) { cmdq_error(cmdq, "open terminal failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); diff --git a/cmd-new-session.c b/cmd-new-session.c index bf843cad..db8416e0 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -145,7 +145,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) /* Open the terminal if necessary. */ if (!detached && !already_attached) { - if (server_client_open(c, NULL, &cause) != 0) { + if (server_client_open(c, &cause) != 0) { cmdq_error(cmdq, "open terminal failed: %s", cause); free(cause); goto error; diff --git a/options-table.c b/options-table.c index ec1d3680..ea848259 100644 --- a/options-table.c +++ b/options-table.c @@ -91,6 +91,14 @@ const struct options_table_entry server_options_table[] = { .default_num = 1 }, + { .name = "terminal-overrides", + .type = OPTIONS_TABLE_STRING, + .default_str = "*256col*:colors=256" + ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" + ":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007" + ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT" + }, + { .name = NULL } }; @@ -466,14 +474,6 @@ const struct options_table_entry session_options_table[] = { .default_num = 0 /* overridden in main() */ }, - { .name = "terminal-overrides", - .type = OPTIONS_TABLE_STRING, - .default_str = "*256col*:colors=256" - ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" - ":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007" - ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT" - }, - { .name = "update-environment", .type = OPTIONS_TABLE_STRING, .default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID " diff --git a/server-client.c b/server-client.c index ed8159f5..35df7531 100644 --- a/server-client.c +++ b/server-client.c @@ -114,11 +114,8 @@ server_client_create(int fd) /* Open client terminal if needed. */ int -server_client_open(struct client *c, struct session *s, char **cause) +server_client_open(struct client *c, char **cause) { - struct options *oo = s != NULL ? &s->options : &global_s_options; - char *overrides; - if (c->flags & CLIENT_CONTROL) return (0); @@ -127,8 +124,7 @@ server_client_open(struct client *c, struct session *s, char **cause) return (-1); } - overrides = options_get_string(oo, "terminal-overrides"); - if (tty_open(&c->tty, overrides, cause) != 0) + if (tty_open(&c->tty, cause) != 0) return (-1); return (0); diff --git a/tmux.1 b/tmux.1 index c0f04094..ba4c8537 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2161,6 +2161,42 @@ disallowedWindowOps: 20,21,SetXprop Or changing this property from the .Xr xterm 1 interactive menu when required. +.It Ic terminal-overrides Ar string +Contains a list of entries which override terminal descriptions read using +.Xr terminfo 5 . +.Ar string +is a comma-separated list of items each a colon-separated string made up of a +terminal type pattern (matched using +.Xr fnmatch 3 ) +and a set of +.Em name=value +entries. +.Pp +For example, to set the +.Ql clear +.Xr terminfo 5 +entry to +.Ql \ee[H\ee[2J +for all terminal types and the +.Ql dch1 +entry to +.Ql \ee[P +for the +.Ql rxvt +terminal type, the option could be set to the string: +.Bd -literal -offset indent +"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P" +.Ed +.Pp +The terminal entry value is passed through +.Xr strunvis 3 +before interpretation. +The default value forcibly corrects the +.Ql colors +entry for terminals which support 256 colours: +.Bd -literal -offset indent +"*256col*:colors=256,xterm*:XT" +.Ed .El .Pp Available session options are: @@ -2605,42 +2641,6 @@ and .Ic status-right strings as UTF-8; notably, this is important for wide characters. This option defaults to off. -.It Ic terminal-overrides Ar string -Contains a list of entries which override terminal descriptions read using -.Xr terminfo 5 . -.Ar string -is a comma-separated list of items each a colon-separated string made up of a -terminal type pattern (matched using -.Xr fnmatch 3 ) -and a set of -.Em name=value -entries. -.Pp -For example, to set the -.Ql clear -.Xr terminfo 5 -entry to -.Ql \ee[H\ee[2J -for all terminal types and the -.Ql dch1 -entry to -.Ql \ee[P -for the -.Ql rxvt -terminal type, the option could be set to the string: -.Bd -literal -offset indent -"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P" -.Ed -.Pp -The terminal entry value is passed through -.Xr strunvis 3 -before interpretation. -The default value forcibly corrects the -.Ql colors -entry for terminals which support 256 colours: -.Bd -literal -offset indent -"*256col*:colors=256,xterm*:XT" -.Ed .It Ic update-environment Ar variables Set a space-separated string containing a list of environment variables to be copied into the session environment when a new session is created or an diff --git a/tmux.h b/tmux.h index c6919622..5801b35e 100644 --- a/tmux.h +++ b/tmux.h @@ -1650,7 +1650,7 @@ void tty_set_title(struct tty *, const char *); void tty_update_mode(struct tty *, int, struct screen *); void tty_force_cursor_colour(struct tty *, const char *); void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int); -int tty_open(struct tty *, const char *, char **); +int tty_open(struct tty *, char **); void tty_close(struct tty *); void tty_free(struct tty *); void tty_write( @@ -1679,7 +1679,7 @@ void tty_bell(struct tty *); /* tty-term.c */ extern struct tty_terms tty_terms; extern const struct tty_term_code_entry tty_term_codes[NTTYCODE]; -struct tty_term *tty_term_find(char *, int, const char *, char **); +struct tty_term *tty_term_find(char *, int, char **); void tty_term_free(struct tty_term *); int tty_term_has(struct tty_term *, enum tty_code_code); const char *tty_term_string(struct tty_term *, enum tty_code_code); @@ -1893,7 +1893,7 @@ void server_add_accept(int); /* server-client.c */ void server_client_handle_key(struct client *, int); void server_client_create(int); -int server_client_open(struct client *, struct session *, char **); +int server_client_open(struct client *, char **); void server_client_lost(struct client *); void server_client_callback(int, short, void *); void server_client_status_timer(void); diff --git a/tty-term.c b/tty-term.c index 8644a845..a66aad83 100644 --- a/tty-term.c +++ b/tty-term.c @@ -305,7 +305,7 @@ tty_term_override(struct tty_term *term, const char *overrides) } struct tty_term * -tty_term_find(char *name, int fd, const char *overrides, char **cause) +tty_term_find(char *name, int fd, char **cause) { struct tty_term *term; const struct tty_term_code_entry *ent; @@ -383,7 +383,10 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause) break; } } - tty_term_override(term, overrides); + + /* Apply terminal overrides. */ + s = options_get_string(&global_options, "terminal-overrides"); + tty_term_override(term, s); /* Delete curses data. */ del_curterm(cur_term); diff --git a/tty.c b/tty.c index 20b7070a..b545dc33 100644 --- a/tty.c +++ b/tty.c @@ -128,7 +128,7 @@ tty_set_size(struct tty *tty, u_int sx, u_int sy) { } int -tty_open(struct tty *tty, const char *overrides, char **cause) +tty_open(struct tty *tty, char **cause) { char out[64]; int fd; @@ -141,7 +141,7 @@ tty_open(struct tty *tty, const char *overrides, char **cause) tty->log_fd = fd; } - tty->term = tty_term_find(tty->termname, tty->fd, overrides, cause); + tty->term = tty_term_find(tty->termname, tty->fd, cause); if (tty->term == NULL) { tty_close(tty); return (-1); From 04f469a3245c528abc7865841d51bc0d222a94f9 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:32:00 +0000 Subject: [PATCH 02/24] Change secondary device attributes response to \033[>84;0;0c which is unique for tmux. --- input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.c b/input.c index 58064ddd..40c9d225 100644 --- a/input.c +++ b/input.c @@ -1147,7 +1147,7 @@ input_csi_dispatch(struct input_ctx *ictx) case INPUT_CSI_DA_TWO: switch (input_get(ictx, 0, 0, 0)) { case 0: - input_reply(ictx, "\033[>0;95;0c"); + input_reply(ictx, "\033[>84;0;0c"); break; default: log_debug("%s: unknown '%c'", __func__, ictx->ch); From 18cb13521840f678290b0a78d4e058c92795fabb Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:32:31 +0000 Subject: [PATCH 03/24] Don't write into buffer if no arguments, reported by Filipe Rosset. --- cmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd.c b/cmd.c index fe55109b..62f4c73d 100644 --- a/cmd.c +++ b/cmd.c @@ -139,6 +139,9 @@ cmd_pack_argv(int argc, char **argv, char *buf, size_t len) size_t arglen; int i; + if (argc == 0) + return (0); + *buf = '\0'; for (i = 0; i < argc; i++) { if (strlcpy(buf, argv[i], len) >= len) From 175f215187b1c978ca4cc4988a78d067122e2b0c Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:34:08 +0000 Subject: [PATCH 04/24] Having three *clock* files is ridiculous, remove clock.c. --- Makefile | 1 - clock.c | 166 ------------------------------------------------ screen-redraw.c | 2 +- tmux.h | 5 +- window-clock.c | 143 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 143 insertions(+), 174 deletions(-) delete mode 100644 clock.c diff --git a/Makefile b/Makefile index e566bb2a..63363f51 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,6 @@ SRCS= arguments.c \ attributes.c \ cfg.c \ client.c \ - clock.c \ cmd-attach-session.c \ cmd-bind-key.c \ cmd-break-pane.c \ diff --git a/clock.c b/clock.c deleted file mode 100644 index 283a4a1e..00000000 --- a/clock.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2009 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include -#include - -#include "tmux.h" - -const char clock_table[14][5][5] = { - { { 1,1,1,1,1 }, /* 0 */ - { 1,0,0,0,1 }, - { 1,0,0,0,1 }, - { 1,0,0,0,1 }, - { 1,1,1,1,1 } }, - { { 0,0,0,0,1 }, /* 1 */ - { 0,0,0,0,1 }, - { 0,0,0,0,1 }, - { 0,0,0,0,1 }, - { 0,0,0,0,1 } }, - { { 1,1,1,1,1 }, /* 2 */ - { 0,0,0,0,1 }, - { 1,1,1,1,1 }, - { 1,0,0,0,0 }, - { 1,1,1,1,1 } }, - { { 1,1,1,1,1 }, /* 3 */ - { 0,0,0,0,1 }, - { 1,1,1,1,1 }, - { 0,0,0,0,1 }, - { 1,1,1,1,1 } }, - { { 1,0,0,0,1 }, /* 4 */ - { 1,0,0,0,1 }, - { 1,1,1,1,1 }, - { 0,0,0,0,1 }, - { 0,0,0,0,1 } }, - { { 1,1,1,1,1 }, /* 5 */ - { 1,0,0,0,0 }, - { 1,1,1,1,1 }, - { 0,0,0,0,1 }, - { 1,1,1,1,1 } }, - { { 1,1,1,1,1 }, /* 6 */ - { 1,0,0,0,0 }, - { 1,1,1,1,1 }, - { 1,0,0,0,1 }, - { 1,1,1,1,1 } }, - { { 1,1,1,1,1 }, /* 7 */ - { 0,0,0,0,1 }, - { 0,0,0,0,1 }, - { 0,0,0,0,1 }, - { 0,0,0,0,1 } }, - { { 1,1,1,1,1 }, /* 8 */ - { 1,0,0,0,1 }, - { 1,1,1,1,1 }, - { 1,0,0,0,1 }, - { 1,1,1,1,1 } }, - { { 1,1,1,1,1 }, /* 9 */ - { 1,0,0,0,1 }, - { 1,1,1,1,1 }, - { 0,0,0,0,1 }, - { 1,1,1,1,1 } }, - { { 0,0,0,0,0 }, /* : */ - { 0,0,1,0,0 }, - { 0,0,0,0,0 }, - { 0,0,1,0,0 }, - { 0,0,0,0,0 } }, - { { 1,1,1,1,1 }, /* A */ - { 1,0,0,0,1 }, - { 1,1,1,1,1 }, - { 1,0,0,0,1 }, - { 1,0,0,0,1 } }, - { { 1,1,1,1,1 }, /* P */ - { 1,0,0,0,1 }, - { 1,1,1,1,1 }, - { 1,0,0,0,0 }, - { 1,0,0,0,0 } }, - { { 1,0,0,0,1 }, /* M */ - { 1,1,0,1,1 }, - { 1,0,1,0,1 }, - { 1,0,0,0,1 }, - { 1,0,0,0,1 } }, -}; - -void -clock_draw(struct screen_write_ctx *ctx, int colour, int style) -{ - struct screen *s = ctx->s; - struct grid_cell gc; - char tim[64], *ptr; - time_t t; - struct tm *tm; - u_int i, j, x, y, idx; - - t = time(NULL); - tm = localtime(&t); - if (style == 0) { - strftime(tim, sizeof tim, "%l:%M ", localtime(&t)); - if (tm->tm_hour >= 12) - strlcat(tim, "PM", sizeof tim); - else - strlcat(tim, "AM", sizeof tim); - } else - strftime(tim, sizeof tim, "%H:%M", tm); - - - screen_write_clearscreen(ctx); - - if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { - if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { - x = (screen_size_x(s) / 2) - (strlen(tim) / 2); - y = screen_size_y(s) / 2; - screen_write_cursormove(ctx, x, y); - - memcpy(&gc, &grid_default_cell, sizeof gc); - colour_set_fg(&gc, colour); - screen_write_puts(ctx, &gc, "%s", tim); - } - return; - } - - x = (screen_size_x(s) / 2) - 3 * strlen(tim); - y = (screen_size_y(s) / 2) - 3; - - memcpy(&gc, &grid_default_cell, sizeof gc); - colour_set_bg(&gc, colour); - for (ptr = tim; *ptr != '\0'; ptr++) { - if (*ptr >= '0' && *ptr <= '9') - idx = *ptr - '0'; - else if (*ptr == ':') - idx = 10; - else if (*ptr == 'A') - idx = 11; - else if (*ptr == 'P') - idx = 12; - else if (*ptr == 'M') - idx = 13; - else { - x += 6; - continue; - } - - for (j = 0; j < 5; j++) { - for (i = 0; i < 5; i++) { - screen_write_cursormove(ctx, x + i, y + j); - if (clock_table[idx][j][i]) - screen_write_putc(ctx, &gc, ' '); - } - } - x += 6; - } -} diff --git a/screen-redraw.c b/screen-redraw.c index 3a082cbf..a7f713a5 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -381,7 +381,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp) for (j = 0; j < 5; j++) { for (i = px; i < px + 5; i++) { tty_cursor(tty, xoff + i, yoff + py + j); - if (clock_table[idx][j][i - px]) + if (window_clock_table[idx][j][i - px]) tty_putc(tty, ' '); } } diff --git a/tmux.h b/tmux.h index 5801b35e..9900489e 100644 --- a/tmux.h +++ b/tmux.h @@ -1713,10 +1713,6 @@ char *paste_print(struct paste_buffer *, size_t); void paste_send_pane(struct paste_buffer *, struct window_pane *, const char *, int); -/* clock.c */ -extern const char clock_table[14][5][5]; -void clock_draw(struct screen_write_ctx *, int, int); - /* arguments.c */ int args_cmp(struct args_entry *, struct args_entry *); RB_PROTOTYPE(args_tree, args_entry, entry, args_cmp); @@ -2222,6 +2218,7 @@ void layout_set_active_changed(struct window *); /* window-clock.c */ extern const struct window_mode window_clock_mode; +extern const char window_clock_table[14][5][5]; /* window-copy.c */ extern const struct window_mode window_copy_mode; diff --git a/window-clock.c b/window-clock.c index 8ec1671e..ede8df5b 100644 --- a/window-clock.c +++ b/window-clock.c @@ -46,6 +46,79 @@ struct window_clock_mode_data { time_t tim; }; +const char window_clock_table[14][5][5] = { + { { 1,1,1,1,1 }, /* 0 */ + { 1,0,0,0,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 0,0,0,0,1 }, /* 1 */ + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 2 */ + { 0,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,0 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 3 */ + { 0,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,0,0,0,1 }, /* 4 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 5 */ + { 1,0,0,0,0 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 6 */ + { 1,0,0,0,0 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 7 */ + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 }, + { 0,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* 8 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 1,1,1,1,1 }, /* 9 */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 0,0,0,0,1 }, + { 1,1,1,1,1 } }, + { { 0,0,0,0,0 }, /* : */ + { 0,0,1,0,0 }, + { 0,0,0,0,0 }, + { 0,0,1,0,0 }, + { 0,0,0,0,0 } }, + { { 1,1,1,1,1 }, /* A */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 } }, + { { 1,1,1,1,1 }, /* P */ + { 1,0,0,0,1 }, + { 1,1,1,1,1 }, + { 1,0,0,0,0 }, + { 1,0,0,0,0 } }, + { { 1,0,0,0,1 }, /* M */ + { 1,1,0,1,1 }, + { 1,0,1,0,1 }, + { 1,0,0,0,1 }, + { 1,0,0,0,1 } }, +}; + struct screen * window_clock_init(struct window_pane *wp) { @@ -114,11 +187,77 @@ window_clock_draw_screen(struct window_pane *wp) struct window_clock_mode_data *data = wp->modedata; struct screen_write_ctx ctx; int colour, style; + struct screen *s = &data->screen; + struct grid_cell gc; + char tim[64], *ptr; + time_t t; + struct tm *tm; + u_int i, j, x, y, idx; colour = options_get_number(&wp->window->options, "clock-mode-colour"); style = options_get_number(&wp->window->options, "clock-mode-style"); - screen_write_start(&ctx, NULL, &data->screen); - clock_draw(&ctx, colour, style); + screen_write_start(&ctx, NULL, s); + + t = time(NULL); + tm = localtime(&t); + if (style == 0) { + strftime(tim, sizeof tim, "%l:%M ", localtime(&t)); + if (tm->tm_hour >= 12) + strlcat(tim, "PM", sizeof tim); + else + strlcat(tim, "AM", sizeof tim); + } else + strftime(tim, sizeof tim, "%H:%M", tm); + + screen_write_clearscreen(&ctx); + + if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { + if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { + x = (screen_size_x(s) / 2) - (strlen(tim) / 2); + y = screen_size_y(s) / 2; + screen_write_cursormove(&ctx, x, y); + + memcpy(&gc, &grid_default_cell, sizeof gc); + colour_set_fg(&gc, colour); + screen_write_puts(&ctx, &gc, "%s", tim); + } + + + screen_write_stop(&ctx); + return; + } + + x = (screen_size_x(s) / 2) - 3 * strlen(tim); + y = (screen_size_y(s) / 2) - 3; + + memcpy(&gc, &grid_default_cell, sizeof gc); + colour_set_bg(&gc, colour); + for (ptr = tim; *ptr != '\0'; ptr++) { + if (*ptr >= '0' && *ptr <= '9') + idx = *ptr - '0'; + else if (*ptr == ':') + idx = 10; + else if (*ptr == 'A') + idx = 11; + else if (*ptr == 'P') + idx = 12; + else if (*ptr == 'M') + idx = 13; + else { + x += 6; + continue; + } + + for (j = 0; j < 5; j++) { + for (i = 0; i < 5; i++) { + screen_write_cursormove(&ctx, x + i, y + j); + if (window_clock_table[idx][j][i]) + screen_write_putc(&ctx, &gc, ' '); + } + } + x += 6; + } + screen_write_stop(&ctx); } From 9368914ee782f6ea9d7ea8f6b28b9d87ffae8023 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:36:43 +0000 Subject: [PATCH 05/24] Add start-of-list, end-of-list, top-line and bottom-line in choice mode, from madmaverick9 at roxxmail dot eu, similar diff a few days later from Marcel Partap. --- mode-key.c | 15 +++++++++++++++ tmux.h | 4 ++++ window-choose.c | 23 +++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/mode-key.c b/mode-key.c index 80a943e4..80a2464d 100644 --- a/mode-key.c +++ b/mode-key.c @@ -76,14 +76,18 @@ const struct mode_key_cmdstr mode_key_cmdstr_edit[] = { /* Choice keys command strings. */ const struct mode_key_cmdstr mode_key_cmdstr_choice[] = { { MODEKEYCHOICE_BACKSPACE, "backspace" }, + { MODEKEYCHOICE_BOTTOMLINE, "bottom-line"}, { MODEKEYCHOICE_CANCEL, "cancel" }, { MODEKEYCHOICE_CHOOSE, "choose" }, { MODEKEYCHOICE_DOWN, "down" }, + { MODEKEYCHOICE_ENDOFLIST, "end-of-list"}, { MODEKEYCHOICE_PAGEDOWN, "page-down" }, { MODEKEYCHOICE_PAGEUP, "page-up" }, { MODEKEYCHOICE_SCROLLDOWN, "scroll-down" }, { MODEKEYCHOICE_SCROLLUP, "scroll-up" }, { MODEKEYCHOICE_STARTNUMBERPREFIX, "start-number-prefix" }, + { MODEKEYCHOICE_STARTOFLIST, "start-of-list"}, + { MODEKEYCHOICE_TOPLINE, "top-line"}, { MODEKEYCHOICE_TREE_COLLAPSE, "tree-collapse" }, { MODEKEYCHOICE_TREE_COLLAPSE_ALL, "tree-collapse-all" }, { MODEKEYCHOICE_TREE_EXPAND, "tree-expand" }, @@ -226,6 +230,12 @@ const struct mode_key_entry mode_key_vi_choice[] = { { 'j', 0, MODEKEYCHOICE_DOWN }, { 'k', 0, MODEKEYCHOICE_UP }, { 'q', 0, MODEKEYCHOICE_CANCEL }, + { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST }, + { 'g', 0, MODEKEYCHOICE_STARTOFLIST }, + { 'H', 0, MODEKEYCHOICE_TOPLINE }, + { 'L', 0, MODEKEYCHOICE_BOTTOMLINE }, + { 'G', 0, MODEKEYCHOICE_ENDOFLIST }, + { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST }, { KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE }, { KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN }, { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN }, @@ -372,6 +382,11 @@ const struct mode_key_entry mode_key_emacs_choice[] = { { '\r', 0, MODEKEYCHOICE_CHOOSE }, { 'q', 0, MODEKEYCHOICE_CANCEL }, { 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP }, + { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST }, + { '<' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTOFLIST }, + { 'R' | KEYC_ESCAPE, 0, MODEKEYCHOICE_TOPLINE }, + { '>' | KEYC_ESCAPE, 0, MODEKEYCHOICE_ENDOFLIST }, + { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST }, { KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE }, { KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN }, { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN }, diff --git a/tmux.h b/tmux.h index 9900489e..3a73dece 100644 --- a/tmux.h +++ b/tmux.h @@ -520,14 +520,18 @@ enum mode_key_cmd { /* Menu (choice) keys. */ MODEKEYCHOICE_BACKSPACE, + MODEKEYCHOICE_BOTTOMLINE, MODEKEYCHOICE_CANCEL, MODEKEYCHOICE_CHOOSE, MODEKEYCHOICE_DOWN, + MODEKEYCHOICE_ENDOFLIST, MODEKEYCHOICE_PAGEDOWN, MODEKEYCHOICE_PAGEUP, MODEKEYCHOICE_SCROLLDOWN, MODEKEYCHOICE_SCROLLUP, MODEKEYCHOICE_STARTNUMBERPREFIX, + MODEKEYCHOICE_STARTOFLIST, + MODEKEYCHOICE_TOPLINE, MODEKEYCHOICE_TREE_COLLAPSE, MODEKEYCHOICE_TREE_COLLAPSE_ALL, MODEKEYCHOICE_TREE_EXPAND, diff --git a/window-choose.c b/window-choose.c index 0cf7f66b..bb881aa5 100644 --- a/window-choose.c +++ b/window-choose.c @@ -679,6 +679,29 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key) window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM, "Goto Item", wp, key); break; + case MODEKEYCHOICE_STARTOFLIST: + data->selected = 0; + data->top = 0; + window_choose_redraw_screen(wp); + break; + case MODEKEYCHOICE_TOPLINE: + data->selected = data->top; + window_choose_redraw_screen(wp); + break; + case MODEKEYCHOICE_BOTTOMLINE: + data->selected = data->top + screen_size_y(s) - 1; + if (data->selected > items - 1) + data->selected = items - 1; + window_choose_redraw_screen(wp); + break; + case MODEKEYCHOICE_ENDOFLIST: + data->selected = items - 1; + if (screen_size_y(s) < items) + data->top = items - screen_size_y(s); + else + data->top = 0; + window_choose_redraw_screen(wp); + break; default: idx = window_choose_index_key(data, key); if (idx < 0 || (u_int) idx >= ARRAY_LENGTH(&data->list)) From b11de5adc7a89a23af2a778d4de12ac697c902a0 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:37:55 +0000 Subject: [PATCH 06/24] Make session_attached a count and add session_many_attached flag. --- format.c | 6 ++---- resize.c | 2 ++ tmux.1 | 3 ++- tmux.h | 2 ++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/format.c b/format.c index bcb897d6..1dca6011 100644 --- a/format.c +++ b/format.c @@ -401,10 +401,8 @@ format_session(struct format_tree *ft, struct session *s) *strchr(tim, '\n') = '\0'; format_add(ft, "session_created_string", "%s", tim); - if (s->flags & SESSION_UNATTACHED) - format_add(ft, "session_attached", "%d", 0); - else - format_add(ft, "session_attached", "%d", 1); + format_add(ft, "session_attached", "%u", s->attached); + format_add(ft, "session_many_attached", "%u", s->attached > 1); } /* Set default format keys for a client. */ diff --git a/resize.c b/resize.c index ff3ec6c5..70379420 100644 --- a/resize.c +++ b/resize.c @@ -55,6 +55,7 @@ recalculate_sizes(void) RB_FOREACH(s, sessions, &sessions) { has_status = options_get_number(&s->options, "status"); + s->attached = 0; ssx = ssy = UINT_MAX; for (j = 0; j < ARRAY_LENGTH(&clients); j++) { c = ARRAY_ITEM(&clients, j); @@ -69,6 +70,7 @@ recalculate_sizes(void) ssy = c->tty.sy - 1; else if (c->tty.sy < ssy) ssy = c->tty.sy; + s->attached++; } } if (ssx == UINT_MAX || ssy == UINT_MAX) { diff --git a/tmux.1 b/tmux.1 index ba4c8537..81626faa 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3136,13 +3136,14 @@ The following variables are available, where appropriate: .It Li "saved_cursor_y" Ta "" Ta "Saved cursor Y in pane" .It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane" .It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane" -.It Li "session_attached" Ta "" Ta "1 if session attached" +.It Li "session_attached" Ta "" Ta "Number of clients session is attached to" .It Li "session_created" Ta "" Ta "Integer time session created" .It Li "session_created_string" Ta "" Ta "String time session created" .It Li "session_group" Ta "" Ta "Number of session group" .It Li "session_grouped" Ta "" Ta "1 if session in a group" .It Li "session_height" Ta "" Ta "Height of session" .It Li "session_id" Ta "" Ta "Unique session ID" +.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached" .It Li "session_name" Ta "#S" Ta "Name of session" .It Li "session_width" Ta "" Ta "Width of session" .It Li "session_windows" Ta "" Ta "Number of windows in session" diff --git a/tmux.h b/tmux.h index 3a73dece..fe4a697b 100644 --- a/tmux.h +++ b/tmux.h @@ -1086,6 +1086,8 @@ struct session { #define SESSION_UNATTACHED 0x1 /* not attached to any clients */ int flags; + u_int attached; + struct termios *tio; struct environ environ; From 0e4d1d8493564ce908b002d8e9dddc105184039e Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:39:31 +0000 Subject: [PATCH 07/24] Add setb -a to append and a copy mode append command, from J Raynor with minor changes. --- cmd-set-buffer.c | 74 ++++++++++++++++++++++++++++++------------------ mode-key.c | 2 ++ paste.c | 2 +- tmux.1 | 5 ++++ tmux.h | 1 + window-copy.c | 48 +++++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 28 deletions(-) diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c index f67f7a0c..0942da9a 100644 --- a/cmd-set-buffer.c +++ b/cmd-set-buffer.c @@ -24,15 +24,15 @@ #include "tmux.h" /* - * Add or set a paste buffer. + * Add, set, or append to a paste buffer. */ enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_set_buffer_entry = { "set-buffer", "setb", - "b:", 1, 1, - CMD_BUFFER_USAGE " data", + "ab:", 1, 1, + "[-a] " CMD_BUFFER_USAGE " data", 0, NULL, cmd_set_buffer_exec @@ -41,35 +41,55 @@ const struct cmd_entry cmd_set_buffer_entry = { enum cmd_retval cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { - struct args *args = self->args; - u_int limit; - char *pdata, *cause; - size_t psize; - int buffer; + struct args *args = self->args; + struct paste_buffer *pb; + u_int limit; + char *pdata, *cause; + size_t psize, newsize; + int buffer; limit = options_get_number(&global_options, "buffer-limit"); - pdata = xstrdup(args->argv[0]); - psize = strlen(pdata); + psize = 0; + pdata = NULL; - if (!args_has(args, 'b')) { + pb = NULL; + buffer = -1; + + if (args_has(args, 'b')) { + buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); + if (cause != NULL) { + cmdq_error(cmdq, "buffer %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + pb = paste_get_index(&global_buffers, buffer); + if (pb == NULL) { + cmdq_error(cmdq, "no buffer %d", buffer); + return (CMD_RETURN_ERROR); + } + } else if (args_has(args, 'a')) { + pb = paste_get_top(&global_buffers); + if (pb != NULL) + buffer = 0; + } + + if (args_has(args, 'a') && pb != NULL) { + psize = pb->size; + pdata = xmalloc(psize); + memcpy(pdata, pb->data, psize); + } + + newsize = strlen(args->argv[0]); + + pdata = xrealloc(pdata, 1, psize + newsize); + memcpy(pdata + psize, args->argv[0], newsize); + psize += newsize; + + if (buffer == -1) paste_add(&global_buffers, pdata, psize, limit); - return (CMD_RETURN_NORMAL); - } - - buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); - if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); - free(cause); - free(pdata); - return (CMD_RETURN_ERROR); - } - - if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { - cmdq_error(cmdq, "no buffer %d", buffer); - free(pdata); - return (CMD_RETURN_ERROR); - } + else + paste_replace(&global_buffers, buffer, pdata, psize); return (CMD_RETURN_NORMAL); } diff --git a/mode-key.c b/mode-key.c index 80a2464d..7f2b9471 100644 --- a/mode-key.c +++ b/mode-key.c @@ -100,6 +100,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_choice[] = { /* Copy keys command strings. */ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = { + { MODEKEYCOPY_APPENDSELECTION, "append-selection" }, { MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" }, { MODEKEYCOPY_BOTTOMLINE, "bottom-line" }, { MODEKEYCOPY_CANCEL, "cancel" }, @@ -272,6 +273,7 @@ const struct mode_key_entry mode_key_vi_copy[] = { { '9', 0, MODEKEYCOPY_STARTNUMBERPREFIX }, { ':', 0, MODEKEYCOPY_GOTOLINE }, { '?', 0, MODEKEYCOPY_SEARCHUP }, + { 'A', 0, MODEKEYCOPY_APPENDSELECTION }, { 'B', 0, MODEKEYCOPY_PREVIOUSSPACE }, { 'D', 0, MODEKEYCOPY_COPYENDOFLINE }, { 'E', 0, MODEKEYCOPY_NEXTSPACEEND }, diff --git a/paste.c b/paste.c index 946935a3..4ec87f35 100644 --- a/paste.c +++ b/paste.c @@ -172,7 +172,7 @@ paste_print(struct paste_buffer *pb, size_t width) /* Paste into a window pane, filtering '\n' according to separator. */ void -paste_send_pane (struct paste_buffer *pb, struct window_pane *wp, +paste_send_pane(struct paste_buffer *pb, struct window_pane *wp, const char *sep, int bracket) { const char *data = pb->data, *end = data + pb->size, *lf; diff --git a/tmux.1 b/tmux.1 index 81626faa..8fd63dc4 100644 --- a/tmux.1 +++ b/tmux.1 @@ -851,6 +851,7 @@ option). The following keys are supported as appropriate for the mode: .Bl -column "FunctionXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent .It Sy "Function" Ta Sy "vi" Ta Sy "emacs" +.It Li "Append selection" Ta "A" Ta "" .It Li "Back to indentation" Ta "^" Ta "M-m" .It Li "Bottom of history" Ta "G" Ta "M-<" .It Li "Clear selection" Ta "Escape" Ta "C-g" @@ -3543,12 +3544,16 @@ The .Fl a option appends to rather than overwriting the file. .It Xo Ic set-buffer +.Op Fl a .Op Fl b Ar buffer-index .Ar data .Xc .D1 (alias: Ic setb ) Set the contents of the specified buffer to .Ar data . +The +.Fl a +option appends to rather than overwriting the buffer. .It Xo Ic show-buffer .Op Fl b Ar buffer-index .Xc diff --git a/tmux.h b/tmux.h index fe4a697b..b30f2080 100644 --- a/tmux.h +++ b/tmux.h @@ -540,6 +540,7 @@ enum mode_key_cmd { MODEKEYCHOICE_UP, /* Copy keys. */ + MODEKEYCOPY_APPENDSELECTION, MODEKEYCOPY_BACKTOINDENTATION, MODEKEYCOPY_BOTTOMLINE, MODEKEYCOPY_CANCEL, diff --git a/window-copy.c b/window-copy.c index 76c9c3ce..7d7f3a20 100644 --- a/window-copy.c +++ b/window-copy.c @@ -58,6 +58,7 @@ void window_copy_copy_buffer(struct window_pane *, int, void *, size_t); void window_copy_copy_pipe( struct window_pane *, struct session *, int, const char *); void window_copy_copy_selection(struct window_pane *, int); +void window_copy_append_selection(struct window_pane *, int); void window_copy_clear_selection(struct window_pane *); void window_copy_copy_line( struct window_pane *, char **, size_t *, u_int, u_int, u_int); @@ -414,6 +415,13 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) cmd = mode_key_lookup(&data->mdata, key, &arg); switch (cmd) { + case MODEKEYCOPY_APPENDSELECTION: + if (sess != NULL) { + window_copy_append_selection(wp, data->numprefix); + window_pane_reset_mode(wp); + return; + } + break; case MODEKEYCOPY_CANCEL: window_pane_reset_mode(wp); return; @@ -1491,6 +1499,46 @@ window_copy_copy_selection(struct window_pane *wp, int idx) window_copy_copy_buffer(wp, idx, buf, len); } +void +window_copy_append_selection(struct window_pane *wp, int idx) +{ + char *buf; + struct paste_buffer *pb; + size_t len; + u_int limit; + struct screen_write_ctx ctx; + + buf = window_copy_get_selection(wp, &len); + if (buf == NULL) + return; + + if (options_get_number(&global_options, "set-clipboard")) { + screen_write_start(&ctx, wp, NULL); + screen_write_setselection(&ctx, buf, len); + screen_write_stop(&ctx); + } + + if (idx == -1) + idx = 0; + + if (idx == 0 && paste_get_top(&global_buffers) == NULL) { + limit = options_get_number(&global_options, "buffer-limit"); + paste_add(&global_buffers, buf, len, limit); + return; + } + + pb = paste_get_index(&global_buffers, idx); + if (pb != NULL) { + buf = xrealloc(buf, 1, len + pb->size); + memmove(buf + pb->size, buf, len); + memcpy(buf, pb->data, pb->size); + len += pb->size; + } + + if (paste_replace(&global_buffers, idx, buf, len) != 0) + free(buf); +} + void window_copy_copy_line(struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex) From fcdae6925a08dc06860f9552ba7a300669f4a038 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:39:59 +0000 Subject: [PATCH 08/24] Use hex constants rather than shifts for mouse events and flags, pointed out by Marcel Partap. --- tmux.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tmux.h b/tmux.h index b30f2080..b7d53727 100644 --- a/tmux.h +++ b/tmux.h @@ -1133,14 +1133,14 @@ LIST_HEAD(tty_terms, tty_term); #define MOUSE_WHEEL_DOWN 1 /* Mouse events. */ -#define MOUSE_EVENT_DOWN (1 << 0) -#define MOUSE_EVENT_DRAG (1 << 1) -#define MOUSE_EVENT_UP (1 << 2) -#define MOUSE_EVENT_CLICK (1 << 3) -#define MOUSE_EVENT_WHEEL (1 << 4) +#define MOUSE_EVENT_DOWN 0x1 +#define MOUSE_EVENT_DRAG 0x2 +#define MOUSE_EVENT_UP 0x4 +#define MOUSE_EVENT_CLICK 0x8 +#define MOUSE_EVENT_WHEEL 0x10 /* Mouse flags. */ -#define MOUSE_RESIZE_PANE (1 << 0) +#define MOUSE_RESIZE_PANE 0x1 /* * Mouse input. When sent by xterm: From 46593e7aa26b83f0ba1b0d36a700d7158ac2b178 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:40:21 +0000 Subject: [PATCH 09/24] Add names for mouse button bits rather than using magic numbers, from Marcel Partap. --- tmux.h | 12 ++++++++++-- tty-keys.c | 10 +++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tmux.h b/tmux.h index b7d53727..94eb5b8f 100644 --- a/tmux.h +++ b/tmux.h @@ -1128,18 +1128,26 @@ struct tty_term { }; LIST_HEAD(tty_terms, tty_term); +/* Mouse button masks. */ +#define MOUSE_MASK_BUTTONS 3 +#define MOUSE_MASK_SHIFT 4 +#define MOUSE_MASK_META 8 +#define MOUSE_MASK_CTRL 16 +#define MOUSE_MASK_DRAG 32 +#define MOUSE_MASK_WHEEL 64 + /* Mouse wheel states. */ #define MOUSE_WHEEL_UP 0 #define MOUSE_WHEEL_DOWN 1 -/* Mouse events. */ +/* Mouse event bits. */ #define MOUSE_EVENT_DOWN 0x1 #define MOUSE_EVENT_DRAG 0x2 #define MOUSE_EVENT_UP 0x4 #define MOUSE_EVENT_CLICK 0x8 #define MOUSE_EVENT_WHEEL 0x10 -/* Mouse flags. */ +/* Mouse flag bits. */ #define MOUSE_RESIZE_PANE 0x1 /* diff --git a/tty-keys.c b/tty-keys.c index 4492df1e..e0e794cc 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -748,21 +748,21 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) m->sgr_rel = sgr_rel; m->x = x; m->y = y; - if (b & 64) { /* wheel button */ - b &= 3; + if (b & MOUSE_MASK_WHEEL) { + b &= MOUSE_MASK_BUTTONS; if (b == 0) m->wheel = MOUSE_WHEEL_UP; else if (b == 1) m->wheel = MOUSE_WHEEL_DOWN; m->event = MOUSE_EVENT_WHEEL; - } else if ((b & 3) == 3) { + } else if ((b & MOUSE_MASK_BUTTONS) == 3) { if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y) { m->event = MOUSE_EVENT_CLICK; } else m->event = MOUSE_EVENT_DRAG; m->event |= MOUSE_EVENT_UP; } else { - if (b & 32) /* drag motion */ + if (b & MOUSE_MASK_DRAG) m->event = MOUSE_EVENT_DRAG; else { if (m->event & MOUSE_EVENT_UP && x == m->x && y == m->y) @@ -773,7 +773,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) m->sy = y; m->event = MOUSE_EVENT_DOWN; } - m->button = (b & 3); + m->button = (b & MOUSE_MASK_BUTTONS); } return (0); From 1704d4a6b799525f510860919b8c8c4315154a05 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:41:07 +0000 Subject: [PATCH 10/24] Don't segfaut when the parent of the layout cell is NULL, from Thomas Adam. --- window.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/window.c b/window.c index 842a5c63..bb69c0bc 100644 --- a/window.c +++ b/window.c @@ -423,10 +423,15 @@ window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp) void window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp) { - struct layout_cell *lc, *lc2; + struct layout_cell *lc, *lc2, *lcparent; + + /* Get the parent cell. */ + lcparent = nextwp->layout_cell->parent; + if (lcparent == NULL) + return; /* Save the target pane in its parent. */ - nextwp->layout_cell->parent->lastwp = nextwp; + lcparent->lastwp = nextwp; /* * Save the source pane in all of its parents up to, but not including, @@ -435,8 +440,7 @@ window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp) if (wp == NULL) return; for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) { - lc2 = nextwp->layout_cell->parent; - for (; lc2 != NULL; lc2 = lc2->parent) { + for (lc2 = lcparent; lc2 != NULL; lc2 = lc2->parent) { if (lc == lc2) return; } From dca7d1c0fd9dc16aca2337c078da7441dbf97eeb Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:41:35 +0000 Subject: [PATCH 11/24] Make message-limit a server option. --- options-table.c | 14 +++++++------- status.c | 6 +----- tmux.1 | 10 +++++----- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/options-table.c b/options-table.c index ea848259..bc25573a 100644 --- a/options-table.c +++ b/options-table.c @@ -81,6 +81,13 @@ const struct options_table_entry server_options_table[] = { .default_num = 0 }, + { .name = "message-limit", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 100 + }, + { .name = "quiet", .type = OPTIONS_TABLE_FLAG, .default_num = 0 /* overridden in main() */ @@ -243,13 +250,6 @@ const struct options_table_entry session_options_table[] = { .style = "message-style" }, - { .name = "message-limit", - .type = OPTIONS_TABLE_NUMBER, - .minimum = 0, - .maximum = INT_MAX, - .default_num = 20 - }, - { .name = "message-style", .type = OPTIONS_TABLE_STYLE, .default_str = "bg=yellow,fg=black" diff --git a/status.c b/status.c index 84589427..bf528b0d 100644 --- a/status.c +++ b/status.c @@ -655,7 +655,6 @@ void printflike2 status_message_set(struct client *c, const char *fmt, ...) { struct timeval tv; - struct session *s = c->session; struct message_entry *msg; va_list ap; int delay; @@ -673,10 +672,7 @@ status_message_set(struct client *c, const char *fmt, ...) msg->msg_time = time(NULL); msg->msg = xstrdup(c->message_string); - if (s == NULL) - limit = 0; - else - limit = options_get_number(&s->options, "message-limit"); + limit = options_get_number(&global_options, "message-limit"); if (ARRAY_LENGTH(&c->message_log) > limit) { limit = ARRAY_LENGTH(&c->message_log) - limit; for (i = 0; i < limit; i++) { diff --git a/tmux.1 b/tmux.1 index 8fd63dc4..3167a05a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -778,7 +778,7 @@ Show client messages or server information. Any messages displayed on the status line are saved in a per-client message log, up to a maximum of the limit set by the .Ar message-limit -session option for the session attached to that client. +server option. With .Fl t , display the log for @@ -2134,6 +2134,10 @@ passed through to applications running in .Nm . Attached clients should be detached and attached again after changing this option. +.It Ic message-limit Ar number +Set the number of error or information messages to save in the message log for +each client. +The default is 100. .It Xo Ic quiet .Op Ic on | off .Xc @@ -2391,10 +2395,6 @@ With the flag to the .Ic set-option command the new style is added otherwise the existing style is replaced. -.It Ic message-limit Ar number -Set the number of error or information messages to save in the message log for -each client. -The default is 20. .It Ic message-style Ar style Set status line message style. For how to specify From f155316be7f24d76dd8fe6eb3dd34c5cf0aae86d Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:42:05 +0000 Subject: [PATCH 12/24] Remove unused log functions. --- log.c | 41 +---------------------------------------- tmux.h | 3 --- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/log.c b/log.c index 2f1400cb..8a922c0a 100644 --- a/log.c +++ b/log.c @@ -41,7 +41,7 @@ __dead void log_vfatal(const char *, va_list); void log_event_cb(unused int severity, const char *msg) { - log_warnx("%s", msg); + log_debug("%s", msg); } /* Open logging to file. */ @@ -86,45 +86,6 @@ log_vwrite(const char *msg, va_list ap) free(fmt); } -/* Log a warning with error string. */ -void printflike1 -log_warn(const char *msg, ...) -{ - va_list ap; - char *fmt; - - va_start(ap, msg); - if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1) - exit(1); - log_vwrite(fmt, ap); - free(fmt); - va_end(ap); -} - -/* Log a warning. */ -void printflike1 -log_warnx(const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - log_vwrite(msg, ap); - va_end(ap); -} - -/* Log an informational message. */ -void printflike1 -log_info(const char *msg, ...) -{ - va_list ap; - - if (log_level > -1) { - va_start(ap, msg); - log_vwrite(msg, ap); - va_end(ap); - } -} - /* Log a debug message. */ void printflike1 log_debug(const char *msg, ...) diff --git a/tmux.h b/tmux.h index 94eb5b8f..9990ccfe 100644 --- a/tmux.h +++ b/tmux.h @@ -2343,9 +2343,6 @@ char *get_proc_name(int, char *); /* log.c */ void log_open(int, const char *); void log_close(void); -void printflike1 log_warn(const char *, ...); -void printflike1 log_warnx(const char *, ...); -void printflike1 log_info(const char *, ...); void printflike1 log_debug(const char *, ...); void printflike1 log_debug2(const char *, ...); __dead void printflike1 log_fatal(const char *, ...); From 7bdb675469336e1c8c7c5039aff369f8245dc450 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:42:27 +0000 Subject: [PATCH 13/24] GRID_DEBUG is no longer needed. --- grid-view.c | 22 ---------------------- grid.c | 18 ------------------ tmux.h | 10 ---------- 3 files changed, 50 deletions(-) diff --git a/grid-view.c b/grid-view.c index 4fe38fed..fca5fd54 100644 --- a/grid-view.c +++ b/grid-view.c @@ -59,8 +59,6 @@ grid_view_clear_history(struct grid *gd) struct grid_line *gl; u_int yy, last; - GRID_DEBUG(gd, ""); - /* Find the last used line. */ last = 0; for (yy = 0; yy < gd->sy; yy++) { @@ -82,8 +80,6 @@ grid_view_clear_history(struct grid *gd) void grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) { - GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny); - px = grid_view_x(gd, px); py = grid_view_y(gd, py); @@ -94,8 +90,6 @@ grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) void grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower) { - GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower); - if (gd->flags & GRID_HISTORY) { grid_collect_history(gd); if (rupper == 0 && rlower == gd->sy - 1) @@ -116,8 +110,6 @@ grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower) void grid_view_scroll_region_down(struct grid *gd, u_int rupper, u_int rlower) { - GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower); - rupper = grid_view_y(gd, rupper); rlower = grid_view_y(gd, rlower); @@ -130,8 +122,6 @@ grid_view_insert_lines(struct grid *gd, u_int py, u_int ny) { u_int sy; - GRID_DEBUG(gd, "py=%u, ny=%u", py, ny); - py = grid_view_y(gd, py); sy = grid_view_y(gd, gd->sy); @@ -145,8 +135,6 @@ grid_view_insert_lines_region(struct grid *gd, u_int rlower, u_int py, u_int ny) { u_int ny2; - GRID_DEBUG(gd, "rlower=%u, py=%u, ny=%u", rlower, py, ny); - rlower = grid_view_y(gd, rlower); py = grid_view_y(gd, py); @@ -162,8 +150,6 @@ grid_view_delete_lines(struct grid *gd, u_int py, u_int ny) { u_int sy; - GRID_DEBUG(gd, "py=%u, ny=%u", py, ny); - py = grid_view_y(gd, py); sy = grid_view_y(gd, gd->sy); @@ -178,8 +164,6 @@ grid_view_delete_lines_region(struct grid *gd, u_int rlower, u_int py, u_int ny) { u_int ny2; - GRID_DEBUG(gd, "rlower=%u, py=%u, ny=%u", rlower, py, ny); - rlower = grid_view_y(gd, rlower); py = grid_view_y(gd, py); @@ -195,8 +179,6 @@ grid_view_insert_cells(struct grid *gd, u_int px, u_int py, u_int nx) { u_int sx; - GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); - px = grid_view_x(gd, px); py = grid_view_y(gd, py); @@ -214,8 +196,6 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx) { u_int sx; - GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); - px = grid_view_x(gd, px); py = grid_view_y(gd, py); @@ -229,8 +209,6 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx) char * grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) { - GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); - px = grid_view_x(gd, px); py = grid_view_y(gd, py); diff --git a/grid.c b/grid.c index 7fb15dc3..df2f8b16 100644 --- a/grid.c +++ b/grid.c @@ -151,8 +151,6 @@ grid_collect_history(struct grid *gd) { u_int yy; - GRID_DEBUG(gd, ""); - if (gd->hsize < gd->hlimit) return; @@ -173,8 +171,6 @@ grid_scroll_history(struct grid *gd) { u_int yy; - GRID_DEBUG(gd, ""); - yy = gd->hsize + gd->sy; gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata); memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]); @@ -189,8 +185,6 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower) struct grid_line *gl_history, *gl_upper, *gl_lower; u_int yy; - GRID_DEBUG(gd, "upper=%u, lower=%u", upper, lower); - /* Create a space for a new line. */ yy = gd->hsize + gd->sy; gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata); @@ -282,8 +276,6 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) { u_int xx, yy; - GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny); - if (nx == 0 || ny == 0) return; @@ -319,8 +311,6 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny) struct grid_line *gl; u_int yy; - GRID_DEBUG(gd, "py=%u, ny=%u", py, ny); - if (ny == 0) return; @@ -342,8 +332,6 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny) { u_int yy; - GRID_DEBUG(gd, "dy=%u, py=%u, ny=%u", dy, py, ny); - if (ny == 0 || py == dy) return; @@ -381,8 +369,6 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx) struct grid_line *gl; u_int xx; - GRID_DEBUG(gd, "dx=%u, px=%u, py=%u, nx=%u", dx, px, py, nx); - if (nx == 0 || px == dx) return; @@ -592,8 +578,6 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, u_int xx; const struct grid_line *gl; - GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); - if (lastgc != NULL && *lastgc == NULL) { memcpy(&lastgc1, &grid_default_cell, sizeof lastgc1); *lastgc = &lastgc1; @@ -661,8 +645,6 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy, struct grid_line *dstl, *srcl; u_int yy; - GRID_DEBUG(src, "dy=%u, sy=%u, ny=%u", dy, sy, ny); - if (dy + ny > dst->hsize + dst->sy) ny = dst->hsize + dst->sy - dy; if (sy + ny > src->hsize + src->sy) diff --git a/tmux.h b/tmux.h index 9990ccfe..df7b5d16 100644 --- a/tmux.h +++ b/tmux.h @@ -663,16 +663,6 @@ struct utf8_data { u_int width; }; -/* Grid output. */ -#if defined(DEBUG) && \ - ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__GNUC__) && __GNUC__ >= 3)) -#define GRID_DEBUG(gd, fmt, ...) log_debug2("%s: (sx=%u, sy=%u, hsize=%u) " \ - fmt, __func__, (gd)->sx, (gd)->sy, (gd)->hsize, ## __VA_ARGS__) -#else -#define GRID_DEBUG(...) -#endif - /* Grid attributes. */ #define GRID_ATTR_BRIGHT 0x1 #define GRID_ATTR_DIM 0x2 From 48478ea0a990cc14d61722f9f8d3f1490d8f417a Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:42:45 +0000 Subject: [PATCH 14/24] Remove log_debug2 as well and simplify log.c. --- input-keys.c | 6 ++-- log.c | 77 ++++++++++++++-------------------------------------- tmux.c | 2 +- 3 files changed, 25 insertions(+), 60 deletions(-) diff --git a/input-keys.c b/input-keys.c index 2de48e97..9247a995 100644 --- a/input-keys.c +++ b/input-keys.c @@ -143,7 +143,7 @@ input_key(struct window_pane *wp, int key) char *out; u_char ch; - log_debug2("writing key 0x%x", key); + log_debug("writing key 0x%x", key); /* * If this is a normal 7-bit key, just send it, with a leading escape @@ -186,11 +186,11 @@ input_key(struct window_pane *wp, int key) break; } if (i == nitems(input_keys)) { - log_debug2("key 0x%x missing", key); + log_debug("key 0x%x missing", key); return; } dlen = strlen(ike->data); - log_debug2("found key 0x%x: \"%s\"", key, ike->data); + log_debug("found key 0x%x: \"%s\"", key, ike->data); /* Prefix a \033 for escape. */ if (key & KEYC_ESCAPE) diff --git a/log.c b/log.c index 8a922c0a..f329107c 100644 --- a/log.c +++ b/log.c @@ -22,20 +22,13 @@ #include #include #include -#include -#include #include "tmux.h" -/* Log file, if needed. */ -FILE *log_file; +FILE *log_file; -/* Debug level. */ -int log_level = 0; - -void log_event_cb(int, const char *); -void log_vwrite(const char *, va_list); -__dead void log_vfatal(const char *, va_list); +void log_event_cb(int, const char *); +void log_vwrite(const char *, va_list); /* Log callback for libevent. */ void @@ -46,12 +39,11 @@ log_event_cb(unused int severity, const char *msg) /* Open logging to file. */ void -log_open(int level, const char *path) +log_open(const char *path) { log_file = fopen(path, "w"); if (log_file == NULL) return; - log_level = level; setlinebuf(log_file); event_set_log_callback(log_event_cb); @@ -65,6 +57,7 @@ log_close(void) { if (log_file != NULL) fclose(log_file); + log_file = NULL; event_set_log_callback(NULL); } @@ -92,63 +85,35 @@ log_debug(const char *msg, ...) { va_list ap; - if (log_level > 0) { - va_start(ap, msg); - log_vwrite(msg, ap); - va_end(ap); - } + va_start(ap, msg); + log_vwrite(msg, ap); + va_end(ap); } -/* Log a debug message at level 2. */ -void printflike1 -log_debug2(const char *msg, ...) -{ - va_list ap; - - if (log_level > 1) { - va_start(ap, msg); - log_vwrite(msg, ap); - va_end(ap); - } -} - -/* Log a critical error, with error string if necessary, and die. */ -__dead void -log_vfatal(const char *msg, va_list ap) -{ - char *fmt; - - if (errno != 0) { - if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) - exit(1); - log_vwrite(fmt, ap); - } else { - if (asprintf(&fmt, "fatal: %s", msg) == -1) - exit(1); - log_vwrite(fmt, ap); - } - free(fmt); - - exit(1); -} - -/* Log a critical error, with error string, and die. */ +/* Log a critical error with error string and die. */ __dead void printflike1 log_fatal(const char *msg, ...) { - va_list ap; + char *fmt; + va_list ap; va_start(ap, msg); - log_vfatal(msg, ap); + if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) + exit(1); + log_vwrite(fmt, ap); + exit(1); } /* Log a critical error and die. */ __dead void printflike1 log_fatalx(const char *msg, ...) { - va_list ap; + char *fmt; + va_list ap; - errno = 0; va_start(ap, msg); - log_vfatal(msg, ap); + if (asprintf(&fmt, "fatal: %s", msg) == -1) + exit(1); + log_vwrite(fmt, ap); + exit(1); } diff --git a/tmux.c b/tmux.c index 6de96ce1..8f9e520d 100644 --- a/tmux.c +++ b/tmux.c @@ -70,7 +70,7 @@ logfile(const char *name) if (debug_level > 0) { xasprintf(&path, "tmux-%s-%ld.log", name, (long) getpid()); - log_open(debug_level, path); + log_open(path); free(path); } } From ee19d304ff366741f6f94334bbc82124a4c44dbc Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:43:35 +0000 Subject: [PATCH 15/24] In four byte UTF-8 sequences, only three bits of the first byte should be used. Fix from Koga Osamu. --- utf8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utf8.c b/utf8.c index 1c81392b..85889dcb 100644 --- a/utf8.c +++ b/utf8.c @@ -311,7 +311,7 @@ utf8_combine(const struct utf8_data *utf8data) value = utf8data->data[3] & 0x3f; value |= (utf8data->data[2] & 0x3f) << 6; value |= (utf8data->data[1] & 0x3f) << 12; - value |= (utf8data->data[0] & 0x3f) << 18; + value |= (utf8data->data[0] & 0x07) << 18; break; } return (value); From 3c06bec03fe269b8a2548c147fe7b4f2eb4d3c7a Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 31 Mar 2014 21:43:55 +0000 Subject: [PATCH 16/24] Don't crash with a zero-length argument to setb, from J Raynor. --- cmd-set-buffer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c index 0942da9a..a206760c 100644 --- a/cmd-set-buffer.c +++ b/cmd-set-buffer.c @@ -56,6 +56,9 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) pb = NULL; buffer = -1; + if ((newsize = strlen(args->argv[0])) == 0) + return (CMD_RETURN_NORMAL); + if (args_has(args, 'b')) { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { @@ -80,8 +83,6 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) memcpy(pdata, pb->data, psize); } - newsize = strlen(args->argv[0]); - pdata = xrealloc(pdata, 1, psize + newsize); memcpy(pdata + psize, args->argv[0], newsize); psize += newsize; From d9960b2d4d4cb6697086d32b24e9e6cbc74df483 Mon Sep 17 00:00:00 2001 From: deraadt Date: Tue, 1 Apr 2014 05:50:30 +0000 Subject: [PATCH 17/24] missed commit matching log.c --- tmux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmux.h b/tmux.h index df7b5d16..6b35e175 100644 --- a/tmux.h +++ b/tmux.h @@ -2331,7 +2331,7 @@ u_int utf8_split2(u_int, u_char *); char *get_proc_name(int, char *); /* log.c */ -void log_open(int, const char *); +void log_open(const char *); void log_close(void); void printflike1 log_debug(const char *, ...); void printflike1 log_debug2(const char *, ...); From b52b40b2bc9e90e2e585aa2158aee45fcbe1db86 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 2 Apr 2014 07:55:09 +0000 Subject: [PATCH 18/24] pane_start_path has gone away. --- tmux.1 | 1 - 1 file changed, 1 deletion(-) diff --git a/tmux.1 b/tmux.1 index 3167a05a..eb0be916 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3128,7 +3128,6 @@ The following variables are available, where appropriate: .It Li "pane_index" Ta "#P" Ta "Index of pane" .It Li "pane_pid" Ta "" Ta "PID of first process in pane" .It Li "pane_start_command" Ta "" Ta "Command pane started with" -.It Li "pane_start_path" Ta "" Ta "Path pane started with" .It Li "pane_tabs" Ta "" Ta "Pane tab positions" .It Li "pane_title" Ta "#T" Ta "Title of pane" .It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane" From 8880bdb67c9d939ec53506d05f5ce1d75be10c97 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 2 Apr 2014 17:08:23 +0000 Subject: [PATCH 19/24] Do not replace ## with # in status_replace1 because it'll be done later by the format code. --- status.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/status.c b/status.c index bf528b0d..029be4c8 100644 --- a/status.c +++ b/status.c @@ -396,9 +396,6 @@ status_replace1(struct client *c, char **iptr, char **optr, char *out, case '{': ptr = (char *) "#{"; goto do_replace; - case '#': - *(*optr)++ = '#'; - break; default: xsnprintf(tmp, sizeof tmp, "#%c", *(*iptr - 1)); ptr = tmp; From 82f3e0e9e68d4078555cd6270473c45a3e60273b Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 2 Apr 2014 17:14:24 +0000 Subject: [PATCH 20/24] Use the same logic for bell with and without visual-bell, from Filip Moc. --- server-window.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server-window.c b/server-window.c index 39699c37..86beeef4 100644 --- a/server-window.c +++ b/server-window.c @@ -85,10 +85,11 @@ server_window_check_bell(struct session *s, struct winlink *wl) return (0); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s || (c->flags & CLIENT_CONTROL)) + if (c == NULL || c->session != s || c->flags & CLIENT_CONTROL) continue; if (!visual) { - tty_bell(&c->tty); + if (c->session->curw->window == w || action == BELL_ANY) + tty_bell(&c->tty); continue; } if (c->session->curw->window == w) From 252a7373d69646ae866e3a4fa18d46f673864c0e Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 2 Apr 2014 18:12:18 +0000 Subject: [PATCH 21/24] Support UTF-8 with choose-buffer, from Kosuke ASAMI. Also make buffer_sample bigger to let it trim at window right edge. --- cmd-choose-buffer.c | 4 +++- cmd-list-buffers.c | 2 +- format.c | 10 ++++++---- paste.c | 23 ++++++++++++----------- tmux.1 | 2 +- tmux.h | 7 ++++--- utf8.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 70 insertions(+), 21 deletions(-) diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c index 359de068..1e0edaa6 100644 --- a/cmd-choose-buffer.c +++ b/cmd-choose-buffer.c @@ -49,6 +49,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq) char *action, *action_data; const char *template; u_int idx; + int utf8flag; if ((c = cmd_current_client(cmdq)) == NULL) { cmdq_error(cmdq, "no client available"); @@ -60,6 +61,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq) if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); + utf8flag = options_get_number(&wl->window->options, "utf8"); if (paste_get_top(&global_buffers) == NULL) return (CMD_RETURN_NORMAL); @@ -79,7 +81,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq) cdata->ft_template = xstrdup(template); format_add(cdata->ft, "line", "%u", idx - 1); - format_paste_buffer(cdata->ft, pb); + format_paste_buffer(cdata->ft, pb, utf8flag); xasprintf(&action_data, "%u", idx - 1); cdata->command = cmd_template_replace(action, action_data, 1); diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c index e36a7cd0..7051eae8 100644 --- a/cmd-list-buffers.c +++ b/cmd-list-buffers.c @@ -55,7 +55,7 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq) while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) { ft = format_create(); format_add(ft, "line", "%u", idx - 1); - format_paste_buffer(ft, pb); + format_paste_buffer(ft, pb, 0); line = format_expand(ft, template); cmdq_print(cmdq, "%s", line); diff --git a/format.c b/format.c index 1dca6011..5fc76b2b 100644 --- a/format.c +++ b/format.c @@ -601,12 +601,14 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp) /* Set default format keys for paste buffer. */ void -format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb) +format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb, + int utf8flag) { - char *pb_print = paste_print(pb, 50); + char *s; format_add(ft, "buffer_size", "%zu", pb->size); - format_add(ft, "buffer_sample", "%s", pb_print); - free(pb_print); + s = paste_make_sample(pb, utf8flag); + format_add(ft, "buffer_sample", "%s", s); + free(s); } diff --git a/paste.c b/paste.c index 4ec87f35..98d71a07 100644 --- a/paste.c +++ b/paste.c @@ -148,25 +148,26 @@ paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size) return (0); } -/* Convert a buffer into a visible string. */ +/* Convert start of buffer into a nice string. */ char * -paste_print(struct paste_buffer *pb, size_t width) +paste_make_sample(struct paste_buffer *pb, int utf8flag) { - char *buf; - size_t len, used; - - if (width < 3) - width = 3; - buf = xmalloc(width * 4 + 1); + char *buf; + size_t len, used; + const int flags = VIS_OCTAL|VIS_TAB|VIS_NL; + const size_t width = 200; len = pb->size; if (len > width) len = width; + buf = xmalloc(len * 4 + 4); - used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL); + if (utf8flag) + used = utf8_strvis(buf, pb->data, len, flags); + else + used = strvisx(buf, pb->data, len, flags); if (pb->size > width || used > width) - strlcpy(buf + width - 3, "...", 4); - + strlcpy(buf + width, "...", 4); return (buf); } diff --git a/tmux.1 b/tmux.1 index eb0be916..8205e026 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3087,7 +3087,7 @@ The following variables are available, where appropriate: .It Li "alternate_on" Ta "" Ta "If pane is in alternate screen" .It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen" .It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen" -.It Li "buffer_sample" Ta "" Ta "First 50 characters from buffer" +.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer" .It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes" .It Li "client_activity" Ta "" Ta "Integer time client last had activity" .It Li "client_activity_string" Ta "" Ta "String time client last had activity" diff --git a/tmux.h b/tmux.h index 6b35e175..7e541458 100644 --- a/tmux.h +++ b/tmux.h @@ -85,7 +85,7 @@ extern char **environ; /* Default template for choose-buffer. */ #define CHOOSE_BUFFER_TEMPLATE \ - "#{line}: #{buffer_size} bytes: \"#{buffer_sample}\"" + "#{line}: #{buffer_size} bytes: #{buffer_sample}" /* Default template for choose-client. */ #define CHOOSE_CLIENT_TEMPLATE \ @@ -1544,7 +1544,7 @@ void format_winlink(struct format_tree *, struct session *, void format_window_pane(struct format_tree *, struct window_pane *); void format_paste_buffer(struct format_tree *, - struct paste_buffer *); + struct paste_buffer *, int); /* mode-key.c */ extern const struct mode_key_table mode_key_tables[]; @@ -1714,7 +1714,7 @@ int paste_free_top(struct paste_stack *); int paste_free_index(struct paste_stack *, u_int); void paste_add(struct paste_stack *, char *, size_t, u_int); int paste_replace(struct paste_stack *, u_int, char *, size_t); -char *paste_print(struct paste_buffer *, size_t); +char *paste_make_sample(struct paste_buffer *, int); void paste_send_pane(struct paste_buffer *, struct window_pane *, const char *, int); @@ -2326,6 +2326,7 @@ int utf8_open(struct utf8_data *, u_char); int utf8_append(struct utf8_data *, u_char); u_int utf8_combine(const struct utf8_data *); u_int utf8_split2(u_int, u_char *); +int utf8_strvis(char *, const char *, size_t, int); /* procname.c */ char *get_proc_name(int, char *); diff --git a/utf8.c b/utf8.c index 85889dcb..082683e8 100644 --- a/utf8.c +++ b/utf8.c @@ -19,6 +19,7 @@ #include #include +#include #include "tmux.h" @@ -350,3 +351,45 @@ utf8_width(const struct utf8_data *utf8data) } return (1); } + +/* + * Encode len characters from src into dst, which is guaranteed to have four + * bytes available for each character from src (for \abc or UTF-8) plus space + * for \0. + */ +int +utf8_strvis(char *dst, const char *src, size_t len, int flag) +{ + struct utf8_data utf8data; + const char *start, *end; + int more; + size_t i; + + start = dst; + end = src + len; + + while (src < end) { + if (utf8_open(&utf8data, *src)) { + more = 1; + while (++src < end && more) + more = utf8_append(&utf8data, *src); + if (!more) { + /* UTF-8 character finished. */ + for (i = 0; i < utf8data.size; i++) + *dst++ = utf8data.data[i]; + continue; + } else if (utf8data.have > 0) { + /* Not a complete UTF-8 character. */ + src -= utf8data.have; + } + } + if (src < end - 1) + dst = vis(dst, src[0], flag, src[1]); + else if (src < end) + dst = vis(dst, src[0], flag, '\0'); + src++; + } + + *dst = '\0'; + return (dst - start); +} From 8824dae6f7b21f95ea824ecc1abc31140763c971 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 3 Apr 2014 08:15:17 +0000 Subject: [PATCH 22/24] A couple of trivial mouse-related style nits. --- input-keys.c | 2 +- tty-keys.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/input-keys.c b/input-keys.c index 9247a995..0370a684 100644 --- a/input-keys.c +++ b/input-keys.c @@ -245,7 +245,7 @@ input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m) paste_send_pane(pb, wp, "\r", wp->screen->mode & MODE_BRACKETPASTE); } - } else if ((m->xb & 3) != 1 && + } else if (m->button != 1 && options_get_number(&wp->window->options, "mode-mouse") == 1) { if (window_pane_set_mode(wp, &window_copy_mode) == 0) { window_copy_init_from_pane(wp); diff --git a/tty-keys.c b/tty-keys.c index e0e794cc..1116df2b 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -756,9 +756,9 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) m->wheel = MOUSE_WHEEL_DOWN; m->event = MOUSE_EVENT_WHEEL; } else if ((b & MOUSE_MASK_BUTTONS) == 3) { - if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y) { + if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y) m->event = MOUSE_EVENT_CLICK; - } else + else m->event = MOUSE_EVENT_DRAG; m->event |= MOUSE_EVENT_UP; } else { From acef311fe356f408690e9f94727ed63a934b742f Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 3 Apr 2014 08:20:29 +0000 Subject: [PATCH 23/24] Work out mouse scroll wheel effect when the mouse is first detected and store it in struct mouse_event, reduce the scroll size the 3 but allow shift to reduce it to 1 and meta and ctrl to multiply by 3 if the terminal supports them, also support wheel in choose mode. From Marcel Partap. --- tmux.h | 1 + tty-keys.c | 9 +++++++++ window-choose.c | 12 +++++++++++- window-copy.c | 21 +++++++++++---------- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/tmux.h b/tmux.h index 7e541458..a9edf8ff 100644 --- a/tmux.h +++ b/tmux.h @@ -1168,6 +1168,7 @@ struct mouse_event { u_int button; u_int clicks; + u_int scroll; int wheel; int event; diff --git a/tty-keys.c b/tty-keys.c index 1116df2b..4f55a80c 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -749,6 +749,15 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) m->x = x; m->y = y; if (b & MOUSE_MASK_WHEEL) { + if (b & MOUSE_MASK_SHIFT) + m->scroll = 1; + else + m->scroll = 3; + if (b & MOUSE_MASK_META) + m->scroll *= 3; + if (b & MOUSE_MASK_CTRL) + m->scroll *= 3; + b &= MOUSE_MASK_BUTTONS; if (b == 0) m->wheel = MOUSE_WHEEL_UP; diff --git a/window-choose.c b/window-choose.c index bb881aa5..c354d46f 100644 --- a/window-choose.c +++ b/window-choose.c @@ -721,7 +721,17 @@ window_choose_mouse( struct window_choose_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct window_choose_mode_item *item; - u_int idx; + u_int i, idx; + + if (m->event == MOUSE_EVENT_WHEEL) { + for (i = 0; i < m->scroll; i++) { + if (m->wheel == MOUSE_WHEEL_UP) + window_choose_key(wp, sess, KEYC_UP); + else + window_choose_key(wp, sess, KEYC_DOWN); + } + return; + } if (~m->event & MOUSE_EVENT_CLICK) return; diff --git a/window-copy.c b/window-copy.c index 7d7f3a20..6e4d6704 100644 --- a/window-copy.c +++ b/window-copy.c @@ -871,18 +871,19 @@ window_copy_mouse( /* If mouse wheel (buttons 4 and 5), scroll. */ if (m->event == MOUSE_EVENT_WHEEL) { - if (m->wheel == MOUSE_WHEEL_UP) { - for (i = 0; i < 5; i++) + for (i = 0; i < m->scroll; i++) { + if (m->wheel == MOUSE_WHEEL_UP) window_copy_cursor_up(wp, 1); - } else if (m->wheel == MOUSE_WHEEL_DOWN) { - for (i = 0; i < 5; i++) + else { window_copy_cursor_down(wp, 1); - /* - * We reached the bottom, leave copy mode, - * but only if no selection is in progress. - */ - if (data->oy == 0 && !s->sel.flag) - goto reset_mode; + + /* + * We reached the bottom, leave copy mode, but + * only if no selection is in progress. + */ + if (data->oy == 0 && !s->sel.flag) + goto reset_mode; + } } return; } From 57c514d2f85f9d1c81601bae32131f1cd2948422 Mon Sep 17 00:00:00 2001 From: Thomas Adam Date: Sat, 5 Apr 2014 12:40:19 +0100 Subject: [PATCH 24/24] Remove ; not used on Linux. --- utf8.c | 1 - 1 file changed, 1 deletion(-) diff --git a/utf8.c b/utf8.c index 1328dd6e..20e35137 100644 --- a/utf8.c +++ b/utf8.c @@ -19,7 +19,6 @@ #include #include -#include #include "tmux.h"