From 8110c7a25f257b13f92f34559efedba204e6ea98 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 1 May 2020 17:01:36 +0100 Subject: [PATCH] Do not hoke into struct window_pane from the tty code and instead set everything up in tty_ctx. Provide a way to initialize the tty_ctx from a callback and use it to let popups draw directly through input_parse in the same way as panes do, rather than forcing a full redraw on every change. --- cmd-display-panes.c | 8 +- format-draw.c | 8 +- input.c | 37 ++--- menu.c | 8 +- mode-tree.c | 2 +- popup.c | 61 ++++++-- screen-redraw.c | 18 ++- screen-write.c | 166 +++++++++++++++++--- server-fn.c | 2 +- status.c | 6 +- tmux.h | 51 ++++-- tty.c | 370 +++++++++++++++++++------------------------- window-clock.c | 2 +- window-copy.c | 24 +-- window.c | 20 --- 15 files changed, 445 insertions(+), 338 deletions(-) diff --git a/cmd-display-panes.c b/cmd-display-panes.c index 0f12b14b..a13a06ae 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -131,9 +131,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, gc.bg = active_colour; else gc.bg = colour; - gc.flags |= GRID_FLAG_NOPALETTE; - - tty_attributes(tty, &gc, wp); + tty_attributes(tty, &gc, &grid_default_cell, NULL); for (ptr = buf; *ptr != '\0'; ptr++) { if (*ptr < '0' || *ptr > '9') continue; @@ -160,9 +158,7 @@ draw_text: gc.fg = active_colour; else gc.fg = colour; - gc.flags |= GRID_FLAG_NOPALETTE; - - tty_attributes(tty, &gc, wp); + tty_attributes(tty, &gc, &grid_default_cell, NULL); tty_puts(tty, buf); tty_cursor(tty, 0, 0); diff --git a/format-draw.c b/format-draw.c index 4a4fc6bc..3751082e 100644 --- a/format-draw.c +++ b/format-draw.c @@ -242,7 +242,7 @@ format_draw_left(struct screen_write_ctx *octx, u_int available, u_int ocx, /* If there is no list left, pass off to the no list function. */ if (width_list == 0) { - screen_write_start(&ctx, NULL, left); + screen_write_start(&ctx, left); screen_write_fast_copy(&ctx, after, 0, 0, width_after, 1); screen_write_stop(&ctx); @@ -334,7 +334,7 @@ format_draw_centre(struct screen_write_ctx *octx, u_int available, u_int ocx, /* If there is no list left, pass off to the no list function. */ if (width_list == 0) { - screen_write_start(&ctx, NULL, centre); + screen_write_start(&ctx, centre); screen_write_fast_copy(&ctx, after, 0, 0, width_after, 1); screen_write_stop(&ctx); @@ -431,7 +431,7 @@ format_draw_right(struct screen_write_ctx *octx, u_int available, u_int ocx, /* If there is no list left, pass off to the no list function. */ if (width_list == 0) { - screen_write_start(&ctx, NULL, right); + screen_write_start(&ctx, right); screen_write_fast_copy(&ctx, after, 0, 0, width_after, 1); screen_write_stop(&ctx); @@ -536,7 +536,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base, */ for (i = 0; i < TOTAL; i++) { screen_init(&s[i], size, 1, 0); - screen_write_start(&ctx[i], NULL, &s[i]); + screen_write_start(&ctx[i], &s[i]); screen_write_clearendofline(&ctx[i], current_default.bg); width[i] = 0; } diff --git a/input.c b/input.c index 97dcbdb0..70681e61 100644 --- a/input.c +++ b/input.c @@ -842,9 +842,9 @@ input_reset(struct input_ctx *ictx, int clear) if (clear && wp != NULL) { if (TAILQ_EMPTY(&wp->modes)) - screen_write_start(sctx, wp, &wp->base); + screen_write_start_pane(sctx, wp, &wp->base); else - screen_write_start(sctx, NULL, &wp->base); + screen_write_start(sctx, &wp->base); screen_write_reset(sctx); screen_write_stop(sctx); } @@ -960,9 +960,9 @@ input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len) /* NULL wp if there is a mode set as don't want to update the tty. */ if (TAILQ_EMPTY(&wp->modes)) - screen_write_start(sctx, wp, &wp->base); + screen_write_start_pane(sctx, wp, &wp->base); else - screen_write_start(sctx, NULL, &wp->base); + screen_write_start(sctx, &wp->base); log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id, ictx->state->name, len, (int)len, buf); @@ -973,15 +973,15 @@ input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len) /* Parse given input for screen. */ void -input_parse_screen(struct input_ctx *ictx, struct screen *s, u_char *buf, - size_t len) +input_parse_screen(struct input_ctx *ictx, struct screen *s, + screen_write_init_ctx_cb cb, void *arg, u_char *buf, size_t len) { struct screen_write_ctx *sctx = &ictx->ctx; if (len == 0) return; - screen_write_start(sctx, NULL, s); + screen_write_start_callback(sctx, s, cb, arg); input_parse(ictx, buf, len); screen_write_stop(sctx); } @@ -1630,7 +1630,6 @@ static void input_csi_dispatch_rm_private(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; - struct window_pane *wp = ictx->wp; struct grid_cell *gc = &ictx->cell.cell; u_int i; @@ -1675,16 +1674,10 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx) break; case 47: case 1047: - if (wp != NULL) - window_pane_alternate_off(wp, gc, 0); - else - screen_alternate_off(sctx->s, gc, 0); + screen_write_alternateoff(sctx, gc, 0); break; case 1049: - if (wp != NULL) - window_pane_alternate_off(wp, gc, 1); - else - screen_alternate_off(sctx->s, gc, 1); + screen_write_alternateoff(sctx, gc, 1); break; case 2004: screen_write_mode_clear(sctx, MODE_BRACKETPASTE); @@ -1780,16 +1773,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) break; case 47: case 1047: - if (wp != NULL) - window_pane_alternate_on(wp, gc, 0); - else - screen_alternate_on(sctx->s, gc, 0); + screen_write_alternateon(sctx, gc, 0); break; case 1049: - if (wp != NULL) - window_pane_alternate_on(wp, gc, 1); - else - screen_alternate_on(sctx->s, gc, 1); + screen_write_alternateon(sctx, gc, 1); break; case 2004: screen_write_mode_set(sctx, MODE_BRACKETPASTE); @@ -2593,7 +2580,7 @@ input_osc_52(struct input_ctx *ictx, const char *p) return; } - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_setselection(&ctx, out, outlen); screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); diff --git a/menu.c b/menu.c index e78999c6..27836694 100644 --- a/menu.c +++ b/menu.c @@ -153,13 +153,15 @@ menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) style_apply(&gc, c->session->curw->window->options, "mode-style", NULL); - screen_write_start(&ctx, NULL, s); + screen_write_start(&ctx, s); screen_write_clearscreen(&ctx, 8); screen_write_menu(&ctx, menu, md->choice, &gc); screen_write_stop(&ctx); - for (i = 0; i < screen_size_y(&md->s); i++) - tty_draw_line(tty, NULL, s, 0, i, menu->width + 4, px, py + i); + for (i = 0; i < screen_size_y(&md->s); i++) { + tty_draw_line(tty, s, 0, i, menu->width + 4, px, py + i, + &grid_default_cell, NULL); + } } static void diff --git a/mode-tree.c b/mode-tree.c index 645e2ae9..8d210d72 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -562,7 +562,7 @@ mode_tree_draw(struct mode_tree_data *mtd) w = mtd->width; h = mtd->height; - screen_write_start(&ctx, NULL, s); + screen_write_start(&ctx, s); screen_write_clearscreen(&ctx, 8); if (mtd->line_size > 10) diff --git a/popup.c b/popup.c index 160b5aa3..c13a38cf 100644 --- a/popup.c +++ b/popup.c @@ -57,6 +57,44 @@ struct popup_data { u_int lb; }; +static void +popup_redraw_cb(const struct tty_ctx *ttyctx) +{ + struct popup_data *pd = ttyctx->arg; + + pd->c->flags |= CLIENT_REDRAWOVERLAY; +} + +static int +popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c) +{ + struct popup_data *pd = ttyctx->arg; + + if (pd->c->flags & CLIENT_REDRAWOVERLAY) + return (-1); + + ttyctx->bigger = 0; + ttyctx->wox = 0; + ttyctx->woy = 0; + ttyctx->wsx = c->tty.sx; + ttyctx->wsy = c->tty.sy; + + ttyctx->xoff = pd->px + 1; + ttyctx->yoff = pd->py + 1; + + return (1); +} + +static void +popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx) +{ + struct popup_data *pd = ctx->arg; + + ttyctx->redraw_cb = popup_redraw_cb; + ttyctx->set_client_cb = popup_set_client_cb; + ttyctx->arg = pd; +} + static void popup_write_screen(struct client *c, struct popup_data *pd) { @@ -72,7 +110,7 @@ popup_write_screen(struct client *c, struct popup_data *pd) else format_defaults(ft, c, NULL, NULL, NULL); - screen_write_start(&ctx, NULL, &pd->s); + screen_write_start(&ctx, &pd->s); screen_write_clearscreen(&ctx, 8); y = 0; @@ -132,7 +170,7 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) u_int i, px = pd->px, py = pd->py; screen_init(&s, pd->sx, pd->sy, 0); - screen_write_start(&ctx, NULL, &s); + screen_write_start(&ctx, &s); screen_write_clearscreen(&ctx, 8); screen_write_box(&ctx, pd->sx, pd->sy); screen_write_cursormove(&ctx, 1, 1, 0); @@ -140,8 +178,10 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) screen_write_stop(&ctx); c->overlay_check = NULL; - for (i = 0; i < pd->sy; i++) - tty_draw_line(tty, NULL, &s, 0, i, pd->sx, px, py + i); + for (i = 0; i < pd->sy; i++){ + tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, + &grid_default_cell, NULL); + } c->overlay_check = popup_check_cb; } @@ -331,11 +371,14 @@ popup_job_update_cb(struct job *job) void *data = EVBUFFER_DATA(evb); size_t size = EVBUFFER_LENGTH(evb); - if (size != 0) { - input_parse_screen(pd->ictx, s, data, size); - evbuffer_drain(evb, size); - pd->c->flags |= CLIENT_REDRAWOVERLAY; - } + if (size == 0) + return; + + pd->c->tty.flags &= ~TTY_FREEZE; + input_parse_screen(pd->ictx, s, popup_init_ctx_cb, pd, data, size); + pd->c->tty.flags |= TTY_FREEZE; + + evbuffer_drain(evb, size); } static void diff --git a/screen-redraw.c b/screen-redraw.c index cf6b7e69..dd5886b2 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -317,7 +317,7 @@ screen_redraw_make_pane_status(struct client *c, struct window *w, screen_init(&wp->status_screen, width, 1, 0); wp->status_screen.mode = 0; - screen_write_start(&ctx, NULL, &wp->status_screen); + screen_write_start(&ctx, &wp->status_screen); gc.attr |= GRID_ATTR_CHARSET; for (i = 0; i < width; i++) @@ -394,7 +394,8 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) if (ctx->statustop) yoff += ctx->statuslines; - tty_draw_line(tty, NULL, s, i, 0, width, x, yoff - ctx->oy); + tty_draw_line(tty, s, i, 0, width, x, yoff - ctx->oy, + &grid_default_cell, NULL); } tty_cursor(tty, 0, 0); } @@ -586,7 +587,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) } } - tty_attributes(tty, gc, NULL); + tty_attributes(tty, gc, &grid_default_cell, NULL); if (ctx->statustop) tty_cursor(tty, i, ctx->statuslines + j); else @@ -647,8 +648,10 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx) y = 0; else y = c->tty.sy - ctx->statuslines; - for (i = 0; i < ctx->statuslines; i++) - tty_draw_line(tty, NULL, s, 0, i, UINT_MAX, 0, y + i); + for (i = 0; i < ctx->statuslines; i++) { + tty_draw_line(tty, s, 0, i, UINT_MAX, 0, y + i, + &grid_default_cell, NULL); + } } /* Draw one pane. */ @@ -659,6 +662,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) struct window *w = c->session->curw->window; struct tty *tty = &c->tty; struct screen *s; + struct grid_cell defaults; u_int i, j, top, x, y, width; log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id); @@ -702,6 +706,8 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u", __func__, c->name, wp->id, i, j, x, y, width); - tty_draw_line(tty, wp, s, i, j, width, x, y); + tty_default_colours(&defaults, wp); + tty_draw_line(tty, s, i, j, width, x, y, &defaults, + wp->palette); } } diff --git a/screen-write.c b/screen-write.c index 32424b39..c7996ec9 100644 --- a/screen-write.c +++ b/screen-write.c @@ -27,8 +27,8 @@ static void screen_write_collect_clear(struct screen_write_ctx *, u_int, u_int); static int screen_write_collect_clear_end(struct screen_write_ctx *, u_int, u_int, u_int); -static int screen_write_collect_clear_start(struct screen_write_ctx *, u_int, - u_int, u_int); +static int screen_write_collect_clear_start(struct screen_write_ctx *, + u_int, u_int, u_int); static void screen_write_collect_scroll(struct screen_write_ctx *); static void screen_write_collect_flush(struct screen_write_ctx *, int, const char *); @@ -101,6 +101,49 @@ screen_write_set_cursor(struct screen_write_ctx *ctx, int cx, int cy) evtimer_add(&w->offset_timer, &tv); } +/* Do a full redraw. */ +static void +screen_write_redraw_cb(const struct tty_ctx *ttyctx) +{ + struct window_pane *wp = ttyctx->arg; + + wp->flags |= PANE_REDRAW; +} + +/* Update context for client. */ +static int +screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c) +{ + struct window_pane *wp = ttyctx->arg; + + if (c->session->curw->window != wp->window) + return (0); + if (wp->layout_cell == NULL) + return (0); + + if (wp->flags & (PANE_REDRAW|PANE_DROP)) + return (-1); + if (c->flags & CLIENT_REDRAWPANES) { + /* + * Redraw is already deferred to redraw another pane - redraw + * this one also when that happens. + */ + log_debug("adding %%%u to deferred redraw", wp->id); + wp->flags |= PANE_REDRAW; + return (-1); + } + + ttyctx->bigger = tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy, + &ttyctx->wsx, &ttyctx->wsy); + + ttyctx->xoff = wp->xoff; + ttyctx->yoff = wp->yoff; + if (status_at_line(c) == 0) + ttyctx->yoff += status_line_size(c); + + return (1); +} + /* Set up context for TTY command. */ static void screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, @@ -110,17 +153,35 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, memset(ttyctx, 0, sizeof *ttyctx); - ttyctx->wp = ctx->wp; + if (ctx->wp != NULL) { + tty_default_colours(&ttyctx->defaults, ctx->wp); + ttyctx->palette = ctx->wp->palette; + } else { + memcpy(&ttyctx->defaults, &grid_default_cell, + sizeof ttyctx->defaults); + ttyctx->palette = NULL; + } + ttyctx->s = s; ttyctx->sx = screen_size_x(s); ttyctx->sy = screen_size_y(s); ttyctx->ocx = s->cx; ttyctx->ocy = s->cy; - ttyctx->orlower = s->rlower; ttyctx->orupper = s->rupper; + if (ctx->init_ctx_cb != NULL) + ctx->init_ctx_cb(ctx, ttyctx); + else { + ttyctx->redraw_cb = screen_write_redraw_cb; + if (ctx->wp == NULL) + ttyctx->set_client_cb = NULL; + else + ttyctx->set_client_cb = screen_write_set_client_cb; + ttyctx->arg = ctx->wp; + } + if (ctx->wp != NULL && !ctx->sync && (sync || ctx->wp != ctx->wp->window->active)) { @@ -151,18 +212,13 @@ screen_write_free_list(struct screen *s) free(s->write_list); } -/* Initialize writing with a window. */ -void -screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp, - struct screen *s) +/* Set up for writing. */ +static void +screen_write_init(struct screen_write_ctx *ctx, struct screen *s) { memset(ctx, 0, sizeof *ctx); - ctx->wp = wp; - if (wp != NULL && s == NULL) - ctx->s = wp->screen; - else - ctx->s = s; + ctx->s = s; if (ctx->s->write_list == NULL) screen_write_make_list(ctx->s); @@ -170,17 +226,51 @@ screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp, ctx->scrolled = 0; ctx->bg = 8; +} + +/* Initialize writing with a pane. */ +void +screen_write_start_pane(struct screen_write_ctx *ctx, struct window_pane *wp, + struct screen *s) +{ + if (s == NULL) + s = wp->screen; + screen_write_init(ctx, s); + ctx->wp = wp; if (log_get_level() != 0) { - if (wp != NULL) { - log_debug("%s: size %ux%u, pane %%%u (at %u,%u)", - __func__, screen_size_x(ctx->s), - screen_size_y(ctx->s), wp->id, wp->xoff, wp->yoff); - } else { - log_debug("%s: size %ux%u, no pane", - __func__, screen_size_x(ctx->s), - screen_size_y(ctx->s)); - } + log_debug("%s: size %ux%u, pane %%%u (at %u,%u)", + __func__, screen_size_x(ctx->s), screen_size_y(ctx->s), + wp->id, wp->xoff, wp->yoff); + } +} + +/* Initialize writing with a callback. */ +void +screen_write_start_callback(struct screen_write_ctx *ctx, struct screen *s, + screen_write_init_ctx_cb cb, void *arg) +{ + screen_write_init(ctx, s); + + ctx->init_ctx_cb = cb; + ctx->arg = arg; + + if (log_get_level() != 0) { + log_debug("%s: size %ux%u, with callback", __func__, + screen_size_x(ctx->s), screen_size_y(ctx->s)); + } +} + + +/* Initialize writing. */ +void +screen_write_start(struct screen_write_ctx *ctx, struct screen *s) +{ + screen_write_init(ctx, s); + + if (log_get_level() != 0) { + log_debug("%s: size %ux%u, no pane", __func__, + screen_size_x(ctx->s), screen_size_y(ctx->s)); } } @@ -1799,3 +1889,35 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) tty_write(tty_cmd_rawstring, &ttyctx); } + +/* Turn alternate screen on. */ +void +screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, + int cursor) +{ + struct tty_ctx ttyctx; + struct window_pane *wp = ctx->wp; + + if (wp != NULL && !options_get_number(wp->options, "alternate-screen")) + return; + screen_alternate_on(ctx->s, gc, cursor); + + screen_write_initctx(ctx, &ttyctx, 1); + ttyctx.redraw_cb(&ttyctx); +} + +/* Turn alternate screen off. */ +void +screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc, + int cursor) +{ + struct tty_ctx ttyctx; + struct window_pane *wp = ctx->wp; + + if (wp != NULL && !options_get_number(wp->options, "alternate-screen")) + return; + screen_alternate_off(ctx->s, gc, cursor); + + screen_write_initctx(ctx, &ttyctx, 1); + ttyctx.redraw_cb(&ttyctx); +} diff --git a/server-fn.c b/server-fn.c index 815d25e2..127afb6b 100644 --- a/server-fn.c +++ b/server-fn.c @@ -319,7 +319,7 @@ server_destroy_pane(struct window_pane *wp, int notify) if (notify) notify_pane("pane-died", wp); - screen_write_start(&ctx, wp, &wp->base); + screen_write_start_pane(&ctx, wp, &wp->base); screen_write_scrollregion(&ctx, 0, screen_size_y(ctx.s) - 1); screen_write_cursormove(&ctx, 0, screen_size_y(ctx.s) - 1, 0); screen_write_linefeed(&ctx, 1, 8); diff --git a/status.c b/status.c index a4844294..b5442550 100644 --- a/status.c +++ b/status.c @@ -372,7 +372,7 @@ status_redraw(struct client *c) screen_resize(&sl->screen, width, lines, 0); changed = force = 1; } - screen_write_start(&ctx, NULL, &sl->screen); + screen_write_start(&ctx, &sl->screen); /* Write the status lines. */ o = options_get(s->options, "status-format"); @@ -509,7 +509,7 @@ status_message_redraw(struct client *c) style_apply(&gc, s->options, "message-style", ft); format_free(ft); - screen_write_start(&ctx, NULL, sl->active); + screen_write_start(&ctx, sl->active); screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); screen_write_cursormove(&ctx, 0, lines - 1, 0); for (offset = 0; offset < c->tty.sx; offset++) @@ -664,7 +664,7 @@ status_prompt_redraw(struct client *c) if (start > c->tty.sx) start = c->tty.sx; - screen_write_start(&ctx, NULL, sl->active); + screen_write_start(&ctx, sl->active); screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1); screen_write_cursormove(&ctx, 0, lines - 1, 0); for (offset = 0; offset < c->tty.sx; offset++) diff --git a/tmux.h b/tmux.h index 55f51361..726fdb26 100644 --- a/tmux.h +++ b/tmux.h @@ -57,7 +57,11 @@ struct mouse_event; struct options; struct options_array_item; struct options_entry; +struct screen_write_collect_item; +struct screen_write_collect_line; +struct screen_write_ctx; struct session; +struct tty_ctx; struct tmuxpeer; struct tmuxproc; struct winlink; @@ -788,13 +792,16 @@ struct screen { }; /* Screen write context. */ -struct screen_write_collect_item; -struct screen_write_collect_line; +typedef void (*screen_write_init_ctx_cb)(struct screen_write_ctx *, + struct tty_ctx *); struct screen_write_ctx { struct window_pane *wp; struct screen *s; int sync; + screen_write_init_ctx_cb init_ctx_cb; + void *arg; + struct screen_write_collect_item *item; u_int scrolled; u_int bg; @@ -1254,8 +1261,6 @@ struct tty { struct termios tio; struct grid_cell cell; - - int last_wp; struct grid_cell last_cell; #define TTY_NOCURSOR 0x1 @@ -1287,8 +1292,14 @@ struct tty { }; /* TTY command context. */ +typedef void (*tty_ctx_redraw_cb)(const struct tty_ctx *); +typedef int (*tty_ctx_set_client_cb)(struct tty_ctx *, struct client *); struct tty_ctx { - struct window_pane *wp; + struct screen *s; + + tty_ctx_redraw_cb redraw_cb; + tty_ctx_set_client_cb set_client_cb; + void *arg; const struct grid_cell *cell; int wrapped; @@ -1316,6 +1327,10 @@ struct tty_ctx { /* The background colour used for clearing (erasing). */ u_int bg; + /* The default colours and palette. */ + struct grid_cell defaults; + int *palette; + /* Containing region (usually window) offset and size. */ int bigger; u_int wox; @@ -1971,7 +1986,7 @@ void tty_update_window_offset(struct window *); void tty_update_client_offset(struct client *); void tty_raw(struct tty *, const char *); void tty_attributes(struct tty *, const struct grid_cell *, - struct window_pane *); + const struct grid_cell *, int *); void tty_reset(struct tty *); void tty_region_off(struct tty *); void tty_margin_off(struct tty *); @@ -1994,8 +2009,8 @@ void tty_send_requests(struct tty *); void tty_stop_tty(struct tty *); void tty_set_title(struct tty *, const char *); void tty_update_mode(struct tty *, int, struct screen *); -void tty_draw_line(struct tty *, struct window_pane *, struct screen *, - u_int, u_int, u_int, u_int, u_int); +void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int, + u_int, u_int, const struct grid_cell *, int *); void tty_sync_start(struct tty *); void tty_sync_end(struct tty *); int tty_open(struct tty *, char **); @@ -2026,6 +2041,7 @@ void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *); void tty_cmd_setselection(struct tty *, const struct tty_ctx *); void tty_cmd_rawstring(struct tty *, const struct tty_ctx *); void tty_cmd_syncstart(struct tty *, const struct tty_ctx *); +void tty_default_colours(struct grid_cell *, struct window_pane *); /* tty-term.c */ extern struct tty_terms tty_terms; @@ -2344,8 +2360,8 @@ void input_reset(struct input_ctx *, int); struct evbuffer *input_pending(struct input_ctx *); void input_parse_pane(struct window_pane *); void input_parse_buffer(struct window_pane *, u_char *, size_t); -void input_parse_screen(struct input_ctx *, struct screen *, u_char *, - size_t); +void input_parse_screen(struct input_ctx *, struct screen *, + screen_write_init_ctx_cb, void *, u_char *, size_t); /* input-key.c */ int input_key_pane(struct window_pane *, key_code, struct mouse_event *); @@ -2428,8 +2444,11 @@ char *grid_view_string_cells(struct grid *, u_int, u_int, u_int); /* screen-write.c */ void screen_write_make_list(struct screen *); void screen_write_free_list(struct screen *); -void screen_write_start(struct screen_write_ctx *, struct window_pane *, - struct screen *); +void screen_write_start_pane(struct screen_write_ctx *, + struct window_pane *, struct screen *); +void screen_write_start(struct screen_write_ctx *, struct screen *); +void screen_write_start_callback(struct screen_write_ctx *, struct screen *, + screen_write_init_ctx_cb, void *); void screen_write_stop(struct screen_write_ctx *); void screen_write_reset(struct screen_write_ctx *); size_t printflike(1, 2) screen_write_strlen(const char *, ...); @@ -2483,6 +2502,10 @@ void screen_write_collect_add(struct screen_write_ctx *, void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); +void screen_write_alternateon(struct screen_write_ctx *, + struct grid_cell *, int); +void screen_write_alternateoff(struct screen_write_ctx *, + struct grid_cell *, int); /* screen-redraw.c */ void screen_redraw_screen(struct client *); @@ -2571,10 +2594,6 @@ struct window_pane *window_pane_find_by_id_str(const char *); struct window_pane *window_pane_find_by_id(u_int); int window_pane_destroy_ready(struct window_pane *); void window_pane_resize(struct window_pane *, u_int, u_int); -void window_pane_alternate_on(struct window_pane *, - struct grid_cell *, int); -void window_pane_alternate_off(struct window_pane *, - struct grid_cell *, int); void window_pane_set_palette(struct window_pane *, u_int, int); void window_pane_unset_palette(struct window_pane *, u_int); void window_pane_reset_palette(struct window_pane *); diff --git a/tty.c b/tty.c index aaf4d639..25a0cd02 100644 --- a/tty.c +++ b/tty.c @@ -34,7 +34,7 @@ static int tty_log_fd = -1; -static int tty_client_ready(struct client *, struct window_pane *); +static int tty_client_ready(struct client *); static void tty_set_italics(struct tty *); static int tty_try_colour(struct tty *, int, const char *); @@ -45,12 +45,9 @@ static void tty_cursor_pane_unless_wrap(struct tty *, const struct tty_ctx *, u_int, u_int); static void tty_invalidate(struct tty *); static void tty_colours(struct tty *, const struct grid_cell *); -static void tty_check_fg(struct tty *, struct window_pane *, - struct grid_cell *); -static void tty_check_bg(struct tty *, struct window_pane *, - struct grid_cell *); -static void tty_check_us(struct tty *, struct window_pane *, - struct grid_cell *); +static void tty_check_fg(struct tty *, int *, struct grid_cell *); +static void tty_check_bg(struct tty *, int *, struct grid_cell *); +static void tty_check_us(struct tty *, int *, struct grid_cell *); static void tty_colours_fg(struct tty *, const struct grid_cell *); static void tty_colours_bg(struct tty *, const struct grid_cell *); static void tty_colours_us(struct tty *, const struct grid_cell *); @@ -61,17 +58,17 @@ static void tty_region(struct tty *, u_int, u_int); static void tty_margin_pane(struct tty *, const struct tty_ctx *); static void tty_margin(struct tty *, u_int, u_int); static int tty_large_region(struct tty *, const struct tty_ctx *); -static int tty_fake_bce(const struct tty *, struct window_pane *, u_int); +static int tty_fake_bce(const struct tty *, const struct grid_cell *, + u_int); static void tty_redraw_region(struct tty *, const struct tty_ctx *); static void tty_emulate_repeat(struct tty *, enum tty_code_code, enum tty_code_code, u_int); static void tty_repeat_space(struct tty *, u_int); static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int); static void tty_cell(struct tty *, const struct grid_cell *, - struct window_pane *); -static void tty_default_colours(struct grid_cell *, struct window_pane *); -static void tty_default_attributes(struct tty *, struct window_pane *, - u_int); + const struct grid_cell *, int *); +static void tty_default_attributes(struct tty *, const struct grid_cell *, + int *, u_int); #define tty_use_margin(tty) \ (tty->term->flags & TERM_DECSLRM) @@ -888,6 +885,27 @@ tty_update_client_offset(struct client *c) c->flags |= (CLIENT_REDRAWWINDOW|CLIENT_REDRAWSTATUS); } +/* Get a palette entry. */ +static int +tty_get_palette(int *palette, int c) +{ + int new; + + if (palette == NULL) + return (-1); + + new = -1; + if (c < 8) + new = palette[c]; + else if (c >= 90 && c <= 97) + new = palette[8 + c - 90]; + else if (c & COLOUR_FLAG_256) + new = palette[c & ~COLOUR_FLAG_256]; + if (new == 0) + return (-1); + return (new); +} + /* * Is the region large enough to be worth redrawing once later rather than * probably several times now? Currently yes if it is more than 50% of the @@ -904,18 +922,11 @@ tty_large_region(__unused struct tty *tty, const struct tty_ctx *ctx) * emulated. */ static int -tty_fake_bce(const struct tty *tty, struct window_pane *wp, u_int bg) +tty_fake_bce(const struct tty *tty, const struct grid_cell *gc, u_int bg) { - struct grid_cell gc; - if (tty_term_flag(tty->term, TTYC_BCE)) return (0); - - memcpy(&gc, &grid_default_cell, sizeof gc); - if (wp != NULL) - tty_default_colours(&gc, wp); - - if (!COLOUR_DEFAULT(bg) || !COLOUR_DEFAULT(gc.bg)) + if (!COLOUR_DEFAULT(bg) || !COLOUR_DEFAULT(gc->bg)) return (1); return (0); } @@ -929,16 +940,15 @@ static void tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - struct window_pane *wp = ctx->wp; u_int i; /* - * If region is large, schedule a window redraw. In most cases this is - * likely to be followed by some more scrolling. + * If region is large, schedule a redraw. In most cases this is likely + * to be followed by some more scrolling. */ if (tty_large_region(tty, ctx)) { - log_debug("%s: %s, large redraw of %%%u", __func__, c->name, wp->id); - wp->flags |= PANE_REDRAW; + log_debug("%s: %s large redraw", __func__, c->name); + ctx->redraw_cb(ctx); return; } @@ -977,8 +987,7 @@ static int tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, u_int nx, u_int *i, u_int *x, u_int *rx, u_int *ry) { - struct window_pane *wp = ctx->wp; - u_int xoff = wp->xoff + px; + u_int xoff = ctx->xoff + px; if (!tty_is_visible(tty, ctx, px, py, nx, 1)) return (0); @@ -1013,8 +1022,8 @@ tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, /* Clear a line. */ static void -tty_clear_line(struct tty *tty, struct window_pane *wp, u_int py, u_int px, - u_int nx, u_int bg) +tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, + u_int px, u_int nx, u_int bg) { struct client *c = tty->client; @@ -1025,7 +1034,7 @@ tty_clear_line(struct tty *tty, struct window_pane *wp, u_int py, u_int px, return; /* If genuine BCE is available, can try escape sequences. */ - if (!tty_fake_bce(tty, wp, bg)) { + if (!tty_fake_bce(tty, defaults, bg)) { /* Off the end of the line, use EL if available. */ if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { tty_cursor(tty, px, py); @@ -1064,7 +1073,7 @@ tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py, log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); if (tty_clamp_line(tty, ctx, px, py, nx, &i, &x, &rx, &ry)) - tty_clear_line(tty, ctx->wp, ry, x, rx, bg); + tty_clear_line(tty, &ctx->defaults, ry, x, rx, bg); } /* Clamp area position to visible part of pane. */ @@ -1073,8 +1082,7 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, u_int nx, u_int ny, u_int *i, u_int *j, u_int *x, u_int *y, u_int *rx, u_int *ry) { - struct window_pane *wp = ctx->wp; - u_int xoff = wp->xoff + px, yoff = wp->yoff + py; + u_int xoff = ctx->xoff + px, yoff = ctx->yoff + py; if (!tty_is_visible(tty, ctx, px, py, nx, ny)) return (0); @@ -1132,8 +1140,8 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, /* Clear an area, adjusting to visible part of pane. */ static void -tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny, - u_int px, u_int nx, u_int bg) +tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py, + u_int ny, u_int px, u_int nx, u_int bg) { struct client *c = tty->client; u_int yy; @@ -1146,7 +1154,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny, return; /* If genuine BCE is available, can try escape sequences. */ - if (!tty_fake_bce(tty, wp, bg)) { + if (!tty_fake_bce(tty, defaults, bg)) { /* Use ED if clearing off the bottom of the terminal. */ if (px == 0 && px + nx >= tty->sx && @@ -1199,7 +1207,7 @@ tty_clear_area(struct tty *tty, struct window_pane *wp, u_int py, u_int ny, /* Couldn't use an escape sequence, loop over the lines. */ for (yy = py; yy < py + ny; yy++) - tty_clear_line(tty, wp, yy, px, nx, bg); + tty_clear_line(tty, defaults, yy, px, nx, bg); } /* Clear an area in a pane. */ @@ -1210,24 +1218,26 @@ tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py, u_int i, j, x, y, rx, ry; if (tty_clamp_area(tty, ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry)) - tty_clear_area(tty, ctx->wp, y, ry, x, rx, bg); + tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg); } static void tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py) { - struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; - u_int nx = ctx->sx, i, x, rx, ry; + struct screen *s = ctx->s; + u_int nx = ctx->sx, i, x, rx, ry; log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger); if (!ctx->bigger) { - tty_draw_line(tty, wp, s, 0, py, nx, ctx->xoff, ctx->yoff + py); + tty_draw_line(tty, s, 0, py, nx, ctx->xoff, ctx->yoff + py, + &ctx->defaults, ctx->palette); return; } - if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) - tty_draw_line(tty, wp, s, i, py, rx, x, ry); + if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) { + tty_draw_line(tty, s, i, py, rx, x, ry, &ctx->defaults, + ctx->palette); + } } static const struct grid_cell * @@ -1265,8 +1275,8 @@ tty_check_overlay(struct tty *tty, u_int px, u_int py) } void -tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, - u_int px, u_int py, u_int nx, u_int atx, u_int aty) +tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, + u_int atx, u_int aty, const struct grid_cell *defaults, int *palette) { struct grid *gd = s->grid; struct grid_cell gc, last; @@ -1314,8 +1324,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, gl = NULL; else gl = grid_get_line(gd, gd->hsize + py - 1); - if (wp == NULL || - gl == NULL || + if (gl == NULL || (~gl->flags & GRID_LINE_WRAPPED) || atx != 0 || tty->cx < tty->sx || @@ -1324,8 +1333,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, atx == 0 && px + sx != nx && tty_term_has(tty->term, TTYC_EL1) && - !tty_fake_bce(tty, wp, 8)) { - tty_default_attributes(tty, wp, 8); + !tty_fake_bce(tty, defaults, 8)) { + tty_default_attributes(tty, defaults, palette, 8); tty_cursor(tty, nx - 1, aty); tty_putcode(tty, TTYC_EL1); cleared = 1; @@ -1352,11 +1361,11 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, gcp->us != last.us || ux + width + gcp->data.width > nx || (sizeof buf) - len < gcp->data.size)) { - tty_attributes(tty, &last, wp); + tty_attributes(tty, &last, defaults, palette); if (last.flags & GRID_FLAG_CLEARED) { log_debug("%s: %zu cleared", __func__, len); - tty_clear_line(tty, wp, aty, atx + ux, width, - last.bg); + tty_clear_line(tty, defaults, aty, atx + ux, + width, last.bg); } else { if (!wrapped || atx != 0 || ux != 0) tty_cursor(tty, atx + ux, aty); @@ -1376,7 +1385,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, if (!tty_check_overlay(tty, atx + ux, aty)) ux += gcp->data.width; else if (ux + gcp->data.width > nx) { - tty_attributes(tty, &last, wp); + tty_attributes(tty, &last, defaults, palette); tty_cursor(tty, atx + ux, aty); for (j = 0; j < gcp->data.width; j++) { if (ux + j > nx) @@ -1385,7 +1394,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, ux++; } } else if (gcp->attr & GRID_ATTR_CHARSET) { - tty_attributes(tty, &last, wp); + tty_attributes(tty, &last, defaults, palette); tty_cursor(tty, atx + ux, aty); for (j = 0; j < gcp->data.size; j++) tty_putc(tty, gcp->data.data[j]); @@ -1397,10 +1406,11 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, } } if (len != 0 && ((~last.flags & GRID_FLAG_CLEARED) || last.bg != 8)) { - tty_attributes(tty, &last, wp); + tty_attributes(tty, &last, defaults, palette); if (last.flags & GRID_FLAG_CLEARED) { log_debug("%s: %zu cleared (end)", __func__, len); - tty_clear_line(tty, wp, aty, atx + ux, width, last.bg); + tty_clear_line(tty, defaults, aty, atx + ux, width, + last.bg); } else { if (!wrapped || atx != 0 || ux != 0) tty_cursor(tty, atx + ux, aty); @@ -1412,8 +1422,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, if (!cleared && ux < nx) { log_debug("%s: %u to end of line (%zu cleared)", __func__, nx - ux, len); - tty_default_attributes(tty, wp, 8); - tty_clear_line(tty, wp, aty, atx + ux, nx - ux, 8); + tty_default_attributes(tty, defaults, palette, 8); + tty_clear_line(tty, defaults, aty, atx + ux, nx - ux, 8); } tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags; @@ -1451,7 +1461,7 @@ tty_sync_end(struct tty *tty) } static int -tty_client_ready(struct client *c, struct window_pane *wp) +tty_client_ready(struct client *c) { if (c->session == NULL || c->tty.term == NULL) return (0); @@ -1459,10 +1469,6 @@ tty_client_ready(struct client *c, struct window_pane *wp) return (0); if (c->tty.flags & TTY_FREEZE) return (0); - if (c->session->curw->window != wp->window) - return (0); - if (wp->layout_cell == NULL) - return (0); return (1); } @@ -1470,36 +1476,19 @@ void tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *), struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - struct client *c; + struct client *c; + int state; - if (wp == NULL) + if (ctx->set_client_cb == NULL) return; - if (wp->flags & (PANE_REDRAW|PANE_DROP)) - return; - TAILQ_FOREACH(c, &clients, entry) { - if (!tty_client_ready(c, wp)) + if (!tty_client_ready(c)) continue; - if (c->flags & CLIENT_REDRAWPANES) { - /* - * Redraw is already deferred to redraw another pane - - * redraw this one also when that happens. - */ - log_debug("adding %%%u to deferred redraw", wp->id); - wp->flags |= PANE_REDRAW; + state = ctx->set_client_cb(ctx, c); + if (state == -1) break; - } - - ctx->bigger = tty_window_offset(&c->tty, &ctx->wox, &ctx->woy, - &ctx->wsx, &ctx->wsy); - - ctx->xoff = wp->xoff; - ctx->yoff = wp->yoff; - - if (status_at_line(c) == 0) - ctx->yoff += status_line_size(c); - + if (state == 0) + continue; cmdfn(&c->tty, ctx); } } @@ -1507,18 +1496,16 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *), void tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - if (ctx->bigger || !tty_full_width(tty, ctx) || - tty_fake_bce(tty, wp, ctx->bg) || + tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_ICH) && !tty_term_has(tty->term, TTYC_ICH1))) { tty_draw_pane(tty, ctx, ctx->ocy); return; } - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -1528,18 +1515,16 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - if (ctx->bigger || !tty_full_width(tty, ctx) || - tty_fake_bce(tty, wp, ctx->bg) || + tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_DCH) && !tty_term_has(tty->term, TTYC_DCH1))) { tty_draw_pane(tty, ctx, ctx->ocy); return; } - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -1554,12 +1539,12 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) return; } - tty_default_attributes(tty, ctx->wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); if (tty_term_has(tty->term, TTYC_ECH) && - !tty_fake_bce(tty, ctx->wp, 8)) + !tty_fake_bce(tty, &ctx->defaults, 8)) tty_putcode1(tty, TTYC_ECH, ctx->num); else tty_repeat_space(tty, ctx->num); @@ -1570,16 +1555,16 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) { if (ctx->bigger || !tty_full_width(tty, ctx) || - tty_fake_bce(tty, ctx->wp, ctx->bg) || + tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_IL1) || - ctx->wp->sx == 1 || - ctx->wp->sy == 1) { + ctx->sx == 1 || + ctx->sy == 1) { tty_redraw_region(tty, ctx); return; } - tty_default_attributes(tty, ctx->wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_off(tty); @@ -1594,16 +1579,16 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) { if (ctx->bigger || !tty_full_width(tty, ctx) || - tty_fake_bce(tty, ctx->wp, ctx->bg) || + tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_DL1) || - ctx->wp->sx == 1 || - ctx->wp->sy == 1) { + ctx->sx == 1 || + ctx->sy == 1) { tty_redraw_region(tty, ctx); return; } - tty_default_attributes(tty, ctx->wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_off(tty); @@ -1616,9 +1601,7 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->sx, ctx->bg); } @@ -1626,10 +1609,9 @@ tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int nx = ctx->sx - ctx->ocx; + u_int nx = ctx->sx - ctx->ocx; - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_clear_pane_line(tty, ctx, ctx->ocy, ctx->ocx, nx, ctx->bg); } @@ -1637,9 +1619,7 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_clear_pane_line(tty, ctx, ctx->ocy, 0, ctx->ocx + 1, ctx->bg); } @@ -1647,24 +1627,22 @@ tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - if (ctx->ocy != ctx->orupper) return; if (ctx->bigger || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || - tty_fake_bce(tty, wp, 8) || + tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || (!tty_term_has(tty->term, TTYC_RI) && !tty_term_has(tty->term, TTYC_RIN)) || - ctx->wp->sx == 1 || - ctx->wp->sy == 1) { + ctx->sx == 1 || + ctx->sy == 1) { tty_redraw_region(tty, ctx); return; } - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1679,22 +1657,20 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - if (ctx->ocy != ctx->orlower) return; if (ctx->bigger || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || - tty_fake_bce(tty, wp, 8) || + tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || - wp->sx == 1 || - wp->sy == 1) { + ctx->sx == 1 || + ctx->sy == 1) { tty_redraw_region(tty, ctx); return; } - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1720,20 +1696,19 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int i; + u_int i; if (ctx->bigger || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || - tty_fake_bce(tty, wp, 8) || + tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || - wp->sx == 1 || - wp->sy == 1) { + ctx->sx == 1 || + ctx->sy == 1) { tty_redraw_region(tty, ctx); return; } - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1757,22 +1732,21 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int i; + u_int i; if (ctx->bigger || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || - tty_fake_bce(tty, wp, 8) || + tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || (!tty_term_has(tty->term, TTYC_RI) && !tty_term_has(tty->term, TTYC_RIN)) || - wp->sx == 1 || - wp->sy == 1) { + ctx->sx == 1 || + ctx->sy == 1) { tty_redraw_region(tty, ctx); return; } - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_margin_pane(tty, ctx); @@ -1789,10 +1763,9 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int px, py, nx, ny; + u_int px, py, nx, ny; - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1814,10 +1787,9 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int px, py, nx, ny; + u_int px, py, nx, ny; - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1839,10 +1811,9 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int px, py, nx, ny; + u_int px, py, nx, ny; - tty_default_attributes(tty, wp, ctx->bg); + tty_default_attributes(tty, &ctx->defaults, ctx->palette, ctx->bg); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1858,15 +1829,14 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - u_int i, j; + u_int i, j; if (ctx->bigger) { - wp->flags |= PANE_REDRAW; + ctx->redraw_cb(ctx); return; } - tty_attributes(tty, &grid_default_cell, wp); + tty_attributes(tty, &grid_default_cell, &ctx->defaults, ctx->palette); tty_region_pane(tty, ctx, 0, ctx->sy - 1); tty_margin_off(tty); @@ -1892,14 +1862,12 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - tty_cell(tty, ctx->cell, ctx->wp); + tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette); } void tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) { - struct window_pane *wp = ctx->wp; - if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) return; @@ -1915,14 +1883,14 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) tty->cy == tty->rlower) tty_draw_pane(tty, ctx, ctx->ocy); else - wp->flags |= PANE_REDRAW; + ctx->redraw_cb(ctx); return; } tty_margin_off(tty); tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); - tty_attributes(tty, ctx->cell, ctx->wp); + tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); tty_putn(tty, ctx->ptr, ctx->num, ctx->num); } @@ -1958,7 +1926,8 @@ tty_cmd_syncstart(struct tty *tty, __unused const struct tty_ctx *ctx) } static void -tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp) +tty_cell(struct tty *tty, const struct grid_cell *gc, + const struct grid_cell *defaults, int *palette) { const struct grid_cell *gcp; @@ -1973,7 +1942,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp) return; /* Set the attributes. */ - tty_attributes(tty, gc, wp); + tty_attributes(tty, gc, defaults, palette); /* Get the cell and if ASCII write with putc to do ACS translation. */ gcp = tty_check_codeset(tty, gc); @@ -1999,21 +1968,16 @@ tty_reset(struct tty *tty) tty_putcode(tty, TTYC_SGR0); memcpy(gc, &grid_default_cell, sizeof *gc); } - memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell); - tty->last_wp = -1; } static void tty_invalidate(struct tty *tty) { memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell); - memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell); - tty->last_wp = -1; tty->cx = tty->cy = UINT_MAX; - tty->rupper = tty->rleft = UINT_MAX; tty->rlower = tty->rright = UINT_MAX; @@ -2089,7 +2053,7 @@ static void tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx) { tty_margin(tty, ctx->xoff - ctx->wox, - ctx->xoff + ctx->wp->sx - 1 - ctx->wox); + ctx->xoff + ctx->sx - 1 - ctx->wox); } /* Set margin at absolute position. */ @@ -2282,27 +2246,24 @@ out: void tty_attributes(struct tty *tty, const struct grid_cell *gc, - struct window_pane *wp) + const struct grid_cell *defaults, int *palette) { struct grid_cell *tc = &tty->cell, gc2; int changed; - /* Ignore cell if it is the same as the last one. */ - if (wp != NULL && - (int)wp->id == tty->last_wp && - ~(wp->flags & PANE_STYLECHANGED) && - gc->attr == tty->last_cell.attr && - gc->fg == tty->last_cell.fg && - gc->bg == tty->last_cell.bg && - gc->us == tty->last_cell.us) - return; - tty->last_wp = (wp != NULL ? (int)wp->id : -1); - memcpy(&tty->last_cell, gc, sizeof tty->last_cell); - /* Copy cell and update default colours. */ memcpy(&gc2, gc, sizeof gc2); - if (wp != NULL) - tty_default_colours(&gc2, wp); + if (gc2.fg == 8) + gc2.fg = defaults->fg; + if (gc2.bg == 8) + gc2.bg = defaults->bg; + + /* Ignore cell if it is the same as the last one. */ + if (gc2.attr == tty->last_cell.attr && + gc2.fg == tty->last_cell.fg && + gc2.bg == tty->last_cell.bg && + gc2.us == tty->last_cell.us) + return; /* * If no setab, try to use the reverse attribute as a best-effort for a @@ -2320,9 +2281,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, } /* Fix up the colours if necessary. */ - tty_check_fg(tty, wp, &gc2); - tty_check_bg(tty, wp, &gc2); - tty_check_us(tty, wp, &gc2); + tty_check_fg(tty, palette, &gc2); + tty_check_bg(tty, palette, &gc2); + tty_check_us(tty, palette, &gc2); /* * If any bits are being cleared or the underline colour is now default, @@ -2377,6 +2338,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc, tty_putcode(tty, TTYC_SMOL); if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty)) tty_putcode(tty, TTYC_SMACS); + + memcpy(&tty->last_cell, &gc2, sizeof tty->last_cell); } static void @@ -2441,7 +2404,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc) } static void -tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) +tty_check_fg(struct tty *tty, int *palette, struct grid_cell *gc) { u_char r, g, b; u_int colours; @@ -2456,7 +2419,7 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) c = gc->fg; if (c < 8 && gc->attr & GRID_ATTR_BRIGHT) c += 90; - if ((c = window_pane_get_palette(wp, c)) != -1) + if ((c = tty_get_palette(palette, c)) != -1) gc->fg = c; } @@ -2497,7 +2460,7 @@ tty_check_fg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) } static void -tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) +tty_check_bg(struct tty *tty, int *palette, struct grid_cell *gc) { u_char r, g, b; u_int colours; @@ -2505,7 +2468,7 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) /* Perform substitution if this pane has a palette. */ if (~gc->flags & GRID_FLAG_NOPALETTE) { - if ((c = window_pane_get_palette(wp, gc->bg)) != -1) + if ((c = tty_get_palette(palette, gc->bg)) != -1) gc->bg = c; } @@ -2548,14 +2511,13 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc) } static void -tty_check_us(__unused struct tty *tty, struct window_pane *wp, - struct grid_cell *gc) +tty_check_us(__unused struct tty *tty, int *palette, struct grid_cell *gc) { int c; /* Perform substitution if this pane has a palette. */ if (~gc->flags & GRID_FLAG_NOPALETTE) { - if ((c = window_pane_get_palette(wp, gc->us)) != -1) + if ((c = tty_get_palette(palette, gc->us)) != -1) gc->us = c; } @@ -2686,11 +2648,12 @@ tty_window_default_style(struct grid_cell *gc, struct window_pane *wp) gc->bg = wp->bg; } -static void +void tty_default_colours(struct grid_cell *gc, struct window_pane *wp) { struct options *oo = wp->options; - int c; + + memcpy(gc, &grid_default_cell, sizeof *gc); if (wp->flags & PANE_STYLECHANGED) { wp->flags &= ~PANE_STYLECHANGED; @@ -2707,12 +2670,6 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) gc->fg = wp->cached_active_gc.fg; else gc->fg = wp->cached_gc.fg; - - if (gc->fg != 8) { - c = window_pane_get_palette(wp, gc->fg); - if (c != -1) - gc->fg = c; - } } if (gc->bg == 8) { @@ -2720,21 +2677,16 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp) gc->bg = wp->cached_active_gc.bg; else gc->bg = wp->cached_gc.bg; - - if (gc->bg != 8) { - c = window_pane_get_palette(wp, gc->bg); - if (c != -1) - gc->bg = c; - } } } static void -tty_default_attributes(struct tty *tty, struct window_pane *wp, u_int bg) +tty_default_attributes(struct tty *tty, const struct grid_cell *defaults, + int *palette, u_int bg) { - static struct grid_cell gc; + struct grid_cell gc; memcpy(&gc, &grid_default_cell, sizeof gc); gc.bg = bg; - tty_attributes(tty, &gc, wp); + tty_attributes(tty, &gc, defaults, palette); } diff --git a/window-clock.c b/window-clock.c index 45d4d47b..8cef3f9a 100644 --- a/window-clock.c +++ b/window-clock.c @@ -219,7 +219,7 @@ window_clock_draw_screen(struct window_mode_entry *wme) colour = options_get_number(wp->window->options, "clock-mode-colour"); style = options_get_number(wp->window->options, "clock-mode-style"); - screen_write_start(&ctx, NULL, s); + screen_write_start(&ctx, s); t = time(NULL); tm = localtime(&t); diff --git a/window-copy.c b/window-copy.c index f5a07a10..9f84ade9 100644 --- a/window-copy.c +++ b/window-copy.c @@ -406,7 +406,7 @@ window_copy_init(struct window_mode_entry *wme, data->screen.cx = data->cx; data->screen.cy = data->cy; - screen_write_start(&ctx, NULL, &data->screen); + screen_write_start(&ctx, &data->screen); for (i = 0; i < screen_size_y(&data->screen); i++) window_copy_write_line(wme, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy, 0); @@ -473,7 +473,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap) memcpy(&gc, &grid_default_cell, sizeof gc); old_hsize = screen_hsize(data->backing); - screen_write_start(&back_ctx, NULL, backing); + screen_write_start(&back_ctx, backing); if (data->backing_written) { /* * On the second or later line, do a CRLF before writing @@ -489,7 +489,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap) data->oy += screen_hsize(data->backing) - old_hsize; - screen_write_start(&ctx, wp, &data->screen); + screen_write_start_pane(&ctx, wp, &data->screen); /* * If the history has changed, draw the top line. @@ -713,7 +713,7 @@ window_copy_size_changed(struct window_mode_entry *wme) window_copy_clear_selection(wme); window_copy_clear_marks(wme); - screen_write_start(&ctx, NULL, s); + screen_write_start(&ctx, s); window_copy_write_lines(wme, &ctx, 0, screen_size_y(s)); screen_write_stop(&ctx); @@ -2822,7 +2822,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex) fy = screen_hsize(data->backing) - data->oy + data->cy; screen_init(&ss, screen_write_strlen("%s", str), 1, 0); - screen_write_start(&ctx, NULL, &ss); + screen_write_start(&ctx, &ss); screen_write_nputs(&ctx, -1, &grid_default_cell, "%s", str); screen_write_stop(&ctx); @@ -2867,7 +2867,7 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, if (ssp == NULL) { width = screen_write_strlen("%s", data->searchstr); screen_init(&ss, width, 1, 0); - screen_write_start(&ctx, NULL, &ss); + screen_write_start(&ctx, &ss); screen_write_nputs(&ctx, -1, &grid_default_cell, "%s", data->searchstr); screen_write_stop(&ctx); @@ -3207,7 +3207,7 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny) struct screen_write_ctx ctx; u_int i; - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); for (i = py; i < py + ny; i++) window_copy_write_line(wme, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy, 0); @@ -3326,7 +3326,7 @@ window_copy_update_cursor(struct window_mode_entry *wme, u_int cx, u_int cy) if (data->cx == screen_size_x(s)) window_copy_redraw_lines(wme, data->cy, 1); else { - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_stop(&ctx); } @@ -3579,7 +3579,7 @@ window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix, struct screen_write_ctx ctx; if (options_get_number(global_options, "set-clipboard") != 0) { - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_setselection(&ctx, buf, len); screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); @@ -3636,7 +3636,7 @@ window_copy_append_selection(struct window_mode_entry *wme) return; if (options_get_number(global_options, "set-clipboard") != 0) { - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_setselection(&ctx, buf, len); screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); @@ -4399,7 +4399,7 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny) window_copy_search_marks(wme, NULL, data->searchregex); window_copy_update_selection(wme, 0, 0); - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0, 0); screen_write_deleteline(&ctx, ny, 8); window_copy_write_lines(wme, &ctx, screen_size_y(s) - ny, ny); @@ -4435,7 +4435,7 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny) window_copy_search_marks(wme, NULL, data->searchregex); window_copy_update_selection(wme, 0, 0); - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0, 0); screen_write_insertline(&ctx, ny, 8); window_copy_write_lines(wme, &ctx, 0, ny); diff --git a/window.c b/window.c index b1d812fc..8121ba2d 100644 --- a/window.c +++ b/window.c @@ -1005,26 +1005,6 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy) wp->flags |= (PANE_RESIZE|PANE_RESIZED); } -void -window_pane_alternate_on(struct window_pane *wp, struct grid_cell *gc, - int cursor) -{ - if (!options_get_number(wp->options, "alternate-screen")) - return; - screen_alternate_on(&wp->base, gc, cursor); - wp->flags |= PANE_REDRAW; -} - -void -window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc, - int cursor) -{ - if (!options_get_number(wp->options, "alternate-screen")) - return; - screen_alternate_off(&wp->base, gc, cursor); - wp->flags |= PANE_REDRAW; -} - void window_pane_set_palette(struct window_pane *wp, u_int n, int colour) {