From 6ea6d46d0a1b206ece54a05af4f3fe7a3d6fe4cc Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 16 May 2020 15:49:20 +0000 Subject: [PATCH] Store and restore cursor position when copy mode is resized, from Anindya Mukherjee. --- grid.c | 2 +- screen.c | 52 ++++++++++++++++++++++++++------------------------ tmux.h | 3 +-- window-copy.c | 53 +++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 70 insertions(+), 40 deletions(-) diff --git a/grid.c b/grid.c index 81f3709c..2437e2ea 100644 --- a/grid.c +++ b/grid.c @@ -1285,7 +1285,7 @@ grid_reflow(struct grid *gd, u_int sx) /* * If the line is exactly right or the first character is wider - * than the targe width, just move it across unchanged. + * than the target width, just move it across unchanged. */ if (width == sx || first > sx) { grid_reflow_move(target, gl); diff --git a/screen.c b/screen.c index f416ac37..227934dd 100644 --- a/screen.c +++ b/screen.c @@ -49,7 +49,7 @@ struct screen_title_entry { TAILQ_HEAD(screen_titles, screen_title_entry); static void screen_resize_y(struct screen *, u_int, int, u_int *); -static void screen_reflow(struct screen *, u_int, u_int *, u_int *); +static void screen_reflow(struct screen *, u_int, u_int *, u_int *, int); /* Free titles stack. */ static void @@ -220,27 +220,19 @@ screen_pop_title(struct screen *s) } } -/* Resize screen and return cursor position. */ +/* Resize screen with options. */ void screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow, - int eat_empty, u_int *cx, u_int *cy) + int eat_empty, int cursor) { - u_int tcx, tcy; + u_int cx = s->cx, cy = s->grid->hsize + s->cy; if (s->write_list != NULL) screen_write_free_list(s); - if (cx == NULL) - cx = &tcx; - *cx = s->cx; - - if (cy == NULL) - cy = т - *cy = s->grid->hsize + s->cy; - log_debug("%s: new size %ux%u, now %ux%u (cursor %u,%u = %u,%u)", __func__, sx, sy, screen_size_x(s), screen_size_y(s), s->cx, s->cy, - *cx, *cy); + cx, cy); if (sx < 1) sx = 1; @@ -254,20 +246,21 @@ screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow, reflow = 0; if (sy != screen_size_y(s)) - screen_resize_y(s, sy, eat_empty, cy); + screen_resize_y(s, sy, eat_empty, &cy); if (reflow) - screen_reflow(s, sx, cx, cy); + screen_reflow(s, sx, &cx, &cy, cursor); - if (*cy >= s->grid->hsize) { - s->cx = *cx; - s->cy = (*cy) - s->grid->hsize; + if (cy >= s->grid->hsize) { + s->cx = cx; + s->cy = cy - s->grid->hsize; } else { s->cx = 0; s->cy = 0; } + log_debug("%s: cursor finished at %u,%u = %u,%u", __func__, s->cx, - s->cy, *cx, *cy); + s->cy, cx, cy); if (s->write_list != NULL) screen_write_make_list(s); @@ -277,7 +270,7 @@ screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow, void screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) { - screen_resize_cursor(s, sx, sy, reflow, 1, NULL, NULL); + screen_resize_cursor(s, sx, sy, reflow, 1, 1); } static void @@ -525,17 +518,26 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, /* Reflow wrapped lines. */ static void -screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy) +screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor) { u_int wx, wy; - grid_wrap_position(s->grid, *cx, *cy, &wx, &wy); - log_debug("%s: cursor %u,%u is %u,%u", __func__, *cx, *cy, wx, wy); + if (cursor) { + 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_unwrap_position(s->grid, cx, cy, wx, wy); - log_debug("%s: new cursor is %u,%u", __func__, *cx,* cy); + if (cursor) { + grid_unwrap_position(s->grid, cx, cy, wx, wy); + log_debug("%s: new cursor is %u,%u", __func__, *cx, *cy); + } + else { + *cx = 0; + *cy = s->grid->hsize; + } } /* diff --git a/tmux.h b/tmux.h index 3c074519..bd746fe7 100644 --- a/tmux.h +++ b/tmux.h @@ -2529,8 +2529,7 @@ void screen_set_path(struct screen *, const char *); void screen_push_title(struct screen *); void screen_pop_title(struct screen *); void screen_resize(struct screen *, u_int, u_int, int); -void screen_resize_cursor(struct screen *, u_int, u_int, int, int, u_int *, - u_int *); +void screen_resize_cursor(struct screen *, u_int, u_int, int, int, int); void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, u_int, int, struct grid_cell *); void screen_clear_selection(struct screen *); diff --git a/window-copy.c b/window-copy.c index 38e87b67..f500a65e 100644 --- a/window-copy.c +++ b/window-copy.c @@ -306,8 +306,9 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx, u_int *cy, int trim) { struct screen *dst; - u_int sy; const struct grid_line *gl; + u_int sy, wx, wy; + int reflow; dst = xcalloc(1, sizeof *dst); @@ -324,6 +325,12 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx, screen_size_x(src), sy, screen_size_x(hint), screen_hsize(src) + screen_size_y(src)); screen_init(dst, screen_size_x(src), sy, screen_hlimit(src)); + + /* + * Ensure history is on for the backing grid so lines are not deleted + * during resizing. + */ + dst->grid->flags |= GRID_HISTORY; grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); dst->grid->sy = sy - screen_hsize(src); @@ -337,8 +344,19 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx, dst->cy = src->cy; } + if (cx != NULL && cy != NULL) { + *cx = dst->cx; + *cy = screen_hsize(dst) + dst->cy; + reflow = (screen_size_x(hint) != screen_size_x(dst)); + } + else + reflow = 0; + if (reflow) + grid_wrap_position(dst->grid, *cx, *cy, &wx, &wy); screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1, - 0, cx, cy); + 0, 0); + if (reflow) + grid_unwrap_position(dst->grid, cx, cy, wx, wy); return (dst); } @@ -392,13 +410,12 @@ window_copy_init(struct window_mode_entry *wme, data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy, wme->swp != wme->wp); + data->cx = cx; if (cy < screen_hsize(data->backing)) { - data->cx = cx; data->cy = 0; data->oy = screen_hsize(data->backing) - cy; } else { - data->cx = data->backing->cx; - data->cy = data->backing->cy; + data->cy = cy - screen_hsize(data->backing); data->oy = 0; } @@ -731,16 +748,28 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy) { struct window_copy_mode_data *data = wme->data; struct screen *s = &data->screen; + struct grid *gd = data->backing->grid; + u_int cx, cy, wx, wy; + int reflow; screen_resize(s, sx, sy, 0); - screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL); + cx = data->cx; + cy = gd->hsize + data->cy - data->oy; + reflow = (gd->sx != sx); + if (reflow) + grid_wrap_position(gd, cx, cy, &wx, &wy); + screen_resize_cursor(data->backing, sx, sy, 1, 0, 0); + if (reflow) + grid_unwrap_position(gd, &cx, &cy, wx, wy); - if (data->cy > sy - 1) - data->cy = sy - 1; - if (data->cx > sx) - data->cx = sx; - if (data->oy > screen_hsize(data->backing)) - data->oy = screen_hsize(data->backing); + data->cx = cx; + if (cy < gd->hsize) { + data->cy = 0; + data->oy = gd->hsize - cy; + } else { + data->cy = cy - gd->hsize; + data->oy = 0; + } window_copy_size_changed(wme); window_copy_redraw_screen(wme);