summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2019-03-20 19:19:12 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2019-03-20 19:19:12 +0000
commitd78036c7a2473520d65a7069d1cc5152aa160c19 (patch)
treef568d16753508155c8e69a13bf39dda810c798b1 /usr.bin
parentbe1fa2aa9b199c1e2c2d7b3a04c1867f1ffeea4f (diff)
Improve cursor positioning after reflow by storing the position as an
offset into the entire history before reflow and restoring it aftewards.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/tmux/grid.c83
-rw-r--r--usr.bin/tmux/screen.c60
-rw-r--r--usr.bin/tmux/tmux.h10
3 files changed, 80 insertions, 73 deletions
diff --git a/usr.bin/tmux/grid.c b/usr.bin/tmux/grid.c
index a12ba180702..fbbc0712109 100644
--- a/usr.bin/tmux/grid.c
+++ b/usr.bin/tmux/grid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: grid.c,v 1.90 2019/03/18 15:25:36 nicm Exp $ */
+/* $OpenBSD: grid.c,v 1.91 2019/03/20 19:19:11 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1030,7 +1030,7 @@ grid_reflow_move(struct grid *gd, struct grid_line *from)
/* Join line below onto this one. */
static void
grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
- u_int width, u_int *cy, int already)
+ u_int width, int already)
{
struct grid_line *gl, *from = NULL;
struct grid_cell gc;
@@ -1128,11 +1128,7 @@ grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
grid_reflow_dead(&gd->linedata[i]);
}
- /* Adjust cursor and scroll positions. */
- if (*cy > to + lines)
- *cy -= lines;
- else if (*cy > to)
- *cy = to;
+ /* Adjust scroll position. */
if (gd->hscrolled > to + lines)
gd->hscrolled -= lines;
else if (gd->hscrolled > to)
@@ -1142,7 +1138,7 @@ grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
/* Split this line into several new ones */
static void
grid_reflow_split(struct grid *target, struct grid *gd, u_int sx, u_int yy,
- u_int at, u_int *cy)
+ u_int at)
{
struct grid_line *gl = &gd->linedata[yy], *first;
struct grid_cell gc;
@@ -1195,9 +1191,7 @@ grid_reflow_split(struct grid *target, struct grid *gd, u_int sx, u_int yy,
memcpy(first, gl, sizeof *first);
grid_reflow_dead(gl);
- /* Adjust the cursor and scroll positions. */
- if (yy <= *cy)
- (*cy) += lines - 1;
+ /* Adjust the scroll position. */
if (yy <= gd->hscrolled)
gd->hscrolled += lines - 1;
@@ -1206,24 +1200,17 @@ grid_reflow_split(struct grid *target, struct grid *gd, u_int sx, u_int yy,
* in the last new line, try to join with the next lines.
*/
if (width < sx && (flags & GRID_LINE_WRAPPED))
- grid_reflow_join(target, gd, sx, yy, width, cy, 1);
+ grid_reflow_join(target, gd, sx, yy, width, 1);
}
/* Reflow lines on grid to new width. */
void
-grid_reflow(struct grid *gd, u_int sx, u_int *cursor)
+grid_reflow(struct grid *gd, u_int sx)
{
struct grid *target;
struct grid_line *gl;
struct grid_cell gc;
- u_int yy, cy, width, i, at, first;
- struct timeval start, tv;
-
- gettimeofday(&start, NULL);
-
- log_debug("%s: %u lines, new width %u", __func__, gd->hsize + gd->sy,
- sx);
- cy = gd->hsize + (*cursor);
+ u_int yy, width, i, at, first;
/*
* Create a destination grid. This is just used as a container for the
@@ -1277,7 +1264,7 @@ grid_reflow(struct grid *gd, u_int sx, u_int *cursor)
* it was previously wrapped.
*/
if (width > sx) {
- grid_reflow_split(target, gd, sx, yy, at, &cy);
+ grid_reflow_split(target, gd, sx, yy, at);
continue;
}
@@ -1286,7 +1273,7 @@ grid_reflow(struct grid *gd, u_int sx, u_int *cursor)
* of the next line.
*/
if (gl->flags & GRID_LINE_WRAPPED)
- grid_reflow_join(target, gd, sx, yy, width, &cy, 0);
+ grid_reflow_join(target, gd, sx, yy, width, 0);
else
grid_reflow_move(target, gl);
}
@@ -1300,20 +1287,42 @@ grid_reflow(struct grid *gd, u_int sx, u_int *cursor)
free(gd->linedata);
gd->linedata = target->linedata;
free(target);
+}
- /*
- * Update scrolled and cursor positions.
- */
- if (gd->hscrolled > gd->hsize)
- gd->hscrolled = gd->hsize;
- if (cy < gd->hsize)
- *cursor = 0;
- else
- *cursor = cy - gd->hsize;
+/* 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)
+{
+ u_int yy, offset = 0;
+
+ if (py > gd->hsize + gd->sy - 1) {
+ px = UINT_MAX;
+ py = gd->hsize + gd->sy - 1;
+ }
- gettimeofday(&tv, NULL);
- timersub(&tv, &start, &tv);
- log_debug("%s: now %u lines (in %llu.%06u seconds)", __func__,
- gd->hsize + gd->sy, (unsigned long long)tv.tv_sec,
- (u_int)tv.tv_usec);
+ 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);
+}
+
+/* Convert offset from the start of the grid to point position. */
+void
+grid_from_offset(struct grid *gd, u_int offset, u_int *px, u_int *py)
+{
+ u_int yy;
+
+ *px = *py = 0;
+
+ for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
+ if (offset <= gd->linedata[yy].cellused)
+ break;
+ offset -= gd->linedata[yy].cellused;
+ }
+ if (offset < gd->linedata[yy].cellused)
+ *px = offset;
+ else
+ *px = gd->linedata[yy].cellused;
+ *py = yy;
}
diff --git a/usr.bin/tmux/screen.c b/usr.bin/tmux/screen.c
index 6fa6cd4eb7d..14872531dba 100644
--- a/usr.bin/tmux/screen.c
+++ b/usr.bin/tmux/screen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: screen.c,v 1.53 2019/01/15 09:56:31 nicm Exp $ */
+/* $OpenBSD: screen.c,v 1.54 2019/03/20 19:19:11 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -48,7 +48,6 @@ struct screen_title_entry {
};
TAILQ_HEAD(screen_titles, screen_title_entry);
-static void screen_resize_x(struct screen *, u_int);
static void screen_resize_y(struct screen *, u_int);
static void screen_reflow(struct screen *, u_int);
@@ -207,13 +206,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
sy = 1;
if (sx != screen_size_x(s)) {
- screen_resize_x(s, sx);
-
- /*
- * It is unclear what should happen to tabs on resize. xterm
- * seems to try and maintain them, rxvt resets them. Resetting
- * is simpler and more reliable so let's do that.
- */
+ s->grid->sx = sx;
screen_reset_tabs(s);
} else
reflow = 0;
@@ -226,28 +219,6 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
}
static void
-screen_resize_x(struct screen *s, u_int sx)
-{
- struct grid *gd = s->grid;
-
- if (sx == 0)
- fatalx("zero size");
-
- /*
- * Treat resizing horizontally simply: just ensure the cursor is
- * on-screen and change the size. Don't bother to truncate any lines -
- * then the data should be accessible if the size is then increased.
- *
- * The only potential wrinkle is if UTF-8 double-width characters are
- * left in the last column, but UTF-8 terminals should deal with this
- * sanely.
- */
- if (s->cx >= sx)
- s->cx = sx - 1;
- gd->sx = sx;
-}
-
-static void
screen_resize_y(struct screen *s, u_int sy)
{
struct grid *gd = s->grid;
@@ -493,5 +464,30 @@ screen_select_cell(struct screen *s, struct grid_cell *dst,
static void
screen_reflow(struct screen *s, u_int new_x)
{
- grid_reflow(s->grid, new_x, &s->cy);
+ u_int offset, cx = s->cx, cy = s->grid->hsize + s->cy;
+ 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_reflow(s->grid, new_x);
+
+ grid_from_offset(s->grid, offset, &cx, &cy);
+ log_debug("%s: new cursor is %u,%u", __func__, cx, cy);
+
+ if (cy >= s->grid->hsize) {
+ s->cx = cx;
+ s->cy = cy - s->grid->hsize;
+ } else {
+ s->cx = 0;
+ s->cy = 0;
+ }
+
+ gettimeofday(&tv, NULL);
+ timersub(&tv, &start, &tv);
+
+ log_debug("%s: reflow took %llu.%06u seconds", __func__,
+ (unsigned long long)tv.tv_sec, (u_int)tv.tv_usec);
}
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 6ce73b24bfb..944ab89aeaf 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.875 2019/03/18 21:46:02 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.876 2019/03/20 19:19:11 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2088,6 +2088,8 @@ void grid_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
void grid_set_cells(struct grid *, u_int, u_int, const struct grid_cell *,
const char *, size_t);
+struct grid_line *grid_get_line(struct grid *, u_int);
+void grid_adjust_lines(struct grid *, u_int);
void grid_clear(struct grid *, u_int, u_int, u_int, u_int, u_int);
void grid_clear_lines(struct grid *, u_int, u_int, u_int);
void grid_move_lines(struct grid *, u_int, u_int, u_int, u_int);
@@ -2096,9 +2098,9 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int,
struct grid_cell **, int, int, int);
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
u_int);
-void grid_reflow(struct grid *, u_int, u_int *);
-struct grid_line *grid_get_line(struct grid *, u_int);
-void grid_adjust_lines(struct grid *, 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 *);
/* grid-view.c */
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);