Merge branch 'obsd-master'

Conflicts:
	server.c
pull/777/merge
Thomas Adam 2017-02-14 13:55:16 +00:00
commit 02e04477de
11 changed files with 236 additions and 155 deletions

View File

@ -68,12 +68,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = item->client;
struct session *s, *as;
struct session *groupwith = item->state.tflag.s;
struct session *s, *as, *groupwith;
struct window *w;
struct environ *env;
struct termios tio, *tiop;
const char *newname, *target, *errstr, *template;
struct session_group *sg;
const char *newname, *errstr, *template, *group, *prefix;
const char *path, *cmd, *cwd, *to_free = NULL;
char **argv, *cause, *cp;
int detached, already_attached, idx, argc;
@ -119,13 +119,29 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
}
}
if ((target = args_get(args, 't')) != NULL) {
/* Is this going to be part of a session group? */
group = args_get(args, 't');
if (group != NULL) {
groupwith = item->state.tflag.s;
if (groupwith == NULL) {
cmdq_error(item, "no such session: %s", target);
goto error;
}
} else
if (!session_check_name(group)) {
cmdq_error(item, "bad group name: %s", group);
goto error;
}
sg = session_group_find(group);
} else
sg = session_group_contains(groupwith);
if (sg != NULL)
prefix = sg->name;
else if (groupwith != NULL)
prefix = groupwith->name;
else
prefix = group;
} else {
groupwith = NULL;
sg = NULL;
prefix = NULL;
}
/* Set -d if no client. */
detached = args_has(args, 'd');
@ -213,7 +229,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
if (!args_has(args, 't') && args->argc != 0) {
argc = args->argc;
argv = args->argv;
} else if (groupwith == NULL) {
} else if (sg == NULL && groupwith == NULL) {
cmd = options_get_string(global_s_options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
@ -239,8 +255,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
/* Create the new session. */
idx = -1 - options_get_number(global_s_options, "base-index");
s = session_create(newname, argc, argv, path, cwd, env, tiop, idx, sx,
sy, &cause);
s = session_create(prefix, newname, argc, argv, path, cwd, env, tiop,
idx, sx, sy, &cause);
environ_free(env);
if (s == NULL) {
cmdq_error(item, "create session failed: %s", cause);
@ -259,8 +275,15 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
* If a target session is given, this is to be part of a session group,
* so add it to the group and synchronize.
*/
if (groupwith != NULL) {
session_group_add(groupwith, s);
if (group != NULL) {
if (sg == NULL) {
if (groupwith != NULL) {
sg = session_group_new(groupwith->name);
session_group_add(sg, groupwith);
} else
sg = session_group_new(group);
}
session_group_add(sg, s);
session_group_synchronize_to(s);
session_select(s, RB_MIN(winlinks, &s->windows)->idx);
}

View File

@ -52,11 +52,11 @@ cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
wl_src = item->state.sflag.wl;
src = item->state.sflag.s;
sg_src = session_group_find(src);
sg_src = session_group_contains(src);
wl_dst = item->state.tflag.wl;
dst = item->state.tflag.s;
sg_dst = session_group_find(dst);
sg_dst = session_group_contains(dst);
if (src != dst && sg_src != NULL && sg_dst != NULL &&
sg_src == sg_dst) {

View File

@ -1117,10 +1117,10 @@ format_defaults_session(struct format_tree *ft, struct session *s)
format_add(ft, "session_height", "%u", s->sy);
format_add(ft, "session_id", "$%u", s->id);
sg = session_group_find(s);
sg = session_group_contains(s);
format_add(ft, "session_grouped", "%d", sg != NULL);
if (sg != NULL)
format_add(ft, "session_group", "%u", session_group_index(sg));
format_add(ft, "session_group", "%s", sg->name);
format_add_tv(ft, "session_created", &s->creation_time);
format_add_tv(ft, "session_last_attached", &s->last_attached_time);

29
grid.c
View File

@ -78,6 +78,20 @@ grid_store_cell(struct grid_cell_entry *gce, const struct grid_cell *gc,
gce->data.data = c;
}
/* Check if a cell should be extended. */
static int
grid_need_extended_cell(const struct grid_cell_entry *gce,
const struct grid_cell *gc)
{
if (gce->flags & GRID_FLAG_EXTENDED)
return (1);
if (gc->data.size != 1 || gc->data.width != 1)
return (1);
if ((gc->fg & COLOUR_FLAG_RGB) ||(gc->bg & COLOUR_FLAG_RGB))
return (1);
return (0);
}
/* Set cell as extended. */
static struct grid_cell *
grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
@ -382,7 +396,6 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{
struct grid_line *gl;
struct grid_cell_entry *gce;
int extended;
if (grid_check_y(gd, py) != 0)
return;
@ -394,14 +407,7 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
gl->cellused = px + 1;
gce = &gl->celldata[px];
extended = (gce->flags & GRID_FLAG_EXTENDED);
if (!extended && (gc->data.size != 1 || gc->data.width != 1))
extended = 1;
if (!extended && (gc->fg & COLOUR_FLAG_RGB))
extended = 1;
if (!extended && (gc->bg & COLOUR_FLAG_RGB))
extended = 1;
if (extended)
if (grid_need_extended_cell(gce, gc))
grid_extended_cell(gl, gce, gc);
else
grid_store_cell(gce, gc, gc->data.data[0]);
@ -428,9 +434,8 @@ grid_set_cells(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc,
for (i = 0; i < slen; i++) {
gce = &gl->celldata[px + i];
if (gce->flags & GRID_FLAG_EXTENDED) {
gcp = &gl->extddata[gce->offset];
memcpy(gcp, gc, sizeof *gcp);
if (grid_need_extended_cell(gce, gc)) {
gcp = grid_extended_cell(gl, gce, gc);
utf8_set(&gcp->data, s[i]);
} else
grid_store_cell(gce, gc, s[i]);

View File

@ -76,7 +76,7 @@ server_redraw_session_group(struct session *s)
{
struct session_group *sg;
if ((sg = session_group_find(s)) == NULL)
if ((sg = session_group_contains(s)) == NULL)
server_redraw_session(s);
else {
TAILQ_FOREACH(s, &sg->sessions, gentry)
@ -100,7 +100,7 @@ server_status_session_group(struct session *s)
{
struct session_group *sg;
if ((sg = session_group_find(s)) == NULL)
if ((sg = session_group_contains(s)) == NULL)
server_status_session(s);
else {
TAILQ_FOREACH(s, &sg->sessions, gentry)
@ -218,7 +218,7 @@ server_kill_window(struct window *w)
}
if (options_get_number(s->options, "renumber-windows")) {
if ((sg = session_group_find(s)) != NULL) {
if ((sg = session_group_contains(s)) != NULL) {
TAILQ_FOREACH(target_s, &sg->sessions, gentry)
session_renumber_windows(target_s);
} else
@ -236,8 +236,8 @@ server_link_window(struct session *src, struct winlink *srcwl,
struct winlink *dstwl;
struct session_group *srcsg, *dstsg;
srcsg = session_group_find(src);
dstsg = session_group_find(dst);
srcsg = session_group_contains(src);
dstsg = session_group_contains(dst);
if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) {
xasprintf(cause, "sessions are grouped");
return (-1);
@ -349,7 +349,7 @@ server_destroy_session_group(struct session *s)
struct session_group *sg;
struct session *s1;
if ((sg = session_group_find(s)) == NULL)
if ((sg = session_group_contains(s)) == NULL)
server_destroy_session(s);
else {
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {

View File

@ -155,7 +155,7 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
RB_INIT(&all_window_panes);
TAILQ_INIT(&clients);
RB_INIT(&sessions);
TAILQ_INIT(&session_groups);
RB_INIT(&session_groups);
key_bindings_init();
gettimeofday(&start_time, NULL);

View File

@ -41,6 +41,9 @@ static void session_group_remove(struct session *);
static u_int session_group_count(struct session_group *);
static void session_group_synchronize1(struct session *, struct session *);
static u_int session_group_count(struct session_group *);
static void session_group_synchronize1(struct session *, struct session *);
RB_GENERATE(sessions, session, entry, session_cmp);
int
@ -49,6 +52,14 @@ session_cmp(struct session *s1, struct session *s2)
return (strcmp(s1->name, s2->name));
}
RB_GENERATE(session_groups, session_group, entry, session_group_cmp);
int
session_group_cmp(struct session_group *s1, struct session_group *s2)
{
return (strcmp(s1->name, s2->name));
}
/*
* Find if session is still alive. This is true if it is still on the global
* sessions list.
@ -106,9 +117,9 @@ session_find_by_id(u_int id)
/* Create a new session. */
struct session *
session_create(const char *name, int argc, char **argv, const char *path,
const char *cwd, struct environ *env, struct termios *tio, int idx,
u_int sx, u_int sy, char **cause)
session_create(const char *prefix, const char *name, int argc, char **argv,
const char *path, const char *cwd, struct environ *env, struct termios *tio,
int idx, u_int sx, u_int sy, char **cause)
{
struct session *s;
struct winlink *wl;
@ -149,7 +160,10 @@ session_create(const char *name, int argc, char **argv, const char *path,
do {
s->id = next_session_id++;
free(s->name);
xasprintf(&s->name, "%u", s->id);
if (prefix != NULL)
xasprintf(&s->name, "%s-%u", prefix, s->id);
else
xasprintf(&s->name, "%u", s->id);
} while (RB_FIND(sessions, &sessions, s) != NULL);
}
RB_INSERT(sessions, &sessions, s);
@ -428,7 +442,7 @@ session_is_linked(struct session *s, struct window *w)
{
struct session_group *sg;
if ((sg = session_group_find(s)) != NULL)
if ((sg = session_group_contains(s)) != NULL)
return (w->references != session_group_count(sg));
return (w->references != 1);
}
@ -539,12 +553,12 @@ session_set_current(struct session *s, struct winlink *wl)
/* Find the session group containing a session. */
struct session_group *
session_group_find(struct session *target)
session_group_contains(struct session *target)
{
struct session_group *sg;
struct session *s;
TAILQ_FOREACH(sg, &session_groups, entry) {
RB_FOREACH(sg, session_groups, &session_groups) {
TAILQ_FOREACH(s, &sg->sessions, gentry) {
if (s == target)
return (sg);
@ -553,39 +567,39 @@ session_group_find(struct session *target)
return (NULL);
}
/* Find session group index. */
u_int
session_group_index(struct session_group *sg)
/* Find session group by name. */
struct session_group *
session_group_find(const char *name)
{
struct session_group *sg2;
u_int i;
struct session_group sg;
i = 0;
TAILQ_FOREACH(sg2, &session_groups, entry) {
if (sg == sg2)
return (i);
i++;
}
fatalx("session group not found");
sg.name = name;
return (RB_FIND(session_groups, &session_groups, &sg));
}
/*
* Add a session to the session group containing target, creating it if
* necessary.
*/
void
session_group_add(struct session *target, struct session *s)
/* Create a new session group. */
struct session_group *
session_group_new(const char *name)
{
struct session_group *sg;
if ((sg = session_group_find(target)) == NULL) {
sg = xmalloc(sizeof *sg);
TAILQ_INSERT_TAIL(&session_groups, sg, entry);
TAILQ_INIT(&sg->sessions);
TAILQ_INSERT_TAIL(&sg->sessions, target, gentry);
}
TAILQ_INSERT_TAIL(&sg->sessions, s, gentry);
if ((sg = session_group_find(name)) != NULL)
return (sg);
sg = xcalloc(1, sizeof *sg);
sg->name = xstrdup(name);
TAILQ_INIT(&sg->sessions);
RB_INSERT(session_groups, &session_groups, sg);
return (sg);
}
/* Add a session to a session group. */
void
session_group_add(struct session_group *sg, struct session *s)
{
if (session_group_contains(s) == NULL)
TAILQ_INSERT_TAIL(&sg->sessions, s, gentry);
}
/* Remove a session from its group and destroy the group if empty. */
@ -594,13 +608,11 @@ session_group_remove(struct session *s)
{
struct session_group *sg;
if ((sg = session_group_find(s)) == NULL)
if ((sg = session_group_contains(s)) == NULL)
return;
TAILQ_REMOVE(&sg->sessions, s, gentry);
if (TAILQ_NEXT(TAILQ_FIRST(&sg->sessions), gentry) == NULL)
TAILQ_REMOVE(&sg->sessions, TAILQ_FIRST(&sg->sessions), gentry);
if (TAILQ_EMPTY(&sg->sessions)) {
TAILQ_REMOVE(&session_groups, sg, entry);
RB_REMOVE(session_groups, &session_groups, sg);
free(sg);
}
}
@ -625,7 +637,7 @@ session_group_synchronize_to(struct session *s)
struct session_group *sg;
struct session *target;
if ((sg = session_group_find(s)) == NULL)
if ((sg = session_group_contains(s)) == NULL)
return;
target = NULL;
@ -633,7 +645,8 @@ session_group_synchronize_to(struct session *s)
if (target != s)
break;
}
session_group_synchronize1(target, s);
if (target != NULL)
session_group_synchronize1(target, s);
}
/* Synchronize a session group to a session. */
@ -643,7 +656,7 @@ session_group_synchronize_from(struct session *target)
struct session_group *sg;
struct session *s;
if ((sg = session_group_find(target)) == NULL)
if ((sg = session_group_contains(target)) == NULL)
return;
TAILQ_FOREACH(s, &sg->sessions, gentry) {

42
tmux.1
View File

@ -816,7 +816,7 @@ Lock all clients attached to
.Op Fl F Ar format
.Op Fl n Ar window-name
.Op Fl s Ar session-name
.Op Fl t Ar target-session
.Op Fl t Ar group-name
.Op Fl x Ar width
.Op Fl y Ar height
.Op Ar shell-command
@ -861,16 +861,27 @@ to
.Pp
If
.Fl t
is given, the new session is
.Em grouped
with
.Ar target-session .
This means they share the same set of windows - all windows from
.Ar target-session
are linked to the new session, any new windows are linked to both sessions and
any windows closed removed from both sessions.
is given, it specifies a
.Ic session group .
Sessions in the same group share the same set of windows - new windows are
linked to all sessions in the group and any windows closed removed from all
sessions.
The current and previous window and any session options remain independent and
either session may be killed without affecting the other.
any session in a group may be killed without affecting the others.
The
.Ar group-name
argument may be:
.Bl -enum -width Ds
.It
the name of an existing group, in which case the new session is added to that
group;
.It
the name of an existing session - the new session is added to the same group
as that session, creating a new group if necessary;
.It
the name for a new group containing only the new session.
.El
.Pp
.Fl n
and
.Ar shell-command
@ -892,6 +903,7 @@ is used, the
.Ic update-environment
option will not be applied.
.It Xo Ic refresh-client
.Op Fl C Ar width,height
.Op Fl S
.Op Fl t Ar target-client
.Xc
@ -902,6 +914,9 @@ with
If
.Fl S
is specified, only update the client's status bar.
.Pp
.Fl C
sets the width and height of a control client.
.It Xo Ic rename-session
.Op Fl t Ar target-session
.Ar new-name
@ -3563,7 +3578,7 @@ The following variables are available, where appropriate:
.It Li "session_activity" Ta "" Ta "Integer time of session last activity"
.It Li "session_created" Ta "" Ta "Integer time session created"
.It Li "session_last_attached" Ta "" Ta "Integer time session last attached"
.It Li "session_group" Ta "" Ta "Number of session group"
.It Li "session_group" Ta "" Ta "Name of session group"
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
.It Li "session_height" Ta "" Ta "Height of session"
.It Li "session_id" Ta "" Ta "Unique session ID"
@ -4203,6 +4218,11 @@ For example:
%end 1363006971 2
.Ed
.Pp
The
.Ic refresh-client
.Fl C
command may be used to set the size of a client in control mode.
.Pp
In control mode,
.Nm
outputs notifications.

27
tmux.h
View File

@ -903,11 +903,12 @@ struct environ_entry {
/* Client session. */
struct session_group {
TAILQ_HEAD(, session) sessions;
const char *name;
TAILQ_HEAD(, session) sessions;
TAILQ_ENTRY(session_group) entry;
RB_ENTRY(session_group) entry;
};
TAILQ_HEAD(session_groups, session_group);
RB_HEAD(session_groups, session_group);
struct session {
u_int id;
@ -1042,7 +1043,10 @@ struct tty {
u_int rright;
int fd;
struct bufferevent *event;
struct event event_in;
struct evbuffer *in;
struct event event_out;
struct evbuffer *out;
struct termios tio;
@ -2212,13 +2216,15 @@ extern struct sessions sessions;
extern struct session_groups session_groups;
int session_cmp(struct session *, struct session *);
RB_PROTOTYPE(sessions, session, entry, session_cmp);
int session_group_cmp(struct session_group *, struct session_group *);
RB_PROTOTYPE(session_groups, session_group, entry, session_group_cmp);
int session_alive(struct session *);
struct session *session_find(const char *);
struct session *session_find_by_id_str(const char *);
struct session *session_find_by_id(u_int);
struct session *session_create(const char *, int, char **, const char *,
const char *, struct environ *, struct termios *, int,
u_int, u_int, char **);
struct session *session_create(const char *, const char *, int, char **,
const char *, const char *, struct environ *,
struct termios *, int, u_int, u_int, char **);
void session_destroy(struct session *);
void session_unref(struct session *);
int session_check_name(const char *);
@ -2237,9 +2243,10 @@ int session_previous(struct session *, int);
int session_select(struct session *, int);
int session_last(struct session *);
int session_set_current(struct session *, struct winlink *);
struct session_group *session_group_find(struct session *);
u_int session_group_index(struct session_group *);
void session_group_add(struct session *, struct session *);
struct session_group *session_group_contains(struct session *);
struct session_group *session_group_find(const char *);
struct session_group *session_group_new(const char *);
void session_group_add(struct session_group *, struct session *);
void session_group_synchronize_to(struct session *);
void session_group_synchronize_from(struct session *);
void session_renumber_windows(struct session *);

View File

@ -532,8 +532,8 @@ tty_keys_next(struct tty *tty)
key_code key;
/* Get key buffer. */
buf = EVBUFFER_DATA(tty->event->input);
len = EVBUFFER_LENGTH(tty->event->input);
buf = EVBUFFER_DATA(tty->in);
len = EVBUFFER_LENGTH(tty->in);
if (len == 0)
return (0);
@ -645,7 +645,7 @@ complete_key:
key = (key & KEYC_MASK_MOD) | KEYC_BSPACE;
/* Remove data from buffer. */
evbuffer_drain(tty->event->input, size);
evbuffer_drain(tty->in, size);
/* Remove key timer. */
if (event_initialized(&tty->key_timer))
@ -671,7 +671,7 @@ discard_key:
log_debug("discard key %.*s %#llx", (int)size, buf, key);
/* Remove data from buffer. */
evbuffer_drain(tty->event->input, size);
evbuffer_drain(tty->in, size);
return (1);
}

121
tty.c
View File

@ -34,11 +34,6 @@
static int tty_log_fd = -1;
static void tty_init_termios(int, struct termios *, struct bufferevent *);
static void tty_read_callback(struct bufferevent *, void *);
static void tty_error_callback(struct bufferevent *, short, void *);
static int tty_client_ready(struct client *, struct window_pane *);
static void tty_set_italics(struct tty *);
@ -159,6 +154,38 @@ tty_set_size(struct tty *tty, u_int sx, u_int sy)
return (1);
}
static void
tty_read_callback(__unused int fd, __unused short events, void *data)
{
struct tty *tty = data;
size_t size = EVBUFFER_LENGTH(tty->in);
int nread;
nread = evbuffer_read(tty->in, tty->fd, -1);
if (nread == -1)
return;
log_debug("%s: read %d bytes (already %zu)", tty->path, nread, size);
while (tty_keys_next(tty))
;
}
static void
tty_write_callback(__unused int fd, __unused short events, void *data)
{
struct tty *tty = data;
size_t size = EVBUFFER_LENGTH(tty->out);
int nwrite;
nwrite = evbuffer_write(tty->out, tty->fd);
if (nwrite == -1)
return;
log_debug("%s: wrote %d bytes (of %zu)", tty->path, nwrite, size);
if (EVBUFFER_LENGTH(tty->out) != 0)
event_add(&tty->event_out, NULL);
}
int
tty_open(struct tty *tty, char **cause)
{
@ -169,10 +196,14 @@ tty_open(struct tty *tty, char **cause)
}
tty->flags |= TTY_OPENED;
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_TIMER);
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE);
tty->event = bufferevent_new(tty->fd, tty_read_callback, NULL,
tty_error_callback, tty);
event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ,
tty_read_callback, tty);
tty->in = evbuffer_new();
event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty);
tty->out = evbuffer_new();
tty_start_tty(tty);
@ -181,50 +212,26 @@ tty_open(struct tty *tty, char **cause)
return (0);
}
static void
tty_read_callback(__unused struct bufferevent *bufev, void *data)
{
struct tty *tty = data;
while (tty_keys_next(tty))
;
}
static void
tty_error_callback(__unused struct bufferevent *bufev, __unused short what,
__unused void *data)
{
}
static void
tty_init_termios(int fd, struct termios *orig_tio, struct bufferevent *bufev)
{
struct termios tio;
if (fd == -1 || tcgetattr(fd, orig_tio) != 0)
return;
setblocking(fd, 0);
if (bufev != NULL)
bufferevent_enable(bufev, EV_READ|EV_WRITE);
memcpy(&tio, orig_tio, sizeof tio);
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
tio.c_iflag |= IGNBRK;
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
ECHOPRT|ECHOKE|ISIG);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &tio) == 0)
tcflush(fd, TCIOFLUSH);
}
void
tty_start_tty(struct tty *tty)
{
tty_init_termios(tty->fd, &tty->tio, tty->event);
struct termios tio;
if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) {
setblocking(tty->fd, 0);
event_add(&tty->event_in, NULL);
memcpy(&tio, &tty->tio, sizeof tio);
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
tio.c_iflag |= IGNBRK;
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
ECHOPRT|ECHOKE|ISIG);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(tty->fd, TCSANOW, &tio) == 0)
tcflush(tty->fd, TCIOFLUSH);
}
tty_putcode(tty, TTYC_SMCUP);
@ -264,7 +271,8 @@ tty_stop_tty(struct tty *tty)
return;
tty->flags &= ~TTY_STARTED;
bufferevent_disable(tty->event, EV_READ|EV_WRITE);
event_del(&tty->event_in);
event_del(&tty->event_out);
/*
* Be flexible about error handling and try not kill the server just
@ -318,7 +326,10 @@ tty_close(struct tty *tty)
tty_stop_tty(tty);
if (tty->flags & TTY_OPENED) {
bufferevent_free(tty->event);
evbuffer_free(tty->in);
event_del(&tty->event_in);
evbuffer_free(tty->out);
event_del(&tty->event_out);
tty_term_free(tty->term);
tty_keys_free(tty);
@ -411,11 +422,13 @@ tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a,
static void
tty_add(struct tty *tty, const char *buf, size_t len)
{
bufferevent_write(tty->event, buf, len);
log_debug("%s: %.*s", tty->path, (int)len, buf);
evbuffer_add(tty->out, buf, len);
log_debug("%s: %.*s", tty->path, (int)len, (const char *)buf);
if (tty_log_fd != -1)
write(tty_log_fd, buf, len);
if (tty->flags & TTY_STARTED)
event_add(&tty->event_out, NULL);
}
void
@ -730,7 +743,7 @@ tty_client_ready(struct client *c, struct window_pane *wp)
{
if (c->session == NULL || c->tty.term == NULL)
return (0);
if (c->flags & CLIENT_SUSPENDED)
if (c->flags & (CLIENT_REDRAW|CLIENT_SUSPENDED))
return (0);
if (c->tty.flags & TTY_FREEZE)
return (0);