diff --git a/screen.c b/screen.c index 6fa0fe11..ff8b1d2e 100644 --- a/screen.c +++ b/screen.c @@ -48,9 +48,8 @@ struct screen_title_entry { }; TAILQ_HEAD(screen_titles, screen_title_entry); -static void screen_resize_y(struct screen *, u_int); - -static void screen_reflow(struct screen *, u_int); +static void screen_resize_y(struct screen *, u_int, int); +static void screen_reflow(struct screen *, u_int, u_int *, u_int *); /* Free titles stack. */ static void @@ -216,10 +215,23 @@ screen_pop_title(struct screen *s) } } -/* Resize screen. */ +/* Resize screen and return cursor position. */ void -screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) +screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow, + int eat_empty, u_int *cx, u_int *cy) { + u_int tcx, tcy; + + if (cx == NULL) + cx = &tcx; + *cx = s->cx; + + if (cy == NULL) + cy = т + *cy = s->grid->hsize + s->cy; + + log_debug("%s: start %u,%u (%u,%u)", __func__, s->cx, s->cy, *cx, *cy); + if (sx < 1) sx = 1; if (sy < 1) @@ -232,14 +244,30 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) reflow = 0; if (sy != screen_size_y(s)) - screen_resize_y(s, sy); + screen_resize_y(s, sy, eat_empty); if (reflow) - screen_reflow(s, sx); + screen_reflow(s, sx, cx, cy); + + if (*cy >= s->grid->hsize) { + s->cx = *cx; + s->cy = (*cy) - s->grid->hsize; + } else { + s->cx = 0; + s->cy = 0; + } + log_debug("%s: finish %u,%u (%u,%u)", __func__, s->cx, s->cy, *cx, *cy); +} + +/* Resize screen. */ +void +screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) +{ + screen_resize_cursor(s, sx, sy, reflow, 1, NULL, NULL); } static void -screen_resize_y(struct screen *s, u_int sy) +screen_resize_y(struct screen *s, u_int sy, int eat_empty) { struct grid *gd = s->grid; u_int needed, available, oldy, i; @@ -264,14 +292,16 @@ screen_resize_y(struct screen *s, u_int sy) needed = oldy - sy; /* Delete as many lines as possible from the bottom. */ - available = oldy - 1 - s->cy; - if (available > 0) { - if (available > needed) - available = needed; - grid_view_delete_lines(gd, oldy - available, available, - 8); + if (eat_empty) { + available = oldy - 1 - s->cy; + if (available > 0) { + if (available > needed) + available = needed; + grid_view_delete_lines(gd, oldy - available, + available, 8); + } + needed -= available; } - needed -= available; /* * Now just increase the history size, if possible, to take @@ -287,7 +317,6 @@ screen_resize_y(struct screen *s, u_int sy) available = needed; grid_view_delete_lines(gd, 0, available, 8); } - s->cy -= needed; } /* Resize line array. */ @@ -307,7 +336,6 @@ screen_resize_y(struct screen *s, u_int sy) available = needed; gd->hscrolled -= available; gd->hsize -= available; - s->cy += available; } else available = 0; needed -= available; @@ -482,25 +510,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, /* Reflow wrapped lines. */ static void -screen_reflow(struct screen *s, u_int new_x) +screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy) { - u_int cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy; + 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); + 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 (cy >= s->grid->hsize) { - s->cx = cx; - s->cy = cy - s->grid->hsize; - } else { - s->cx = 0; - s->cy = 0; - } + grid_unwrap_position(s->grid, cx, cy, wx, wy); + log_debug("%s: new cursor is %u,%u", __func__, *cx,* cy); } /* diff --git a/tmux.h b/tmux.h index 260891b2..73b6b941 100644 --- a/tmux.h +++ b/tmux.h @@ -2437,6 +2437,8 @@ 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_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 f6f29f9a..2b42eb2a 100644 --- a/window-copy.c +++ b/window-copy.c @@ -298,30 +298,33 @@ window_copy_scroll_timer(__unused int fd, __unused short events, void *arg) } static struct screen * -window_copy_clone_screen(struct screen *src, struct screen *hint) +window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx, + u_int *cy) { - struct screen *dst; - struct screen_write_ctx ctx; - u_int dy, sy; + struct screen *dst; + u_int sy; + const struct grid_line *gl; dst = xcalloc(1, sizeof *dst); sy = screen_hsize(src) + screen_size_y(src); - if (screen_size_y(hint) > sy) - dy = screen_size_y(hint); - else - dy = sy; - screen_init(dst, screen_size_x(src), dy, src->grid->hlimit); - - grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); - if (screen_size_y(hint) < sy) { - dst->grid->sy = screen_size_y(hint); - dst->grid->hsize = sy - screen_size_y(hint); + while (sy > screen_hsize(src)) { + gl = grid_peek_line(src->grid, sy - 1); + if (gl->cellused != 0) + break; + sy--; } + screen_init(dst, screen_size_x(src), sy, screen_hlimit(src)); + grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); - screen_write_start(&ctx, NULL, dst); - screen_write_cursormove(&ctx, 0, dst->grid->sy + sy - dy - 1, 0); - screen_write_stop(&ctx); + dst->grid->sy = sy - screen_hsize(src); + dst->grid->hsize = screen_hsize(src); + dst->grid->hscrolled = src->grid->hscrolled; + dst->cx = src->cx; + dst->cy = src->cy; + + screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1, + 0, cx, cy); return (dst); } @@ -370,22 +373,22 @@ window_copy_init(struct window_mode_entry *wme, { struct window_pane *wp = wme->swp; struct window_copy_mode_data *data; + struct screen *base = &wp->base; struct screen_write_ctx ctx; - u_int i; + u_int i, cx, cy; data = window_copy_common_init(wme); - data->backing = window_copy_clone_screen(&wp->base, &data->screen); + data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy); - data->cx = wp->base.cx; - if (data->cx > screen_size_x(&data->screen) - 1) - data->cx = screen_size_x(&data->screen) - 1; - - data->cy = screen_hsize(&wp->base) + wp->base.cy; - if (data->cy < screen_hsize(data->backing)) { - data->oy = screen_hsize(data->backing) - data->cy; + if (cy < screen_hsize(data->backing)) { + data->cx = cx; data->cy = 0; - } else - data->cy -= screen_hsize(data->backing); + data->oy = screen_hsize(data->backing) - cy; + } else { + data->cx = data->backing->cx; + data->cy = data->backing->cy; + data->oy = 0; + } data->scroll_exit = args_has(args, 'e'); data->hide_position = args_has(args, 'H'); @@ -697,8 +700,8 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy) struct screen_write_ctx ctx; int search; - screen_resize(s, sx, sy, 1); - screen_resize(data->backing, sx, sy, 1); + screen_resize(s, sx, sy, 0); + screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL); if (data->cy > sy - 1) data->cy = sy - 1; @@ -2024,7 +2027,8 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) screen_free(data->backing); free(data->backing); - data->backing = window_copy_clone_screen(&wp->base, &data->screen); + data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, + NULL); return (WINDOW_COPY_CMD_REDRAW); }