diff --git a/image-grid.c b/image-grid.c index 17ee63a59..cace505f5 100644 --- a/image-grid.c +++ b/image-grid.c @@ -374,6 +374,53 @@ image_grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, free(maps); } +/* Copy clipped image spans between grid areas. */ +void +image_grid_copy_area(struct grid *dst, u_int dx, u_int dy, struct grid *src, + u_int px, u_int py, u_int sx, u_int sy) +{ + struct image_copy_map *maps = NULL; + struct image_placement *plmt; + struct image_line *src_line, *dst_line; + struct image_span *span; + u_int nmaps = 0, row, start, end, span_end; + + if (dst == src || sx == 0 || sy == 0) + return; + if (dy >= dst->hsize + dst->sy || py >= src->hsize + src->sy) + return; + if (sy > dst->hsize + dst->sy - dy) + sy = dst->hsize + dst->sy - dy; + if (sy > src->hsize + src->sy - py) + sy = src->hsize + src->sy - py; + end = px + sx; + if (end < px) + end = UINT_MAX; + + for (row = 0; row < sy; row++) { + src_line = src->linedata[py + row].images; + if (src_line == NULL) + continue; + dst_line = NULL; + TAILQ_FOREACH(span, &src_line->spans, line_entry) { + span_end = span->x + span->sx; + start = (span->x > px ? span->x : px); + if (start >= end || span_end <= px) + continue; + if (span_end > end) + span_end = end; + if (dst_line == NULL) + dst_line = image_line_get(&dst->linedata[dy + row]); + plmt = image_copy_placement(dst, span->placement, &maps, + &nmaps); + image_span_add(dst_line, plmt, dx + start - px, + span_end - start, span->source_x + start - span->x, + span->source_y); + } + } + free(maps); +} + /* Check whether a grid line has any image spans. */ int image_grid_line_has_images(struct grid_line *gl) diff --git a/tmux-image.h b/tmux-image.h index eebc23292..c380ecc31 100644 --- a/tmux-image.h +++ b/tmux-image.h @@ -87,6 +87,8 @@ void image_grid_move_cells(struct grid *, u_int, u_int, u_int, u_int); void image_grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, u_int); +void image_grid_copy_area(struct grid *, u_int, u_int, struct grid *, + u_int, u_int, u_int, u_int); int image_grid_line_has_images(struct grid_line *); int image_grid_area_has_images(struct grid *, u_int, u_int, u_int, u_int); diff --git a/window-copy.c b/window-copy.c index 3d40ffe24..39add5b28 100644 --- a/window-copy.c +++ b/window-copy.c @@ -73,6 +73,10 @@ static void window_copy_write_line(struct window_mode_entry *, struct screen_write_ctx *, u_int); static void window_copy_write_lines(struct window_mode_entry *, struct screen_write_ctx *, u_int, u_int); +#ifdef ENABLE_IMAGES +static void window_copy_update_image_refresh(struct window_copy_mode_data *); +static int window_copy_visible_has_images(struct window_copy_mode_data *); +#endif static char *window_copy_match_at_cursor(struct window_copy_mode_data *); static void window_copy_scroll_to(struct window_mode_entry *, u_int, u_int, int); @@ -293,6 +297,12 @@ struct window_copy_mode_data { u_int oy; /* number of lines scrolled up */ +#ifdef ENABLE_IMAGES + u_int image_base; /* where images were last drawn for */ + int image_base_set; + int image_refresh; +#endif + u_int selx; /* beginning of selection */ u_int sely; @@ -656,6 +666,9 @@ window_copy_init(struct window_mode_entry *wme, data->my = screen_hsize(data->backing) + data->cy - data->oy; data->showmark = 0; +#ifdef ENABLE_IMAGES + window_copy_update_image_refresh(data); +#endif screen_write_start(&ctx, &data->screen); for (i = 0; i < screen_size_y(&data->screen); i++) window_copy_write_line(wme, &ctx, i); @@ -1227,6 +1240,9 @@ window_copy_size_changed(struct window_mode_entry *wme) window_copy_clear_marks(wme); data->searchindex = searchindex; +#ifdef ENABLE_IMAGES + window_copy_update_image_refresh(data); +#endif screen_write_start(&ctx, s); window_copy_write_lines(wme, &ctx, 0, screen_size_y(s)); screen_write_stop(&ctx); @@ -5576,6 +5592,16 @@ window_copy_write_one(struct window_mode_entry *wme, for (fx = 0; fx < nx; fx++) { grid_get_cell(gd, fx, fy, &gc); if (fx + gc.data.width <= nx) { +#ifdef ENABLE_IMAGES + if (image_grid_area_has_images(gd, fx, fy, + gc.data.width, 1)) { + grid_view_set_cell(ctx->s->grid, px + fx, py, + &gc); + screen_write_cursormove(ctx, + px + fx + gc.data.width, py, 0); + continue; + } +#endif window_copy_update_style(wme, fx, fy, &gc, mgc, cgc, mkgc, clgc); if (gc.flags & GRID_FLAG_PADDING) { @@ -5824,6 +5850,14 @@ window_copy_write_line(struct window_mode_entry *wme, window_copy_write_one(wme, ctx, width, py, hsize - data->oy + py, content_sx, &mgc, &cgc, &mkgc, &clgc); +#ifdef ENABLE_IMAGES + image_grid_free_line(s->grid, &s->grid->linedata[s->grid->hsize + py]); + image_grid_copy_area(s->grid, width, s->grid->hsize + py, + data->backing->grid, 0, hsize - data->oy + py, content_sx, 1); + if (data->image_refresh) + image_redraw_area(ctx, width, py, content_sx, 1); +#endif + if (py == 0 && s->rupper < s->rlower && !data->hide_position) { value = options_get_string(oo, "copy-mode-position-format"); if (*value != '\0') { @@ -5874,6 +5908,34 @@ window_copy_redraw_selection(struct window_mode_entry *wme, u_int old_y) window_copy_redraw_lines(wme, start, end - start + 1); } +#ifdef ENABLE_IMAGES +/* Refresh images when the visible range of history changes. */ +static void +window_copy_update_image_refresh(struct window_copy_mode_data *data) +{ + u_int base = screen_hsize(data->backing) - data->oy; + + if (!data->image_base_set || base != data->image_base) + data->image_refresh = 1; + else + data->image_refresh = 0; + data->image_base = base; + data->image_base_set = 1; +} + +/* Check whether visible history contains images. */ +static int +window_copy_visible_has_images(struct window_copy_mode_data *data) +{ + struct grid *gd = data->backing->grid; + struct screen *s = &data->screen; + u_int sx = screen_size_x(s), sy = screen_size_y(s); + u_int hsize = screen_hsize(data->backing); + + return (image_grid_area_has_images(gd, 0, hsize - data->oy, sx, sy)); +} +#endif + static void window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny) { @@ -5883,6 +5945,10 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny) struct screen_write_ctx ctx; u_int i; +#ifdef ENABLE_IMAGES + window_copy_update_image_refresh(data); +#endif + if (window_copy_line_number_width(wme) != 0) { screen_write_start(&ctx, &data->screen); for (i = py; i < py + ny; i++) @@ -7373,6 +7439,13 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny) window_copy_redraw_screen(wme); return; } +#ifdef ENABLE_IMAGES + if (window_copy_visible_has_images(data)) { + window_copy_redraw_screen(wme); + return; + } + window_copy_update_image_refresh(data); +#endif if (window_copy_line_numbers_active(wme)) { if (window_copy_line_number_mode(wme) != WINDOW_COPY_LINE_NUMBERS_ABSOLUTE) { @@ -7444,6 +7517,13 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny) window_copy_redraw_screen(wme); return; } +#ifdef ENABLE_IMAGES + if (window_copy_visible_has_images(data)) { + window_copy_redraw_screen(wme); + return; + } + window_copy_update_image_refresh(data); +#endif if (window_copy_line_numbers_active(wme)) { if (window_copy_line_number_mode(wme) != WINDOW_COPY_LINE_NUMBERS_ABSOLUTE) {