diff --git a/Makefile.am b/Makefile.am index 014554d4..5e8c75ba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -137,6 +137,7 @@ dist_tmux_SOURCES = \ grid.c \ input-keys.c \ input.c \ + image.c \ job.c \ key-bindings.c \ key-string.c \ diff --git a/image.c b/image.c new file mode 100644 index 00000000..a7f566fc --- /dev/null +++ b/image.c @@ -0,0 +1,99 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "tmux.h" + +static struct images all_images = TAILQ_HEAD_INITIALIZER(all_images); +static u_int all_images_count; + +static void +image_free(struct image *im) +{ + struct screen *s = im->s; + + TAILQ_REMOVE(&all_images, im, all_entry); + all_images_count--; + + TAILQ_REMOVE(&s->images, im, entry); + free(im); +} + +void +image_free_all(struct screen *s) +{ + struct image *im, *im1; + + TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) + image_free(im); +} + +void +image_store(struct screen *s, struct sixel_image *si) +{ + struct image *im; + + im = xcalloc(1, sizeof *im); + im->s = s; + im->data = si; + + im->px = s->cx; + im->py = s->cy; + sixel_size_in_cells(si, &im->sx, &im->sy); + + TAILQ_INSERT_TAIL(&s->images, im, entry); + + TAILQ_INSERT_TAIL(&all_images, im, all_entry); + if (++all_images_count == 10/*XXX*/) + image_free(TAILQ_FIRST(&all_images)); +} + +int +image_check_line(struct screen *s, u_int py, u_int ny) +{ + struct image *im, *im1; + int redraw = 0; + + TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) { + if (py + ny > im->py && py < im->py + im->sy) { + image_free(im); + redraw = 1; + } + } + return (redraw); +} + +int +image_check_area(struct screen *s, u_int px, u_int py, u_int nx, u_int ny) +{ + struct image *im, *im1; + int redraw = 0; + + TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) { + if (py + ny <= im->py || py >= im->py + im->sy) + continue; + if (px + nx <= im->px || px >= im->px + im->sx) + continue; + image_free(im); + redraw = 1; + } + return (redraw); +} diff --git a/input.c b/input.c index 5adfdd8f..0cf614ff 100644 --- a/input.c +++ b/input.c @@ -2173,7 +2173,6 @@ input_dcs_dispatch(struct input_ctx *ictx) if (si != NULL) { sixel_log(si); screen_write_sixelimage(sctx, si); - sixel_free(si); } } diff --git a/screen-write.c b/screen-write.c index 05bb6467..2d376e66 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1676,10 +1676,14 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) void screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si) { + struct screen *s = ctx->s; struct tty_ctx ttyctx; + image_store(s, si); + screen_write_initctx(ctx, &ttyctx); ttyctx.ptr = si; + screen_write_collect_flush(ctx, 0); tty_write(tty_cmd_sixelimage, &ttyctx); } diff --git a/screen.c b/screen.c index 405932ef..6ecb4d97 100644 --- a/screen.c +++ b/screen.c @@ -83,6 +83,8 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->tabs = NULL; s->sel = NULL; + TAILQ_INIT(&s->images); + screen_reinit(s); } @@ -104,6 +106,7 @@ screen_reinit(struct screen *s) screen_clear_selection(s); screen_free_titles(s); + image_free_all(s); } /* Destroy a screen. */ @@ -118,6 +121,7 @@ screen_free(struct screen *s) grid_destroy(s->grid); screen_free_titles(s); + image_free_all(s); } /* Reset tabs to default, eight spaces apart. */ diff --git a/tmux.h b/tmux.h index ae1ccbbd..668654e3 100644 --- a/tmux.h +++ b/tmux.h @@ -709,6 +709,21 @@ struct style { enum style_default_type default_type; }; +/* Image. */ +struct image { + struct screen *s; + struct sixel_image *data; + + u_int px; + u_int py; + u_int sx; + u_int sy; + + TAILQ_ENTRY (image) all_entry; + TAILQ_ENTRY (image) entry; +}; +TAILQ_HEAD(images, image); + /* Virtual screen. */ struct screen_sel; struct screen_titles; @@ -729,10 +744,10 @@ struct screen { u_int rlower; /* scroll region bottom */ int mode; - bitstr_t *tabs; - struct screen_sel *sel; + + struct images images; }; /* Screen write context. */ @@ -2705,6 +2720,12 @@ struct window_pane *spawn_pane(struct spawn_context *, char **); /* regsub.c */ char *regsub(const char *, const char *, const char *, int); +/* image.c */ +void image_free_all(struct screen *); +void image_store(struct screen *, struct sixel_image *); +int image_check_line(struct screen *, u_int, u_int); +int image_check_area(struct screen *, u_int, u_int, u_int, u_int); + /* sixel.c */ struct sixel_image *sixel_parse(const char *, size_t, u_int, u_int); void sixel_free(struct sixel_image *); diff --git a/tty.c b/tty.c index b52e91f3..afc224f6 100644 --- a/tty.c +++ b/tty.c @@ -1875,19 +1875,16 @@ void tty_cmd_sixelimage(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; struct sixel_image *si = ctx->ptr; struct sixel_image *new; int flags = (tty->term->flags|tty->term_flags); char *data; size_t size; - u_int cx = s->cx, cy = s->cy, sx, sy; + u_int cx = ctx->ocx, cy = ctx->ocy, sx, sy; u_int i, j, x, y, rx, ry; - if ((~flags & TERM_SIXEL) && !tty_term_has(tty->term, TTYC_SXL)) { - wp->flags |= PANE_REDRAW; + if ((~flags & TERM_SIXEL) && !tty_term_has(tty->term, TTYC_SXL)) return; - } if (tty->xpixel == 0 || tty->ypixel == 0) return;