diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2019-04-02 08:45:33 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2019-04-02 08:45:33 +0000 |
commit | 5ea38ce071eefcbbe25b2e24977eb1cd1c810c33 (patch) | |
tree | 27ba07e9dd1738c5455ad28b9d03986330955c75 /usr.bin | |
parent | 45df6659c1fb4e7220083ed979a7903080b2d308 (diff) |
Store and restore cursor across reflow by working out a position based
on unwrapped lines, rather than a grid offset. Fixes problems reported
by Thomas Sattler and Paul de Weerd.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/grid.c | 73 | ||||
-rw-r--r-- | usr.bin/tmux/screen.c | 10 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 6 |
3 files changed, 55 insertions, 34 deletions
diff --git a/usr.bin/tmux/grid.c b/usr.bin/tmux/grid.c index e4edba4367b..47c5ded3f96 100644 --- a/usr.bin/tmux/grid.c +++ b/usr.bin/tmux/grid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: grid.c,v 1.92 2019/04/01 19:33:38 nicm Exp $ */ +/* $OpenBSD: grid.c,v 1.93 2019/04/02 08:45:32 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -1291,40 +1291,61 @@ grid_reflow(struct grid *gd, u_int sx) free(target); } -/* Convert point position to offset from the start of the grid. */ -u_int -grid_to_offset(struct grid *gd, u_int px, u_int py) +/* Convert to position based on wrapped lines. */ +void +grid_wrap_position(struct grid *gd, u_int px, u_int py, u_int *wx, u_int *wy) { - u_int yy, offset = 0; - - if (py > gd->hsize + gd->sy - 1) { - px = UINT_MAX; - py = gd->hsize + gd->sy - 1; + u_int ax = 0, ay = 0, yy; + + for (yy = 0; yy < py; yy++) { + if (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + ax += gd->linedata[yy].cellused; + else { + ax = 0; + ay++; + } } - - for (yy = 0; yy < py; yy++) - offset += gd->linedata[yy].cellused; - if (px > gd->linedata[yy].cellused) - px = gd->linedata[yy].cellused; - return (offset + px); + if (px >= gd->linedata[yy].cellused) + ax = UINT_MAX; + else + ax += px; + *wx = ax; + *wy = ay; } -/* Convert offset from the start of the grid to point position. */ +/* Convert position based on wrapped lines back. */ void -grid_from_offset(struct grid *gd, u_int offset, u_int *px, u_int *py) +grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy) { - u_int yy; - - *px = *py = 0; + u_int yy, ax = 0, ay = 0; for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) { - if (offset <= gd->linedata[yy].cellused) + if (ay == wy) break; - offset -= gd->linedata[yy].cellused; + if (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + ax += gd->linedata[yy].cellused; + else { + ax = 0; + ay++; + } } - if (offset < gd->linedata[yy].cellused) - *px = offset; - else - *px = gd->linedata[yy].cellused; + + /* + * yy is now 0 on the unwrapped line which contains wx. Walk forwards + * until we find the end or the line now containing wx. + */ + if (wx == UINT_MAX) { + while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + yy++; + wx = gd->linedata[yy].cellused; + } else { + while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) { + if (wx < gd->linedata[yy].cellused) + break; + wx -= gd->linedata[yy].cellused; + yy++; + } + } + *px = wx; *py = yy; } diff --git a/usr.bin/tmux/screen.c b/usr.bin/tmux/screen.c index 14872531dba..a0bb5bb639e 100644 --- a/usr.bin/tmux/screen.c +++ b/usr.bin/tmux/screen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen.c,v 1.54 2019/03/20 19:19:11 nicm Exp $ */ +/* $OpenBSD: screen.c,v 1.55 2019/04/02 08:45:32 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -464,17 +464,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, static void screen_reflow(struct screen *s, u_int new_x) { - u_int offset, cx = s->cx, cy = s->grid->hsize + s->cy; + u_int cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy; struct timeval start, tv; gettimeofday(&start, NULL); - offset = grid_to_offset(s->grid, cx, cy); - log_debug("%s: cursor %u,%u offset is %u", __func__, cx, cy, offset); + grid_wrap_position(s->grid, cx, cy, &wx, &wy); + log_debug("%s: cursor %u,%u is %u,%u", __func__, cx, cy, wx, wy); grid_reflow(s->grid, new_x); - grid_from_offset(s->grid, offset, &cx, &cy); + grid_unwrap_position(s->grid, &cx, &cy, wx, wy); log_debug("%s: new cursor is %u,%u", __func__, cx, cy); if (cy >= s->grid->hsize) { diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 86f5a58b8f6..750ac755722 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.877 2019/03/25 18:59:55 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.878 2019/04/02 08:45:32 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -2101,8 +2101,8 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int, void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, u_int); void grid_reflow(struct grid *, u_int); -u_int grid_to_offset(struct grid *, u_int, u_int); -void grid_from_offset(struct grid *, u_int, u_int *, u_int *); +void grid_wrap_position(struct grid *, u_int, u_int, u_int *, u_int *); +void grid_unwrap_position(struct grid *, u_int *, u_int *, u_int, u_int); /* grid-view.c */ void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *); |