xref: /netbsd-src/external/bsd/tmux/dist/image.c (revision c23f9150cad51fdd442fa1806fac769ae26a1fdd)
1*c23f9150Swiz /* $OpenBSD$ */
2*c23f9150Swiz 
3*c23f9150Swiz /*
4*c23f9150Swiz  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5*c23f9150Swiz  *
6*c23f9150Swiz  * Permission to use, copy, modify, and distribute this software for any
7*c23f9150Swiz  * purpose with or without fee is hereby granted, provided that the above
8*c23f9150Swiz  * copyright notice and this permission notice appear in all copies.
9*c23f9150Swiz  *
10*c23f9150Swiz  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*c23f9150Swiz  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*c23f9150Swiz  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*c23f9150Swiz  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*c23f9150Swiz  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15*c23f9150Swiz  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16*c23f9150Swiz  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*c23f9150Swiz  */
18*c23f9150Swiz 
19*c23f9150Swiz #include <sys/types.h>
20*c23f9150Swiz 
21*c23f9150Swiz #include <stdlib.h>
22*c23f9150Swiz #include <string.h>
23*c23f9150Swiz 
24*c23f9150Swiz #include "tmux.h"
25*c23f9150Swiz 
26*c23f9150Swiz static struct images	all_images = TAILQ_HEAD_INITIALIZER(all_images);
27*c23f9150Swiz static u_int		all_images_count;
28*c23f9150Swiz 
29*c23f9150Swiz static void
image_free(struct image * im)30*c23f9150Swiz image_free(struct image *im)
31*c23f9150Swiz {
32*c23f9150Swiz 	struct screen	*s = im->s;
33*c23f9150Swiz 
34*c23f9150Swiz 	TAILQ_REMOVE(&all_images, im, all_entry);
35*c23f9150Swiz 	all_images_count--;
36*c23f9150Swiz 
37*c23f9150Swiz 	TAILQ_REMOVE(&s->images, im, entry);
38*c23f9150Swiz 	sixel_free(im->data);
39*c23f9150Swiz 	free(im->fallback);
40*c23f9150Swiz 	free(im);
41*c23f9150Swiz }
42*c23f9150Swiz 
43*c23f9150Swiz int
image_free_all(struct screen * s)44*c23f9150Swiz image_free_all(struct screen *s)
45*c23f9150Swiz {
46*c23f9150Swiz 	struct image	*im, *im1;
47*c23f9150Swiz 	int		 redraw = !TAILQ_EMPTY(&s->images);
48*c23f9150Swiz 
49*c23f9150Swiz 	TAILQ_FOREACH_SAFE(im, &s->images, entry, im1)
50*c23f9150Swiz 		image_free(im);
51*c23f9150Swiz 	return (redraw);
52*c23f9150Swiz }
53*c23f9150Swiz 
54*c23f9150Swiz /* Create text placeholder for an image. */
55*c23f9150Swiz static void
image_fallback(char ** ret,u_int sx,u_int sy)56*c23f9150Swiz image_fallback(char **ret, u_int sx, u_int sy)
57*c23f9150Swiz {
58*c23f9150Swiz 	char	*buf, *label;
59*c23f9150Swiz 	u_int	 py, size, lsize;
60*c23f9150Swiz 
61*c23f9150Swiz 	/* Allocate first line. */
62*c23f9150Swiz 	lsize = xasprintf(&label, "SIXEL IMAGE (%ux%u)\r\n", sx, sy) + 1;
63*c23f9150Swiz 	if (sx < lsize - 3)
64*c23f9150Swiz 		size = lsize - 1;
65*c23f9150Swiz 	else
66*c23f9150Swiz 		size = sx + 2;
67*c23f9150Swiz 
68*c23f9150Swiz 	/* Remaining lines. Every placeholder line has \r\n at the end. */
69*c23f9150Swiz 	size += (sx + 2) * (sy - 1) + 1;
70*c23f9150Swiz 	*ret = buf = xmalloc(size);
71*c23f9150Swiz 
72*c23f9150Swiz 	/* Render first line. */
73*c23f9150Swiz 	if (sx < lsize - 3) {
74*c23f9150Swiz 		memcpy(buf, label, lsize);
75*c23f9150Swiz 		buf += lsize - 1;
76*c23f9150Swiz 	} else {
77*c23f9150Swiz 		memcpy(buf, label, lsize - 3);
78*c23f9150Swiz 		buf += lsize - 3;
79*c23f9150Swiz 		memset(buf, '+', sx - lsize + 3);
80*c23f9150Swiz 		buf += sx - lsize + 3;
81*c23f9150Swiz 		snprintf(buf, 3, "\r\n");
82*c23f9150Swiz 		buf += 2;
83*c23f9150Swiz 	}
84*c23f9150Swiz 
85*c23f9150Swiz 	/* Remaining lines. */
86*c23f9150Swiz 	for (py = 1; py < sy; py++) {
87*c23f9150Swiz 		memset(buf, '+', sx);
88*c23f9150Swiz 		buf += sx;
89*c23f9150Swiz 		snprintf(buf, 3, "\r\n");
90*c23f9150Swiz 		buf += 2;
91*c23f9150Swiz 	}
92*c23f9150Swiz 
93*c23f9150Swiz 	free(label);
94*c23f9150Swiz }
95*c23f9150Swiz 
96*c23f9150Swiz struct image*
image_store(struct screen * s,struct sixel_image * si)97*c23f9150Swiz image_store(struct screen *s, struct sixel_image *si)
98*c23f9150Swiz {
99*c23f9150Swiz 	struct image	*im;
100*c23f9150Swiz 
101*c23f9150Swiz 	im = xcalloc(1, sizeof *im);
102*c23f9150Swiz 	im->s = s;
103*c23f9150Swiz 	im->data = si;
104*c23f9150Swiz 
105*c23f9150Swiz 	im->px = s->cx;
106*c23f9150Swiz 	im->py = s->cy;
107*c23f9150Swiz 	sixel_size_in_cells(si, &im->sx, &im->sy);
108*c23f9150Swiz 
109*c23f9150Swiz 	image_fallback(&im->fallback, im->sx, im->sy);
110*c23f9150Swiz 
111*c23f9150Swiz 	TAILQ_INSERT_TAIL(&s->images, im, entry);
112*c23f9150Swiz 
113*c23f9150Swiz 	TAILQ_INSERT_TAIL(&all_images, im, all_entry);
114*c23f9150Swiz 	if (++all_images_count == 10/*XXX*/)
115*c23f9150Swiz 		image_free(TAILQ_FIRST(&all_images));
116*c23f9150Swiz 
117*c23f9150Swiz 	return (im);
118*c23f9150Swiz }
119*c23f9150Swiz 
120*c23f9150Swiz int
image_check_line(struct screen * s,u_int py,u_int ny)121*c23f9150Swiz image_check_line(struct screen *s, u_int py, u_int ny)
122*c23f9150Swiz {
123*c23f9150Swiz 	struct image	*im, *im1;
124*c23f9150Swiz 	int		 redraw = 0;
125*c23f9150Swiz 
126*c23f9150Swiz 	TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
127*c23f9150Swiz 		if (py + ny > im->py && py < im->py + im->sy) {
128*c23f9150Swiz 			image_free(im);
129*c23f9150Swiz 			redraw = 1;
130*c23f9150Swiz 		}
131*c23f9150Swiz 	}
132*c23f9150Swiz 	return (redraw);
133*c23f9150Swiz }
134*c23f9150Swiz 
135*c23f9150Swiz int
image_check_area(struct screen * s,u_int px,u_int py,u_int nx,u_int ny)136*c23f9150Swiz image_check_area(struct screen *s, u_int px, u_int py, u_int nx, u_int ny)
137*c23f9150Swiz {
138*c23f9150Swiz 	struct image	*im, *im1;
139*c23f9150Swiz 	int		 redraw = 0;
140*c23f9150Swiz 
141*c23f9150Swiz 	TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
142*c23f9150Swiz 		if (py + ny <= im->py || py >= im->py + im->sy)
143*c23f9150Swiz 			continue;
144*c23f9150Swiz 		if (px + nx <= im->px || px >= im->px + im->sx)
145*c23f9150Swiz 			continue;
146*c23f9150Swiz 		image_free(im);
147*c23f9150Swiz 		redraw = 1;
148*c23f9150Swiz 	}
149*c23f9150Swiz 	return (redraw);
150*c23f9150Swiz }
151*c23f9150Swiz 
152*c23f9150Swiz int
image_scroll_up(struct screen * s,u_int lines)153*c23f9150Swiz image_scroll_up(struct screen *s, u_int lines)
154*c23f9150Swiz {
155*c23f9150Swiz 	struct image		*im, *im1;
156*c23f9150Swiz 	int			 redraw = 0;
157*c23f9150Swiz 	u_int			 sx, sy;
158*c23f9150Swiz 	struct sixel_image	*new;
159*c23f9150Swiz 
160*c23f9150Swiz 	TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
161*c23f9150Swiz 		if (im->py >= lines) {
162*c23f9150Swiz 			im->py -= lines;
163*c23f9150Swiz 			redraw = 1;
164*c23f9150Swiz 			continue;
165*c23f9150Swiz 		}
166*c23f9150Swiz 		if (im->py + im->sy <= lines) {
167*c23f9150Swiz 			image_free(im);
168*c23f9150Swiz 			redraw = 1;
169*c23f9150Swiz 			continue;
170*c23f9150Swiz 		}
171*c23f9150Swiz 		sx = im->sx;
172*c23f9150Swiz 		sy = (im->py + im->sy) - lines;
173*c23f9150Swiz 
174*c23f9150Swiz 		new = sixel_scale(im->data, 0, 0, 0, im->sy - sy, sx, sy, 1);
175*c23f9150Swiz 		sixel_free(im->data);
176*c23f9150Swiz 		im->data = new;
177*c23f9150Swiz 
178*c23f9150Swiz 		im->py = 0;
179*c23f9150Swiz 		sixel_size_in_cells(im->data, &im->sx, &im->sy);
180*c23f9150Swiz 
181*c23f9150Swiz 		free(im->fallback);
182*c23f9150Swiz 		image_fallback(&im->fallback, im->sx, im->sy);
183*c23f9150Swiz 		redraw = 1;
184*c23f9150Swiz 	}
185*c23f9150Swiz 	return (redraw);
186*c23f9150Swiz }
187