diff options
-rw-r--r-- | cmd-new-session.c | 49 | ||||
-rw-r--r-- | cmd-swap-window.c | 4 | ||||
-rw-r--r-- | format.c | 4 | ||||
-rw-r--r-- | grid.c | 29 | ||||
-rw-r--r-- | server-fn.c | 12 | ||||
-rw-r--r-- | server.c | 2 | ||||
-rw-r--r-- | session.c | 93 | ||||
-rw-r--r-- | tmux.1 | 42 | ||||
-rw-r--r-- | tmux.h | 27 | ||||
-rw-r--r-- | tty-keys.c | 8 | ||||
-rw-r--r-- | tty.c | 121 |
11 files changed, 236 insertions, 155 deletions
diff --git a/cmd-new-session.c b/cmd-new-session.c index deda88f2..08fc6065 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -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); } diff --git a/cmd-swap-window.c b/cmd-swap-window.c index 0a93fa6e..38252745 100644 --- a/cmd-swap-window.c +++ b/cmd-swap-window.c @@ -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) { @@ -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); @@ -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]); diff --git a/server-fn.c b/server-fn.c index 6e629ccf..ef348f8a 100644 --- a/server-fn.c +++ b/server-fn.c @@ -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) { @@ -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); @@ -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; - - i = 0; - TAILQ_FOREACH(sg2, &session_groups, entry) { - if (sg == sg2) - return (i); - i++; - } + struct session_group sg; - 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) { @@ -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. @@ -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 *); @@ -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); } @@ -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,72 +154,84 @@ tty_set_size(struct tty *tty, u_int sx, u_int sy) return (1); } -int -tty_open(struct tty *tty, char **cause) -{ - tty->term = tty_term_find(tty->term_name, tty->fd, cause); - if (tty->term == NULL) { - tty_close(tty); - return (-1); - } - tty->flags |= TTY_OPENED; - - tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_TIMER); - - tty->event = bufferevent_new(tty->fd, tty_read_callback, NULL, - tty_error_callback, tty); - - tty_start_tty(tty); - - tty_keys_build(tty); - - return (0); -} - static void -tty_read_callback(__unused struct bufferevent *bufev, void *data) +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_error_callback(__unused struct bufferevent *bufev, __unused short what, - __unused void *data) +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); } -static void -tty_init_termios(int fd, struct termios *orig_tio, struct bufferevent *bufev) +int +tty_open(struct tty *tty, char **cause) { - struct termios tio; + tty->term = tty_term_find(tty->term_name, tty->fd, cause); + if (tty->term == NULL) { + tty_close(tty); + return (-1); + } + tty->flags |= TTY_OPENED; - if (fd == -1 || tcgetattr(fd, orig_tio) != 0) - return; + tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE); - setblocking(fd, 0); + event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ, + tty_read_callback, tty); + tty->in = evbuffer_new(); - if (bufev != NULL) - bufferevent_enable(bufev, EV_READ|EV_WRITE); + event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty); + tty->out = evbuffer_new(); - 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); + tty_start_tty(tty); + + tty_keys_build(tty); + + return (0); } 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); |