aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alerts.c10
-rw-r--r--client.c18
-rw-r--r--cmd-attach-session.c5
-rw-r--r--cmd-bind-key.c42
-rw-r--r--cmd-display-message.c16
-rw-r--r--cmd-display-panes.c91
-rw-r--r--cmd-list-keys.c2
-rw-r--r--cmd-load-buffer.c24
-rw-r--r--cmd-queue.c2
-rw-r--r--cmd-select-pane.c1
-rw-r--r--cmd-set-buffer.c10
-rw-r--r--cmd-set-environment.c25
-rw-r--r--cmd-source-file.c14
-rw-r--r--cmd-unbind-key.c54
-rw-r--r--colour.c6
-rw-r--r--compat.h4
-rw-r--r--configure.ac6
-rw-r--r--control.c4
-rw-r--r--format.c38
-rw-r--r--grid.c21
-rw-r--r--input-keys.c2
-rw-r--r--input.c47
-rw-r--r--key-bindings.c10
-rw-r--r--mode-tree.c2
-rw-r--r--options-table.c9
-rw-r--r--options.c42
-rw-r--r--popup.c2
-rw-r--r--proc.c1
-rw-r--r--server-client.c12
-rw-r--r--server-fn.c1
-rw-r--r--server.c8
-rw-r--r--status.c12
-rw-r--r--tmux.158
-rw-r--r--tmux.c4
-rw-r--r--tmux.h16
-rw-r--r--tty-term.c2
-rw-r--r--tty.c22
-rw-r--r--window-copy.c156
-rw-r--r--window-customize.c10
39 files changed, 539 insertions, 270 deletions
diff --git a/alerts.c b/alerts.c
index 9675934a..0f2eb179 100644
--- a/alerts.c
+++ b/alerts.c
@@ -200,7 +200,7 @@ alerts_check_bell(struct window *w)
* not check WINLINK_BELL).
*/
s = wl->session;
- if (s->curw != wl) {
+ if (s->curw != wl || s->attached == 0) {
wl->flags |= WINLINK_BELL;
server_status_session(s);
}
@@ -236,7 +236,7 @@ alerts_check_activity(struct window *w)
if (wl->flags & WINLINK_ACTIVITY)
continue;
s = wl->session;
- if (s->curw != wl) {
+ if (s->curw != wl || s->attached == 0) {
wl->flags |= WINLINK_ACTIVITY;
server_status_session(s);
}
@@ -272,7 +272,7 @@ alerts_check_silence(struct window *w)
if (wl->flags & WINLINK_SILENCE)
continue;
s = wl->session;
- if (s->curw != wl) {
+ if (s->curw != wl || s->attached == 0) {
wl->flags |= WINLINK_SILENCE;
server_status_session(s);
}
@@ -316,9 +316,9 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option)
if (visual == VISUAL_OFF)
continue;
if (c->session->curw == wl)
- status_message_set(c, 1, "%s in current window", type);
+ status_message_set(c, -1, 1, "%s in current window", type);
else {
- status_message_set(c, 1, "%s in window %d", type,
+ status_message_set(c, -1, 1, "%s in window %d", type,
wl->idx);
}
}
diff --git a/client.c b/client.c
index b652754b..8880c8ba 100644
--- a/client.c
+++ b/client.c
@@ -59,7 +59,8 @@ static struct client_files client_files = RB_INITIALIZER(&client_files);
static __dead void client_exec(const char *,const char *);
static int client_get_lock(char *);
-static int client_connect(struct event_base *, const char *, int);
+static int client_connect(struct event_base *, const char *,
+ uint64_t);
static void client_send_identify(const char *, const char *, int);
static void client_signal(int);
static void client_dispatch(struct imsg *, void *);
@@ -100,7 +101,7 @@ client_get_lock(char *lockfile)
/* Connect client to server. */
static int
-client_connect(struct event_base *base, const char *path, int flags)
+client_connect(struct event_base *base, const char *path, uint64_t flags)
{
struct sockaddr_un sa;
size_t size;
@@ -238,7 +239,8 @@ client_exit(void)
/* Client main loop. */
int
-client_main(struct event_base *base, int argc, char **argv, int flags, int feat)
+client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
+ int feat)
{
struct cmd_parse_result *pr;
struct msg_command *data;
@@ -284,7 +286,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags, int feat)
/* Save the flags. */
client_flags = flags;
- log_debug("flags are %#llx", client_flags);
+ log_debug("flags are %#llx", (unsigned long long)client_flags);
/* Initialize the client socket and start the server. */
fd = client_connect(base, socket_path, client_flags);
@@ -442,6 +444,8 @@ client_send_identify(const char *ttynam, const char *cwd, int feat)
pid_t pid;
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
+ proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &client_flags,
+ sizeof client_flags);
if ((s = getenv("TERM")) == NULL)
s = "";
@@ -891,7 +895,8 @@ client_dispatch_wait(struct imsg *imsg)
fatalx("bad MSG_FLAGS string");
memcpy(&client_flags, data, sizeof client_flags);
- log_debug("new flags are %#llx", client_flags);
+ log_debug("new flags are %#llx",
+ (unsigned long long)client_flags);
break;
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
@@ -944,7 +949,8 @@ client_dispatch_attached(struct imsg *imsg)
fatalx("bad MSG_FLAGS string");
memcpy(&client_flags, data, sizeof client_flags);
- log_debug("new flags are %#llx", client_flags);
+ log_debug("new flags are %#llx",
+ (unsigned long long)client_flags);
break;
case MSG_DETACH:
case MSG_DETACHKILL:
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 38d9c024..6a7ebba7 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -59,7 +59,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
struct session *s;
struct winlink *wl;
struct window_pane *wp;
- char *cause;
+ char *cwd, *cause;
enum msgtype msgtype;
if (RB_EMPTY(&sessions)) {
@@ -99,8 +99,9 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
}
if (cflag != NULL) {
+ cwd = format_single(item, cflag, c, s, wl, wp);
free((void *)s->cwd);
- s->cwd = format_single(item, cflag, c, s, wl, wp);
+ s->cwd = cwd;
}
if (fflag)
server_client_set_flags(c, fflag);
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index dcb56c06..b4e4167c 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -33,9 +33,9 @@ const struct cmd_entry cmd_bind_key_entry = {
.name = "bind-key",
.alias = "bind",
- .args = { "nrN:T:", 2, -1 },
+ .args = { "nrN:T:", 1, -1 },
.usage = "[-nr] [-T key-table] [-N note] key "
- "command [arguments]",
+ "[command [arguments]]",
.flags = CMD_AFTERHOOK,
.exec = cmd_bind_key_exec
@@ -46,7 +46,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
key_code key;
- const char *tablename, *note;
+ const char *tablename, *note = args_get(args, 'N');
struct cmd_parse_result *pr;
char **argv = args->argv;
int argc = args->argc, repeat;
@@ -65,22 +65,24 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
tablename = "prefix";
repeat = args_has(args, 'r');
- if (argc == 2)
- pr = cmd_parse_from_string(argv[1], NULL);
- else
- pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL);
- switch (pr->status) {
- case CMD_PARSE_EMPTY:
- cmdq_error(item, "empty command");
- return (CMD_RETURN_ERROR);
- case CMD_PARSE_ERROR:
- cmdq_error(item, "%s", pr->error);
- free(pr->error);
- return (CMD_RETURN_ERROR);
- case CMD_PARSE_SUCCESS:
- break;
- }
- note = args_get(args, 'N');
- key_bindings_add(tablename, key, note, repeat, pr->cmdlist);
+ if (argc != 1) {
+ if (argc == 2)
+ pr = cmd_parse_from_string(argv[1], NULL);
+ else
+ pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL);
+ switch (pr->status) {
+ case CMD_PARSE_EMPTY:
+ cmdq_error(item, "empty command");
+ return (CMD_RETURN_ERROR);
+ case CMD_PARSE_ERROR:
+ cmdq_error(item, "%s", pr->error);
+ free(pr->error);
+ return (CMD_RETURN_ERROR);
+ case CMD_PARSE_SUCCESS:
+ break;
+ }
+ key_bindings_add(tablename, key, note, repeat, pr->cmdlist);
+ } else
+ key_bindings_add(tablename, key, note, repeat, NULL);
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-display-message.c b/cmd-display-message.c
index 634f0a93..fc9c4851 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -39,8 +39,8 @@ const struct cmd_entry cmd_display_message_entry = {
.name = "display-message",
.alias = "display",
- .args = { "ac:Ipt:F:v", 0, 1 },
- .usage = "[-aIpv] [-c target-client] [-F format] "
+ .args = { "acd:Ipt:F:v", 0, 1 },
+ .usage = "[-aIpv] [-c target-client] [-d delay] [-F format] "
CMD_TARGET_PANE_USAGE " [message]",
.target = { 't', CMD_FIND_PANE, 0 },
@@ -68,6 +68,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
struct window_pane *wp = target->wp;
const char *template;
char *msg, *cause;
+ int delay = -1;
struct format_tree *ft;
int flags;
@@ -85,6 +86,15 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
+ if (args_has(args, 'd')) {
+ delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
+ if (cause != NULL) {
+ cmdq_error(item, "delay %s", cause);
+ free(cause);
+ return (CMD_RETURN_ERROR);
+ }
+ }
+
template = args_get(args, 'F');
if (args->argc != 0)
template = args->argv[0];
@@ -117,7 +127,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'p'))
cmdq_print(item, "%s", msg);
else if (tc != NULL)
- status_message_set(tc, 0, "%s", msg);
+ status_message_set(tc, delay, 0, "%s", msg);
free(msg);
format_free(ft);
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index a13a06ae..352b2e4d 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -55,11 +55,11 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct session *s = c->session;
struct options *oo = s->options;
struct window *w = wp->window;
- struct grid_cell gc;
- u_int idx, px, py, i, j, xoff, yoff, sx, sy;
+ struct grid_cell fgc, bgc;
+ u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
int colour, active_colour;
- char buf[16], *ptr;
- size_t len;
+ char buf[16], lbuf[16], rbuf[16], *ptr;
+ size_t len, llen, rlen;
if (wp->xoff + wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + ctx->sx ||
@@ -109,29 +109,50 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
px = sx / 2;
py = sy / 2;
- if (window_pane_index(wp, &idx) != 0)
+ if (window_pane_index(wp, &pane) != 0)
fatalx("index not found");
- len = xsnprintf(buf, sizeof buf, "%u", idx);
+ len = xsnprintf(buf, sizeof buf, "%u", pane);
if (sx < len)
return;
colour = options_get_number(oo, "display-panes-colour");
active_colour = options_get_number(oo, "display-panes-active-colour");
+ memcpy(&fgc, &grid_default_cell, sizeof fgc);
+ memcpy(&bgc, &grid_default_cell, sizeof bgc);
+ if (w->active == wp) {
+ fgc.fg = active_colour;
+ bgc.bg = active_colour;
+ } else {
+ fgc.fg = colour;
+ bgc.bg = colour;
+ }
+
+ rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy);
+ if (pane > 9 && pane < 35)
+ llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
+ else
+ llen = 0;
+
if (sx < len * 6 || sy < 5) {
- tty_cursor(tty, xoff + px - len / 2, yoff + py);
- goto draw_text;
+ tty_attributes(tty, &fgc, &grid_default_cell, NULL);
+ if (sx >= len + llen + 1) {
+ len += llen + 1;
+ tty_cursor(tty, xoff + px - len / 2, yoff + py);
+ tty_putn(tty, buf, len, len);
+ tty_putn(tty, " ", 1, 1);
+ tty_putn(tty, lbuf, llen, llen);
+ } else {
+ tty_cursor(tty, xoff + px - len / 2, yoff + py);
+ tty_putn(tty, buf, len, len);
+ }
+ goto out;
}
px -= len * 3;
py -= 2;
- memcpy(&gc, &grid_default_cell, sizeof gc);
- if (w->active == wp)
- gc.bg = active_colour;
- else
- gc.bg = colour;
- tty_attributes(tty, &gc, &grid_default_cell, NULL);
+ tty_attributes(tty, &bgc, &grid_default_cell, NULL);
for (ptr = buf; *ptr != '\0'; ptr++) {
if (*ptr < '0' || *ptr > '9')
continue;
@@ -147,20 +168,20 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
px += 6;
}
- len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
- if (sx < len || sy < 6)
- return;
- tty_cursor(tty, xoff + sx - len, yoff);
-
-draw_text:
- memcpy(&gc, &grid_default_cell, sizeof gc);
- if (w->active == wp)
- gc.fg = active_colour;
- else
- gc.fg = colour;
- tty_attributes(tty, &gc, &grid_default_cell, NULL);
- tty_puts(tty, buf);
+ if (sy <= 6)
+ goto out;
+ tty_attributes(tty, &fgc, &grid_default_cell, NULL);
+ if (rlen != 0 && sx >= rlen) {
+ tty_cursor(tty, xoff + sx - rlen, yoff);
+ tty_putn(tty, rbuf, rlen, rlen);
+ }
+ if (llen != 0) {
+ tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1,
+ yoff + py + 5);
+ tty_putn(tty, lbuf, llen, llen);
+ }
+out:
tty_cursor(tty, 0, 0);
}
@@ -197,11 +218,21 @@ cmd_display_panes_key(struct client *c, struct key_event *event)
struct window *w = c->session->curw->window;
struct window_pane *wp;
enum cmd_parse_status status;
-
- if (event->key < '0' || event->key > '9')
+ u_int index;
+ key_code key;
+
+ if (event->key >= '0' && event->key <= '9')
+ index = event->key - '0';
+ else if ((event->key & KEYC_MASK_MODIFIERS) == 0) {
+ key = (event->key & KEYC_MASK_KEY);
+ if (key >= 'a' && key <= 'z')
+ index = 10 + (key - 'a');
+ else
+ return (-1);
+ } else
return (-1);
- wp = window_pane_at_index(w, event->key - '0');
+ wp = window_pane_at_index(w, index);
if (wp == NULL)
return (1);
window_unzoom(w);
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index b3bdbd12..dd82e57e 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -114,7 +114,7 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
note = xstrdup(bd->note);
tmp = utf8_padcstr(key, keywidth + 1);
if (args_has(args, '1') && tc != NULL)
- status_message_set(tc, 1, "%s%s%s", prefix, tmp, note);
+ status_message_set(tc, -1, 1, "%s%s%s", prefix, tmp, note);
else
cmdq_print(item, "%s%s%s", prefix, tmp, note);
free(tmp);
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 49e834d6..bca9a860 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -37,14 +37,15 @@ const struct cmd_entry cmd_load_buffer_entry = {
.name = "load-buffer",
.alias = "loadb",
- .args = { "b:", 1, 1 },
- .usage = CMD_BUFFER_USAGE " path",
+ .args = { "b:t:w", 1, 1 },
+ .usage = CMD_BUFFER_USAGE " " CMD_TARGET_CLIENT_USAGE " path",
- .flags = CMD_AFTERHOOK,
+ .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_load_buffer_exec
};
struct cmd_load_buffer_data {
+ struct client *client;
struct cmdq_item *item;
char *name;
};
@@ -54,6 +55,7 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
int closed, struct evbuffer *buffer, void *data)
{
struct cmd_load_buffer_data *cdata = data;
+ struct client *tc = cdata->client;
struct cmdq_item *item = cdata->item;
void *bdata = EVBUFFER_DATA(buffer);
size_t bsize = EVBUFFER_LENGTH(buffer);
@@ -72,7 +74,12 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
cmdq_error(item, "%s", cause);
free(cause);
free(copy);
- }
+ } else if (tc != NULL &&
+ tc->session != NULL &&
+ (~tc->flags & CLIENT_DEAD))
+ tty_set_selection(&tc->tty, copy, bsize);
+ if (tc != NULL)
+ server_client_unref(tc);
}
cmdq_continue(item);
@@ -84,16 +91,19 @@ static enum cmd_retval
cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
+ struct client *tc = cmdq_get_target_client(item);
struct cmd_load_buffer_data *cdata;
const char *bufname = args_get(args, 'b');
char *path;
- cdata = xmalloc(sizeof *cdata);
+ cdata = xcalloc(1, sizeof *cdata);
cdata->item = item;
if (bufname != NULL)
cdata->name = xstrdup(bufname);
- else
- cdata->name = NULL;
+ if (args_has(args, 'w') && tc != NULL) {
+ cdata->client = tc;
+ cdata->client->references++;
+ }
path = format_single_from_target(item, args->argv[0]);
file_read(cmdq_get_client(item), path, cmd_load_buffer_done, cdata);
diff --git a/cmd-queue.c b/cmd-queue.c
index 693f7d90..36f1c9be 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -858,7 +858,7 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
c->retval = 1;
} else {
*msg = toupper((u_char) *msg);
- status_message_set(c, 1, "%s", msg);
+ status_message_set(c, -1, 1, "%s", msg);
}
free(msg);
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index b0c78d74..30529722 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -198,6 +198,7 @@ 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)) {
+ notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
}
diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c
index 0f3fffce..94d8cd52 100644
--- a/cmd-set-buffer.c
+++ b/cmd-set-buffer.c
@@ -33,10 +33,11 @@ const struct cmd_entry cmd_set_buffer_entry = {
.name = "set-buffer",
.alias = "setb",
- .args = { "ab:n:", 0, 1 },
- .usage = "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
+ .args = { "ab:t:n:w", 0, 1 },
+ .usage = "[-aw] " CMD_BUFFER_USAGE " [-n new-buffer-name] "
+ CMD_TARGET_CLIENT_USAGE " data",
- .flags = CMD_AFTERHOOK,
+ .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_set_buffer_exec
};
@@ -55,6 +56,7 @@ static enum cmd_retval
cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
+ struct client *tc = cmdq_get_target_client(item);
struct paste_buffer *pb;
char *bufdata, *cause;
const char *bufname, *olddata;
@@ -118,6 +120,8 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
+ if (args_has(args, 'w') && tc != NULL)
+ tty_set_selection(&tc->tty, bufdata, bufsize);
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-set-environment.c b/cmd-set-environment.c
index 3c43b635..f142df53 100644
--- a/cmd-set-environment.c
+++ b/cmd-set-environment.c
@@ -34,8 +34,8 @@ const struct cmd_entry cmd_set_environment_entry = {
.name = "set-environment",
.alias = "setenv",
- .args = { "hgrt:u", 1, 2 },
- .usage = "[-hgru] " CMD_TARGET_SESSION_USAGE " name [value]",
+ .args = { "Fhgrt:u", 1, 2 },
+ .usage = "[-Fhgru] " CMD_TARGET_SESSION_USAGE " name [value]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@@ -50,6 +50,8 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_find_state *target = cmdq_get_target(item);
struct environ *env;
const char *name, *value, *tflag;
+ char *expand = NULL;
+ enum cmd_retval retval = CMD_RETURN_NORMAL;
name = args->argv[0];
if (*name == '\0') {
@@ -63,6 +65,8 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
if (args->argc < 2)
value = NULL;
+ else if (args_has(args, 'F'))
+ value = expand = format_single_from_target(item, args->argv[1]);
else
value = args->argv[1];
@@ -75,7 +79,8 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "no such session: %s", tflag);
else
cmdq_error(item, "no current session");
- return (CMD_RETURN_ERROR);
+ retval = CMD_RETURN_ERROR;
+ goto out;
}
env = target->s->environ;
}
@@ -83,25 +88,31 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'u')) {
if (value != NULL) {
cmdq_error(item, "can't specify a value with -u");
- return (CMD_RETURN_ERROR);
+ retval = CMD_RETURN_ERROR;
+ goto out;
}
environ_unset(env, name);
} else if (args_has(args, 'r')) {
if (value != NULL) {
cmdq_error(item, "can't specify a value with -r");
- return (CMD_RETURN_ERROR);
+ retval = CMD_RETURN_ERROR;
+ goto out;
}
environ_clear(env, name);
} else {
if (value == NULL) {
cmdq_error(item, "no value specified");
- return (CMD_RETURN_ERROR);
+ retval = CMD_RETURN_ERROR;
+ goto out;
}
+
if (args_has(args, 'h'))
environ_set(env, name, ENVIRON_HIDDEN, "%s", value);
else
environ_set(env, name, 0, "%s", value);
}
- return (CMD_RETURN_NORMAL);
+out:
+ free(expand);
+ return (retval);
}
diff --git a/cmd-source-file.c b/cmd-source-file.c
index f5a0ca4b..1da59193 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -35,8 +35,8 @@ const struct cmd_entry cmd_source_file_entry = {
.name = "source-file",
.alias = "source",
- .args = { "nqv", 1, -1 },
- .usage = "[-nqv] path ...",
+ .args = { "Fnqv", 1, -1 },
+ .usage = "[-Fnqv] path ...",
.flags = 0,
.exec = cmd_source_file_exec
@@ -126,7 +126,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_source_file_data *cdata;
struct client *c = cmdq_get_client(item);
enum cmd_retval retval = CMD_RETURN_NORMAL;
- char *pattern, *cwd;
+ char *pattern, *cwd, *expand = NULL;
const char *path, *error;
glob_t g;
int i, result;
@@ -145,7 +145,12 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB);
for (i = 0; i < args->argc; i++) {
- path = args->argv[i];
+ if (args_has(args, 'F')) {
+ free(expand);
+ expand = format_single_from_target(item, args->argv[i]);
+ path = expand;
+ } else
+ path = args->argv[i];
if (strcmp(path, "-") == 0) {
cmd_source_file_add(cdata, "-");
continue;
@@ -172,6 +177,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
free(pattern);
continue;
}
+ free(expand);
free(pattern);
for (j = 0; j < g.gl_pathc; j++)
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index 4b9f39a6..a29831af 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -32,8 +32,8 @@ const struct cmd_entry cmd_unbind_key_entry = {
.name = "unbind-key",
.alias = "unbind",
- .args = { "anT:", 0, 1 },
- .usage = "[-an] [-T key-table] key",
+ .args = { "anqT:", 0, 1 },
+ .usage = "[-anq] [-T key-table] key",
.flags = CMD_AFTERHOOK,
.exec = cmd_unbind_key_exec
@@ -45,44 +45,54 @@ cmd_unbind_key_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
key_code key;
const char *tablename;
+ int quiet = args_has(args, 'q');
- if (!args_has(args, 'a')) {
- if (args->argc != 1) {
- cmdq_error(item, "missing key");
- return (CMD_RETURN_ERROR);
- }
- key = key_string_lookup_string(args->argv[0]);
- if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
- cmdq_error(item, "unknown key: %s", args->argv[0]);
- return (CMD_RETURN_ERROR);
- }
- } else {
+ if (args_has(args, 'a')) {
if (args->argc != 0) {
- cmdq_error(item, "key given with -a");
+ if (!quiet)
+ cmdq_error(item, "key given with -a");
return (CMD_RETURN_ERROR);
}
- key = KEYC_UNKNOWN;
- }
- if (key == KEYC_UNKNOWN) {
tablename = args_get(args, 'T');
if (tablename == NULL) {
- key_bindings_remove_table("root");
- key_bindings_remove_table("prefix");
- return (CMD_RETURN_NORMAL);
+ if (args_has(args, 'n'))
+ tablename = "root";
+ else
+ tablename = "prefix";
}
if (key_bindings_get_table(tablename, 0) == NULL) {
- cmdq_error(item, "table %s doesn't exist", tablename);
+ if (!quiet) {
+ cmdq_error(item, "table %s doesn't exist" ,
+ tablename);
+ }
return (CMD_RETURN_ERROR);
}
+
key_bindings_remove_table(tablename);
return (CMD_RETURN_NORMAL);
}
+ if (args->argc != 1) {
+ if (!quiet)
+ cmdq_error(item, "missing key");
+ return (CMD_RETURN_ERROR);
+ }
+
+ key = key_string_lookup_string(args->argv[0]);
+ if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
+ if (!quiet)
+ cmdq_error(item, "unknown key: %s", args->argv[0]);
+ return (CMD_RETURN_ERROR);
+ }
+
if (args_has(args, 'T')) {
tablename = args_get(args, 'T');
if (key_bindings_get_table(tablename, 0) == NULL) {
- cmdq_error(item, "table %s doesn't exist", tablename);
+ if (!quiet) {
+ cmdq_error(item, "table %s doesn't exist" ,
+ tablename);
+ }
return (CMD_RETURN_ERROR);
}
} else if (args_has(args, 'n'))
diff --git a/colour.c b/colour.c
index c7972878..ee4b95db 100644
--- a/colour.c
+++ b/colour.c
@@ -189,6 +189,12 @@ colour_fromstring(const char *s)
return (-1);
return (n | COLOUR_FLAG_256);
}
+ if (strncasecmp(s, "color", (sizeof "color") - 1) == 0) {
+ n = strtonum(s + (sizeof "color") - 1, 0, 255, &errstr);
+ if (errstr != NULL)
+ return (-1);
+ return (n | COLOUR_FLAG_256);
+ }
if (strcasecmp(s, "default") == 0)
return (8);
diff --git a/compat.h b/compat.h
index 5b23b178..4efad6ee 100644
--- a/compat.h
+++ b/compat.h
@@ -35,6 +35,10 @@
#define __attribute__(a)
#endif
+#ifdef BROKEN___DEAD
+#undef __dead
+#endif
+
#ifndef __unused
#define __unused __attribute__ ((__unused__))
#endif
diff --git a/configure.ac b/configure.ac
index 22a48c8d..eb1a9594 100644
--- a/configure.ac
+++ b/configure.ac
@@ -570,6 +570,12 @@ case "$host_os" in
AC_MSG_RESULT(darwin)
PLATFORM=darwin
#
+ # OS X uses __dead2 instead of __dead, like FreeBSD. But it
+ # defines __dead away so it needs to be removed before we can
+ # replace it.
+ #
+ AC_DEFINE(BROKEN___DEAD)
+ #
# OS X CMSG_FIRSTHDR is broken, so redefine it with a working
# one. daemon works but has some stupid side effects, so use
# our internal version which has a workaround.
diff --git a/control.c b/control.c
index c52f2020..e86429cf 100644
--- a/control.c
+++ b/control.c
@@ -688,8 +688,8 @@ control_write_pending(struct client *c, struct control_pane *cp, size_t limit)
else
age = 0;
log_debug("%s: %s: output block %zu (age %llu) for %%%u "
- "(used %zu/%zu)", __func__, c->name, cb->size, age,
- cp->pane, used, limit);
+ "(used %zu/%zu)", __func__, c->name, cb->size,
+ (unsigned long long)age, cp->pane, used, limit);
size = cb->size;
if (size > limit - used)
diff --git a/format.c b/format.c
index ced7b515..b88120cb 100644
--- a/format.c
+++ b/format.c
@@ -94,6 +94,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_WINDOWS 0x100
#define FORMAT_PANES 0x200
#define FORMAT_PRETTY 0x400
+#define FORMAT_LENGTH 0x800
/* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 10
@@ -1642,7 +1643,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
/*
* Modifiers are a ; separated list of the forms:
- * l,m,C,b,d,t,q,E,T,S,W,P,<,>
+ * l,m,C,b,d,n,t,q,E,T,S,W,P,<,>
* =a
* =/a
* =/a/
@@ -1659,7 +1660,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
cp++;
/* Check single character modifiers with no arguments. */
- if (strchr("lbdqETSWP<>", cp[0]) != NULL &&
+ if (strchr("lbdnqETSWP<>", cp[0]) != NULL &&
format_is_end(cp[1])) {
format_add_modifier(&list, count, cp, 1, NULL, 0);
cp++;
@@ -2117,6 +2118,9 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
case 'd':
modifiers |= FORMAT_DIRNAME;
break;
+ case 'n':
+ modifiers |= FORMAT_LENGTH;
+ break;
case 't':
modifiers |= FORMAT_TIMESTRING;
if (fm->argc < 1)
@@ -2296,13 +2300,17 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
if (value == NULL)
value = xstrdup("");
} else {
- /* Neither: look up directly. */
- value = format_find(ft, copy, modifiers, time_format);
- if (value == NULL) {
- format_log(ft, "format '%s' not found", copy);
- value = xstrdup("");
- } else
- format_log(ft, "format '%s' found: %s", copy, value);
+ if (strstr(copy, "#{") != 0) {
+ format_log(ft, "expanding inner format '%s'", copy);
+ value = format_expand(ft, copy);
+ } else {
+ value = format_find(ft, copy, modifiers, time_format);
+ if (value == NULL) {
+ format_log(ft, "format '%s' not found", copy);
+ value = xstrdup("");
+ } else
+ format_log(ft, "format '%s' found: %s", copy, value);
+ }
}
done:
@@ -2311,8 +2319,7 @@ done:
new = format_expand(ft, value);
free(value);
value = new;
- }
- else if (modifiers & FORMAT_EXPANDTIME) {
+ } else if (modifiers & FORMAT_EXPANDTIME) {
new = format_expand_time(ft, value);
free(value);
value = new;
@@ -2366,6 +2373,14 @@ done:
format_log(ft, "applied padding width %d: %s", width, value);
}
+ /* Replace with the length if needed. */
+ if (modifiers & FORMAT_LENGTH) {
+ xasprintf(&new, "%zu", strlen(value));
+ free(value);
+ value = new;
+ format_log(ft, "replacing with length: %s", new);
+ }
+
/* Expand the buffer and copy in the value. */
valuelen = strlen(value);
while (*len - *off < valuelen + 1) {
@@ -2889,6 +2904,7 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_dead", "%d", wp->fd == -1);
else
format_add(ft, "pane_dead", "0");
+ format_add(ft, "pane_last", "%d", wp == w->last);
if (server_check_marked() && marked_pane.wp == wp)
format_add(ft, "pane_marked", "1");
diff --git a/grid.c b/grid.c
index 5ea5bf62..96302fc3 100644
--- a/grid.c
+++ b/grid.c
@@ -463,7 +463,7 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
sx = gd->sx / 4;
else if (sx < gd->sx / 2)
sx = gd->sx / 2;
- else
+ else if (gd->sx > sx)
sx = gd->sx;
gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata);
@@ -1277,7 +1277,7 @@ grid_reflow(struct grid *gd, u_int sx)
struct grid *target;
struct grid_line *gl;
struct grid_cell gc;
- u_int yy, width, i, at, first;
+ u_int yy, width, i, at;
/*
* Create a destination grid. This is just used as a container for the
@@ -1294,13 +1294,12 @@ grid_reflow(struct grid *gd, u_int sx)
continue;
/*
- * Work out the width of this line. first is the width of the
- * first character, at is the point at which the available
- * width is hit, and width is the full line width.
+ * Work out the width of this line. at is the point at which
+ * the available width is hit, and width is the full line
+ * width.
*/
- first = at = width = 0;
+ at = width = 0;
if (~gl->flags & GRID_LINE_EXTENDED) {
- first = 1;
width = gl->cellused;
if (width > sx)
at = sx;
@@ -1309,8 +1308,6 @@ grid_reflow(struct grid *gd, u_int sx)
} else {
for (i = 0; i < gl->cellused; i++) {
grid_get_cell1(gl, i, &gc);
- if (i == 0)
- first = gc.data.width;
if (at == 0 && width + gc.data.width > sx)
at = i;
width += gc.data.width;
@@ -1318,10 +1315,10 @@ grid_reflow(struct grid *gd, u_int sx)
}
/*
- * If the line is exactly right or the first character is wider
- * than the target width, just move it across unchanged.
+ * If the line is exactly right, just move it across
+ * unchanged.
*/
- if (width == sx || first > sx) {
+ if (width == sx) {
grid_reflow_move(target, gl);
continue;
}
diff --git a/input-keys.c b/input-keys.c
index ff402503..32ca4b97 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -555,6 +555,8 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
modifier = '8';
break;
+ default:
+ fatalx("invalid key modifiers: %llx", key);
}
xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier);
bufferevent_write(bev, tmp, strlen(tmp));
diff --git a/input.c b/input.c
index a3850371..42a60c92 100644
--- a/input.c
+++ b/input.c
@@ -65,7 +65,7 @@ struct input_param {
INPUT_MISSING,
INPUT_NUMBER,
INPUT_STRING
- } type;
+ } type;
union {
int num;
char *str;
@@ -81,7 +81,7 @@ struct input_ctx {
struct input_cell cell;
struct input_cell old_cell;
- u_int old_cx;
+ u_int old_cx;
u_int old_cy;
int old_mode;
@@ -121,7 +121,7 @@ struct input_ctx {
* All input received since we were last in the ground state. Sent to
* control clients on connection.
*/
- struct evbuffer *since_ground;
+ struct evbuffer *since_ground;
};
/* Helper functions. */
@@ -1867,6 +1867,7 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
case 2:
screen_pop_title(sctx->s);
if (wp != NULL) {
+ notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
}
@@ -2261,6 +2262,7 @@ input_exit_osc(struct input_ctx *ictx)
case 0:
case 2:
if (screen_set_title(sctx->s, p) && wp != NULL) {
+ notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
}
@@ -2326,6 +2328,7 @@ input_exit_apc(struct input_ctx *ictx)
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL) {
+ notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
}
@@ -2456,13 +2459,31 @@ input_osc_parse_colour(const char *p, u_int *r, u_int *g, u_int *b)
return (1);
}
+/* Reply to a colour request. */
+static void
+input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c)
+{
+ u_char r, g, b;
+ const char *end;
+
+ if (c == 8 || (~c & COLOUR_FLAG_RGB))
+ return;
+ colour_split_rgb(c, &r, &g, &b);
+
+ if (ictx->input_end == INPUT_END_BEL)
+ end = "\007";
+ else
+ end = "\033\\";
+ input_reply(ictx, "\033]%u;rgb:%02hhx/%02hhx/%02hhx%s", n, r, g, b, end);
+}
+
/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
static void
input_osc_4(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
char *copy, *s, *next = NULL;
- long idx;
+ long idx;
u_int r, g, b;
if (wp == NULL)
@@ -2494,17 +2515,22 @@ bad:
free(copy);
}
-/* Handle the OSC 10 sequence for setting foreground colour. */
+/* Handle the OSC 10 sequence for setting and querying foreground colour. */
static void
input_osc_10(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
+ struct grid_cell defaults;
u_int r, g, b;
if (wp == NULL)
return;
- if (strcmp(p, "?") == 0)
+
+ if (strcmp(p, "?") == 0) {
+ tty_default_colours(&defaults, wp);
+ input_osc_colour_reply(ictx, 10, defaults.fg);
return;
+ }
if (!input_osc_parse_colour(p, &r, &g, &b))
goto bad;
@@ -2517,17 +2543,22 @@ bad:
log_debug("bad OSC 10: %s", p);
}
-/* Handle the OSC 11 sequence for setting background colour. */
+/* Handle the OSC 11 sequence for setting and querying background colour. */
static void
input_osc_11(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
+ struct grid_cell defaults;
u_int r, g, b;
if (wp == NULL)
return;
- if (strcmp(p, "?") == 0)
+
+ if (strcmp(p, "?") == 0) {
+ tty_default_colours(&defaults, wp);
+ input_osc_colour_reply(ictx, 11, defaults.bg);
return;
+ }
if (!input_osc_parse_colour(p, &r, &g, &b))
goto bad;
diff --git a/key-bindings.c b/key-bindings.c
index f11bb430..63d4bb26 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -191,6 +191,16 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat,
table = key_bindings_get_table(name, 1);
bd = key_bindings_get(table, key & ~KEYC_MASK_FLAGS);
+ if (cmdlist == NULL) {
+ if (bd != NULL) {
+ free((void *)bd->note);
+ if (note != NULL)
+ bd->note = xstrdup(note);
+ else
+ bd->note = NULL;
+ }
+ return;
+ }
if (bd != NULL) {
RB_REMOVE(key_bindings, &table->key_bindings, bd);
key_bindings_free(bd);
diff --git a/mode-tree.c b/mode-tree.c
index c4b776f9..a47c0c06 100644
--- a/mode-tree.c
+++ b/mode-tree.c
@@ -1176,7 +1176,7 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs,
if (status == CMD_PARSE_ERROR) {
if (c != NULL) {
*error = toupper((u_char)*error);
- status_message_set(c, 1, "%s", error);
+ status_message_set(c, -1, 1, "%s", error);
}
free(error);
}
diff --git a/options-table.c b/options-table.c
index 0555d43e..873f8d67 100644
--- a/options-table.c
+++ b/options-table.c
@@ -170,6 +170,14 @@ static const char *options_table_status_format_default[] = {
.separator = "" \
}
+/* Map of name conversions. */
+const struct options_name_map options_other_names[] = {
+ { "display-panes-color", "display-panes-colour" },
+ { "display-panes-active-color", "display-panes-active-colour" },
+ { "clock-mode-color", "clock-mode-colour" },
+ { NULL, NULL }
+};
+
/* Top-level options. */
const struct options_table_entry options_table[] = {
/* Server options. */
@@ -1120,6 +1128,7 @@ const struct options_table_entry options_table[] = {
OPTIONS_TABLE_PANE_HOOK("pane-focus-out", ""),
OPTIONS_TABLE_PANE_HOOK("pane-mode-changed", ""),
OPTIONS_TABLE_PANE_HOOK("pane-set-clipboard", ""),
+ OPTIONS_TABLE_PANE_HOOK("pane-title-changed", ""),
OPTIONS_TABLE_HOOK("session-closed", ""),
OPTIONS_TABLE_HOOK("session-created", ""),
OPTIONS_TABLE_HOOK("session-renamed", ""),
diff --git a/options.c b/options.c
index 336eb732..09850f7e 100644
--- a/options.c
+++ b/options.c
@@ -95,6 +95,18 @@ options_cmp(struct options_entry *lhs, struct options_entry *rhs)
return (strcmp(lhs->name, rhs->name));
}
+static const char *
+options_map_name(const char *name)
+{
+ const struct options_name_map *map;
+
+ for (map = options_other_names; map->from != NULL; map++) {
+ if (strcmp(map->from, name) == 0)
+ return (map->to);
+ }
+ return (name);
+}
+
static const struct options_table_entry *
options_parent_table_entry(struct options *oo, const char *s)
{
@@ -204,10 +216,14 @@ options_next(struct options_entry *o)
struct options_entry *
options_get_only(struct options *oo, const char *name)
{
- struct options_entry o;
+ struct options_entry o = { .name = name }, *found;
- o.name = name;
- return (RB_FIND(options_tree, &oo->tree, &o));
+ found = RB_FIND(options_tree, &oo->tree, &o);
+ if (found == NULL) {
+ o.name = options_map_name(name);
+ return (RB_FIND(options_tree, &oo->tree, &o));
+ }
+ return (found);
}
struct options_entry *
@@ -608,19 +624,21 @@ char *
options_match(const char *s, int *idx, int *ambiguous)
{
const struct options_table_entry *oe, *found;
- char *name;
+ char *parsed;
+ const char *name;
size_t namelen;
- name = options_parse(s, idx);
- if (name == NULL)
+ parsed = options_parse(s, idx);
+ if (parsed == NULL)
return (NULL);
- namelen = strlen(name);
-
- if (*name == '@') {
+ if (*parsed == '@') {
*ambiguous = 0;
- return (name);
+ return (parsed);
}
+ name = options_map_name(parsed);
+ namelen = strlen(name);
+
found = NULL;
for (oe = options_table; oe->name != NULL; oe++) {
if (strcmp(oe->name, name) == 0) {
@@ -630,13 +648,13 @@ options_match(const char *s, int *idx, int *ambiguous)
if (strncmp(oe->name, name, namelen) == 0) {
if (found != NULL) {
*ambiguous = 1;
- free(name);
+ free(parsed);
return (NULL);
}
found = oe;
}
}
- free(name);
+ free(parsed);
if (found == NULL) {
*ambiguous = 0;
return (NULL);
diff --git a/popup.c b/popup.c
index 6f2ab101..0ad20c5f 100644
--- a/popup.c
+++ b/popup.c
@@ -261,7 +261,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
pd->sx = m->x - pd->px;
pd->sy = m->y - pd->py;
- screen_resize(&pd->s, pd->sx, pd->sy, 0);
+ screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0);
if (pd->ictx == NULL)
popup_write_screen(c, pd);
else if (pd->job != NULL)
diff --git a/proc.c b/proc.c
index ebc39386..9291344b 100644
--- a/proc.c
+++ b/proc.c
@@ -239,6 +239,7 @@ proc_set_signals(struct tmuxproc *tp, void (*signalcb)(int))
sigaction(SIGTSTP, &sa, NULL);
sigaction(SIGTTIN, &sa, NULL);
sigaction(SIGTTOU, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
signal_set(&tp->ev_sigint, SIGINT, proc_signal_cb, tp);
signal_add(&tp->ev_sigint, NULL);
diff --git a/server-client.c b/server-client.c
index 5749ba94..62281c83 100644
--- a/server-client.c
+++ b/server-client.c
@@ -1660,8 +1660,6 @@ server_client_reset_state(struct client *c)
s = wp->screen;
if (s != NULL)
mode = s->mode;
- if (c->prompt_string != NULL || c->message_string != NULL)
- mode &= ~MODE_CURSOR;
log_debug("%s: client %s mode %x", __func__, c->name, mode);
/* Reset region and margin. */
@@ -1985,6 +1983,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
switch (imsg->hdr.type) {
case MSG_IDENTIFY_FEATURES:
case MSG_IDENTIFY_FLAGS:
+ case MSG_IDENTIFY_LONGFLAGS:
case MSG_IDENTIFY_TERM:
case MSG_IDENTIFY_TTYNAME:
case MSG_IDENTIFY_CWD:
@@ -2143,6 +2142,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
const char *data, *home;
size_t datalen;
int flags, feat;
+ uint64_t longflags;
char *name;
if (c->flags & CLIENT_IDENTIFIED)
@@ -2167,6 +2167,14 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
c->flags |= flags;
log_debug("client %p IDENTIFY_FLAGS %#x", c, flags);
break;
+ case MSG_IDENTIFY_LONGFLAGS:
+ if (datalen != sizeof longflags)
+ fatalx("bad MSG_IDENTIFY_LONGFLAGS size");
+ memcpy(&longflags, data, sizeof longflags);
+ c->flags |= longflags;
+ log_debug("client %p IDENTIFY_LONGFLAGS %#llx", c,
+ (unsigned long long)longflags);
+ break;
case MSG_IDENTIFY_TERM:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_IDENTIFY_TERM string");
diff --git a/server-fn.c b/server-fn.c
index d5e7cbd7..e3cc181f 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -342,6 +342,7 @@ server_destroy_pane(struct window_pane *wp, int notify)
time(&t);
ctime_r(&t, tim);
+ tim[strcspn(tim, "\n")] = '\0';
if (WIFEXITED(wp->status)) {
screen_write_nputs(&ctx, -1, &gc,
diff --git a/server.c b/server.c
index ffbd28c1..9a1875f4 100644
--- a/server.c
+++ b/server.c
@@ -157,7 +157,7 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
{
int pair[2];
sigset_t set, oldset;
- struct client *c;
+ struct client *c = NULL;
char *cause = NULL;
sigfillset(&set);
@@ -223,9 +223,11 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
}
if (cause != NULL) {
- cmdq_append(c, cmdq_get_error(cause));
+ if (c != NULL) {
+ cmdq_append(c, cmdq_get_error(cause));
+ c->flags |= CLIENT_EXIT;
+ }
free(cause);
- c->flags |= CLIENT_EXIT;
}
server_add_accept(0);
diff --git a/status.c b/status.c
index 7313d2a0..668c0a3b 100644
--- a/status.c
+++ b/status.c
@@ -423,11 +423,11 @@ status_redraw(struct client *c)
/* Set a status line message. */
void
-status_message_set(struct client *c, int ignore_styles, const char *fmt, ...)
+status_message_set(struct client *c, int delay, int ignore_styles,
+ const char *fmt, ...)
{
struct timeval tv;
va_list ap;
- int delay;
status_message_clear(c);
status_push_screen(c);
@@ -439,7 +439,12 @@ status_message_set(struct client *c, int ignore_styles, const char *fmt, ...)
server_add_message("%s message: %s", c->name, c->message_string);
- delay = options_get_number(c->session->options, "display-time");
+ /*
+ * With delay -1, the display-time option is used; zero means wait for
+ * key press; more than zero is the actual delay time in milliseconds.
+ */
+ if (delay == -1)
+ delay = options_get_number(c->session->options, "display-time");
if (delay > 0) {
tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L;
@@ -447,6 +452,7 @@ status_message_set(struct client *c, int ignore_styles, const char *fmt, ...)
if (event_initialized(&c->message_timer))
evtimer_del(&c->message_timer);
evtimer_set(&c->message_timer, status_message_callback, c);
+
evtimer_add(&c->message_timer, &tv);
}
diff --git a/tmux.1 b/tmux.1
index 65ce211f..9b8f4420 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1407,7 +1407,7 @@ and
.Fl T
show debugging information about jobs and terminals.
.It Xo Ic source-file
-.Op Fl nqv
+.Op Fl Fnqv
.Ar path
.Ar ...
.Xc
@@ -1418,6 +1418,11 @@ Execute commands from one or more files specified by
.Xr glob 7
patterns).
If
+.Fl F
+is present, then
+.Ar path
+is expanded as a format.
+If
.Fl q
is given, no error will be returned if
.Ar path
@@ -3034,7 +3039,7 @@ Send the prefix key, or with
.Fl 2
the secondary prefix key, to a window as if it was pressed.
.It Xo Ic unbind-key
-.Op Fl an
+.Op Fl anq
.Op Fl T Ar key-table
.Ar key
.Xc
@@ -3049,6 +3054,9 @@ are the same as for
If
.Fl a
is present, all key bindings are removed.
+The
+.Fl q
+option prevents errors being returned.
.El
.Sh OPTIONS
The appearance and behaviour of
@@ -3159,6 +3167,9 @@ flag unsets an option, so a session inherits the option from the global
options (or with
.Fl g ,
restores a global option to the default).
+.Ar value
+depends on the option and may be a number, a string, or a flag (on, off, or
+omitted to toggle).
.Pp
The
.Fl o
@@ -3230,9 +3241,6 @@ includes hooks (omitted by default).
.Fl A
includes options inherited from a parent set of options, such options are
marked with an asterisk.
-.Ar value
-depends on the option and may be a number, a string, or a flag (on, off, or
-omitted to toggle).
.El
.Pp
Available server options are:
@@ -4574,6 +4582,9 @@ pads the string to a given width, for example
.Ql #{p10:pane_title}
will result in a width of at least 10 characters.
A positive width pads on the left, a negative on the right.
+.Ql n
+expands to the length of the variable, for example
+.Ql #{n:window_name} .
.Pp
Prefixing a time variable with
.Ql t:\&
@@ -4770,6 +4781,7 @@ The following variables are available, where appropriate:
.It Li "pane_in_mode" Ta "" Ta "1 if pane is in a mode"
.It Li "pane_index" Ta "#P" Ta "Index of pane"
.It Li "pane_input_off" Ta "" Ta "1 if input to pane is disabled"
+.It Li "pane_last" Ta "" Ta "1 if last pane"
.It Li "pane_left" Ta "" Ta "Left of pane"
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
.It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set"
@@ -5098,7 +5110,7 @@ section).
Commands to alter and view the environment are:
.Bl -tag -width Ds
.It Xo Ic set-environment
-.Op Fl hgru
+.Op Fl Fhgru
.Op Fl t Ar target-session
.Ar name Op Ar value
.Xc
@@ -5109,6 +5121,11 @@ If
is used, the change is made in the global environment; otherwise, it is applied
to the session environment for
.Ar target-session .
+If
+.Fl F
+is present, then
+.Ar value
+is expanded as a format.
The
.Fl u
flag unsets a variable.
@@ -5378,6 +5395,7 @@ The following keys are also available:
.It Xo Ic display-message
.Op Fl aIpv
.Op Fl c Ar target-client
+.Op Fl d Ar delay
.Op Fl t Ar target-pane
.Op Ar message
.Xc
@@ -5387,7 +5405,14 @@ If
.Fl p
is given, the output is printed to stdout, otherwise it is displayed in the
.Ar target-client
-status line.
+status line for up to
+.Ar delay
+milliseconds.
+If
+.Ar delay
+is not given, the
+.Ic message-time
+option is used; a delay of zero waits for a key press.
The format of
.Ar message
is described in the
@@ -5629,12 +5654,21 @@ See the
.Sx FORMATS
section.
.It Xo Ic load-buffer
+.Op Fl w
.Op Fl b Ar buffer-name
+.Op Fl t Ar target-client
.Ar path
.Xc
.D1 (alias: Ic loadb )
Load the contents of the specified paste buffer from
.Ar path .
+If
+.Fl w
+is given, the buffer is also sent to the clipboard for
+.Ar target-client
+using the
+.Xr xterm 1
+escape sequence, if possible.
.It Xo Ic paste-buffer
.Op Fl dpr
.Op Fl b Ar buffer-name
@@ -5671,14 +5705,22 @@ The
.Fl a
option appends to rather than overwriting the file.
.It Xo Ic set-buffer
-.Op Fl a
+.Op Fl aw
.Op Fl b Ar buffer-name
+.Op Fl t Ar target-client
.Op Fl n Ar new-buffer-name
.Ar data
.Xc
.D1 (alias: Ic setb )
Set the contents of the specified buffer to
.Ar data .
+If
+.Fl w
+is given, the buffer is also sent to the clipboard for
+.Ar target-client
+using the
+.Xr xterm 1
+escape sequence, if possible.
The
.Fl a
option appends to rather than overwriting the buffer.
diff --git a/tmux.c b/tmux.c
index b9a676a2..066714df 100644
--- a/tmux.c
+++ b/tmux.c
@@ -322,8 +322,8 @@ main(int argc, char **argv)
char *path = NULL, *label = NULL;
char *cause, **var;
const char *s, *shell, *cwd;
- int opt, flags = 0, keys;
- int feat = 0;
+ int opt, keys, feat = 0;
+ uint64_t flags = 0;
const struct options_table_entry *oe;
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL &&
diff --git a/tmux.h b/tmux.h
index a17ae5c6..d828a238 100644
--- a/tmux.h
+++ b/tmux.h
@@ -498,6 +498,7 @@ enum msgtype {
MSG_IDENTIFY_CWD,
MSG_IDENTIFY_FEATURES,
MSG_IDENTIFY_STDOUT,
+ MSG_IDENTIFY_LONGFLAGS,
MSG_COMMAND = 200,
MSG_DETACH,
@@ -1790,6 +1791,7 @@ enum options_table_type {
struct options_table_entry {
const char *name;
+ const char *alternative_name;
enum options_table_type type;
int scope;
int flags;
@@ -1809,6 +1811,11 @@ struct options_table_entry {
const char *unit;
};
+struct options_name_map {
+ const char *from;
+ const char *to;
+};
+
/* Common command usages. */
#define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#define CMD_TARGET_WINDOW_USAGE "[-t target-window]"
@@ -2041,7 +2048,8 @@ int options_remove_or_default(struct options_entry *, int,
char **);
/* options-table.c */
-extern const struct options_table_entry options_table[];
+extern const struct options_table_entry options_table[];
+extern const struct options_name_map options_other_names[];
/* job.c */
typedef void (*job_update_cb) (struct job *);
@@ -2121,6 +2129,7 @@ int tty_open(struct tty *, char **);
void tty_close(struct tty *);
void tty_free(struct tty *);
void tty_update_features(struct tty *);
+void tty_set_selection(struct tty *, const char *, size_t);
void tty_write(void (*)(struct tty *, const struct tty_ctx *),
struct tty_ctx *);
void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *);
@@ -2325,7 +2334,7 @@ void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...);
void cmd_wait_for_flush(void);
/* client.c */
-int client_main(struct event_base *, int, char **, int, int);
+int client_main(struct event_base *, int, char **, uint64_t, int);
/* key-bindings.c */
struct key_table *key_bindings_get_table(const char *, int);
@@ -2452,8 +2461,7 @@ struct style_range *status_get_range(struct client *, u_int, u_int);
void status_init(struct client *);
void status_free(struct client *);
int status_redraw(struct client *);
-void printflike(3, 4) status_message_set(struct client *, int, const char *,
- ...);
+void status_message_set(struct client *, int, int, const char *, ...);
void status_message_clear(struct client *);
int status_message_redraw(struct client *);
void status_prompt_set(struct client *, struct cmd_find_state *,
diff --git a/tty-term.c b/tty-term.c
index 9ad88597..a5d57cd7 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -305,6 +305,8 @@ tty_term_strip(const char *s)
ptr++;
if (*ptr == '>')
ptr++;
+ if (*ptr == '\0')
+ break;
}
buf[len++] = *ptr;
diff --git a/tty.c b/tty.c
index 14b770e2..30b94e04 100644
--- a/tty.c
+++ b/tty.c
@@ -1896,19 +1896,27 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx)
{
- char *buf;
- size_t off;
+ tty_set_selection(tty, ctx->ptr, ctx->num);
+}
+
+void
+tty_set_selection(struct tty *tty, const char *buf, size_t len)
+{
+ char *encoded;
+ size_t size;
+ if (~tty->flags & TTY_STARTED)
+ return;
if (!tty_term_has(tty->term, TTYC_MS))
return;
- off = 4 * ((ctx->num + 2) / 3) + 1; /* storage for base64 */
- buf = xmalloc(off);
+ size = 4 * ((len + 2) / 3) + 1; /* storage for base64 */
+ encoded = xmalloc(size);
- b64_ntop(ctx->ptr, ctx->num, buf, off);
- tty_putcode_ptr2(tty, TTYC_MS, "", buf);
+ b64_ntop(buf, len, encoded, size);
+ tty_putcode_ptr2(tty, TTYC_MS, "", encoded);
- free(buf);
+ free(encoded);
}
void
diff --git a/window-copy.c b/window-copy.c
index 7103131d..1dc0c293 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -72,14 +72,13 @@ static int window_copy_search_marks(struct window_mode_entry *,
struct screen *, int, int);
static void window_copy_clear_marks(struct window_mode_entry *);
static void window_copy_move_left(struct screen *, u_int *, u_int *, int);
-static void window_copy_move_right(struct screen *, u_int *, u_int *, int);
static int window_copy_is_lowercase(const char *);
static int window_copy_search_jump(struct window_mode_entry *,
struct grid *, struct grid *, u_int, u_int, u_int, int, int,
- int, int);
-static int window_copy_search(struct window_mode_entry *, int, int);
-static int window_copy_search_up(struct window_mode_entry *, int);
-static int window_copy_search_down(struct window_mode_entry *, int);
+ int, int, u_int *);
+static int window_copy_search(struct window_mode_entry *, int, int, int);
+static int window_copy_search_up(struct window_mode_entry *, int, int);
+static int window_copy_search_down(struct window_mode_entry *, int, int);
static void window_copy_goto_line(struct window_mode_entry *, const char *);
static void window_copy_update_cursor(struct window_mode_entry *, u_int,
u_int);
@@ -110,7 +109,7 @@ static void window_copy_cursor_back_to_indentation(
static void window_copy_cursor_end_of_line(struct window_mode_entry *);
static void window_copy_other_end(struct window_mode_entry *);
static void window_copy_cursor_left(struct window_mode_entry *);
-static void window_copy_cursor_right(struct window_mode_entry *);
+static void window_copy_cursor_right(struct window_mode_entry *, int);
static void window_copy_cursor_up(struct window_mode_entry *, int);
static void window_copy_cursor_down(struct window_mode_entry *, int);
static void window_copy_cursor_jump(struct window_mode_entry *);
@@ -1094,7 +1093,7 @@ window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
u_int np = wme->prefix;
for (; np != 0; np--)
- window_copy_cursor_right(wme);
+ window_copy_cursor_right(wme, 0);
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -1685,10 +1684,10 @@ window_copy_cmd_search_again(struct window_copy_cmd_state *cs)
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
for (; np != 0; np--)
- window_copy_search_up(wme, data->searchregex);
+ window_copy_search_up(wme, data->searchregex, 1);
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
for (; np != 0; np--)
- window_copy_search_down(wme, data->searchregex);
+ window_copy_search_down(wme, data->searchregex, 1);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -1702,10 +1701,10 @@ window_copy_cmd_search_reverse(struct window_copy_cmd_state *cs)
if (data->searchtype == WINDOW_COPY_SEARCHUP) {
for (; np != 0; np--)
- window_copy_search_down(wme, data->searchregex);
+ window_copy_search_down(wme, data->searchregex, 1);
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
for (; np != 0; np--)
- window_copy_search_up(wme, data->searchregex);
+ window_copy_search_up(wme, data->searchregex, 1);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -1953,7 +1952,7 @@ window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
data->searchregex = 1;
data->timeout = 0;
for (; np != 0; np--)
- window_copy_search_up(wme, 1);
+ window_copy_search_up(wme, 1, 0);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -1973,7 +1972,7 @@ window_copy_cmd_search_backward_text(struct window_copy_cmd_state *cs)
data->searchregex = 0;
data->timeout = 0;
for (; np != 0; np--)
- window_copy_search_up(wme, 0);
+ window_copy_search_up(wme, 0, 0);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -1993,7 +1992,7 @@ window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
data->searchregex = 1;
data->timeout = 0;
for (; np != 0; np--)
- window_copy_search_down(wme, 1);
+ window_copy_search_down(wme, 1, 0);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -2013,7 +2012,7 @@ window_copy_cmd_search_forward_text(struct window_copy_cmd_state *cs)
data->searchregex = 0;
data->timeout = 0;
for (; np != 0; np--)
- window_copy_search_down(wme, 0);
+ window_copy_search_down(wme, 0, 0);
}
return (WINDOW_COPY_CMD_NOTHING);
}
@@ -2052,7 +2051,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
- if (!window_copy_search_up(wme, 0)) {
+ if (!window_copy_search_up(wme, 0, 1)) {
window_copy_clear_marks(wme);
return (WINDOW_COPY_CMD_REDRAW);
}
@@ -2062,7 +2061,7 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
- if (!window_copy_search_down(wme, 0)) {
+ if (!window_copy_search_down(wme, 0, 0)) {
window_copy_clear_marks(wme);
return (WINDOW_COPY_CMD_REDRAW);
}
@@ -2105,7 +2104,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
- if (!window_copy_search_down(wme, 0)) {
+ if (!window_copy_search_down(wme, 0, 1)) {
window_copy_clear_marks(wme);
return (WINDOW_COPY_CMD_REDRAW);
}
@@ -2115,7 +2114,7 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
data->searchregex = 0;
free(data->searchstr);
data->searchstr = xstrdup(argument);
- if (!window_copy_search_up(wme, 0)) {
+ if (!window_copy_search_up(wme, 0, 1)) {
window_copy_clear_marks(wme);
return (WINDOW_COPY_CMD_REDRAW);
}
@@ -2406,8 +2405,8 @@ window_copy_search_compare(struct grid *gd, u_int px, u_int py,
}
static int
-window_copy_search_lr(struct grid *gd,
- struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last, int cis)
+window_copy_search_lr(struct grid *gd, struct grid *sgd, u_int *ppx, u_int py,
+ u_int first, u_int last, int cis)
{
u_int ax, bx, px, pywrap, endline;
int matched;
@@ -2817,23 +2816,6 @@ window_copy_move_left(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
*fx = *fx - 1;
}
-static void
-window_copy_move_right(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
-{
- if (*fx == screen_size_x(s) - 1) { /* right */
- if (*fy == screen_hsize(s) + screen_size_y(s) - 1) { /* bottom */
- if (wrapflag) {
- *fx = 0;
- *fy = 0;
- }
- return;
- }
- *fx = 0;
- *fy = *fy + 1;
- } else
- *fx = *fx + 1;
-}
-
static int
window_copy_is_lowercase(const char *ptr)
{
@@ -2854,7 +2836,7 @@ window_copy_is_lowercase(const char *ptr)
static int
window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap,
- int direction, int regex)
+ int direction, int regex, u_int *foundlen)
{
u_int i, px, sx, ssize = 1;
int found = 0, cflags = REG_EXTENDED;
@@ -2871,6 +2853,7 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
free(sbuf);
return (0);
}
+ free(sbuf);
}
if (direction) {
@@ -2878,15 +2861,20 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
if (regex) {
found = window_copy_search_lr_regex(gd,
&px, &sx, i, fx, gd->sx, &reg);
+ if (found)
+ *foundlen = sx;
} else {
found = window_copy_search_lr(gd, sgd,
&px, i, fx, gd->sx, cis);
+ if (found)
+ *foundlen = sgd->sx;
}
if (found)
break;
fx = 0;
}
} else {
+ *foundlen = 0;
for (i = fy + 1; endline < i; i--) {
if (regex) {
found = window_copy_search_rl_regex(gd,
@@ -2902,10 +2890,8 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
fx = gd->sx - 1;
}
}
- if (regex) {
- free(sbuf);
+ if (regex)
regfree(&reg);
- }
if (found) {
window_copy_scroll_to(wme, px, i, 1);
@@ -2915,7 +2901,7 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
return (window_copy_search_jump(wme, gd, sgd,
direction ? 0 : gd->sx - 1,
direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0,
- direction, regex));
+ direction, regex, foundlen));
}
return (0);
}
@@ -2925,7 +2911,8 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
* down.
*/
static int
-window_copy_search(struct window_mode_entry *wme, int direction, int regex)
+window_copy_search(struct window_mode_entry *wme, int direction, int regex,
+ int again)
{
struct window_pane *wp = wme->wp;
struct window_copy_mode_data *data = wme->data;
@@ -2933,7 +2920,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex)
struct screen_write_ctx ctx;
struct grid *gd = s->grid;
const char *str = data->searchstr;
- u_int fx, fy, endline;
+ u_int fx, fy, endline, i, foundlen;
int wrapflag, cis, found, visible_only;
if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0')
@@ -2961,18 +2948,23 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex)
wrapflag = options_get_number(wp->window->options, "wrap-search");
cis = window_copy_is_lowercase(str);
- if (direction) {
- window_copy_move_right(s, &fx, &fy, wrapflag);
+ if (direction)
endline = gd->hsize + gd->sy - 1;
- } else {
- window_copy_move_left(s, &fx, &fy, wrapflag);
+ else {
+ if (again)
+ window_copy_move_left(s, &fx, &fy, wrapflag);
endline = 0;
}
found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis,
- wrapflag, direction, regex);
- if (found)
+ wrapflag, direction, regex, &foundlen);
+ if (found) {
window_copy_search_marks(wme, &ss, regex, visible_only);
+ if (foundlen != 0) {
+ for (i = 0; i < foundlen; i++)
+ window_copy_cursor_right(wme, 1);
+ }
+ }
window_copy_redraw_screen(wme);
screen_free(&ss);
@@ -2995,8 +2987,8 @@ window_copy_visible_lines(struct window_copy_mode_data *data, u_int *start,
}
static int
-window_copy_search_mark_at(struct window_copy_mode_data *data, u_int px, u_int py,
- u_int *at)
+window_copy_search_mark_at(struct window_copy_mode_data *data, u_int px,
+ u_int py, u_int *at)
{
struct screen *s = data->backing;
struct grid *gd = s->grid;
@@ -3049,6 +3041,7 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp,
free(sbuf);
return (0);
}
+ free(sbuf);
}
tstart = get_timer();
@@ -3096,7 +3089,7 @@ again:
data->searchgen++;
}
- px++;
+ px += width;
}
t = get_timer();
@@ -3146,10 +3139,8 @@ again:
out:
if (ssp == &ss)
screen_free(&ss);
- if (regex) {
- free(sbuf);
+ if (regex)
regfree(&reg);
- }
return (1);
}
@@ -3163,15 +3154,15 @@ window_copy_clear_marks(struct window_mode_entry *wme)
}
static int
-window_copy_search_up(struct window_mode_entry *wme, int regex)
+window_copy_search_up(struct window_mode_entry *wme, int regex, int again)
{
- return (window_copy_search(wme, 0, regex));
+ return (window_copy_search(wme, 0, regex, again));
}
static int
-window_copy_search_down(struct window_mode_entry *wme, int regex)
+window_copy_search_down(struct window_mode_entry *wme, int regex, int again)
{
- return (window_copy_search(wme, 1, regex));
+ return (window_copy_search(wme, 1, regex, again));
}
static void
@@ -3256,7 +3247,7 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
{
struct window_copy_mode_data *data = wme->data;
u_int mark, start, end, cy, cursor, current;
- int inv = 0;
+ int inv = 0, found = 0;
if (data->showmark && fy == data->my) {
gc->attr = mkgc->attr;
@@ -3282,20 +3273,28 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
return;
cy = screen_hsize(data->backing) - data->oy + data->cy;
- if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0 &&
- data->searchmark[cursor] == mark) {
- window_copy_match_start_end(data, cursor, &start, &end);
- if (current >= start && current <= end) {
- gc->attr = cgc->attr;
- if (inv) {
- gc->fg = cgc->bg;
- gc->bg = cgc->fg;
- }
- else {
- gc->fg = cgc->fg;
- gc->bg = cgc->bg;
+ if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) {
+ if (data->searchmark[cursor] == mark)
+ found = 1;
+ else if (cursor != 0) {
+ cursor--;
+ if (data->searchmark[cursor] == mark)
+ found = 1;
+ }
+ if (found) {
+ window_copy_match_start_end(data, cursor, &start, &end);
+ if (current >= start && current <= end) {
+ gc->attr = cgc->attr;
+ if (inv) {
+ gc->fg = cgc->bg;
+ gc->bg = cgc->fg;
+ }
+ else {
+ gc->fg = cgc->fg;
+ gc->bg = cgc->bg;
+ }
+ return;
}
- return;
}
}
@@ -3370,7 +3369,8 @@ window_copy_write_line(struct window_mode_entry *wme,
} else if (data->searchthis == -1) {
size = xsnprintf(hdr, sizeof hdr,
"(%d%s results) [%u/%u]", data->searchcount,
- data->searchmore ? "+" : "", data->oy, hsize);
+ data->searchmore ? "+" : "", data->oy,
+ hsize);
} else {
size = xsnprintf(hdr, sizeof hdr,
"(%d/%d results) [%u/%u]", data->searchthis,
@@ -4142,7 +4142,7 @@ window_copy_cursor_left(struct window_mode_entry *wme)
}
static void
-window_copy_cursor_right(struct window_mode_entry *wme)
+window_copy_cursor_right(struct window_mode_entry *wme, int all)
{
struct window_copy_mode_data *data = wme->data;
u_int px, py, yy, cx, cy;
@@ -4150,7 +4150,7 @@ window_copy_cursor_right(struct window_mode_entry *wme)
py = screen_hsize(data->backing) + data->cy - data->oy;
yy = screen_hsize(data->backing) + screen_size_y(data->backing) - 1;
- if (data->screen.sel != NULL && data->rectflag)
+ if (all || (data->screen.sel != NULL && data->rectflag))
px = screen_size_x(&data->screen);
else
px = window_copy_find_length(wme, py);
diff --git a/window-customize.c b/window-customize.c
index ecafc776..1dad07cd 100644
--- a/window-customize.c
+++ b/window-customize.c
@@ -380,7 +380,7 @@ window_customize_build_options(struct window_customize_modedata *data,
struct format_tree *ft, const char *filter, struct cmd_find_state *fs)
{
struct mode_tree_item *top;
- struct options_entry *o, *loop;
+ struct options_entry *o = NULL, *loop;
const char **list = NULL, *name;
u_int size = 0, i;
enum window_customize_scope scope;
@@ -1003,7 +1003,7 @@ window_customize_set_option_callback(struct client *c, void *itemdata,
fail:
*cause = toupper((u_char)*cause);
- status_message_set(c, 1, "%s", cause);
+ status_message_set(c, -1, 1, "%s", cause);
free(cause);
return (0);
}
@@ -1018,7 +1018,7 @@ window_customize_set_option(struct client *c,
struct options *oo;
struct window_customize_itemdata *new_item;
int flag, idx = item->idx;
- enum window_customize_scope scope;
+ enum window_customize_scope scope = WINDOW_CUSTOMIZE_NONE;
u_int choice;
const char *name = item->name, *space = "";
char *prompt, *value, *text;
@@ -1031,7 +1031,7 @@ window_customize_set_option(struct client *c,
return;
oe = options_table_entry(o);
- if (~oe->scope & OPTIONS_TABLE_PANE)
+ if (oe != NULL && ~oe->scope & OPTIONS_TABLE_PANE)
pane = 0;
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) {
scope = item->scope;
@@ -1209,7 +1209,7 @@ window_customize_set_command_callback(struct client *c, void *itemdata,
fail:
*error = toupper((u_char)*error);
- status_message_set(c, 1, "%s", error);
+ status_message_set(c, -1, 1, "%s", error);
free(error);
return (0);
}