We are going to need the updated screen data for emulating the scroll region,

which may involve changing the cursor position; however, the old (before
redraw) cursor position is necessary for writing to the tty. So, save it before
doing the redraw then update the internal screen then update the tty.

Not sure I like this solution but it does the job for now.
This commit is contained in:
Nicholas Marriott 2009-02-11 17:04:39 +00:00
parent 91c9d95279
commit 514fe11727
4 changed files with 124 additions and 79 deletions

View File

@ -1,4 +1,4 @@
/* $Id: screen-redraw.c,v 1.21 2009-02-11 06:50:15 nicm Exp $ */
/* $Id: screen-redraw.c,v 1.22 2009-02-11 17:04:38 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -135,15 +135,13 @@ screen_redraw_line(struct client *c, struct screen *s, u_int oy, u_int py)
if (sx > c->sx)
sx = c->sx;
for (i = 0; i < sx; i++) {
s->cx = i;
s->cy = py;
gc = grid_view_peek_cell(s->grid, i, py);
tty_cursor(&c->tty, i, py, oy);
if (screen_check_selection(s, i, py)) {
memcpy(&tc, &s->sel.cell, sizeof tc);
tc.data = gc->data;
tty_cell(&c->tty, s, oy, &tc);
tty_cell(&c->tty, &tc);
} else
tty_cell(&c->tty, s, oy, gc);
tty_cell(&c->tty, gc);
}
}

View File

@ -1,4 +1,4 @@
/* $Id: screen-write.c,v 1.32 2009-02-11 06:31:09 nicm Exp $ */
/* $Id: screen-write.c,v 1.33 2009-02-11 17:04:39 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -22,6 +22,8 @@
#include "tmux.h"
void screen_write_save(struct screen_write_ctx *);
/* Initialise writing with a window. */
void
screen_write_start(
@ -95,6 +97,19 @@ screen_write_copy(struct screen_write_ctx *ctx,
}
}
/* Save cursor and region positions. */
void
screen_write_save(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
s->old_cx = s->cx;
s->old_cy = s->cy;
s->old_rlower = s->rlower;
s->old_rupper = s->rupper;
}
/* Cursor up by ny. */
void
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
@ -177,10 +192,12 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0)
return;
tty_write_cmd(ctx->wp, TTY_INSERTCHARACTER, nx);
screen_write_save(ctx);
if (s->cx <= screen_size_x(s) - 1)
grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
tty_write_cmd(ctx->wp, TTY_INSERTCHARACTER, nx);
}
/* Delete nx characters. */
@ -197,10 +214,12 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0)
return;
tty_write_cmd(ctx->wp, TTY_DELETECHARACTER, nx);
screen_write_save(ctx);
if (s->cx <= screen_size_x(s) - 1)
grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
tty_write_cmd(ctx->wp, TTY_DELETECHARACTER, nx);
}
/* Insert ny lines. */
@ -217,7 +236,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
tty_write_cmd(ctx->wp, TTY_INSERTLINE, ny);
screen_write_save(ctx);
if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_insert_lines(s->grid, s->cy, ny);
@ -225,6 +244,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
grid_view_insert_lines_region(
s->grid, s->rupper, s->rlower, s->cy, ny);
}
tty_write_cmd(ctx->wp, TTY_INSERTLINE, ny);
}
/* Delete ny lines. */
@ -241,7 +262,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
tty_write_cmd(ctx->wp, TTY_DELETELINE, ny);
screen_write_save(ctx);
if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_delete_lines(s->grid, s->cy, ny);
@ -249,6 +270,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
grid_view_delete_lines_region(
s->grid, s->rupper, s->rlower, s->cy, ny);
}
tty_write_cmd(ctx->wp, TTY_DELETELINE, ny);
}
/* Clear line at cursor. */
@ -257,9 +280,11 @@ screen_write_clearline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
tty_write_cmd(ctx->wp, TTY_CLEARLINE);
screen_write_save(ctx);
grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
tty_write_cmd(ctx->wp, TTY_CLEARLINE);
}
/* Clear to end of line from cursor. */
@ -269,12 +294,14 @@ screen_write_clearendofline(struct screen_write_ctx *ctx)
struct screen *s = ctx->s;
u_int sx;
sx = screen_size_x(s);
screen_write_save(ctx);
tty_write_cmd(ctx->wp, TTY_CLEARENDOFLINE);
sx = screen_size_x(s);
if (s->cx <= sx - 1)
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
tty_write_cmd(ctx->wp, TTY_CLEARENDOFLINE);
}
/* Clear to start of line from cursor. */
@ -284,14 +311,16 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
struct screen *s = ctx->s;
u_int sx;
sx = screen_size_x(s);
screen_write_save(ctx);
tty_write_cmd(ctx->wp, TTY_CLEARSTARTOFLINE);
sx = screen_size_x(s);
if (s->cx > sx - 1)
grid_view_clear(s->grid, 0, s->cy, sx, 1);
else
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
tty_write_cmd(ctx->wp, TTY_CLEARSTARTOFLINE);
}
/* Move cursor to px,py. */
@ -327,12 +356,14 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
tty_write_cmd(ctx->wp, TTY_REVERSEINDEX);
screen_write_save(ctx);
if (s->cy == s->rupper)
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
else if (s->cy > 0)
s->cy--;
tty_write_cmd(ctx->wp, TTY_REVERSEINDEX);
}
/* Set scroll region. */
@ -387,12 +418,14 @@ screen_write_linefeed(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
tty_write_cmd(ctx->wp, TTY_LINEFEED);
screen_write_save(ctx);
if (s->cy == s->rlower)
grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
else if (s->cy < screen_size_y(s) - 1)
s->cy++;
tty_write_cmd(ctx->wp, TTY_LINEFEED);
}
/* Carriage return (cursor to start of line). */
@ -435,14 +468,16 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
struct screen *s = ctx->s;
u_int sx, sy;
screen_write_save(ctx);
sx = screen_size_x(s);
sy = screen_size_y(s);
tty_write_cmd(ctx->wp, TTY_CLEARENDOFSCREEN);
if (s->cx <= sx - 1)
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
tty_write_cmd(ctx->wp, TTY_CLEARENDOFSCREEN);
}
/* Clear to start of screen. */
@ -452,9 +487,9 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
struct screen *s = ctx->s;
u_int sx;
sx = screen_size_x(s);
screen_write_save(ctx);
tty_write_cmd(ctx->wp, TTY_CLEARSTARTOFSCREEN);
sx = screen_size_x(s);
if (s->cy > 0)
grid_view_clear(s->grid, 0, 0, sx, s->cy - 1);
@ -462,6 +497,8 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
grid_view_clear(s->grid, 0, s->cy, sx, 1);
else
grid_view_clear(s->grid, 0, s->cy, s->cx, 1);
tty_write_cmd(ctx->wp, TTY_CLEARSTARTOFSCREEN);
}
/* Clear entire screen. */
@ -470,9 +507,11 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
tty_write_cmd(ctx->wp, TTY_CLEARSCREEN);
screen_write_save(ctx);
grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
tty_write_cmd(ctx->wp, TTY_CLEARSCREEN);
}
/* Write cell data. */
@ -572,15 +611,18 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
ic->flags |= GRID_FLAG_PADDING;
}
/* Write the actual cell. */
/* Set the cell. */
grid_view_set_cell(gd, s->cx, s->cy, gc);
/* Move the cursor. */
screen_write_save(ctx);
s->cx += width;
/* Draw to the screen if necessary. */
if (screen_check_selection(s, s->cx, s->cy)) {
memcpy(&tc, &s->sel.cell, sizeof tc);
tc.data = gc->data;
tty_write_cmd(ctx->wp, TTY_CELL, &tc);
} else
tty_write_cmd(ctx->wp, TTY_CELL, gc);
/* Move the cursor. */
s->cx += width;
}

