/* $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 #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); sixel_free(im->data); free(im->fallback); free(im); } int image_free_all(struct screen *s) { struct image *im, *im1; int redraw = !TAILQ_EMPTY(&s->images); TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) image_free(im); return (redraw); } /* Create text placeholder for an image. */ static void image_fallback(char **ret, u_int sx, u_int sy) { char *buf, *label; u_int py, size, lsize; /* Allocate first line. */ lsize = xasprintf(&label, "SIXEL IMAGE (%ux%u)\r\n", sx, sy) + 1; if (sx < lsize - 3) size = lsize - 1; else size = sx + 2; /* Remaining lines. Every placeholder line has \r\n at the end. */ size += (sx + 2) * (sy - 1) + 1; *ret = buf = xmalloc(size); /* Render first line. */ if (sx < lsize - 3) { memcpy(buf, label, lsize); buf += lsize - 1; } else { memcpy(buf, label, lsize - 3); buf += lsize - 3; memset(buf, '+', sx - lsize + 3); buf += sx - lsize + 3; snprintf(buf, 3, "\r\n"); buf += 2; } /* Remaining lines. */ for (py = 1; py < sy; py++) { memset(buf, '+', sx); buf += sx; snprintf(buf, 3, "\r\n"); buf += 2; } free(label); } struct image* 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); image_fallback(&im->fallback, 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)); return (im); } 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); } int image_scroll_up(struct screen *s, u_int lines) { struct image *im, *im1; int redraw = 0; u_int sx, sy; struct sixel_image *new; TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) { if (im->py >= lines) { im->py -= lines; redraw = 1; continue; } if (im->py + im->sy <= lines) { image_free(im); redraw = 1; continue; } sx = im->sx; sy = (im->py + im->sy) - lines; new = sixel_scale(im->data, 0, 0, 0, im->sy - sy, sx, sy, 1); sixel_free(im->data); im->data = new; im->py = 0; sixel_size_in_cells(im->data, &im->sx, &im->sy); free(im->fallback); image_fallback(&im->fallback, im->sx, im->sy); redraw = 1; } return (redraw); }