mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Add support for scroll up escape sequence (CSI S) and use it when
possible instead of sending individual line feeds.
This commit is contained in:
		
							
								
								
									
										5
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								input.c
									
									
									
									
									
								
							@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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" },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								tty.c
									
									
									
									
									
								
							@@ -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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user