13
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.266 2009-02-11 07:02:34 nicm Exp $ */
/* $Id: tmux.h,v 1.267 2009-02-11 17:04:39 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -496,9 +496,15 @@ struct screen {
u_int cx; /* cursor x */
u_int cy; /* cursor y */
u_int old_cx;
u_int old_cy;
u_int rupper; /* scroll region top */
u_int rlower; /* scroll region bottom */
u_int old_rupper;
u_int old_rlower;
int mode;
struct screen_sel sel;
@ -1011,9 +1017,10 @@ void options_set_number(struct options *, const char *, long long);
long long options_get_number(struct options *, const char *);
/* tty.c */
void tty_reset(struct tty *);
void tty_region(struct tty *, u_int, u_int, u_int);
void tty_cursor(struct tty *, u_int, u_int, u_int);
void tty_cell(struct tty *,
struct screen *, u_int, const struct grid_cell *);
void tty_cell(struct tty *, const struct grid_cell *);
void tty_putcode(struct tty *, enum tty_code_code);
void tty_putcode1(struct tty *, enum tty_code_code, int);
void tty_putcode2(struct tty *, enum tty_code_code, int, int);

96
tty.c
View File

@ -1,4 +1,4 @@
/* $Id: tty.c,v 1.67 2009-02-11 07:02:34 nicm Exp $ */
/* $Id: tty.c,v 1.68 2009-02-11 17:04:39 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -35,8 +35,6 @@ void tty_emulate_repeat(
void tty_raw(struct tty *, const char *);
void tty_reset(struct tty *);
void tty_region(struct tty *, struct screen *, u_int);
void tty_attributes(struct tty *, const struct grid_cell *);
void tty_attributes_fg(struct tty *, const struct grid_cell *);
void tty_attributes_bg(struct tty *, const struct grid_cell *);
@ -399,7 +397,7 @@ tty_cmd_insertcharacter(struct tty *tty, struct window_pane *wp, va_list ap)
ua = va_arg(ap, u_int);
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
if (tty_term_has(tty->term, TTYC_ICH) ||
tty_term_has(tty->term, TTYC_ICH1))
@ -409,7 +407,7 @@ tty_cmd_insertcharacter(struct tty *tty, struct window_pane *wp, va_list ap)
while (ua-- > 0)
tty_putc(tty, ' ');
tty_putcode(tty, TTYC_RMIR);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, s->old_cx);
}
}
@ -422,7 +420,7 @@ tty_cmd_deletecharacter(struct tty *tty, struct window_pane *wp, va_list ap)
ua = va_arg(ap, u_int);
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_emulate_repeat(tty, TTYC_DCH, TTYC_DCH1, ua);
}
@ -436,8 +434,8 @@ tty_cmd_insertline(struct tty *tty, struct window_pane *wp, va_list ap)
ua = va_arg(ap, u_int);
tty_reset(tty);
tty_region(tty, s, wp->yoff);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_region(tty, s->old_rupper, s->old_rlower, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_emulate_repeat(tty, TTYC_IL, TTYC_IL1, ua);
}
@ -451,8 +449,8 @@ tty_cmd_deleteline(struct tty *tty, struct window_pane *wp, va_list ap)
ua = va_arg(ap, u_int);
tty_reset(tty);
tty_region(tty, s, wp->yoff);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_region(tty, s->old_rupper, s->old_rlower, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_emulate_repeat(tty, TTYC_DL, TTYC_DL1, ua);
}
@ -464,17 +462,17 @@ tty_cmd_clearline(struct tty *tty, struct window_pane *wp, unused va_list ap)
u_int i;
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
if (tty_term_has(tty->term, TTYC_EL)) {
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, 0);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, 0);
tty_putcode(tty, TTYC_EL);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, s->old_cx);
} else {
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, 0);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, 0);
for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, s->old_cx);
}
}
@ -486,15 +484,15 @@ tty_cmd_clearendofline(
u_int i;
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
if (tty_term_has(tty->term, TTYC_EL))
tty_putcode(tty, TTYC_EL);
else {
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, s->cx);
for (i = s->cx; i < screen_size_x(s); i++)
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, s->old_cx);
for (i = s->old_cx; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, s->old_cx);
}
}
@ -506,15 +504,15 @@ tty_cmd_clearstartofline(
u_int i;
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
if (tty_term_has(tty->term, TTYC_EL1))
tty_putcode(tty, TTYC_EL1);
else {
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, 0);
for (i = 0; i < s->cx + 1; i++)
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, 0);
for (i = 0; i < s->old_cx + 1; i++)
tty_putc(tty, ' ');
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, wp->yoff + s->old_cy, s->old_cx);
}
}
@ -524,8 +522,8 @@ tty_cmd_reverseindex(struct tty *tty, struct window_pane *wp, unused va_list ap)
struct screen *s = wp->screen;
tty_reset(tty);
tty_region(tty, s, wp->yoff);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_region(tty, s->old_rupper, s->old_rlower, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_putcode(tty, TTYC_RI);
}
@ -536,8 +534,8 @@ tty_cmd_linefeed(struct tty *tty, struct window_pane *wp, unused va_list ap)
struct screen *s = wp->screen;
tty_reset(tty);
tty_region(tty, s, wp->yoff);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_region(tty, s->old_rupper, s->old_rlower, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_putc(tty, '\n');
tty->cy++;
@ -553,23 +551,23 @@ tty_cmd_clearendofscreen(
oy = wp->yoff;
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, wp->yoff);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
if (tty_term_has(tty->term, TTYC_EL)) {
for (i = oy + s->cy; i < oy + screen_size_y(s); i++) {
for (i = oy + s->old_cy; i < oy + screen_size_y(s); i++) {
tty_putcode(tty, TTYC_EL);
if (i != screen_size_y(s) - 1)
tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1);
}
} else {
for (i = s->cx; i < screen_size_y(s); i++)
for (i = s->old_cx; i < screen_size_y(s); i++)
tty_putc(tty, ' ');
for (j = oy + s->cy; j < oy + screen_size_y(s); j++) {
for (j = oy + s->old_cy; j < oy + screen_size_y(s); j++) {
for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
}
}
tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, oy + s->old_cy, s->old_cx);
}
void
@ -582,24 +580,24 @@ tty_cmd_clearstartofscreen(
oy = wp->yoff;
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, oy);
tty_cursor(tty, s->old_cx, s->old_cy, oy);
tty_putcode2(tty, TTYC_CUP, oy, 0);
if (tty_term_has(tty->term, TTYC_EL)) {
for (i = 0; i < oy + s->cy; i++) {
for (i = 0; i < oy + s->old_cy; i++) {
tty_putcode(tty, TTYC_EL);
tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1);
}
tty_putcode2(tty, TTYC_CUP, oy + s->cy, 0);
tty_putcode2(tty, TTYC_CUP, oy + s->old_cy, 0);
} else {
for (j = 0; j < oy + s->cy; j++) {
for (j = 0; j < oy + s->old_cy; j++) {
for (i = 0; i < screen_size_x(s); i++)
tty_putc(tty, ' ');
}
}
for (i = 0; i < s->cx; i++)
for (i = 0; i < s->old_cx; i++)
tty_putc(tty, ' ');
tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, oy + s->old_cy, s->old_cx);
}
void
@ -612,7 +610,7 @@ tty_cmd_clearscreen(
oy = wp->yoff;
tty_reset(tty);
tty_cursor(tty, s->cx, s->cy, oy);
tty_cursor(tty, s->old_cx, s->old_cy, oy);
tty_putcode2(tty, TTYC_CUP, oy, 0);
if (tty_term_has(tty->term, TTYC_EL)) {
@ -627,28 +625,28 @@ tty_cmd_clearscreen(
tty_putc(tty, ' ');
}
}
tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx);
tty_putcode2(tty, TTYC_CUP, oy + s->old_cy, s->old_cx);
}
void
tty_cmd_cell(struct tty *tty, struct window_pane *wp, va_list ap)
{
struct screen *s = wp->screen;
struct grid_cell *gc;
gc = va_arg(ap, struct grid_cell *);
tty_cell(tty, wp->screen, wp->yoff, gc);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_cell(tty, gc);
}
void
tty_cell(
struct tty *tty, struct screen *s, u_int oy, const struct grid_cell *gc)
tty_cell(struct tty *tty, const struct grid_cell *gc)
{
u_int i, width;
u_char out[4];
tty_cursor(tty, s->cx, s->cy, oy);
/* If this is a padding character, do nothing. */
if (gc->flags & GRID_FLAG_PADDING)
return;
@ -697,11 +695,11 @@ tty_reset(struct tty *tty)
}
void
tty_region(struct tty *tty, struct screen *s, u_int oy)
tty_region(struct tty *tty, u_int rupper, u_int rlower, u_int oy)
{
if (tty->rlower != oy + s->rlower || tty->rupper != oy + s->rupper) {
tty->rlower = oy + s->rlower;
tty->rupper = oy + s->rupper;
if (tty->rlower != oy + rlower || tty->rupper != oy + rupper) {
tty->rlower = oy + rlower;
tty->rupper = oy + rupper;
tty->cx = 0;
tty->cy = 0;
tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower);