Line | Count | Source |
1 | | /* $OpenBSD: grid-view.c,v 1.39 2026/08/03 12:58:53 nicm Exp $ */ |
2 | | |
3 | | /* |
4 | | * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> |
5 | | * |
6 | | * Permission to use, copy, modify, and distribute this software for any |
7 | | * purpose with or without fee is hereby granted, provided that the above |
8 | | * copyright notice and this permission notice appear in all copies. |
9 | | * |
10 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | | * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER |
15 | | * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
16 | | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | | */ |
18 | | |
19 | | #include <sys/types.h> |
20 | | |
21 | | #include <string.h> |
22 | | |
23 | | #include "tmux.h" |
24 | | |
25 | | /* |
26 | | * Grid view functions. These work using coordinates relative to the visible |
27 | | * screen area. |
28 | | */ |
29 | | |
30 | 0 | #define grid_view_x(gd, x) (x) |
31 | 0 | #define grid_view_y(gd, y) ((gd)->hsize + (y)) |
32 | | |
33 | | /* Get cell. */ |
34 | | void |
35 | | grid_view_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc) |
36 | 0 | { |
37 | 0 | grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc); |
38 | 0 | } |
39 | | |
40 | | /* Set cell. */ |
41 | | void |
42 | | grid_view_set_cell(struct grid *gd, u_int px, u_int py, |
43 | | const struct grid_cell *gc) |
44 | 0 | { |
45 | 0 | grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc); |
46 | 0 | } |
47 | | |
48 | | /* Set padding. */ |
49 | | void |
50 | | grid_view_set_padding(struct grid *gd, u_int px, u_int py, int bg) |
51 | 0 | { |
52 | 0 | grid_set_padding(gd, grid_view_x(gd, px), grid_view_y(gd, py), bg); |
53 | 0 | } |
54 | | |
55 | | /* Set cells. */ |
56 | | void |
57 | | grid_view_set_cells(struct grid *gd, u_int px, u_int py, |
58 | | const struct grid_cell *gc, const char *s, size_t slen) |
59 | 0 | { |
60 | 0 | grid_set_cells(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc, s, |
61 | 0 | slen); |
62 | 0 | } |
63 | | |
64 | | /* Clear into history. */ |
65 | | void |
66 | | grid_view_clear_history(struct grid *gd, u_int bg) |
67 | 0 | { |
68 | 0 | struct grid_line *gl; |
69 | 0 | u_int yy, last; |
70 | | |
71 | | /* Find the last used line. */ |
72 | 0 | last = 0; |
73 | 0 | for (yy = 0; yy < gd->sy; yy++) { |
74 | 0 | gl = grid_get_line(gd, grid_view_y(gd, yy)); |
75 | 0 | if (gl->cellused != 0) |
76 | 0 | last = yy + 1; |
77 | | #ifdef ENABLE_IMAGES |
78 | | else if (image_grid_line_has_images(gl)) |
79 | | last = yy + 1; |
80 | | #endif |
81 | 0 | } |
82 | 0 | if (last == 0) { |
83 | 0 | grid_view_clear(gd, 0, 0, gd->sx, gd->sy, bg); |
84 | 0 | return; |
85 | 0 | } |
86 | | |
87 | | /* Scroll the lines into the history. */ |
88 | 0 | for (yy = 0; yy < last; yy++) { |
89 | 0 | grid_collect_history(gd, 0); |
90 | 0 | grid_scroll_history(gd, bg); |
91 | 0 | } |
92 | 0 | if (last < gd->sy) |
93 | 0 | grid_view_clear(gd, 0, 0, gd->sx, gd->sy - last, bg); |
94 | 0 | gd->hscrolled = 0; |
95 | 0 | } |
96 | | |
97 | | /* Clear area. */ |
98 | | void |
99 | | grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, |
100 | | u_int bg) |
101 | 0 | { |
102 | 0 | px = grid_view_x(gd, px); |
103 | 0 | py = grid_view_y(gd, py); |
104 | |
|
105 | 0 | grid_clear(gd, px, py, nx, ny, bg); |
106 | 0 | } |
107 | | |
108 | | /* Scroll region up. */ |
109 | | void |
110 | | grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower, |
111 | | u_int bg) |
112 | 0 | { |
113 | | #ifdef ENABLE_IMAGES |
114 | | struct image_saved *saved; |
115 | | #endif |
116 | 0 | u_int n = rlower - rupper; |
117 | |
|
118 | 0 | if (gd->flags & GRID_HISTORY) { |
119 | 0 | grid_collect_history(gd, 0); |
120 | 0 | if (rupper == 0 && rlower == gd->sy - 1) |
121 | 0 | grid_scroll_history(gd, bg); |
122 | 0 | else { |
123 | 0 | rupper = grid_view_y(gd, rupper); |
124 | 0 | rlower = grid_view_y(gd, rlower); |
125 | | #ifdef ENABLE_IMAGES |
126 | | saved = image_grid_save_lines(gd, rupper, rupper + 1, n, 1); |
127 | | #endif |
128 | 0 | grid_scroll_history_region(gd, rupper, rlower, bg); |
129 | | #ifdef ENABLE_IMAGES |
130 | | image_grid_restore_lines(gd, saved); |
131 | | #endif |
132 | 0 | } |
133 | 0 | } else { |
134 | 0 | rupper = grid_view_y(gd, rupper); |
135 | 0 | rlower = grid_view_y(gd, rlower); |
136 | | #ifdef ENABLE_IMAGES |
137 | | saved = image_grid_save_lines(gd, rupper, rupper + 1, n, 1); |
138 | | #endif |
139 | 0 | grid_move_lines(gd, rupper, rupper + 1, n, bg); |
140 | | #ifdef ENABLE_IMAGES |
141 | | image_grid_restore_lines(gd, saved); |
142 | | #endif |
143 | 0 | } |
144 | 0 | } |
145 | | |
146 | | /* Scroll region down. */ |
147 | | void |
148 | | grid_view_scroll_region_down(struct grid *gd, u_int rupper, u_int rlower, |
149 | | u_int bg) |
150 | 0 | { |
151 | | #ifdef ENABLE_IMAGES |
152 | | struct image_saved *saved; |
153 | | #endif |
154 | |
|
155 | 0 | rupper = grid_view_y(gd, rupper); |
156 | 0 | rlower = grid_view_y(gd, rlower); |
157 | |
|
158 | | #ifdef ENABLE_IMAGES |
159 | | saved = image_grid_save_lines(gd, rupper + 1, rupper, rlower - rupper, 1); |
160 | | #endif |
161 | 0 | grid_move_lines(gd, rupper + 1, rupper, rlower - rupper, bg); |
162 | | #ifdef ENABLE_IMAGES |
163 | | image_grid_restore_lines(gd, saved); |
164 | | #endif |
165 | 0 | } |
166 | | |
167 | | /* Insert lines. */ |
168 | | void |
169 | | grid_view_insert_lines(struct grid *gd, u_int py, u_int ny, u_int bg) |
170 | 0 | { |
171 | | #ifdef ENABLE_IMAGES |
172 | | struct image_saved *saved; |
173 | | #endif |
174 | 0 | u_int sy; |
175 | |
|
176 | 0 | py = grid_view_y(gd, py); |
177 | |
|
178 | 0 | sy = grid_view_y(gd, gd->sy); |
179 | |
|
180 | | #ifdef ENABLE_IMAGES |
181 | | saved = image_grid_save_lines(gd, py + ny, py, sy - py - ny, 0); |
182 | | #endif |
183 | 0 | grid_move_lines(gd, py + ny, py, sy - py - ny, bg); |
184 | | #ifdef ENABLE_IMAGES |
185 | | image_grid_restore_lines(gd, saved); |
186 | | #endif |
187 | 0 | } |
188 | | |
189 | | /* Insert lines in region. */ |
190 | | void |
191 | | grid_view_insert_lines_region(struct grid *gd, u_int rlower, u_int py, |
192 | | u_int ny, u_int bg) |
193 | 0 | { |
194 | | #ifdef ENABLE_IMAGES |
195 | | struct image_saved *saved; |
196 | | #endif |
197 | 0 | u_int ny2; |
198 | |
|
199 | 0 | rlower = grid_view_y(gd, rlower); |
200 | |
|
201 | 0 | py = grid_view_y(gd, py); |
202 | |
|
203 | 0 | ny2 = rlower + 1 - py - ny; |
204 | | #ifdef ENABLE_IMAGES |
205 | | saved = image_grid_save_lines(gd, rlower + 1 - ny2, py, ny2, 0); |
206 | | #endif |
207 | 0 | grid_move_lines(gd, rlower + 1 - ny2, py, ny2, bg); |
208 | | #ifdef ENABLE_IMAGES |
209 | | image_grid_restore_lines(gd, saved); |
210 | | #endif |
211 | 0 | grid_clear(gd, 0, py + ny2, gd->sx, ny - ny2, bg); |
212 | 0 | } |
213 | | |
214 | | /* Delete lines. */ |
215 | | void |
216 | | grid_view_delete_lines(struct grid *gd, u_int py, u_int ny, u_int bg) |
217 | 0 | { |
218 | | #ifdef ENABLE_IMAGES |
219 | | struct image_saved *saved; |
220 | | #endif |
221 | 0 | u_int sy; |
222 | |
|
223 | 0 | py = grid_view_y(gd, py); |
224 | |
|
225 | 0 | sy = grid_view_y(gd, gd->sy); |
226 | |
|
227 | | #ifdef ENABLE_IMAGES |
228 | | saved = image_grid_save_lines(gd, py, py + ny, sy - py - ny, 0); |
229 | | #endif |
230 | 0 | grid_move_lines(gd, py, py + ny, sy - py - ny, bg); |
231 | | #ifdef ENABLE_IMAGES |
232 | | image_grid_restore_lines(gd, saved); |
233 | | #endif |
234 | 0 | grid_clear(gd, 0, sy - ny, gd->sx, ny, bg); |
235 | 0 | } |
236 | | |
237 | | /* Delete lines inside scroll region. */ |
238 | | void |
239 | | grid_view_delete_lines_region(struct grid *gd, u_int rlower, u_int py, |
240 | | u_int ny, u_int bg) |
241 | 0 | { |
242 | | #ifdef ENABLE_IMAGES |
243 | | struct image_saved *saved; |
244 | | #endif |
245 | 0 | u_int ny2; |
246 | |
|
247 | 0 | rlower = grid_view_y(gd, rlower); |
248 | |
|
249 | 0 | py = grid_view_y(gd, py); |
250 | |
|
251 | 0 | ny2 = rlower + 1 - py - ny; |
252 | | #ifdef ENABLE_IMAGES |
253 | | saved = image_grid_save_lines(gd, py, py + ny, ny2, 0); |
254 | | #endif |
255 | 0 | grid_move_lines(gd, py, py + ny, ny2, bg); |
256 | | #ifdef ENABLE_IMAGES |
257 | | image_grid_restore_lines(gd, saved); |
258 | | #endif |
259 | 0 | grid_clear(gd, 0, py + ny2, gd->sx, ny - ny2, bg); |
260 | 0 | } |
261 | | |
262 | | /* Insert characters. */ |
263 | | void |
264 | | grid_view_insert_cells(struct grid *gd, u_int px, u_int py, u_int nx, u_int bg) |
265 | 0 | { |
266 | 0 | u_int sx; |
267 | |
|
268 | 0 | px = grid_view_x(gd, px); |
269 | 0 | py = grid_view_y(gd, py); |
270 | |
|
271 | 0 | sx = grid_view_x(gd, gd->sx); |
272 | |
|
273 | 0 | if (px >= sx - 1) |
274 | 0 | grid_clear(gd, px, py, 1, 1, bg); |
275 | 0 | else |
276 | 0 | grid_move_cells(gd, px + nx, px, py, sx - px - nx, bg); |
277 | 0 | } |
278 | | |
279 | | /* Delete characters. */ |
280 | | void |
281 | | grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx, u_int bg) |
282 | 0 | { |
283 | 0 | u_int sx; |
284 | |
|
285 | 0 | px = grid_view_x(gd, px); |
286 | 0 | py = grid_view_y(gd, py); |
287 | |
|
288 | 0 | sx = grid_view_x(gd, gd->sx); |
289 | |
|
290 | 0 | grid_move_cells(gd, px, px + nx, py, sx - px - nx, bg); |
291 | 0 | grid_clear(gd, sx - nx, py, nx, 1, bg); |
292 | 0 | } |
293 | | |
294 | | /* Convert cells into a string. */ |
295 | | char * |
296 | | grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) |
297 | 0 | { |
298 | 0 | px = grid_view_x(gd, px); |
299 | 0 | py = grid_view_y(gd, py); |
300 | |
|
301 | 0 | return (grid_string_cells(gd, px, py, nx, NULL, 0, NULL)); |
302 | 0 | } |