diff --git a/tmux.1 b/tmux.1 index d4f5a891..012219f3 100644 --- a/tmux.1 +++ b/tmux.1 @@ -860,7 +860,7 @@ If 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 grouo and any windows closed removed from all +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 any session in a group may be killed without affecting the others. diff --git a/tmux.h b/tmux.h index 2a5dbe65..d2621f8b 100644 --- a/tmux.h +++ b/tmux.h @@ -1041,7 +1041,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; diff --git a/tty-keys.c b/tty-keys.c index f23411ae..ecd4bb20 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -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); } diff --git a/tty.c b/tty.c index 7bf24273..4e7af46e 100644 --- a/tty.c +++ b/tty.c @@ -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_del(&tty->event_out); +} + 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);