From 9a0763c3a06e589bd5d27046655603faea8c667f Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 22 May 2020 11:07:04 +0000 Subject: [PATCH] Move client offset stuff into control.c since only control clients will need it. --- cmd-refresh-client.c | 6 +-- control.c | 125 +++++++++++++++++++++++++++++++++++++++++-- server-client.c | 84 +++++++++-------------------- tmux.h | 25 +++------ 4 files changed, 157 insertions(+), 83 deletions(-) diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index 65537917..4eb8417b 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -46,7 +46,6 @@ static void cmd_refresh_client_update_offset(struct client *tc, const char *value) { struct window_pane *wp; - struct client_offset *co; char *copy, *colon; u_int pane; @@ -63,11 +62,10 @@ cmd_refresh_client_update_offset(struct client *tc, const char *value) if (wp == NULL) goto out; - co = server_client_add_pane_offset(tc, wp); if (strcmp(colon, "on") == 0) - co->flags &= ~CLIENT_OFFSET_OFF; + control_set_pane_on(tc, wp); else if (strcmp(colon, "off") == 0) - co->flags |= CLIENT_OFFSET_OFF; + control_set_pane_off(tc, wp); out: free(copy); diff --git a/control.c b/control.c index b1bcd2c1..24c26fea 100644 --- a/control.c +++ b/control.c @@ -26,6 +26,124 @@ #include "tmux.h" +/* Control offsets. */ +struct control_offset { + u_int pane; + + struct window_pane_offset offset; + int flags; +#define CONTROL_OFFSET_OFF 0x1 + + RB_ENTRY(control_offset) entry; +}; +RB_HEAD(control_offsets, control_offset); + +/* Compare client offsets. */ +static int +control_offset_cmp(struct control_offset *co1, struct control_offset *co2) +{ + if (co1->pane < co2->pane) + return (-1); + if (co1->pane > co2->pane) + return (1); + return (0); +} +RB_GENERATE_STATIC(control_offsets, control_offset, entry, control_offset_cmp); + +/* Get pane offsets for this client. */ +static struct control_offset * +control_get_offset(struct client *c, struct window_pane *wp) +{ + struct control_offset co = { .pane = wp->id }; + + if (c->offsets == NULL) + return (NULL); + return (RB_FIND(control_offsets, c->offsets, &co)); +} + +/* Add pane offsets for this client. */ +static struct control_offset * +control_add_offset(struct client *c, struct window_pane *wp) +{ + struct control_offset *co; + + co = control_get_offset(c, wp); + if (co != NULL) + return (co); + + if (c->offsets == NULL) { + c->offsets = xmalloc(sizeof *c->offsets); + RB_INIT(c->offsets); + } + + co = xcalloc(1, sizeof *co); + co->pane = wp->id; + RB_INSERT(control_offsets, c->offsets, co); + memcpy(&co->offset, &wp->offset, sizeof co->offset); + return (co); +} + +/* Free control offsets. */ +void +control_free_offsets(struct client *c) +{ + struct control_offset *co, *co1; + + if (c->offsets == NULL) + return; + RB_FOREACH_SAFE(co, control_offsets, c->offsets, co1) { + RB_REMOVE(control_offsets, c->offsets, co); + free(co); + } + free(c->offsets); +} + +/* Get offsets for client. */ +struct window_pane_offset * +control_pane_offset(struct client *c, struct window_pane *wp, int *off) +{ + struct control_offset *co; + + if (c->flags & CLIENT_CONTROL_NOOUTPUT) { + *off = 0; + return (NULL); + } + + co = control_get_offset(c, wp); + if (co == NULL) { + *off = 0; + return (NULL); + } + if (co->flags & CONTROL_OFFSET_OFF) { + *off = 1; + return (NULL); + } + return (&co->offset); +} + +/* Set pane as on. */ +void +control_set_pane_on(struct client *c, struct window_pane *wp) +{ + struct control_offset *co; + + co = control_get_offset(c, wp); + if (co != NULL) { + co->flags &= ~CONTROL_OFFSET_OFF; + memcpy(&co->offset, &wp->offset, sizeof co->offset); + } +} + +/* Set pane as off. */ +void +control_set_pane_off(struct client *c, struct window_pane *wp) +{ + struct control_offset *co; + + co = control_add_offset(c, wp); + co->flags |= CONTROL_OFFSET_OFF; +} + /* Write a line. */ void control_write(struct client *c, const char *fmt, ...) @@ -42,7 +160,7 @@ control_write(struct client *c, const char *fmt, ...) void control_write_output(struct client *c, struct window_pane *wp) { - struct client_offset *co; + struct control_offset *co; struct evbuffer *message; u_char *new_data; size_t new_size, i; @@ -57,8 +175,8 @@ control_write_output(struct client *c, struct window_pane *wp) if (winlink_find_by_window(&c->session->windows, wp->window) == NULL) return; - co = server_client_add_pane_offset(c, wp); - if (co->flags & CLIENT_OFFSET_OFF) { + co = control_add_offset(c, wp); + if (co->flags & CONTROL_OFFSET_OFF) { window_pane_update_used_data(wp, &co->offset, SIZE_MAX, 1); return; } @@ -133,6 +251,7 @@ control_callback(__unused struct client *c, __unused const char *path, } } +/* Initialize for control mode. */ void control_start(struct client *c) { diff --git a/server-client.c b/server-client.c index 02abd73a..1f0ac66f 100644 --- a/server-client.c +++ b/server-client.c @@ -71,43 +71,6 @@ server_client_window_cmp(struct client_window *cw1, } RB_GENERATE(client_windows, client_window, entry, server_client_window_cmp); -/* Compare client offsets. */ -static int -server_client_offset_cmp(struct client_offset *co1, struct client_offset *co2) -{ - if (co1->pane < co2->pane) - return (-1); - if (co1->pane > co2->pane) - return (1); - return (0); -} -RB_GENERATE(client_offsets, client_offset, entry, server_client_offset_cmp); - -/* Get pane offsets for this client. */ -struct client_offset * -server_client_get_pane_offset(struct client *c, struct window_pane *wp) -{ - struct client_offset co = { .pane = wp->id }; - - return (RB_FIND(client_offsets, &c->offsets, &co)); -} - -/* Add pane offsets for this client. */ -struct client_offset * -server_client_add_pane_offset(struct client *c, struct window_pane *wp) -{ - struct client_offset *co; - - co = server_client_get_pane_offset(c, wp); - if (co != NULL) - return (co); - co = xcalloc(1, sizeof *co); - co->pane = wp->id; - RB_INSERT(client_offsets, &c->offsets, co); - memcpy(&co->offset, &wp->offset, sizeof co->offset); - return (co); -} - /* Number of attached clients. */ u_int server_client_how_many(void) @@ -264,7 +227,6 @@ server_client_create(int fd) c->queue = cmdq_new(); RB_INIT(&c->windows); - RB_INIT(&c->offsets); RB_INIT(&c->files); c->tty.fd = -1; @@ -325,7 +287,6 @@ server_client_lost(struct client *c) { struct client_file *cf, *cf1; struct client_window *cw, *cw1; - struct client_offset *co, *co1; c->flags |= CLIENT_DEAD; @@ -341,10 +302,7 @@ server_client_lost(struct client *c) RB_REMOVE(client_windows, &c->windows, cw); free(cw); } - RB_FOREACH_SAFE(co, client_offsets, &c->offsets, co1) { - RB_REMOVE(client_offsets, &c->offsets, co); - free(co); - } + control_free_offsets(c); TAILQ_REMOVE(&clients, c, entry); log_debug("lost client %p", c); @@ -1542,8 +1500,9 @@ server_client_check_pane_buffer(struct window_pane *wp) struct evbuffer *evb = wp->event->input; size_t minimum; struct client *c; - struct client_offset *co; - int off = !TAILQ_EMPTY(&clients); + struct window_pane_offset *wpo; + int off = 1, flag; + u_int attached_clients = 0; /* * Work out the minimum acknowledged size. This is the most that can be @@ -1555,20 +1514,28 @@ server_client_check_pane_buffer(struct window_pane *wp) TAILQ_FOREACH(c, &clients, entry) { if (c->session == NULL) continue; - if ((~c->flags & CLIENT_CONTROL) || - (c->flags & CLIENT_CONTROL_NOOUTPUT) || - (co = server_client_get_pane_offset(c, wp)) == NULL) { + attached_clients++; + + if (~c->flags & CLIENT_CONTROL) { off = 0; continue; } - if (~co->flags & CLIENT_OFFSET_OFF) + wpo = control_pane_offset(c, wp, &flag); + if (wpo == NULL) { off = 0; + continue; + } + if (!flag) + off = 0; + log_debug("%s: %s has %zu bytes used, %zu bytes acknowledged " - "for %%%u", __func__, c->name, co->offset.used, - co->offset.acknowledged, wp->id); - if (co->offset.acknowledged < minimum) - minimum = co->offset.acknowledged; + "for %%%u", __func__, c->name, wpo->used, wpo->acknowledged, + wp->id); + if (wpo->acknowledged < minimum) + minimum = wpo->acknowledged; } + if (attached_clients == 0) + off = 0; minimum -= wp->base_offset; if (minimum == 0) goto out; @@ -1593,10 +1560,10 @@ server_client_check_pane_buffer(struct window_pane *wp) TAILQ_FOREACH(c, &clients, entry) { if (c->session == NULL || (~c->flags & CLIENT_CONTROL)) continue; - co = server_client_get_pane_offset(c, wp); - if (co != NULL) { - co->offset.acknowledged -= wp->base_offset; - co->offset.used -= wp->base_offset; + wpo = control_pane_offset(c, wp, &flag); + if (wpo != NULL && !flag) { + wpo->acknowledged -= wp->base_offset; + wpo->used -= wp->base_offset; } } wp->base_offset = minimum; @@ -2394,9 +2361,10 @@ server_client_set_flags(struct client *c, const char *flags) c->flags &= ~flag; else c->flags |= flag; + if (flag == CLIENT_CONTROL_NOOUTPUT) + control_free_offsets(c); } free(copy); - } /* Get client flags. This is only flags useful to show to users. */ diff --git a/tmux.h b/tmux.h index cfb63e36..6965f132 100644 --- a/tmux.h +++ b/tmux.h @@ -45,6 +45,7 @@ struct cmdq_item; struct cmdq_list; struct cmdq_state; struct cmds; +struct control_offsets; struct environ; struct format_job_tree; struct format_tree; @@ -1549,18 +1550,6 @@ struct client_window { }; RB_HEAD(client_windows, client_window); -/* Client offsets. */ -struct client_offset { - u_int pane; - - struct window_pane_offset offset; - int flags; -#define CLIENT_OFFSET_OFF 0x1 - - RB_ENTRY(client_offset) entry; -}; -RB_HEAD(client_offsets, client_offset); - /* Client connection. */ typedef int (*prompt_input_cb)(struct client *, void *, const char *, int); typedef void (*prompt_free_cb)(void *); @@ -1575,7 +1564,7 @@ struct client { struct cmdq_list *queue; struct client_windows windows; - struct client_offsets offsets; + struct control_offsets *offsets; pid_t pid; int fd; @@ -2359,11 +2348,6 @@ void printflike(1, 2) server_add_message(const char *, ...); /* server-client.c */ RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp); -RB_PROTOTYPE(client_offsets, client_offset, entry, server_client_offset_cmp); -struct client_offset *server_client_get_pane_offset(struct client *, - struct window_pane *); -struct client_offset *server_client_add_pane_offset(struct client *, - struct window_pane *); u_int server_client_how_many(void); void server_client_set_overlay(struct client *, u_int, overlay_check_cb, overlay_mode_cb, overlay_draw_cb, overlay_key_cb, @@ -2830,6 +2814,11 @@ char *parse_window_name(const char *); /* control.c */ void control_start(struct client *); +void control_set_pane_on(struct client *, struct window_pane *); +void control_set_pane_off(struct client *, struct window_pane *); +struct window_pane_offset *control_pane_offset(struct client *, + struct window_pane *, int *); +void control_free_offsets(struct client *); void printflike(2, 3) control_write(struct client *, const char *, ...); void control_write_output(struct client *, struct window_pane *);