Merge branch 'obsd-master'

Conflicts:
	server.c
This commit is contained in:
Thomas Adam
2017-02-14 13:55:16 +00:00
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 args *args = self->args;
struct client *c = item->client; struct client *c = item->client;
struct session *s, *as; struct session *s, *as, *groupwith;
struct session *groupwith = item->state.tflag.s;
struct window *w; struct window *w;
struct environ *env; struct environ *env;
struct termios tio, *tiop; 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; const char *path, *cmd, *cwd, *to_free = NULL;
char **argv, *cause, *cp; char **argv, *cause, *cp;
int detached, already_attached, idx, argc; 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) { if (groupwith == NULL) {
cmdq_error(item, "no such session: %s", target); if (!session_check_name(group)) {
goto error; cmdq_error(item, "bad group name: %s", group);
} goto error;
} else }
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; groupwith = NULL;
sg = NULL;
prefix = NULL;
}
/* Set -d if no client. */ /* Set -d if no client. */
detached = args_has(args, 'd'); 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) { if (!args_has(args, 't') && args->argc != 0) {
argc = args->argc; argc = args->argc;
argv = args->argv; argv = args->argv;
} else if (groupwith == NULL) { } else if (sg == NULL && groupwith == NULL) {
cmd = options_get_string(global_s_options, "default-command"); cmd = options_get_string(global_s_options, "default-command");
if (cmd != NULL && *cmd != '\0') { if (cmd != NULL && *cmd != '\0') {
argc = 1; argc = 1;
@@ -239,8 +255,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
/* Create the new session. */ /* Create the new session. */
idx = -1 - options_get_number(global_s_options, "base-index"); idx = -1 - options_get_number(global_s_options, "base-index");
s = session_create(newname, argc, argv, path, cwd, env, tiop, idx, sx, s = session_create(prefix, newname, argc, argv, path, cwd, env, tiop,
sy, &cause); idx, sx, sy, &cause);
environ_free(env); environ_free(env);
if (s == NULL) { if (s == NULL) {
cmdq_error(item, "create session failed: %s", cause); 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, * If a target session is given, this is to be part of a session group,
* so add it to the group and synchronize. * so add it to the group and synchronize.
*/ */
if (groupwith != NULL) { if (group != NULL) {
session_group_add(groupwith, s); 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_group_synchronize_to(s);
session_select(s, RB_MIN(winlinks, &s->windows)->idx); 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; wl_src = item->state.sflag.wl;
src = item->state.sflag.s; src = item->state.sflag.s;
sg_src = session_group_find(src); sg_src = session_group_contains(src);
wl_dst = item->state.tflag.wl; wl_dst = item->state.tflag.wl;
dst = item->state.tflag.s; 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 && if (src != dst && sg_src != NULL && sg_dst != NULL &&
sg_src == sg_dst) { 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_height", "%u", s->sy);
format_add(ft, "session_id", "$%u", s->id); 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); format_add(ft, "session_grouped", "%d", sg != NULL);
if (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_created", &s->creation_time);
format_add_tv(ft, "session_last_attached", &s->last_attached_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; 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. */ /* Set cell as extended. */
static struct grid_cell * static struct grid_cell *
grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce, 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_line *gl;
struct grid_cell_entry *gce; struct grid_cell_entry *gce;
int extended;
if (grid_check_y(gd, py) != 0) if (grid_check_y(gd, py) != 0)
return; 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; gl->cellused = px + 1;
gce = &gl->celldata[px]; gce = &gl->celldata[px];
extended = (gce->flags & GRID_FLAG_EXTENDED); if (grid_need_extended_cell(gce, gc))
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)
grid_extended_cell(gl, gce, gc); grid_extended_cell(gl, gce, gc);
else else
grid_store_cell(gce, gc, gc->data.data[0]); 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++) { for (i = 0; i < slen; i++) {
gce = &gl->celldata[px + i]; gce = &gl->celldata[px + i];
if (gce->flags & GRID_FLAG_EXTENDED) { if (grid_need_extended_cell(gce, gc)) {
gcp = &gl->extddata[gce->offset]; gcp = grid_extended_cell(gl, gce, gc);
memcpy(gcp, gc, sizeof *gcp);
utf8_set(&gcp->data, s[i]); utf8_set(&gcp->data, s[i]);
} else } else
grid_store_cell(gce, gc, s[i]); grid_store_cell(gce, gc, s[i]);

View File

@@ -76,7 +76,7 @@ server_redraw_session_group(struct session *s)
{ {
struct session_group *sg; struct session_group *sg;
if ((sg = session_group_find(s)) == NULL) if ((sg = session_group_contains(s)) == NULL)
server_redraw_session(s); server_redraw_session(s);
else { else {
TAILQ_FOREACH(s, &sg->sessions, gentry) TAILQ_FOREACH(s, &sg->sessions, gentry)
@@ -100,7 +100,7 @@ server_status_session_group(struct session *s)
{ {
struct session_group *sg; struct session_group *sg;
if ((sg = session_group_find(s)) == NULL) if ((sg = session_group_contains(s)) == NULL)
server_status_session(s); server_status_session(s);
else { else {
TAILQ_FOREACH(s, &sg->sessions, gentry) 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 (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) TAILQ_FOREACH(target_s, &sg->sessions, gentry)
session_renumber_windows(target_s); session_renumber_windows(target_s);
} else } else
@@ -236,8 +236,8 @@ server_link_window(struct session *src, struct winlink *srcwl,
struct winlink *dstwl; struct winlink *dstwl;
struct session_group *srcsg, *dstsg; struct session_group *srcsg, *dstsg;
srcsg = session_group_find(src); srcsg = session_group_contains(src);
dstsg = session_group_find(dst); dstsg = session_group_contains(dst);
if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) { if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) {
xasprintf(cause, "sessions are grouped"); xasprintf(cause, "sessions are grouped");
return (-1); return (-1);
@@ -349,7 +349,7 @@ server_destroy_session_group(struct session *s)
struct session_group *sg; struct session_group *sg;
struct session *s1; struct session *s1;
if ((sg = session_group_find(s)) == NULL) if ((sg = session_group_contains(s)) == NULL)
server_destroy_session(s); server_destroy_session(s);
else { else {
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) { 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); RB_INIT(&all_window_panes);
TAILQ_INIT(&clients); TAILQ_INIT(&clients);
RB_INIT(&sessions); RB_INIT(&sessions);
TAILQ_INIT(&session_groups); RB_INIT(&session_groups);
key_bindings_init(); key_bindings_init();
gettimeofday(&start_time, NULL); 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 u_int session_group_count(struct session_group *);
static void session_group_synchronize1(struct session *, struct session *); 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); RB_GENERATE(sessions, session, entry, session_cmp);
int int
@@ -49,6 +52,14 @@ session_cmp(struct session *s1, struct session *s2)
return (strcmp(s1->name, s2->name)); 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 * Find if session is still alive. This is true if it is still on the global
* sessions list. * sessions list.
@@ -106,9 +117,9 @@ session_find_by_id(u_int id)
/* Create a new session. */ /* Create a new session. */
struct session * struct session *
session_create(const char *name, int argc, char **argv, const char *path, session_create(const char *prefix, const char *name, int argc, char **argv,
const char *cwd, struct environ *env, struct termios *tio, int idx, const char *path, const char *cwd, struct environ *env, struct termios *tio,
u_int sx, u_int sy, char **cause) int idx, u_int sx, u_int sy, char **cause)
{ {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
@@ -149,7 +160,10 @@ session_create(const char *name, int argc, char **argv, const char *path,
do { do {
s->id = next_session_id++; s->id = next_session_id++;
free(s->name); 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); } while (RB_FIND(sessions, &sessions, s) != NULL);
} }
RB_INSERT(sessions, &sessions, s); RB_INSERT(sessions, &sessions, s);
@@ -428,7 +442,7 @@ session_is_linked(struct session *s, struct window *w)
{ {
struct session_group *sg; 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 != session_group_count(sg));
return (w->references != 1); return (w->references != 1);
} }
@@ -539,12 +553,12 @@ session_set_current(struct session *s, struct winlink *wl)
/* Find the session group containing a session. */ /* Find the session group containing a session. */
struct session_group * struct session_group *
session_group_find(struct session *target) session_group_contains(struct session *target)
{ {
struct session_group *sg; struct session_group *sg;
struct session *s; struct session *s;
TAILQ_FOREACH(sg, &session_groups, entry) { RB_FOREACH(sg, session_groups, &session_groups) {
TAILQ_FOREACH(s, &sg->sessions, gentry) { TAILQ_FOREACH(s, &sg->sessions, gentry) {
if (s == target) if (s == target)
return (sg); return (sg);
@@ -553,39 +567,39 @@ session_group_find(struct session *target)
return (NULL); return (NULL);
} }
/* Find session group index. */ /* Find session group by name. */
u_int struct session_group *
session_group_index(struct session_group *sg) session_group_find(const char *name)
{ {
struct session_group *sg2; struct session_group sg;
u_int i;
i = 0; sg.name = name;
TAILQ_FOREACH(sg2, &session_groups, entry) { return (RB_FIND(session_groups, &session_groups, &sg));
if (sg == sg2)
return (i);
i++;
}
fatalx("session group not found");
} }
/* /* Create a new session group. */
* Add a session to the session group containing target, creating it if struct session_group *
* necessary. session_group_new(const char *name)
*/
void
session_group_add(struct session *target, struct session *s)
{ {
struct session_group *sg; struct session_group *sg;
if ((sg = session_group_find(target)) == NULL) { if ((sg = session_group_find(name)) != NULL)
sg = xmalloc(sizeof *sg); return (sg);
TAILQ_INSERT_TAIL(&session_groups, sg, entry);
TAILQ_INIT(&sg->sessions); sg = xcalloc(1, sizeof *sg);
TAILQ_INSERT_TAIL(&sg->sessions, target, gentry); sg->name = xstrdup(name);
} TAILQ_INIT(&sg->sessions);
TAILQ_INSERT_TAIL(&sg->sessions, s, gentry);
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. */ /* 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; struct session_group *sg;
if ((sg = session_group_find(s)) == NULL) if ((sg = session_group_contains(s)) == NULL)
return; return;
TAILQ_REMOVE(&sg->sessions, s, gentry); 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)) { if (TAILQ_EMPTY(&sg->sessions)) {
TAILQ_REMOVE(&session_groups, sg, entry); RB_REMOVE(session_groups, &session_groups, sg);
free(sg); free(sg);
} }
} }
@@ -625,7 +637,7 @@ session_group_synchronize_to(struct session *s)
struct session_group *sg; struct session_group *sg;
struct session *target; struct session *target;
if ((sg = session_group_find(s)) == NULL) if ((sg = session_group_contains(s)) == NULL)
return; return;
target = NULL; target = NULL;
@@ -633,7 +645,8 @@ session_group_synchronize_to(struct session *s)
if (target != s) if (target != s)
break; break;
} }
session_group_synchronize1(target, s); if (target != NULL)
session_group_synchronize1(target, s);
} }
/* Synchronize a session group to a session. */ /* Synchronize a session group to a session. */
@@ -643,7 +656,7 @@ session_group_synchronize_from(struct session *target)
struct session_group *sg; struct session_group *sg;
struct session *s; struct session *s;
if ((sg = session_group_find(target)) == NULL) if ((sg = session_group_contains(target)) == NULL)
return; return;
TAILQ_FOREACH(s, &sg->sessions, gentry) { 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 F Ar format
.Op Fl n Ar window-name .Op Fl n Ar window-name
.Op Fl s Ar session-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 x Ar width
.Op Fl y Ar height .Op Fl y Ar height
.Op Ar shell-command .Op Ar shell-command
@@ -861,16 +861,27 @@ to
.Pp .Pp
If If
.Fl t .Fl t
is given, the new session is is given, it specifies a
.Em grouped .Ic session group .
with Sessions in the same group share the same set of windows - new windows are
.Ar target-session . linked to all sessions in the group and any windows closed removed from all
This means they share the same set of windows - all windows from sessions.
.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.
The current and previous window and any session options remain independent and 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 .Fl n
and and
.Ar shell-command .Ar shell-command
@@ -892,6 +903,7 @@ is used, the
.Ic update-environment .Ic update-environment
option will not be applied. option will not be applied.
.It Xo Ic refresh-client .It Xo Ic refresh-client
.Op Fl C Ar width,height
.Op Fl S .Op Fl S
.Op Fl t Ar target-client .Op Fl t Ar target-client
.Xc .Xc
@@ -902,6 +914,9 @@ with
If If
.Fl S .Fl S
is specified, only update the client's status bar. 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 .It Xo Ic rename-session
.Op Fl t Ar target-session .Op Fl t Ar target-session
.Ar new-name .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_activity" Ta "" Ta "Integer time of session last activity"
.It Li "session_created" Ta "" Ta "Integer time session created" .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_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_grouped" Ta "" Ta "1 if session in a group"
.It Li "session_height" Ta "" Ta "Height of session" .It Li "session_height" Ta "" Ta "Height of session"
.It Li "session_id" Ta "" Ta "Unique session ID" .It Li "session_id" Ta "" Ta "Unique session ID"
@@ -4203,6 +4218,11 @@ For example:
%end 1363006971 2 %end 1363006971 2
.Ed .Ed
.Pp .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, In control mode,
.Nm .Nm
outputs notifications. outputs notifications.

27
tmux.h
View File

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

View File

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

121
tty.c
View File

@@ -34,11 +34,6 @@
static int tty_log_fd = -1; 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 int tty_client_ready(struct client *, struct window_pane *);
static void tty_set_italics(struct tty *); 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); 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 int
tty_open(struct tty *tty, char **cause) 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_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, event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ,
tty_error_callback, tty); 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); tty_start_tty(tty);
@@ -181,50 +212,26 @@ tty_open(struct tty *tty, char **cause)
return (0); 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 void
tty_start_tty(struct tty *tty) 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); tty_putcode(tty, TTYC_SMCUP);
@@ -264,7 +271,8 @@ tty_stop_tty(struct tty *tty)
return; return;
tty->flags &= ~TTY_STARTED; 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 * 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); tty_stop_tty(tty);
if (tty->flags & TTY_OPENED) { 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_term_free(tty->term);
tty_keys_free(tty); tty_keys_free(tty);
@@ -411,11 +422,13 @@ tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a,
static void static void
tty_add(struct tty *tty, const char *buf, size_t len) tty_add(struct tty *tty, const char *buf, size_t len)
{ {
bufferevent_write(tty->event, buf, len); evbuffer_add(tty->out, buf, len);
log_debug("%s: %.*s", tty->path, (int)len, buf); log_debug("%s: %.*s", tty->path, (int)len, (const char *)buf);
if (tty_log_fd != -1) if (tty_log_fd != -1)
write(tty_log_fd, buf, len); write(tty_log_fd, buf, len);
if (tty->flags & TTY_STARTED)
event_add(&tty->event_out, NULL);
} }
void void
@@ -730,7 +743,7 @@ tty_client_ready(struct client *c, struct window_pane *wp)
{ {
if (c->session == NULL || c->tty.term == NULL) if (c->session == NULL || c->tty.term == NULL)
return (0); return (0);
if (c->flags & CLIENT_SUSPENDED) if (c->flags & (CLIENT_REDRAW|CLIENT_SUSPENDED))
return (0); return (0);
if (c->tty.flags & TTY_FREEZE) if (c->tty.flags & TTY_FREEZE)
return (0); return (0);