aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--alerts.c (renamed from server-window.c)167
-rw-r--r--arguments.c6
-rw-r--r--cmd-choose-buffer.c4
-rw-r--r--cmd-paste-buffer.c33
-rw-r--r--cmd-save-buffer.c23
-rw-r--r--cmd-set-buffer.c39
-rw-r--r--cmd-set-option.c6
-rw-r--r--cmd-show-environment.c2
-rw-r--r--cmd-swap-pane.c2
-rw-r--r--format.c352
-rw-r--r--input.c9
-rw-r--r--layout-set.c6
-rw-r--r--log.c9
-rw-r--r--names.c65
-rw-r--r--paste.c63
-rw-r--r--screen.c8
-rw-r--r--server-client.c8
-rw-r--r--server.c3
-rw-r--r--session.c1
-rw-r--r--status.c16
-rw-r--r--tmux.c4
-rw-r--r--tmux.h75
-rw-r--r--window-copy.c32
-rw-r--r--window.c47
-rw-r--r--xterm-keys.c2
26 files changed, 595 insertions, 389 deletions
diff --git a/Makefile.am b/Makefile.am
index 3173ba99..e9a6bd33 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,6 +57,7 @@ endif
# List of sources.
dist_tmux_SOURCES = \
+ alerts.c \
arguments.c \
attributes.c \
cfg.c \
@@ -156,7 +157,6 @@ dist_tmux_SOURCES = \
screen.c \
server-client.c \
server-fn.c \
- server-window.c \
server.c \
session.c \
signal.c \
diff --git a/server-window.c b/alerts.c
index c96c2602..cfdd30e3 100644
--- a/server-window.c
+++ b/alerts.c
@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
- * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ * Copyright (c) 2015 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,42 +19,133 @@
#include <sys/types.h>
#include <event.h>
-#include <stdlib.h>
-#include <unistd.h>
#include "tmux.h"
-int server_window_check_bell(struct session *, struct winlink *);
-int server_window_check_activity(struct session *, struct winlink *);
-int server_window_check_silence(struct session *, struct winlink *);
-void ring_bell(struct session *);
+int alerts_fired;
+
+void alerts_timer(int, short, void *);
+int alerts_enabled(struct window *, int);
+void alerts_callback(int, short, void *);
+void alerts_reset(struct window *);
+
+int alerts_check_bell(struct session *, struct winlink *);
+int alerts_check_activity(struct session *, struct winlink *);
+int alerts_check_silence(struct session *, struct winlink *);
+void alerts_ring_bell(struct session *);
+
+void
+alerts_timer(unused int fd, unused short events, void *arg)
+{
+ struct window *w = arg;
+
+ log_debug("@%u alerts timer expired", w->id);
+ alerts_reset(w);
+ alerts_queue(w, WINDOW_SILENCE);
+}
-/* Window functions that need to happen every loop. */
void
-server_window_loop(void)
+alerts_callback(unused int fd, unused short events, unused void *arg)
{
struct window *w;
struct session *s;
struct winlink *wl;
+ int flags, alerts;
RB_FOREACH(w, windows, &windows) {
RB_FOREACH(s, sessions, &sessions) {
RB_FOREACH(wl, winlinks, &s->windows) {
if (wl->window != w)
continue;
+ flags = w->flags;
- if (server_window_check_bell(s, wl) ||
- server_window_check_activity(s, wl) ||
- server_window_check_silence(s, wl))
+ alerts = alerts_check_bell(s, wl);
+ alerts |= alerts_check_activity(s, wl);
+ alerts |= alerts_check_silence(s, wl);
+ if (alerts != 0)
server_status_session(s);
+
+ log_debug("%s:%d @%u alerts check, alerts %#x, "
+ "flags %#x", s->name, wl->idx, w->id,
+ alerts, flags);
}
}
}
+ alerts_fired = 0;
}
-/* Check for bell in window. */
int
-server_window_check_bell(struct session *s, struct winlink *wl)
+alerts_enabled(struct window *w, int flags)
+{
+ struct session *s;
+
+ if (flags & WINDOW_ACTIVITY) {
+ if (options_get_number(&w->options, "monitor-activity"))
+ return (1);
+ }
+ if (flags & WINDOW_SILENCE) {
+ if (options_get_number(&w->options, "monitor-silence") != 0)
+ return (1);
+ }
+ if (~flags & WINDOW_BELL)
+ return (0);
+ RB_FOREACH(s, sessions, &sessions) {
+ if (!session_has(s, w))
+ continue;
+ if (options_get_number(&s->options, "bell-action") != BELL_NONE)
+ return (1);
+ }
+ return (0);
+}
+
+void
+alerts_reset_all(void)
+{
+ struct window *w;
+
+ RB_FOREACH(w, windows, &windows)
+ alerts_reset(w);
+}
+
+void
+alerts_reset(struct window *w)
+{
+ struct timeval tv;
+
+ w->flags &= ~WINDOW_SILENCE;
+ event_del(&w->alerts_timer);
+
+ timerclear(&tv);
+ tv.tv_sec = options_get_number(&w->options, "monitor-silence");
+
+ log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
+ if (tv.tv_sec != 0)
+ event_add(&w->alerts_timer, &tv);
+}
+
+void
+alerts_queue(struct window *w, int flags)
+{
+ if (!event_initialized(&w->alerts_timer))
+ evtimer_set(&w->alerts_timer, alerts_timer, w);
+
+ if (w->flags & flags)
+ return;
+ w->flags |= flags;
+ log_debug("@%u alerts flags added %#x", w->id, flags);
+
+ if (!alerts_fired && alerts_enabled(w, flags)) {
+ log_debug("alerts check queued (by @%u)", w->id);
+ event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
+ alerts_fired = 1;
+ }
+
+ if (flags & WINDOW_ACTIVITY)
+ alerts_reset(w);
+}
+
+int
+alerts_check_bell(struct session *s, struct winlink *wl)
{
struct client *c;
struct window *w = wl->window;
@@ -69,10 +160,11 @@ server_window_check_bell(struct session *s, struct winlink *wl)
if (s->curw->window == w)
w->flags &= ~WINDOW_BELL;
- visual = options_get_number(&s->options, "visual-bell");
action = options_get_number(&s->options, "bell-action");
if (action == BELL_NONE)
return (0);
+
+ visual = options_get_number(&s->options, "visual-bell");
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s || c->flags & CLIENT_CONTROL)
continue;
@@ -92,12 +184,11 @@ server_window_check_bell(struct session *s, struct winlink *wl)
status_message_set(c, "Bell in window %d", wl->idx);
}
- return (1);
+ return (WINDOW_BELL);
}
-/* Check for activity in window. */
int
-server_window_check_activity(struct session *s, struct winlink *wl)
+alerts_check_activity(struct session *s, struct winlink *wl)
{
struct client *c;
struct window *w = wl->window;
@@ -114,7 +205,7 @@ server_window_check_activity(struct session *s, struct winlink *wl)
return (0);
if (options_get_number(&s->options, "bell-on-alert"))
- ring_bell(s);
+ alerts_ring_bell(s);
wl->flags |= WINLINK_ACTIVITY;
if (options_get_number(&s->options, "visual-activity")) {
@@ -125,45 +216,28 @@ server_window_check_activity(struct session *s, struct winlink *wl)
}
}
- return (1);
+ return (WINDOW_ACTIVITY);
}
-/* Check for silence in window. */
int
-server_window_check_silence(struct session *s, struct winlink *wl)
+alerts_check_silence(struct session *s, struct winlink *wl)
{
struct client *c;
struct window *w = wl->window;
- struct timeval timer;
- int silence_interval, timer_difference;
-
- if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
- return (0);
- if (s->curw == wl && !(s->flags & SESSION_UNATTACHED)) {
- /*
- * Reset the timer for this window if we've focused it. We
- * don't want the timer tripping as soon as we've switched away
- * from this window.
- */
- if (gettimeofday(&w->silence_timer, NULL) != 0)
- fatal("gettimeofday failed");
+ if (s->curw->window == w)
+ w->flags &= ~WINDOW_SILENCE;
+ if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
return (0);
- }
-
- silence_interval = options_get_number(&w->options, "monitor-silence");
- if (silence_interval == 0)
+ if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
return (0);
- if (gettimeofday(&timer, NULL) != 0)
- fatal("gettimeofday");
- timer_difference = timer.tv_sec - w->silence_timer.tv_sec;
- if (timer_difference <= silence_interval)
+ if (options_get_number(&w->options, "monitor-silence") == 0)
return (0);
if (options_get_number(&s->options, "bell-on-alert"))
- ring_bell(s);
+ alerts_ring_bell(s);
wl->flags |= WINLINK_SILENCE;
if (options_get_number(&s->options, "visual-silence")) {
@@ -174,12 +248,11 @@ server_window_check_silence(struct session *s, struct winlink *wl)
}
}
- return (1);
+ return (WINDOW_SILENCE);
}
-/* Ring terminal bell. */
void
-ring_bell(struct session *s)
+alerts_ring_bell(struct session *s)
{
struct client *c;
diff --git a/arguments.c b/arguments.c
index ca6cc760..9f080f52 100644
--- a/arguments.c
+++ b/arguments.c
@@ -28,6 +28,12 @@
* Manipulate command arguments.
*/
+struct args_entry {
+ u_char flag;
+ char *value;
+ RB_ENTRY(args_entry) entry;
+};
+
struct args_entry *args_find(struct args *, u_char);
RB_GENERATE(args_tree, args_entry, entry, args_cmp);
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index af178976..b4590306 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -65,7 +65,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
utf8flag = options_get_number(&wl->window->options, "utf8");
- if (paste_get_top() == NULL)
+ if (paste_get_top(NULL) == NULL)
return (CMD_RETURN_NORMAL);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
@@ -85,7 +85,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
cdata->ft_template = xstrdup(template);
format_defaults_paste_buffer(cdata->ft, pb, utf8flag);
- xasprintf(&action_data, "%s", pb->name);
+ xasprintf(&action_data, "%s", paste_buffer_name(pb));
cdata->command = cmd_template_replace(action, action_data, 1);
free(action_data);
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 5d91aeff..5027a4f8 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -47,7 +47,9 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp;
struct session *s;
struct paste_buffer *pb;
- const char *sepstr, *bufname;
+ const char *sepstr, *bufname, *bufdata, *bufend, *line;
+ size_t seplen, bufsize;
+ int bracket = args_has(args, 'p');
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
@@ -57,7 +59,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
bufname = args_get(args, 'b');
if (bufname == NULL)
- pb = paste_get_top();
+ pb = paste_get_top(NULL);
else {
pb = paste_get_name(bufname);
if (pb == NULL) {
@@ -66,7 +68,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
}
}
- if (pb != NULL) {
+ if (pb != NULL && ~wp->flags & PANE_INPUTOFF) {
sepstr = args_get(args, 's');
if (sepstr == NULL) {
if (args_has(args, 'r'))
@@ -74,10 +76,31 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
else
sepstr = "\r";
}
- paste_send_pane(pb, wp, sepstr, args_has(args, 'p'));
+ seplen = strlen(sepstr);
+
+ if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
+ bufferevent_write(wp->event, "\033[200~", 6);
+
+ bufdata = paste_buffer_data(pb, &bufsize);
+ bufend = bufdata + bufsize;
+
+ for (;;) {
+ line = memchr(bufdata, '\n', bufend - bufdata);
+ if (line == NULL)
+ break;
+
+ bufferevent_write(wp->event, bufdata, line - bufdata);
+ bufferevent_write(wp->event, sepstr, seplen);
+
+ bufdata = line + 1;
+ }
+ if (bufdata != bufend)
+ bufferevent_write(wp->event, bufdata, bufend - bufdata);
+
+ if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
+ bufferevent_write(wp->event, "\033[201~", 6);
}
- /* Delete the buffer if -d. */
if (args_has(args, 'd')) {
if (bufname == NULL)
paste_free_top();
diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c
index 86e302ae..1e020934 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -56,14 +56,14 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
struct paste_buffer *pb;
- const char *path, *bufname;
- char *start, *end, *msg;
- size_t size, used, msglen;
+ const char *path, *bufname, *bufdata, *start, *end;
+ char *msg;
+ size_t size, used, msglen, bufsize;
int cwd, fd;
FILE *f;
if (!args_has(args, 'b')) {
- if ((pb = paste_get_top()) == NULL) {
+ if ((pb = paste_get_top(NULL)) == NULL) {
cmdq_error(cmdq, "no buffers");
return (CMD_RETURN_ERROR);
}
@@ -75,6 +75,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
}
+ bufdata = paste_buffer_data(pb, &bufsize);
if (self->entry == &cmd_show_buffer_entry)
path = "-";
@@ -113,7 +114,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
- if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
+ if (fwrite(bufdata, 1, bufsize, f) != bufsize) {
cmdq_error(cmdq, "%s: fwrite error", path);
fclose(f);
return (CMD_RETURN_ERROR);
@@ -123,25 +124,25 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
do_stdout:
- evbuffer_add(c->stdout_data, pb->data, pb->size);
+ evbuffer_add(c->stdout_data, bufdata, bufsize);
server_push_stdout(c);
return (CMD_RETURN_NORMAL);
do_print:
- if (pb->size > (INT_MAX / 4) - 1) {
+ if (bufsize > (INT_MAX / 4) - 1) {
cmdq_error(cmdq, "buffer too big");
return (CMD_RETURN_ERROR);
}
msg = NULL;
used = 0;
- while (used != pb->size) {
- start = pb->data + used;
- end = memchr(start, '\n', pb->size - used);
+ while (used != bufsize) {
+ start = bufdata + used;
+ end = memchr(start, '\n', bufsize - used);
if (end != NULL)
size = end - start;
else
- size = pb->size - used;
+ size = bufsize - used;
msglen = size * 4 + 1;
msg = xrealloc(msg, msglen);
diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c
index 0ec362b3..4fa7ca11 100644
--- a/cmd-set-buffer.c
+++ b/cmd-set-buffer.c
@@ -42,9 +42,9 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct paste_buffer *pb;
- char *pdata, *cause;
- const char *bufname;
- size_t psize, newsize;
+ char *bufdata, *cause;
+ const char *bufname, *olddata;
+ size_t bufsize, newsize;
bufname = NULL;
@@ -58,12 +58,11 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
bufname = args_get(args, 'b');
if (bufname == NULL) {
- pb = paste_get_top();
+ pb = paste_get_top(&bufname);
if (pb == NULL) {
cmdq_error(cmdq, "no buffer");
return (CMD_RETURN_ERROR);
}
- bufname = pb->name;
}
if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
@@ -79,37 +78,33 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "no data specified");
return (CMD_RETURN_ERROR);
}
-
- psize = 0;
- pdata = NULL;
-
pb = NULL;
+ bufsize = 0;
+ bufdata = NULL;
+
if ((newsize = strlen(args->argv[0])) == 0)
return (CMD_RETURN_NORMAL);
if (args_has(args, 'b')) {
bufname = args_get(args, 'b');
pb = paste_get_name(bufname);
- } else if (args_has(args, 'a')) {
- pb = paste_get_top();
- if (pb != NULL)
- bufname = pb->name;
- }
+ } else if (args_has(args, 'a'))
+ pb = paste_get_top(&bufname);
if (args_has(args, 'a') && pb != NULL) {
- psize = pb->size;
- pdata = xmalloc(psize);
- memcpy(pdata, pb->data, psize);
+ olddata = paste_buffer_data(pb, &bufsize);
+ bufdata = xmalloc(bufsize);
+ memcpy(bufdata, olddata, bufsize);
}
- pdata = xrealloc(pdata, psize + newsize);
- memcpy(pdata + psize, args->argv[0], newsize);
- psize += newsize;
+ bufdata = xrealloc(bufdata, bufsize + newsize);
+ memcpy(bufdata + bufsize, args->argv[0], newsize);
+ bufsize += newsize;
- if (paste_set(pdata, psize, bufname, &cause) != 0) {
+ if (paste_set(bufdata, bufsize, bufname, &cause) != 0) {
cmdq_error(cmdq, "%s", cause);
- free(pdata);
+ free(bufdata);
free(cause);
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 56ca91e0..98ab2513 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -180,14 +180,14 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
if (strcmp(oe->name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) {
if (options_get_number(&w->options, "automatic-rename"))
- queue_window_name(w);
- else if (event_initialized(&w->name_timer))
- evtimer_del(&w->name_timer);
+ w->active->flags |= PANE_CHANGED;
}
}
if (strcmp(oe->name, "status") == 0 ||
strcmp(oe->name, "status-interval") == 0)
status_timer_start_all();
+ if (strcmp(oe->name, "monitor-silence") == 0)
+ alerts_reset_all();
/* Update sizes and redraw. May not need it but meh. */
recalculate_sizes();
diff --git a/cmd-show-environment.c b/cmd-show-environment.c
index a61cf3f4..af24d91b 100644
--- a/cmd-show-environment.c
+++ b/cmd-show-environment.c
@@ -56,7 +56,7 @@ cmd_show_environment_escape(struct environ_entry *envent)
}
*out = '\0';
- return ret;
+ return (ret);
}
void
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index c4751c36..dc2b7246 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -58,12 +58,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
- src_wl = dst_wl;
} else if (args_has(self->args, 'U')) {
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
- src_wl = dst_wl;
} else {
src_wl = cmd_find_pane_marked(cmdq, NULL, NULL,
&src_wp);
diff --git a/format.c b/format.c
index 9cacbd98..5f31fa86 100644
--- a/format.c
+++ b/format.c
@@ -36,14 +36,27 @@
* string.
*/
+struct format_entry;
+typedef void (*format_cb)(struct format_tree *, struct format_entry *);
+
void format_job_callback(struct job *);
const char *format_job_get(struct format_tree *, const char *);
void format_job_timer(int, short, void *);
+void format_cb_host(struct format_tree *, struct format_entry *);
+void format_cb_host_short(struct format_tree *, struct format_entry *);
+void format_cb_pid(struct format_tree *, struct format_entry *);
+void format_cb_session_alerts(struct format_tree *, struct format_entry *);
+void format_cb_window_layout(struct format_tree *, struct format_entry *);
+void format_cb_start_command(struct format_tree *, struct format_entry *);
+void format_cb_current_command(struct format_tree *, struct format_entry *);
+void format_cb_history_bytes(struct format_tree *, struct format_entry *);
+void format_cb_pane_tabs(struct format_tree *, struct format_entry *);
+
+void format_add_cb(struct format_tree *, const char *, format_cb);
int format_replace(struct format_tree *, const char *, size_t, char **,
size_t *, size_t *);
char *format_time_string(time_t);
-char *format_get_command(struct window_pane *);
void format_defaults_pane_tabs(struct format_tree *, struct window_pane *);
void format_defaults_session(struct format_tree *, struct session *);
@@ -80,18 +93,19 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
/* Entry in format tree. */
struct format_entry {
- char *key;
- char *value;
-
- RB_ENTRY(format_entry) entry;
+ char *key;
+ char *value;
+ format_cb cb;
+ RB_ENTRY(format_entry) entry;
};
/* Format entry tree. */
struct format_tree {
- struct window *w;
- struct session *s;
+ struct window *w;
+ struct session *s;
+ struct window_pane *wp;
- int status;
+ int status;
RB_HEAD(format_entry_tree, format_entry) tree;
};
@@ -258,6 +272,170 @@ format_job_timer(unused int fd, unused short events, unused void *arg)
evtimer_add(&format_job_event, &tv);
}
+/* Callback for host. */
+void
+format_cb_host(unused struct format_tree *ft, struct format_entry *fe)
+{
+ char host[HOST_NAME_MAX + 1];
+
+ if (gethostname(host, sizeof host) != 0)
+ fe->value = xstrdup("");
+ else
+ fe->value = xstrdup(host);
+}
+
+/* Callback for host_short. */
+void
+format_cb_host_short(unused struct format_tree *ft, struct format_entry *fe)
+{
+ char host[HOST_NAME_MAX + 1], *cp;
+
+ if (gethostname(host, sizeof host) != 0)
+ fe->value = xstrdup("");
+ else {
+ if ((cp = strchr(host, '.')) != NULL)
+ *cp = '\0';
+ fe->value = xstrdup(host);
+ }
+}
+
+/* Callback for pid. */
+void
+format_cb_pid(unused struct format_tree *ft, struct format_entry *fe)
+{
+ xasprintf(&fe->value, "%ld", (long)getpid());
+}
+
+/* Callback for session_alerts. */
+void
+format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe)
+{
+ struct session *s = ft->s;
+ struct winlink *wl;
+ char alerts[256], tmp[16];
+
+ if (s == NULL)
+ return;
+
+ *alerts = '\0';
+ RB_FOREACH(wl, winlinks, &s->windows) {
+ if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
+ continue;
+ xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
+
+ if (*alerts != '\0')
+ strlcat(alerts, ",", sizeof alerts);
+ strlcat(alerts, tmp, sizeof alerts);
+ if (wl->flags & WINLINK_ACTIVITY)
+ strlcat(alerts, "#", sizeof alerts);
+ if (wl->flags & WINLINK_BELL)
+ strlcat(alerts, "!", sizeof alerts);
+ if (wl->flags & WINLINK_SILENCE)
+ strlcat(alerts, "~", sizeof alerts);
+ }
+ fe->value = xstrdup(alerts);
+}
+
+/* Callback for window_layout. */
+void
+format_cb_window_layout(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window *w = ft->w;
+
+ if (w == NULL)
+ return;
+
+ if (w->saved_layout_root != NULL)
+ fe->value = layout_dump(w->saved_layout_root);
+ else
+ fe->value = layout_dump(w->layout_root);
+}
+
+/* Callback for pane_start_command. */
+void
+format_cb_start_command(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window_pane *wp = ft->wp;
+
+ if (wp == NULL)
+ return;
+
+ fe->value = cmd_stringify_argv(wp->argc, wp->argv);
+}
+
+/* Callback for pane_current_command. */
+void
+format_cb_current_command(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window_pane *wp = ft->wp;
+ char *cmd;
+
+ if (wp == NULL)
+ return;
+
+ cmd = get_proc_name(wp->fd, wp->tty);
+ if (cmd == NULL || *cmd == '\0') {
+ free(cmd);
+ cmd = cmd_stringify_argv(wp->argc, wp->argv);
+ if (cmd == NULL || *cmd == '\0') {
+ free(cmd);
+ cmd = xstrdup(wp->shell);
+ }
+ }
+ fe->value = parse_window_name(cmd);
+ free(cmd);
+}
+
+/* Callback for history_bytes. */
+void
+format_cb_history_bytes(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window_pane *wp = ft->wp;
+ struct grid *gd;
+ struct grid_line *gl;
+ unsigned long long size;
+ u_int i;
+
+ if (wp == NULL)
+ return;
+ gd = wp->base.grid;
+
+ size = 0;
+ for (i = 0; i < gd->hsize; i++) {
+ gl = &gd->linedata[i];
+ size += gl->cellsize * sizeof *gl->celldata;
+ }
+ size += gd->hsize * sizeof *gd->linedata;
+
+ xasprintf(&fe->value, "%llu", size);
+}
+
+/* Callback for pane_tabs. */
+void
+format_cb_pane_tabs(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window_pane *wp = ft->wp;
+ struct evbuffer *buffer;
+ u_int i;
+ int size;
+
+ if (wp == NULL)
+ return;
+
+ buffer = evbuffer_new();
+ for (i = 0; i < wp->base.grid->sx; i++) {
+ if (!bit_test(wp->base.tabs, i))
+ continue;
+
+ if (EVBUFFER_LENGTH(buffer) > 0)
+ evbuffer_add(buffer, ",", 1);
+ evbuffer_add_printf(buffer, "%u", i);
+ }
+ size = EVBUFFER_LENGTH(buffer);
+ xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer));
+ evbuffer_free(buffer);
+}
+
/* Create a new tree. */
struct format_tree *
format_create(void)
@@ -270,7 +448,6 @@ struct format_tree *
format_create_status(int status)
{
struct format_tree *ft;
- char host[HOST_NAME_MAX + 1], *ptr;
if (!event_initialized(&format_job_event)) {
evtimer_set(&format_job_event, format_job_timer, NULL);
@@ -281,13 +458,9 @@ format_create_status(int status)
RB_INIT(&ft->tree);
ft->status = status;
- if (gethostname(host, sizeof host) == 0) {
- format_add(ft, "host", "%s", host);
- if ((ptr = strchr(host, '.')) != NULL)
- *ptr = '\0';
- format_add(ft, "host_short", "%s", host);
- }
- format_add(ft, "pid", "%ld", (long) getpid());
+ format_add_cb(ft, "host", format_cb_host);
+ format_add_cb(ft, "host_short", format_cb_host_short);
+ format_add_cb(ft, "pid", format_cb_pid);
return (ft);
}
@@ -319,17 +492,42 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
fe = xmalloc(sizeof *fe);
fe->key = xstrdup(key);
+ fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
+ if (fe_now != NULL) {
+ free(fe->key);
+ free(fe);
+ free(fe_now->value);
+ fe = fe_now;
+ }
+
+ fe->cb = NULL;
+
va_start(ap, fmt);
xvasprintf(&fe->value, fmt, ap);
va_end(ap);
+}
+
+/* Add a key and function. */
+void
+format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
+{
+ struct format_entry *fe;
+ struct format_entry *fe_now;
+
+ fe = xmalloc(sizeof *fe);
+ fe->key = xstrdup(key);
fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
if (fe_now != NULL) {
- free(fe_now->value);
- fe_now->value = fe->value;
free(fe->key);
free(fe);
+ free(fe_now->value);
+ fe = fe_now;
}
+
+ fe->cb = cb;
+
+ fe->value = NULL;
}
/* Find a format entry. */
@@ -364,8 +562,11 @@ format_find(struct format_tree *ft, const char *key)
fe_find.key = (char *) key;
fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
- if (fe != NULL)
+ if (fe != NULL) {
+ if (fe->value == NULL && fe->cb != NULL)
+ fe->cb(ft, fe);
return (fe->value);
+ }
envent = NULL;
if (ft->s != NULL)
@@ -507,7 +708,7 @@ char *
format_expand(struct format_tree *ft, const char *fmt)
{
char *buf, *tmp, *cmd;
- const char *ptr, *s;
+ const char *ptr, *s, *saved = fmt;
size_t off, len, n, slen;
int ch, brackets;
@@ -611,29 +812,10 @@ format_expand(struct format_tree *ft, const char *fmt)
}
buf[off] = '\0';
+ log_debug("format '%s' -> '%s'", saved, buf);
return (buf);
}
-/* Get command name for format. */
-char *
-format_get_command(struct window_pane *wp)
-{
- char *cmd, *out;
-
- cmd = osdep_get_name(wp->fd, wp->tty);
- if (cmd == NULL || *cmd == '\0') {
- free(cmd);
- cmd = cmd_stringify_argv(wp->argc, wp->argv);
- if (cmd == NULL || *cmd == '\0') {
- free(cmd);
- cmd = xstrdup(wp->shell);
- }
- }
- out = parse_window_name(cmd);
- free(cmd);
- return (out);
-}
-
/* Get time as a string. */
char *
format_time_string(time_t t)
@@ -674,8 +856,6 @@ format_defaults_session(struct format_tree *ft, struct session *s)
{
struct session_group *sg;
time_t t;
- struct winlink *wl;
- char alerts[256], tmp[16];
ft->s = s;
@@ -701,23 +881,7 @@ format_defaults_session(struct format_tree *ft, struct session *s)
format_add(ft, "session_attached", "%u", s->attached);
format_add(ft, "session_many_attached", "%d", s->attached > 1);
- *alerts = '\0';
- RB_FOREACH (wl, winlinks, &s->windows) {
- if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
- continue;
- xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
-
- if (*alerts != '\0')
- strlcat(alerts, ",", sizeof alerts);
- strlcat(alerts, tmp, sizeof alerts);
- if (wl->flags & WINLINK_ACTIVITY)
- strlcat(alerts, "#", sizeof alerts);
- if (wl->flags & WINLINK_BELL)
- strlcat(alerts, "!", sizeof alerts);
- if (wl->flags & WINLINK_SILENCE)
- strlcat(alerts, "~", sizeof alerts);
- }
- format_add(ft, "session_alerts", "%s", alerts);
+ format_add_cb(ft, "session_alerts", format_cb_session_alerts);
}
/* Set default format keys for a client. */
@@ -776,16 +940,10 @@ format_defaults_client(struct format_tree *ft, struct client *c)
void
format_defaults_window(struct format_tree *ft, struct window *w)
{
- char *layout;
time_t t;
ft->w = w;
- if (w->saved_layout_root != NULL)
- layout = layout_dump(w->saved_layout_root);
- else
- layout = layout_dump(w->layout_root);
-
t = w->activity_time.tv_sec;
format_add(ft, "window_activity", "%lld", (long long) t);
format_add(ft, "window_activity_string", "%s", format_time_string(t));
@@ -794,12 +952,10 @@ format_defaults_window(struct format_tree *ft, struct window *w)
format_add(ft, "window_name", "%s", w->name);
format_add(ft, "window_width", "%u", w->sx);
format_add(ft, "window_height", "%u", w->sy);
- format_add(ft, "window_layout", "%s", layout);
+ format_add_cb(ft, "window_layout", format_cb_window_layout);
format_add(ft, "window_panes", "%u", window_count_panes(w));
format_add(ft, "window_zoomed_flag", "%d",
!!(w->flags & WINDOW_ZOOMED));
-
- free(layout);
}
/* Set default format keys for a winlink. */
@@ -834,51 +990,21 @@ format_defaults_winlink(struct format_tree *ft, struct session *s,
free(flags);
}
-/* Add window pane tabs. */
-void
-format_defaults_pane_tabs(struct format_tree *ft, struct window_pane *wp)
-{
- struct evbuffer *buffer;
- u_int i;
-
- buffer = evbuffer_new();
- for (i = 0; i < wp->base.grid->sx; i++) {
- if (!bit_test(wp->base.tabs, i))
- continue;
-
- if (EVBUFFER_LENGTH(buffer) > 0)
- evbuffer_add(buffer, ",", 1);
- evbuffer_add_printf(buffer, "%u", i);
- }
-
- format_add(ft, "pane_tabs", "%.*s", (int) EVBUFFER_LENGTH(buffer),
- EVBUFFER_DATA(buffer));
- evbuffer_free(buffer);
-}
-
/* Set default format keys for a window pane. */
void
format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
{
- struct grid *gd = wp->base.grid;
- struct grid_line *gl;
- unsigned long long size;
- u_int i, idx;
- char *cmd, *cwd;
- int status;
+ struct grid *gd = wp->base.grid;
+ u_int idx;
+ int status;
if (ft->w == NULL)
ft->w = wp->window;
+ ft->wp = wp;
- size = 0;
- for (i = 0; i < gd->hsize; i++) {
- gl = &gd->linedata[i];
- size += gl->cellsize * sizeof *gl->celldata;
- }
- size += gd->hsize * sizeof *gd->linedata;
format_add(ft, "history_size", "%u", gd->hsize);
format_add(ft, "history_limit", "%u", gd->hlimit);
- format_add(ft, "history_bytes", "%llu", size);
+ format_add_cb(ft, "history_bytes", format_cb_history_bytes);
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
@@ -909,16 +1035,8 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_tty", "%s", wp->tty);
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
- if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
- format_add(ft, "pane_current_path", "%s", cwd);
- if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
- format_add(ft, "pane_start_command", "%s", cmd);
- free(cmd);
- }
- if ((cmd = format_get_command(wp)) != NULL) {
- format_add(ft, "pane_current_command", "%s", cmd);
- free(cmd);
- }
+ format_add_cb(ft, "pane_start_command", format_cb_start_command);
+ format_add_cb(ft, "pane_current_command", format_cb_current_command);
format_add(ft, "cursor_x", "%u", wp->base.cx);
format_add(ft, "cursor_y", "%u", wp->base.cy);
@@ -949,7 +1067,7 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "mouse_utf8_flag", "%d",
!!(wp->base.mode & MODE_MOUSE_UTF8));
- format_defaults_pane_tabs(ft, wp);
+ format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
}
/* Set default format keys for paste buffer. */
@@ -957,10 +1075,12 @@ void
format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
int utf8flag)
{
+ size_t bufsize;
char *s;
- format_add(ft, "buffer_size", "%zu", pb->size);
- format_add(ft, "buffer_name", "%s", pb->name);
+ paste_buffer_data(pb, &bufsize);
+ format_add(ft, "buffer_size", "%zu", bufsize);
+ format_add(ft, "buffer_name", "%s", paste_buffer_name(pb));
s = paste_make_sample(pb, utf8flag);
format_add(ft, "buffer_sample", "%s", s);
diff --git a/input.c b/input.c
index 7ec35c88..cfe6b4af 100644
--- a/input.c
+++ b/input.c
@@ -844,14 +844,9 @@ input_parse(struct window_pane *wp)
if (EVBUFFER_LENGTH(evb) == 0)
return;
+ window_update_activity(wp->window);
wp->flags |= PANE_CHANGED;
- wp->window->flags |= WINDOW_ACTIVITY;
- wp->window->flags &= ~WINDOW_SILENCE;
-
- if (gettimeofday(&wp->window->activity_time, NULL) != 0)
- fatal("gettimeofday failed");
-
/*
* Open the screen. Use NULL wp if there is a mode set as don't want to
* update the tty.
@@ -1081,7 +1076,7 @@ input_c0_dispatch(struct input_ctx *ictx)
case '\000': /* NUL */
break;
case '\007': /* BEL */
- wp->window->flags |= WINDOW_BELL;
+ alerts_queue(wp->window, WINDOW_BELL);
break;
case '\010': /* BS */
screen_write_backspace(sctx);
diff --git a/layout-set.c b/layout-set.c
index 64b655a0..da94cff2 100644
--- a/layout-set.c
+++ b/layout-set.c
@@ -44,12 +44,6 @@ const struct {
{ "tiled", layout_set_tiled },
};
-const char *
-layout_set_name(u_int layout)
-{
- return (layout_sets[layout].name);
-}
-
int
layout_set_lookup(const char *name)
{
diff --git a/log.c b/log.c
index 9afeb2ae..2fe12a17 100644
--- a/log.c
+++ b/log.c
@@ -67,14 +67,15 @@ log_close(void)
void
log_vwrite(const char *msg, va_list ap)
{
- char *fmt;
- time_t t;
+ char *fmt;
+ struct timeval tv;
if (log_file == NULL)
return;
- t = time(NULL);
- if (asprintf(&fmt, "%lld %s\n", (long long)t, msg) == -1)
+ gettimeofday(&tv, NULL);
+ if (asprintf(&fmt, "%lld.%06d %s\n", (long long)tv.tv_sec,
+ (int)tv.tv_usec, msg) == -1)
exit(1);
if (vfprintf(log_file, fmt, ap) == -1)
exit(1);
diff --git a/names.c b/names.c
index aa0673ea..e880c577 100644
--- a/names.c
+++ b/names.c
@@ -25,47 +25,76 @@
#include "tmux.h"
-void window_name_callback(unused int, unused short, void *);
+void name_time_callback(int, short, void *);
+int name_time_expired(struct window *, struct timeval *);
void
-queue_window_name(struct window *w)
+name_time_callback(unused int fd, unused short events, void *arg)
{
- struct timeval tv;
+ struct window *w = arg;
- tv.tv_sec = 0;
- tv.tv_usec = NAME_INTERVAL * 1000L;
+ /* The event loop will call check_window_name for us on the way out. */
+ log_debug("@%u name timer expired", w->id);
+}
+
+int
+name_time_expired(struct window *w, struct timeval *tv)
+{
+ struct timeval offset;
- if (event_initialized(&w->name_timer))
- evtimer_del(&w->name_timer);
- evtimer_set(&w->name_timer, window_name_callback, w);
- evtimer_add(&w->name_timer, &tv);
+ timersub(tv, &w->name_time, &offset);
+ if (offset.tv_sec != 0 || offset.tv_usec > NAME_INTERVAL)
+ return (0);
+ return (NAME_INTERVAL - offset.tv_usec);
}
void
-window_name_callback(unused int fd, unused short events, void *data)
+check_window_name(struct window *w)
{
- struct window *w = data;
+ struct timeval tv, next;
char *name;
+ int left;
if (w->active == NULL)
return;
- if (!options_get_number(&w->options, "automatic-rename")) {
- if (event_initialized(&w->name_timer))
- event_del(&w->name_timer);
+ if (!options_get_number(&w->options, "automatic-rename"))
return;
- }
- queue_window_name(w);
- if (~w->active->flags & PANE_CHANGED)
+ if (~w->active->flags & PANE_CHANGED) {
+ log_debug("@%u active pane not changed", w->id);
+ return;
+ }
+ log_debug("@%u active pane changed", w->id);
+
+ gettimeofday(&tv, NULL);
+ left = name_time_expired(w, &tv);
+ if (left != 0) {
+ if (!event_initialized(&w->name_event))
+ evtimer_set(&w->name_event, name_time_callback, w);
+ if (!evtimer_pending(&w->name_event, NULL)) {
+ log_debug("@%u name timer queued (%d left)", w->id, left);
+ timerclear(&next);
+ next.tv_usec = left;
+ event_add(&w->name_event, &next);
+ } else
+ log_debug("@%u name timer already queued (%d left)", w->id, left);
return;
+ }
+ memcpy(&w->name_time, &tv, sizeof w->name_time);
+ if (event_initialized(&w->name_event))
+ evtimer_del(&w->name_event);
+
w->active->flags &= ~PANE_CHANGED;
name = format_window_name(w);
if (strcmp(name, w->name) != 0) {
+ log_debug("@%u new name %s (was %s)", w->id, name, w->name);
window_set_name(w, name);
server_status_window(w);
- }
+ } else
+ log_debug("@%u name not changed (still %s)", w->id, w->name);
+
free(name);
}
diff --git a/paste.c b/paste.c
index 05f4c760..11357731 100644
--- a/paste.c
+++ b/paste.c
@@ -29,6 +29,18 @@
* string!
*/
+struct paste_buffer {
+ char *data;
+ size_t size;
+
+ char *name;
+ int automatic;
+ u_int order;
+
+ RB_ENTRY(paste_buffer) name_entry;
+ RB_ENTRY(paste_buffer) time_entry;
+};
+
u_int paste_next_index;
u_int paste_next_order;
u_int paste_num_automatic;
@@ -59,6 +71,22 @@ paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b)
return (0);
}
+/* Get paste buffer name. */
+const char *
+paste_buffer_name(struct paste_buffer *pb)
+{
+ return (pb->name);
+}
+
+/* Get paste buffer data. */
+const char *
+paste_buffer_data(struct paste_buffer *pb, size_t *size)
+{
+ if (size != NULL)
+ *size = pb->size;
+ return (pb->data);
+}
+
/* Walk paste buffers by name. */
struct paste_buffer *
paste_walk(struct paste_buffer *pb)
@@ -70,13 +98,15 @@ paste_walk(struct paste_buffer *pb)
/* Get the most recent automatic buffer. */
struct paste_buffer *
-paste_get_top(void)
+paste_get_top(const char **name)
{
struct paste_buffer *pb;
pb = RB_MIN(paste_time_tree, &paste_by_time);
if (pb == NULL)
return (NULL);
+ if (name != NULL)
+ *name = pb->name;
return (pb);
}
@@ -86,7 +116,7 @@ paste_free_top(void)
{
struct paste_buffer *pb;
- pb = paste_get_top();
+ pb = paste_get_top(NULL);
if (pb == NULL)
return (-1);
return (paste_free_name(pb->name));
@@ -288,32 +318,3 @@ paste_make_sample(struct paste_buffer *pb, int utf8flag)
strlcpy(buf + width, "...", 4);
return (buf);
}
-
-/* Paste into a window pane, filtering '\n' according to separator. */
-void
-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;
- size_t seplen;
-
- if (wp->flags & PANE_INPUTOFF)
- return;
-
- if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
- bufferevent_write(wp->event, "\033[200~", 6);
-
- seplen = strlen(sep);
- while ((lf = memchr(data, '\n', end - data)) != NULL) {
- if (lf != data)
- bufferevent_write(wp->event, data, lf - data);
- bufferevent_write(wp->event, sep, seplen);
- data = lf + 1;
- }
-
- if (end != data)
- bufferevent_write(wp->event, data, end - data);
-
- if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
- bufferevent_write(wp->event, "\033[201~", 6);
-}
diff --git a/screen.c b/screen.c
index c1df95ad..01314330 100644
--- a/screen.c
+++ b/screen.c
@@ -32,14 +32,8 @@ void screen_resize_y(struct screen *, u_int);
void
screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
{
- char host[HOST_NAME_MAX+1];
-
s->grid = grid_create(sx, sy, hlimit);
-
- if (gethostname(host, sizeof(host)) == 0)
- s->title = xstrdup(host);
- else
- s->title = xstrdup("");
+ s->title = xstrdup("");
s->cstyle = 0;
s->ccolour = xstrdup("");
diff --git a/server-client.c b/server-client.c
index 1faf5968..632c5f99 100644
--- a/server-client.c
+++ b/server-client.c
@@ -550,13 +550,6 @@ server_client_handle_key(struct client *c, int key)
w = s->curw->window;
wp = w->active;
- /* No session, do nothing. */
- if (c->session == NULL)
- return;
- s = c->session;
- w = c->session->curw->window;
- wp = w->active;
-
/* Update the activity timer. */
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday failed");
@@ -716,6 +709,7 @@ server_client_loop(void)
}
wp->flags &= ~PANE_REDRAW;
}
+ check_window_name(w);
}
}
diff --git a/server.c b/server.c
index 62d05ebe..2a888f22 100644
--- a/server.c
+++ b/server.c
@@ -251,9 +251,10 @@ void
server_loop(void)
{
while (!server_should_shutdown()) {
+ log_debug("event dispatch enter");
event_loop(EVLOOP_ONCE);
+ log_debug("event dispatch exit");
- server_window_loop();
server_client_loop();
}
}
diff --git a/session.c b/session.c
index b8472c2a..604af6e6 100644
--- a/session.c
+++ b/session.c
@@ -518,6 +518,7 @@ session_set_current(struct session *s, struct winlink *wl)
winlink_stack_push(&s->lastw, s->curw);
s->curw = wl;
winlink_clear_flags(wl);
+ window_update_activity(wl->window);
return (0);
}
diff --git a/status.c b/status.c
index 93cee2b1..29cb686c 100644
--- a/status.c
+++ b/status.c
@@ -815,10 +815,9 @@ status_prompt_key(struct client *c, int key)
struct options *oo = &sess->options;
struct paste_buffer *pb;
char *s, *first, *last, word[64], swapc;
- const char *histstr;
- const char *wsep = NULL;
+ const char *histstr, *bufdata, *wsep = NULL;
u_char ch;
- size_t size, n, off, idx;
+ size_t size, n, off, idx, bufsize;
size = strlen(c->prompt_buffer);
switch (mode_key_lookup(&c->prompt_mdata, key, NULL)) {
@@ -1067,24 +1066,25 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_PASTE:
- if ((pb = paste_get_top()) == NULL)
+ if ((pb = paste_get_top(NULL)) == NULL)
break;
- for (n = 0; n < pb->size; n++) {
- ch = (u_char) pb->data[n];
+ bufdata = paste_buffer_data(pb, &bufsize);
+ for (n = 0; n < bufsize; n++) {
+ ch = (u_char)bufdata[n];
if (ch < 32 || ch == 127)
break;
}
c->prompt_buffer = xrealloc(c->prompt_buffer, size + n + 1);
if (c->prompt_index == size) {
- memcpy(c->prompt_buffer + c->prompt_index, pb->data, n);
+ memcpy(c->prompt_buffer + c->prompt_index, bufdata, n);
c->prompt_index += n;
c->prompt_buffer[c->prompt_index] = '\0';
} else {
memmove(c->prompt_buffer + c->prompt_index + n,
c->prompt_buffer + c->prompt_index,
size + 1 - c->prompt_index);
- memcpy(c->prompt_buffer + c->prompt_index, pb->data, n);
+ memcpy(c->prompt_buffer + c->prompt_index, bufdata, n);
c->prompt_index += n;
}
diff --git a/tmux.c b/tmux.c
index 61c95af8..21dc15e1 100644
--- a/tmux.c
+++ b/tmux.c
@@ -200,7 +200,7 @@ shell_exec(const char *shell, const char *shellcmd)
fatal("execl failed");
}
-const char*
+const char *
find_home(void)
{
struct passwd *pw;
@@ -215,7 +215,7 @@ find_home(void)
home = NULL;
}
- return home;
+ return (home);
}
int
diff --git a/tmux.h b/tmux.h
index 8678794e..78d5eaa3 100644
--- a/tmux.h
+++ b/tmux.h
@@ -51,8 +51,8 @@ extern char **environ;
*/
#define PANE_MINIMUM 2
-/* Automatic name refresh interval, in milliseconds. */
-#define NAME_INTERVAL 500
+/* Automatic name refresh interval, in microseconds. Must be < 1 second. */
+#define NAME_INTERVAL 500000
/*
* UTF-8 data size. This must be big enough to hold combined characters as well
@@ -873,9 +873,13 @@ RB_HEAD(window_pane_tree, window_pane);
/* Window structure. */
struct window {
u_int id;
+
char *name;
- struct event name_timer;
- struct timeval silence_timer;
+ struct event name_event;
+ struct timeval name_time;
+
+ struct event alerts_timer;
+
struct timeval activity_time;
struct window_pane *active;
@@ -957,19 +961,6 @@ struct layout_cell {
TAILQ_ENTRY(layout_cell) entry;
};
-/* Paste buffer. */
-struct paste_buffer {
- char *data;
- size_t size;
-
- char *name;
- int automatic;
- u_int order;
-
- RB_ENTRY(paste_buffer) name_entry;
- RB_ENTRY(paste_buffer) time_entry;
-};
-
/* Environment variable. */
struct environ_entry {
char *name;
@@ -1270,13 +1261,8 @@ struct client {
TAILQ_HEAD(clients, client);
/* Parsed arguments structures. */
-struct args_entry {
- u_char flag;
- char *value;
- RB_ENTRY(args_entry) entry;
-};
+struct args_entry;
RB_HEAD(args_tree, args_entry);
-
struct args {
struct args_tree tree;
int argc;
@@ -1452,6 +1438,20 @@ void cfg_add_cause(const char *, ...);
void cfg_print_causes(struct cmd_q *);
void cfg_show_causes(struct session *);
+/* paste.c */
+struct paste_buffer;
+const char *paste_buffer_name(struct paste_buffer *);
+const char *paste_buffer_data(struct paste_buffer *, size_t *);
+struct paste_buffer *paste_walk(struct paste_buffer *);
+struct paste_buffer *paste_get_top(const char **);
+struct paste_buffer *paste_get_name(const char *);
+int paste_free_top(void);
+int paste_free_name(const char *);
+void paste_add(char *, size_t);
+int paste_rename(const char *, const char *, char **);
+int paste_set(char *, size_t, const char *, char **);
+char *paste_make_sample(struct paste_buffer *, int);
+
/* format.c */
struct format_tree;
struct format_tree *format_create(void);
@@ -1636,19 +1636,6 @@ void tty_keys_build(struct tty *);
void tty_keys_free(struct tty *);
int tty_keys_next(struct tty *);
-/* paste.c */
-struct paste_buffer *paste_walk(struct paste_buffer *);
-struct paste_buffer *paste_get_top(void);
-struct paste_buffer *paste_get_name(const char *);
-int paste_free_top(void);
-int paste_free_name(const char *);
-void paste_add(char *, size_t);
-int paste_rename(const char *, const char *, char **);
-int paste_set(char *, size_t, const char *, char **);
-char *paste_make_sample(struct paste_buffer *, int);
-void paste_send_pane(struct paste_buffer *, struct window_pane *,
- const char *, int);
-
/* arguments.c */
int args_cmp(struct args_entry *, struct args_entry *);
RB_PROTOTYPE(args_tree, args_entry, entry, args_cmp);
@@ -1830,6 +1817,10 @@ void key_bindings_dispatch(struct key_binding *, struct client *,
int key_string_lookup_string(const char *);
const char *key_string_lookup_key(int);
+/* alerts.c */
+void alerts_reset_all(void);
+void alerts_queue(struct window *, int);
+
/* server.c */
extern struct clients clients;
extern struct clients dead_clients;
@@ -1854,12 +1845,8 @@ int server_client_open(struct client *, char **);
void server_client_unref(struct client *);
void server_client_lost(struct client *);
void server_client_callback(int, short, void *);
-void server_client_status_timer(void);
void server_client_loop(void);
-/* server-window.c */
-void server_window_loop(void);
-
/* server-fn.c */
void server_fill_environ(struct session *, struct environ *);
void server_write_ready(struct client *);
@@ -1879,7 +1866,6 @@ void server_status_window(struct window *);
void server_lock(void);
void server_lock_session(struct session *);
void server_lock_client(struct client *);
-int server_unlock(const char *);
void server_kill_window(struct window *);
int server_link_window(struct session *,
struct winlink *, struct session *, int, int, int, char **);
@@ -2029,7 +2015,6 @@ void screen_write_cursormove(struct screen_write_ctx *, u_int, u_int);
void screen_write_reverseindex(struct screen_write_ctx *);
void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
void screen_write_linefeed(struct screen_write_ctx *, int);
-void screen_write_linefeedscreen(struct screen_write_ctx *, int);
void screen_write_carriagereturn(struct screen_write_ctx *);
void screen_write_clearendofscreen(struct screen_write_ctx *);
void screen_write_clearstartofscreen(struct screen_write_ctx *);
@@ -2085,13 +2070,13 @@ void winlink_stack_push(struct winlink_stack *, struct winlink *);
void winlink_stack_remove(struct winlink_stack *, struct winlink *);
struct window *window_find_by_id_str(const char *);
struct window *window_find_by_id(u_int);
+void window_update_activity(struct window *);
struct window *window_create1(u_int, u_int);
struct window *window_create(const char *, int, char **, const char *,
const char *, int, struct environ *, struct termios *,
u_int, u_int, u_int, char **);
void window_destroy(struct window *);
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
-void window_set_active_at(struct window *, u_int, u_int);
struct window_pane *window_find_string(struct window *, const char *);
int window_has_pane(struct window *, struct window_pane *);
int window_set_active_pane(struct window *, struct window_pane *);
@@ -2172,12 +2157,10 @@ char *layout_dump(struct layout_cell *);
int layout_parse(struct window *, const char *);
/* layout-set.c */
-const char *layout_set_name(u_int);
int layout_set_lookup(const char *);
u_int layout_set_select(struct window *, u_int);
u_int layout_set_next(struct window *);
u_int layout_set_previous(struct window *);
-void layout_set_active_changed(struct window *);
/* window-clock.c */
extern const struct window_mode window_clock_mode;
@@ -2213,7 +2196,7 @@ void window_choose_collapse_all(struct window_pane *);
void window_choose_set_current(struct window_pane *, u_int);
/* names.c */
-void queue_window_name(struct window *);
+void check_window_name(struct window *);
char *default_window_name(struct window *);
char *format_window_name(struct window *);
char *parse_window_name(const char *);
diff --git a/window-copy.c b/window-copy.c
index 850b437a..460dd10b 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -782,7 +782,8 @@ window_copy_key_input(struct window_pane *wp, int key)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
- size_t inputlen, n;
+ const char *bufdata;
+ size_t inputlen, n, bufsize;
int np;
struct paste_buffer *pb;
u_char ch;
@@ -800,17 +801,18 @@ window_copy_key_input(struct window_pane *wp, int key)
*data->inputstr = '\0';
break;
case MODEKEYEDIT_PASTE:
- if ((pb = paste_get_top()) == NULL)
+ if ((pb = paste_get_top(NULL)) == NULL)
break;
- for (n = 0; n < pb->size; n++) {
- ch = (u_char) pb->data[n];
+ bufdata = paste_buffer_data(pb, &bufsize);
+ for (n = 0; n < bufsize; n++) {
+ ch = (u_char)bufdata[n];
if (ch < 32 || ch == 127)
break;
}
inputlen = strlen(data->inputstr);
data->inputstr = xrealloc(data->inputstr, inputlen + n + 1);
- memcpy(data->inputstr + inputlen, pb->data, n);
+ memcpy(data->inputstr + inputlen, bufdata, n);
data->inputstr[inputlen + n] = '\0';
break;
case MODEKEYEDIT_ENTER:
@@ -1491,7 +1493,8 @@ window_copy_append_selection(struct window_pane *wp, const char *bufname)
{
char *buf;
struct paste_buffer *pb;
- size_t len;
+ const char *bufdata;
+ size_t len, bufsize;
struct screen_write_ctx ctx;
buf = window_copy_get_selection(wp, &len);
@@ -1504,17 +1507,16 @@ window_copy_append_selection(struct window_pane *wp, const char *bufname)
screen_write_stop(&ctx);
}
- if (bufname == NULL || *bufname == '\0') {
- pb = paste_get_top();
- if (pb != NULL)
- bufname = pb->name;
- } else
+ if (bufname == NULL || *bufname == '\0')
+ pb = paste_get_top(&bufname);
+ else
pb = paste_get_name(bufname);
if (pb != NULL) {
- buf = xrealloc(buf, len + pb->size);
- memmove(buf + pb->size, buf, len);
- memcpy(buf, pb->data, pb->size);
- len += pb->size;
+ bufdata = paste_buffer_data(pb, &bufsize);
+ buf = xrealloc(buf, len + bufsize);
+ memmove(buf + bufsize, buf, len);
+ memcpy(buf, bufdata, bufsize);
+ len += bufsize;
}
if (paste_set(buf, len, bufname, NULL) != 0)
free(buf);
diff --git a/window.c b/window.c
index 525dad51..f75785c7 100644
--- a/window.c
+++ b/window.c
@@ -276,6 +276,13 @@ window_find_by_id(u_int id)
return (RB_FIND(windows, &windows, &w));
}
+void
+window_update_activity(struct window *w)
+{
+ gettimeofday(&w->activity_time, NULL);
+ alerts_queue(w, WINDOW_ACTIVITY);
+}
+
struct window *
window_create1(u_int sx, u_int sy)
{
@@ -294,18 +301,15 @@ window_create1(u_int sx, u_int sy)
w->sx = sx;
w->sy = sy;
- if (gettimeofday(&w->activity_time, NULL) != 0)
- fatal("gettimeofday failed");
-
options_init(&w->options, &global_w_options);
- if (options_get_number(&w->options, "automatic-rename"))
- queue_window_name(w);
w->references = 0;
w->id = next_window_id++;
RB_INSERT(windows, &windows, w);
+ window_update_activity(w);
+
return (w);
}
@@ -348,8 +352,11 @@ window_destroy(struct window *w)
layout_free_cell(w->saved_layout_root);
free(w->old_layout);
- if (event_initialized(&w->name_timer))
- evtimer_del(&w->name_timer);
+ if (event_initialized(&w->name_event))
+ evtimer_del(&w->name_event);
+
+ if (event_initialized(&w->alerts_timer))
+ evtimer_del(&w->alerts_timer);
options_free(&w->options);
@@ -432,16 +439,6 @@ window_get_active_at(struct window *w, u_int x, u_int y)
return (NULL);
}
-void
-window_set_active_at(struct window *w, u_int x, u_int y)
-{
- struct window_pane *wp;
-
- wp = window_get_active_at(w, x, y);
- if (wp != NULL && wp != w->active)
- window_set_active_pane(w, wp);
-}
-
struct window_pane *
window_find_string(struct window *w, const char *s)
{
@@ -703,6 +700,7 @@ struct window_pane *
window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
{
struct window_pane *wp;
+ char host[HOST_NAME_MAX + 1];
wp = xcalloc(1, sizeof *wp);
wp->window = w;
@@ -739,6 +737,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
screen_init(&wp->base, sx, sy, hlimit);
wp->screen = &wp->base;
+ if (gethostname(host, sizeof host) == 0)
+ screen_set_title(&wp->base, host);
+
input_init(wp);
return (wp);
@@ -941,14 +942,6 @@ window_pane_read_callback(unused struct bufferevent *bufev, void *data)
input_parse(wp);
wp->pipe_off = EVBUFFER_LENGTH(evb);
-
- /*
- * If we get here, we're not outputting anymore, so set the silence
- * flag on the window.
- */
- wp->window->flags |= WINDOW_SILENCE;
- if (gettimeofday(&wp->window->silence_timer, NULL) != 0)
- fatal("gettimeofday failed");
return;
start_timer:
@@ -1078,7 +1071,7 @@ window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
if ((s = wp->mode->init(wp)) != NULL)
wp->screen = s;
- wp->flags |= PANE_REDRAW;
+ wp->flags |= (PANE_REDRAW|PANE_CHANGED);
return (0);
}
@@ -1092,7 +1085,7 @@ window_pane_reset_mode(struct window_pane *wp)
wp->mode = NULL;
wp->screen = &wp->base;
- wp->flags |= PANE_REDRAW;
+ wp->flags |= (PANE_REDRAW|PANE_CHANGED);
}
void
diff --git a/xterm-keys.c b/xterm-keys.c
index 5ca75d89..10d51c78 100644
--- a/xterm-keys.c
+++ b/xterm-keys.c
@@ -120,6 +120,8 @@ xterm_keys_match(const char *template, const char *buf, size_t len,
size_t pos;
int retval;
+ *modifiers = 0;
+
if (len == 0)
return (0);