From 4f0fc9c88e0160e3b34031091572ec2893623e93 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 8 Feb 2017 17:31:10 +0000 Subject: Add support for scroll up escape sequence (CSI S) and use it when possible instead of sending individual line feeds. --- usr.bin/tmux/input.c | 7 ++++++- usr.bin/tmux/screen-write.c | 41 ++++++++++++++++++++++++++++++++++++----- usr.bin/tmux/tmux.h | 6 +++++- usr.bin/tmux/tty-term.c | 3 ++- usr.bin/tmux/tty.c | 28 +++++++++++++++++++++++++++- 5 files changed, 76 insertions(+), 9 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/tmux/input.c b/usr.bin/tmux/input.c index f26a73ad525..5c50566e117 100644 --- a/usr.bin/tmux/input.c +++ b/usr.bin/tmux/input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.114 2017/02/08 16:45:18 nicm Exp $ */ +/* $OpenBSD: input.c,v 1.115 2017/02/08 17:31:09 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -222,6 +222,7 @@ enum input_csi_type { INPUT_CSI_SGR, INPUT_CSI_SM, INPUT_CSI_SM_PRIVATE, + INPUT_CSI_SU, INPUT_CSI_TBC, INPUT_CSI_VPA, INPUT_CSI_WINOPS, @@ -243,6 +244,7 @@ static const struct input_table_entry input_csi_table[] = { { 'L', "", INPUT_CSI_IL }, { 'M', "", INPUT_CSI_DL }, { 'P', "", INPUT_CSI_DCH }, + { 'S', "", INPUT_CSI_SU }, { 'X', "", INPUT_CSI_ECH }, { 'Z', "", INPUT_CSI_CBT }, { 'c', "", INPUT_CSI_DA }, @@ -1413,6 +1415,9 @@ input_csi_dispatch(struct input_ctx *ictx) case INPUT_CSI_SM_PRIVATE: input_csi_dispatch_sm_private(ictx); break; + case INPUT_CSI_SU: + screen_write_scrollup(sctx, input_get(ictx, 0, 1, 1)); + break; case INPUT_CSI_TBC: switch (input_get(ictx, 0, 0, 0)) { case 0: diff --git a/usr.bin/tmux/screen-write.c b/usr.bin/tmux/screen-write.c index 98ee28365cc..0ab014c9589 100644 --- a/usr.bin/tmux/screen-write.c +++ b/usr.bin/tmux/screen-write.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-write.c,v 1.109 2017/02/08 16:45:18 nicm Exp $ */ +/* $OpenBSD: screen-write.c,v 1.110 2017/02/08 17:31:09 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -839,6 +839,8 @@ screen_write_scrollregion(struct screen_write_ctx *ctx, u_int rupper, if (rupper >= rlower) /* cannot be one line */ return; + screen_write_collect_flush(ctx); + /* Cursor moves to top-left. */ s->cx = 0; s->cy = 0; @@ -854,7 +856,6 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped) struct screen *s = ctx->s; struct grid *gd = s->grid; struct grid_line *gl; - struct tty_ctx ttyctx; gl = &gd->linedata[gd->hsize + s->cy]; if (wrapped) @@ -864,14 +865,32 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped) if (s->cy == s->rlower) { grid_view_scroll_region_up(gd, s->rupper, s->rlower); - screen_write_collect_scroll(ctx); - screen_write_initctx(ctx, &ttyctx); - tty_write(tty_cmd_linefeed, &ttyctx); + ctx->scrolled++; } else if (s->cy < screen_size_y(s) - 1) s->cy++; } +/* Scroll up. */ +void +screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines) +{ + struct screen *s = ctx->s; + struct grid *gd = s->grid; + u_int i; + + if (lines == 0) + lines = 1; + else if (lines > s->rlower - s->rupper + 1) + lines = s->rlower - s->rupper + 1; + + for (i = 0; i < lines; i++) { + grid_view_scroll_region_up(gd, s->rupper, s->rlower); + screen_write_collect_scroll(ctx); + } + ctx->scrolled += lines; +} + /* Carriage return (cursor to start of line). */ void screen_write_carriagereturn(struct screen_write_ctx *ctx) @@ -1009,6 +1028,18 @@ screen_write_collect_flush(struct screen_write_ctx *ctx) u_int y, cx, cy; struct tty_ctx ttyctx; + if (ctx->scrolled != 0) { + log_debug("%s: scrolled %u (region %u-%u)", __func__, + ctx->scrolled, s->rupper, s->rlower); + if (ctx->scrolled > s->rlower - s->rupper + 1) + ctx->scrolled = s->rlower - s->rupper + 1; + + screen_write_initctx(ctx, &ttyctx); + ttyctx.num = ctx->scrolled; + tty_write(tty_cmd_scrollup, &ttyctx); + } + ctx->scrolled = 0; + cx = s->cx; cy = s->cy; for (y = 0; y < screen_size_y(s); y++) { TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) { diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index a982c97a4a7..3288163a5d2 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.720 2017/02/08 16:45:18 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.721 2017/02/08 17:31:09 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -241,6 +241,7 @@ enum tty_code_code { TTYC_ICH1, /* insert_character, ic */ TTYC_IL, /* parm_insert_line, IL */ TTYC_IL1, /* insert_line, il */ + TTYC_INDN, /* parm_index, indn */ TTYC_INVIS, /* enter_secure_mode, mk */ TTYC_IS1, /* init_1string, i1 */ TTYC_IS2, /* init_2string, i2 */ @@ -663,6 +664,7 @@ struct screen_write_ctx { struct screen_write_collect_item *item; struct screen_write_collect_line *list; + u_int scrolled; u_int cells; u_int written; @@ -1658,6 +1660,7 @@ void tty_cmd_erasecharacter(struct tty *, const struct tty_ctx *); void tty_cmd_insertcharacter(struct tty *, const struct tty_ctx *); void tty_cmd_insertline(struct tty *, const struct tty_ctx *); void tty_cmd_linefeed(struct tty *, const struct tty_ctx *); +void tty_cmd_scrollup(struct tty *, const struct tty_ctx *); 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 *); @@ -1984,6 +1987,7 @@ void screen_write_cursormove(struct screen_write_ctx *, u_int, u_int); void screen_write_reverseindex(struct screen_write_ctx *); void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int); void screen_write_linefeed(struct screen_write_ctx *, int); +void screen_write_scrollup(struct screen_write_ctx *, u_int); void screen_write_carriagereturn(struct screen_write_ctx *); void screen_write_clearendofscreen(struct screen_write_ctx *, u_int); void screen_write_clearstartofscreen(struct screen_write_ctx *, u_int); diff --git a/usr.bin/tmux/tty-term.c b/usr.bin/tmux/tty-term.c index c85d050b385..227d4d2ef49 100644 --- a/usr.bin/tmux/tty-term.c +++ b/usr.bin/tmux/tty-term.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-term.c,v 1.50 2017/02/06 22:05:11 nicm Exp $ */ +/* $OpenBSD: tty-term.c,v 1.51 2017/02/08 17:31:09 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -95,6 +95,7 @@ static const struct tty_term_code_entry tty_term_codes[] = { [TTYC_ICH1] = { TTYCODE_STRING, "ich1" }, [TTYC_IL] = { TTYCODE_STRING, "il" }, [TTYC_IL1] = { TTYCODE_STRING, "il1" }, + [TTYC_INDN] = { TTYCODE_STRING, "indn" }, [TTYC_INVIS] = { TTYCODE_STRING, "invis" }, [TTYC_IS1] = { TTYCODE_STRING, "is1" }, [TTYC_IS2] = { TTYCODE_STRING, "is2" }, diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index d06e5dc4a7f..49e68a880a2 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.239 2017/02/08 16:45:18 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.240 2017/02/08 17:31:09 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1021,6 +1021,32 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) tty_putc(tty, '\n'); } +void +tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) +{ + struct window_pane *wp = ctx->wp; + u_int i; + + if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) || + tty_fake_bce(tty, wp, ctx->bg) || + !tty_term_has(tty->term, TTYC_CSR)) { + tty_redraw_region(tty, ctx); + return; + } + + tty_attributes(tty, &grid_default_cell, wp); + + tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); + tty_margin_pane(tty, ctx); + + if (ctx->num == 1 || !tty_term_has(tty->term, TTYC_INDN)) { + tty_cursor(tty, tty->rright, ctx->yoff + tty->rlower); + for (i = 0; i < ctx->num; i++) + tty_putc(tty, '\n'); + } else + tty_putcode1(tty, TTYC_INDN, ctx->num); +} + void tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx) { -- cgit v1.2.3