=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/control.c,v retrieving revision 1.37 retrieving revision 1.38 diff -c -r1.37 -r1.38 *** src/usr.bin/tmux/control.c 2020/06/02 08:17:27 1.37 --- src/usr.bin/tmux/control.c 2020/06/05 07:33:57 1.38 *************** *** 1,4 **** ! /* $OpenBSD: control.c,v 1.37 2020/06/02 08:17:27 nicm Exp $ */ /* * Copyright (c) 2012 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: control.c,v 1.38 2020/06/05 07:33:57 nicm Exp $ */ /* * Copyright (c) 2012 Nicholas Marriott *************** *** 65,70 **** --- 65,71 ---- int flags; #define CONTROL_PANE_OFF 0x1 + #define CONTROL_PANE_PAUSED 0x2 int pending_flag; TAILQ_ENTRY(control_pane) pending_entry; *************** *** 153,158 **** --- 154,172 ---- return (cp); } + /* Discard output for a pane. */ + static void + control_discard_pane(struct client *c, struct control_pane *cp) + { + struct control_state *cs = c->control_state; + struct control_block *cb, *cb1; + + TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) { + TAILQ_REMOVE(&cp->blocks, cb, entry); + control_free_block(cs, cb); + } + } + /* Get actual pane for this client. */ static struct window_pane * control_window_pane(struct client *c, u_int pane) *************** *** 197,203 **** } cp = control_get_pane(c, wp); ! if (cp == NULL) { *off = 0; return (NULL); } --- 211,217 ---- } cp = control_get_pane(c, wp); ! if (cp == NULL || (cp->flags & CONTROL_PANE_PAUSED)) { *off = 0; return (NULL); } *************** *** 216,222 **** struct control_pane *cp; cp = control_get_pane(c, wp); ! if (cp != NULL) { cp->flags &= ~CONTROL_PANE_OFF; memcpy(&cp->offset, &wp->offset, sizeof cp->offset); memcpy(&cp->queued, &wp->offset, sizeof cp->queued); --- 230,236 ---- struct control_pane *cp; cp = control_get_pane(c, wp); ! if (cp != NULL && (cp->flags & CONTROL_PANE_OFF)) { cp->flags &= ~CONTROL_PANE_OFF; memcpy(&cp->offset, &wp->offset, sizeof cp->offset); memcpy(&cp->queued, &wp->offset, sizeof cp->queued); *************** *** 233,238 **** --- 247,267 ---- cp->flags |= CONTROL_PANE_OFF; } + /* Continue a paused pane. */ + void + control_continue_pane(struct client *c, struct window_pane *wp) + { + struct control_pane *cp; + + cp = control_get_pane(c, wp); + if (cp != NULL && (cp->flags & CONTROL_PANE_PAUSED)) { + cp->flags &= ~CONTROL_PANE_PAUSED; + memcpy(&cp->offset, &wp->offset, sizeof cp->offset); + memcpy(&cp->queued, &wp->offset, sizeof cp->queued); + control_write(c, "%%continue %%%u", wp->id); + } + } + /* Write a line. */ static void control_vwrite(struct client *c, const char *fmt, va_list ap) *************** *** 285,290 **** --- 314,320 ---- struct control_pane *cp; struct control_block *cb; size_t new_size; + uint64_t t; if (winlink_find_by_window(&c->session->windows, wp->window) == NULL) return; *************** *** 296,303 **** return; } cp = control_add_pane(c, wp); ! if (cp->flags & CONTROL_PANE_OFF) goto ignore; window_pane_get_new_data(wp, &cp->queued, &new_size); if (new_size == 0) --- 326,347 ---- return; } cp = control_add_pane(c, wp); ! if (cp->flags & (CONTROL_PANE_OFF|CONTROL_PANE_PAUSED)) goto ignore; + if (c->flags & CLIENT_CONTROL_PAUSEAFTER) { + cb = TAILQ_FIRST(&cp->blocks); + if (cb != NULL) { + t = get_timer(); + log_debug("%s: %s: %%%u is %lld behind", __func__, + c->name, wp->id, (long long)t - cb->t); + if (cb->t < t - c->pause_age) { + cp->flags |= CONTROL_PANE_PAUSED; + control_discard_pane(c, cp); + control_write(c, "%%pause %%%u", wp->id); + return; + } + } + } window_pane_get_new_data(wp, &cp->queued, &new_size); if (new_size == 0) *************** *** 585,604 **** } } ! /* Flush all output for a client that is detaching. */ void ! control_flush(struct client *c) { struct control_state *cs = c->control_state; struct control_pane *cp; - struct control_block *cb, *cb1; ! RB_FOREACH(cp, control_panes, &cs->panes) { ! TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) { ! TAILQ_REMOVE(&cp->blocks, cb, entry); ! control_free_block(cs, cb); ! } ! } } /* Stop control mode. */ --- 629,643 ---- } } ! /* Discard all output for a client. */ void ! control_discard(struct client *c) { struct control_state *cs = c->control_state; struct control_pane *cp; ! RB_FOREACH(cp, control_panes, &cs->panes) ! control_discard_pane(c, cp); } /* Stop control mode. */