screen-redraw.c revision 1.1.1.14 1 1.1.1.5 christos /* $OpenBSD$ */
2 1.1 jmmv
3 1.1 jmmv /*
4 1.1.1.6 christos * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott (at) gmail.com>
5 1.1 jmmv *
6 1.1 jmmv * Permission to use, copy, modify, and distribute this software for any
7 1.1 jmmv * purpose with or without fee is hereby granted, provided that the above
8 1.1 jmmv * copyright notice and this permission notice appear in all copies.
9 1.1 jmmv *
10 1.1 jmmv * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 1.1 jmmv * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 1.1 jmmv * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 1.1 jmmv * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 1.1 jmmv * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 1.1 jmmv * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 1.1 jmmv * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 1.1 jmmv */
18 1.1 jmmv
19 1.1 jmmv #include <sys/types.h>
20 1.1 jmmv
21 1.1.1.9 christos #include <stdlib.h>
22 1.1 jmmv #include <string.h>
23 1.1 jmmv
24 1.1 jmmv #include "tmux.h"
25 1.1 jmmv
26 1.1.1.9 christos static void screen_redraw_draw_borders(struct screen_redraw_ctx *);
27 1.1.1.9 christos static void screen_redraw_draw_panes(struct screen_redraw_ctx *);
28 1.1.1.9 christos static void screen_redraw_draw_status(struct screen_redraw_ctx *);
29 1.1.1.10 christos static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
30 1.1.1.10 christos struct window_pane *);
31 1.1.1.12 christos static void screen_redraw_set_context(struct client *,
32 1.1.1.12 christos struct screen_redraw_ctx *);
33 1.1 jmmv
34 1.1.1.12 christos #define START_ISOLATE "\342\201\246"
35 1.1.1.12 christos #define END_ISOLATE "\342\201\251"
36 1.1.1.12 christos
37 1.1.1.13 wiz /* Border in relation to a pane. */
38 1.1.1.12 christos enum screen_redraw_border_type {
39 1.1.1.12 christos SCREEN_REDRAW_OUTSIDE,
40 1.1.1.12 christos SCREEN_REDRAW_INSIDE,
41 1.1.1.13 wiz SCREEN_REDRAW_BORDER_LEFT,
42 1.1.1.13 wiz SCREEN_REDRAW_BORDER_RIGHT,
43 1.1.1.13 wiz SCREEN_REDRAW_BORDER_TOP,
44 1.1.1.13 wiz SCREEN_REDRAW_BORDER_BOTTOM
45 1.1.1.12 christos };
46 1.1.1.13 wiz #define BORDER_MARKERS " +,.-"
47 1.1.1.12 christos
48 1.1.1.12 christos /* Get cell border character. */
49 1.1.1.12 christos static void
50 1.1.1.13 wiz screen_redraw_border_set(struct window *w, struct window_pane *wp,
51 1.1.1.13 wiz enum pane_lines pane_lines, int cell_type, struct grid_cell *gc)
52 1.1.1.12 christos {
53 1.1.1.12 christos u_int idx;
54 1.1.1.12 christos
55 1.1.1.13 wiz if (cell_type == CELL_OUTSIDE && w->fill_character != NULL) {
56 1.1.1.13 wiz utf8_copy(&gc->data, &w->fill_character[0]);
57 1.1.1.13 wiz return;
58 1.1.1.13 wiz }
59 1.1.1.13 wiz
60 1.1.1.12 christos switch (pane_lines) {
61 1.1.1.12 christos case PANE_LINES_NUMBER:
62 1.1.1.12 christos if (cell_type == CELL_OUTSIDE) {
63 1.1.1.12 christos gc->attr |= GRID_ATTR_CHARSET;
64 1.1.1.12 christos utf8_set(&gc->data, CELL_BORDERS[CELL_OUTSIDE]);
65 1.1.1.12 christos break;
66 1.1.1.12 christos }
67 1.1.1.12 christos gc->attr &= ~GRID_ATTR_CHARSET;
68 1.1.1.12 christos if (wp != NULL && window_pane_index(wp, &idx) == 0)
69 1.1.1.12 christos utf8_set(&gc->data, '0' + (idx % 10));
70 1.1.1.12 christos else
71 1.1.1.12 christos utf8_set(&gc->data, '*');
72 1.1.1.12 christos break;
73 1.1.1.12 christos case PANE_LINES_DOUBLE:
74 1.1.1.12 christos gc->attr &= ~GRID_ATTR_CHARSET;
75 1.1.1.13 wiz utf8_copy(&gc->data, tty_acs_double_borders(cell_type));
76 1.1.1.12 christos break;
77 1.1.1.12 christos case PANE_LINES_HEAVY:
78 1.1.1.12 christos gc->attr &= ~GRID_ATTR_CHARSET;
79 1.1.1.13 wiz utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
80 1.1.1.12 christos break;
81 1.1.1.12 christos case PANE_LINES_SIMPLE:
82 1.1.1.12 christos gc->attr &= ~GRID_ATTR_CHARSET;
83 1.1.1.13 wiz utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
84 1.1.1.12 christos break;
85 1.1.1.12 christos default:
86 1.1.1.12 christos gc->attr |= GRID_ATTR_CHARSET;
87 1.1.1.12 christos utf8_set(&gc->data, CELL_BORDERS[cell_type]);
88 1.1.1.12 christos break;
89 1.1.1.12 christos }
90 1.1.1.12 christos }
91 1.1.1.12 christos
92 1.1.1.12 christos /* Return if window has only two panes. */
93 1.1.1.7 christos static int
94 1.1.1.12 christos screen_redraw_two_panes(struct window *w, int direction)
95 1.1 jmmv {
96 1.1.1.12 christos struct window_pane *wp;
97 1.1.1.12 christos
98 1.1.1.12 christos wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
99 1.1.1.12 christos if (wp == NULL)
100 1.1.1.12 christos return (0); /* one pane */
101 1.1.1.12 christos if (TAILQ_NEXT(wp, entry) != NULL)
102 1.1.1.12 christos return (0); /* more than two panes */
103 1.1.1.12 christos if (direction == 0 && wp->xoff == 0)
104 1.1.1.12 christos return (0);
105 1.1.1.12 christos if (direction == 1 && wp->yoff == 0)
106 1.1 jmmv return (0);
107 1.1.1.12 christos return (1);
108 1.1.1.12 christos }
109 1.1.1.12 christos
110 1.1.1.12 christos /* Check if cell is on the border of a pane. */
111 1.1.1.12 christos static enum screen_redraw_border_type
112 1.1.1.12 christos screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py,
113 1.1.1.12 christos int pane_status)
114 1.1.1.12 christos {
115 1.1.1.13 wiz struct options *oo = wp->window->options;
116 1.1.1.13 wiz int split = 0;
117 1.1.1.13 wiz u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy;
118 1.1.1.12 christos
119 1.1.1.12 christos /* Inside pane. */
120 1.1.1.12 christos if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey)
121 1.1.1.12 christos return (SCREEN_REDRAW_INSIDE);
122 1.1 jmmv
123 1.1.1.13 wiz /* Get pane indicator. */
124 1.1.1.13 wiz switch (options_get_number(oo, "pane-border-indicators")) {
125 1.1.1.13 wiz case PANE_BORDER_COLOUR:
126 1.1.1.13 wiz case PANE_BORDER_BOTH:
127 1.1.1.13 wiz split = 1;
128 1.1.1.13 wiz break;
129 1.1.1.13 wiz }
130 1.1.1.13 wiz
131 1.1 jmmv /* Left/right borders. */
132 1.1.1.12 christos if (pane_status == PANE_STATUS_OFF) {
133 1.1.1.13 wiz if (screen_redraw_two_panes(wp->window, 0) && split) {
134 1.1.1.12 christos if (wp->xoff == 0 && px == wp->sx && py <= wp->sy / 2)
135 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_RIGHT);
136 1.1.1.12 christos if (wp->xoff != 0 &&
137 1.1.1.12 christos px == wp->xoff - 1 &&
138 1.1.1.12 christos py > wp->sy / 2)
139 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_LEFT);
140 1.1.1.12 christos } else {
141 1.1.1.12 christos if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
142 1.1.1.12 christos if (wp->xoff != 0 && px == wp->xoff - 1)
143 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_LEFT);
144 1.1.1.12 christos if (px == ex)
145 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_RIGHT);
146 1.1.1.12 christos }
147 1.1.1.12 christos }
148 1.1.1.12 christos } else {
149 1.1.1.12 christos if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
150 1.1.1.12 christos if (wp->xoff != 0 && px == wp->xoff - 1)
151 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_LEFT);
152 1.1.1.12 christos if (px == ex)
153 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_RIGHT);
154 1.1.1.12 christos }
155 1.1 jmmv }
156 1.1 jmmv
157 1.1 jmmv /* Top/bottom borders. */
158 1.1.1.12 christos if (pane_status == PANE_STATUS_OFF) {
159 1.1.1.13 wiz if (screen_redraw_two_panes(wp->window, 1) && split) {
160 1.1.1.12 christos if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2)
161 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_BOTTOM);
162 1.1.1.12 christos if (wp->yoff != 0 &&
163 1.1.1.12 christos py == wp->yoff - 1 &&
164 1.1.1.12 christos px > wp->sx / 2)
165 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_TOP);
166 1.1.1.12 christos } else {
167 1.1.1.12 christos if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
168 1.1.1.12 christos if (wp->yoff != 0 && py == wp->yoff - 1)
169 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_TOP);
170 1.1.1.12 christos if (py == ey)
171 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_BOTTOM);
172 1.1.1.12 christos }
173 1.1.1.12 christos }
174 1.1.1.12 christos } else if (pane_status == PANE_STATUS_TOP) {
175 1.1.1.12 christos if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
176 1.1.1.12 christos if (wp->yoff != 0 && py == wp->yoff - 1)
177 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_TOP);
178 1.1.1.12 christos }
179 1.1.1.12 christos } else {
180 1.1.1.12 christos if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
181 1.1.1.12 christos if (py == ey)
182 1.1.1.13 wiz return (SCREEN_REDRAW_BORDER_BOTTOM);
183 1.1.1.12 christos }
184 1.1 jmmv }
185 1.1 jmmv
186 1.1 jmmv /* Outside pane. */
187 1.1.1.12 christos return (SCREEN_REDRAW_OUTSIDE);
188 1.1 jmmv }
189 1.1 jmmv
190 1.1.1.12 christos /* Check if a cell is on a border. */
191 1.1.1.7 christos static int
192 1.1.1.12 christos screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status)
193 1.1 jmmv {
194 1.1 jmmv struct window *w = c->session->curw->window;
195 1.1 jmmv struct window_pane *wp;
196 1.1.1.12 christos
197 1.1.1.12 christos /* Outside the window? */
198 1.1.1.12 christos if (px > w->sx || py > w->sy)
199 1.1.1.12 christos return (0);
200 1.1.1.12 christos
201 1.1.1.12 christos /* On the window border? */
202 1.1.1.12 christos if (px == w->sx || py == w->sy)
203 1.1.1.12 christos return (1);
204 1.1 jmmv
205 1.1 jmmv /* Check all the panes. */
206 1.1 jmmv TAILQ_FOREACH(wp, &w->panes, entry) {
207 1.1 jmmv if (!window_pane_visible(wp))
208 1.1 jmmv continue;
209 1.1.1.12 christos switch (screen_redraw_pane_border(wp, px, py, pane_status)) {
210 1.1.1.12 christos case SCREEN_REDRAW_INSIDE:
211 1.1.1.12 christos return (0);
212 1.1.1.12 christos case SCREEN_REDRAW_OUTSIDE:
213 1.1.1.12 christos break;
214 1.1.1.13 wiz default:
215 1.1.1.13 wiz return (1);
216 1.1.1.12 christos }
217 1.1 jmmv }
218 1.1 jmmv
219 1.1 jmmv return (0);
220 1.1 jmmv }
221 1.1 jmmv
222 1.1.1.12 christos /* Work out type of border cell from surrounding cells. */
223 1.1.1.12 christos static int
224 1.1.1.12 christos screen_redraw_type_of_cell(struct client *c, u_int px, u_int py,
225 1.1.1.12 christos int pane_status)
226 1.1.1.12 christos {
227 1.1.1.12 christos struct window *w = c->session->curw->window;
228 1.1.1.12 christos u_int sx = w->sx, sy = w->sy;
229 1.1.1.12 christos int borders = 0;
230 1.1.1.12 christos
231 1.1.1.12 christos /* Is this outside the window? */
232 1.1.1.12 christos if (px > sx || py > sy)
233 1.1.1.12 christos return (CELL_OUTSIDE);
234 1.1.1.12 christos
235 1.1.1.12 christos /*
236 1.1.1.12 christos * Construct a bitmask of whether the cells to the left (bit 4), right,
237 1.1.1.12 christos * top, and bottom (bit 1) of this cell are borders.
238 1.1.1.12 christos */
239 1.1.1.12 christos if (px == 0 || screen_redraw_cell_border(c, px - 1, py, pane_status))
240 1.1.1.12 christos borders |= 8;
241 1.1.1.12 christos if (px <= sx && screen_redraw_cell_border(c, px + 1, py, pane_status))
242 1.1.1.12 christos borders |= 4;
243 1.1.1.12 christos if (pane_status == PANE_STATUS_TOP) {
244 1.1.1.12 christos if (py != 0 &&
245 1.1.1.12 christos screen_redraw_cell_border(c, px, py - 1, pane_status))
246 1.1.1.12 christos borders |= 2;
247 1.1.1.12 christos if (screen_redraw_cell_border(c, px, py + 1, pane_status))
248 1.1.1.12 christos borders |= 1;
249 1.1.1.12 christos } else if (pane_status == PANE_STATUS_BOTTOM) {
250 1.1.1.12 christos if (py == 0 ||
251 1.1.1.12 christos screen_redraw_cell_border(c, px, py - 1, pane_status))
252 1.1.1.12 christos borders |= 2;
253 1.1.1.12 christos if (py != sy - 1 &&
254 1.1.1.12 christos screen_redraw_cell_border(c, px, py + 1, pane_status))
255 1.1.1.12 christos borders |= 1;
256 1.1.1.12 christos } else {
257 1.1.1.12 christos if (py == 0 ||
258 1.1.1.12 christos screen_redraw_cell_border(c, px, py - 1, pane_status))
259 1.1.1.12 christos borders |= 2;
260 1.1.1.12 christos if (screen_redraw_cell_border(c, px, py + 1, pane_status))
261 1.1.1.12 christos borders |= 1;
262 1.1.1.12 christos }
263 1.1.1.12 christos
264 1.1.1.12 christos /*
265 1.1.1.12 christos * Figure out what kind of border this cell is. Only one bit set
266 1.1.1.12 christos * doesn't make sense (can't have a border cell with no others
267 1.1.1.12 christos * connected).
268 1.1.1.12 christos */
269 1.1.1.12 christos switch (borders) {
270 1.1.1.12 christos case 15: /* 1111, left right top bottom */
271 1.1.1.12 christos return (CELL_JOIN);
272 1.1.1.12 christos case 14: /* 1110, left right top */
273 1.1.1.12 christos return (CELL_BOTTOMJOIN);
274 1.1.1.12 christos case 13: /* 1101, left right bottom */
275 1.1.1.12 christos return (CELL_TOPJOIN);
276 1.1.1.12 christos case 12: /* 1100, left right */
277 1.1.1.12 christos return (CELL_LEFTRIGHT);
278 1.1.1.12 christos case 11: /* 1011, left top bottom */
279 1.1.1.12 christos return (CELL_RIGHTJOIN);
280 1.1.1.12 christos case 10: /* 1010, left top */
281 1.1.1.12 christos return (CELL_BOTTOMRIGHT);
282 1.1.1.12 christos case 9: /* 1001, left bottom */
283 1.1.1.12 christos return (CELL_TOPRIGHT);
284 1.1.1.12 christos case 7: /* 0111, right top bottom */
285 1.1.1.12 christos return (CELL_LEFTJOIN);
286 1.1.1.12 christos case 6: /* 0110, right top */
287 1.1.1.12 christos return (CELL_BOTTOMLEFT);
288 1.1.1.12 christos case 5: /* 0101, right bottom */
289 1.1.1.12 christos return (CELL_TOPLEFT);
290 1.1.1.12 christos case 3: /* 0011, top bottom */
291 1.1.1.12 christos return (CELL_TOPBOTTOM);
292 1.1.1.12 christos }
293 1.1.1.12 christos return (CELL_OUTSIDE);
294 1.1.1.12 christos }
295 1.1.1.12 christos
296 1.1 jmmv /* Check if cell inside a pane. */
297 1.1.1.7 christos static int
298 1.1.1.7 christos screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
299 1.1.1.3 christos struct window_pane **wpp)
300 1.1 jmmv {
301 1.1 jmmv struct window *w = c->session->curw->window;
302 1.1.1.12 christos struct window_pane *wp, *active;
303 1.1.1.12 christos int border;
304 1.1.1.7 christos u_int right, line;
305 1.1.1.7 christos
306 1.1.1.7 christos *wpp = NULL;
307 1.1 jmmv
308 1.1 jmmv if (px > w->sx || py > w->sy)
309 1.1 jmmv return (CELL_OUTSIDE);
310 1.1.1.12 christos if (px == w->sx || py == w->sy) /* window border */
311 1.1.1.12 christos return (screen_redraw_type_of_cell(c, px, py, pane_status));
312 1.1 jmmv
313 1.1.1.11 christos if (pane_status != PANE_STATUS_OFF) {
314 1.1.1.12 christos active = wp = server_client_get_pane(c);
315 1.1.1.12 christos do {
316 1.1.1.7 christos if (!window_pane_visible(wp))
317 1.1.1.12 christos goto next1;
318 1.1.1.7 christos
319 1.1.1.11 christos if (pane_status == PANE_STATUS_TOP)
320 1.1.1.7 christos line = wp->yoff - 1;
321 1.1.1.7 christos else
322 1.1.1.7 christos line = wp->yoff + wp->sy;
323 1.1.1.7 christos right = wp->xoff + 2 + wp->status_size - 1;
324 1.1.1.7 christos
325 1.1.1.7 christos if (py == line && px >= wp->xoff + 2 && px <= right)
326 1.1.1.7 christos return (CELL_INSIDE);
327 1.1.1.12 christos
328 1.1.1.12 christos next1:
329 1.1.1.12 christos wp = TAILQ_NEXT(wp, entry);
330 1.1.1.12 christos if (wp == NULL)
331 1.1.1.12 christos wp = TAILQ_FIRST(&w->panes);
332 1.1.1.12 christos } while (wp != active);
333 1.1.1.7 christos }
334 1.1.1.7 christos
335 1.1.1.12 christos active = wp = server_client_get_pane(c);
336 1.1.1.12 christos do {
337 1.1 jmmv if (!window_pane_visible(wp))
338 1.1.1.12 christos goto next2;
339 1.1.1.3 christos *wpp = wp;
340 1.1 jmmv
341 1.1 jmmv /*
342 1.1.1.12 christos * If definitely inside, return. If not on border, skip.
343 1.1.1.12 christos * Otherwise work out the cell.
344 1.1 jmmv */
345 1.1.1.12 christos border = screen_redraw_pane_border(wp, px, py, pane_status);
346 1.1.1.12 christos if (border == SCREEN_REDRAW_INSIDE)
347 1.1.1.12 christos return (CELL_INSIDE);
348 1.1.1.12 christos if (border == SCREEN_REDRAW_OUTSIDE)
349 1.1.1.12 christos goto next2;
350 1.1.1.12 christos return (screen_redraw_type_of_cell(c, px, py, pane_status));
351 1.1.1.12 christos
352 1.1.1.12 christos next2:
353 1.1.1.12 christos wp = TAILQ_NEXT(wp, entry);
354 1.1.1.12 christos if (wp == NULL)
355 1.1.1.12 christos wp = TAILQ_FIRST(&w->panes);
356 1.1.1.12 christos } while (wp != active);
357 1.1 jmmv
358 1.1 jmmv return (CELL_OUTSIDE);
359 1.1 jmmv }
360 1.1 jmmv
361 1.1.1.5 christos /* Check if the border of a particular pane. */
362 1.1.1.7 christos static int
363 1.1.1.12 christos screen_redraw_check_is(u_int px, u_int py, int pane_status,
364 1.1.1.12 christos struct window_pane *wp)
365 1.1.1.3 christos {
366 1.1.1.12 christos enum screen_redraw_border_type border;
367 1.1.1.3 christos
368 1.1.1.12 christos border = screen_redraw_pane_border(wp, px, py, pane_status);
369 1.1.1.13 wiz if (border != SCREEN_REDRAW_INSIDE && border != SCREEN_REDRAW_OUTSIDE)
370 1.1.1.3 christos return (1);
371 1.1.1.12 christos return (0);
372 1.1.1.7 christos }
373 1.1.1.7 christos
374 1.1.1.7 christos /* Update pane status. */
375 1.1.1.7 christos static int
376 1.1.1.12 christos screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
377 1.1.1.13 wiz struct screen_redraw_ctx *rctx, enum pane_lines pane_lines)
378 1.1.1.7 christos {
379 1.1.1.12 christos struct window *w = wp->window;
380 1.1.1.7 christos struct grid_cell gc;
381 1.1.1.7 christos const char *fmt;
382 1.1.1.7 christos struct format_tree *ft;
383 1.1.1.10 christos char *expanded;
384 1.1.1.12 christos int pane_status = rctx->pane_status;
385 1.1.1.12 christos u_int width, i, cell_type, px, py;
386 1.1.1.7 christos struct screen_write_ctx ctx;
387 1.1.1.7 christos struct screen old;
388 1.1.1.7 christos
389 1.1.1.12 christos ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS);
390 1.1.1.12 christos format_defaults(ft, c, c->session, c->session->curw, wp);
391 1.1.1.7 christos
392 1.1.1.12 christos if (wp == server_client_get_pane(c))
393 1.1.1.12 christos style_apply(&gc, w->options, "pane-active-border-style", ft);
394 1.1.1.12 christos else
395 1.1.1.12 christos style_apply(&gc, w->options, "pane-border-style", ft);
396 1.1.1.13 wiz fmt = options_get_string(wp->options, "pane-border-format");
397 1.1.1.7 christos
398 1.1.1.10 christos expanded = format_expand_time(ft, fmt);
399 1.1.1.10 christos if (wp->sx < 4)
400 1.1.1.10 christos wp->status_size = width = 0;
401 1.1.1.10 christos else
402 1.1.1.10 christos wp->status_size = width = wp->sx - 4;
403 1.1.1.10 christos
404 1.1.1.7 christos memcpy(&old, &wp->status_screen, sizeof old);
405 1.1.1.10 christos screen_init(&wp->status_screen, width, 1, 0);
406 1.1.1.7 christos wp->status_screen.mode = 0;
407 1.1.1.7 christos
408 1.1.1.12 christos screen_write_start(&ctx, &wp->status_screen);
409 1.1.1.10 christos
410 1.1.1.12 christos for (i = 0; i < width; i++) {
411 1.1.1.12 christos px = wp->xoff + 2 + i;
412 1.1.1.12 christos if (rctx->pane_status == PANE_STATUS_TOP)
413 1.1.1.12 christos py = wp->yoff - 1;
414 1.1.1.12 christos else
415 1.1.1.12 christos py = wp->yoff + wp->sy;
416 1.1.1.12 christos cell_type = screen_redraw_type_of_cell(c, px, py, pane_status);
417 1.1.1.13 wiz screen_redraw_border_set(w, wp, pane_lines, cell_type, &gc);
418 1.1.1.12 christos screen_write_cell(&ctx, &gc);
419 1.1.1.12 christos }
420 1.1.1.10 christos gc.attr &= ~GRID_ATTR_CHARSET;
421 1.1.1.10 christos
422 1.1.1.10 christos screen_write_cursormove(&ctx, 0, 0, 0);
423 1.1.1.13 wiz format_draw(&ctx, &gc, width, expanded, NULL, 0);
424 1.1.1.7 christos screen_write_stop(&ctx);
425 1.1.1.7 christos
426 1.1.1.10 christos free(expanded);
427 1.1.1.7 christos format_free(ft);
428 1.1.1.7 christos
429 1.1.1.7 christos if (grid_compare(wp->status_screen.grid, old.grid) == 0) {
430 1.1.1.7 christos screen_free(&old);
431 1.1.1.7 christos return (0);
432 1.1.1.7 christos }
433 1.1.1.7 christos screen_free(&old);
434 1.1.1.7 christos return (1);
435 1.1.1.7 christos }
436 1.1.1.7 christos
437 1.1.1.7 christos /* Draw pane status. */
438 1.1.1.7 christos static void
439 1.1.1.10 christos screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
440 1.1.1.7 christos {
441 1.1.1.10 christos struct client *c = ctx->c;
442 1.1.1.7 christos struct window *w = c->session->curw->window;
443 1.1.1.7 christos struct tty *tty = &c->tty;
444 1.1.1.7 christos struct window_pane *wp;
445 1.1.1.10 christos struct screen *s;
446 1.1.1.10 christos u_int i, x, width, xoff, yoff, size;
447 1.1.1.10 christos
448 1.1.1.10 christos log_debug("%s: %s @%u", __func__, c->name, w->id);
449 1.1.1.7 christos
450 1.1.1.7 christos TAILQ_FOREACH(wp, &w->panes, entry) {
451 1.1.1.7 christos if (!window_pane_visible(wp))
452 1.1.1.7 christos continue;
453 1.1.1.10 christos s = &wp->status_screen;
454 1.1.1.10 christos
455 1.1.1.10 christos size = wp->status_size;
456 1.1.1.11 christos if (ctx->pane_status == PANE_STATUS_TOP)
457 1.1.1.7 christos yoff = wp->yoff - 1;
458 1.1.1.7 christos else
459 1.1.1.7 christos yoff = wp->yoff + wp->sy;
460 1.1.1.10 christos xoff = wp->xoff + 2;
461 1.1.1.10 christos
462 1.1.1.10 christos if (xoff + size <= ctx->ox ||
463 1.1.1.10 christos xoff >= ctx->ox + ctx->sx ||
464 1.1.1.10 christos yoff < ctx->oy ||
465 1.1.1.10 christos yoff >= ctx->oy + ctx->sy)
466 1.1.1.10 christos continue;
467 1.1.1.7 christos
468 1.1.1.10 christos if (xoff >= ctx->ox && xoff + size <= ctx->ox + ctx->sx) {
469 1.1.1.10 christos /* All visible. */
470 1.1.1.10 christos i = 0;
471 1.1.1.10 christos x = xoff - ctx->ox;
472 1.1.1.10 christos width = size;
473 1.1.1.10 christos } else if (xoff < ctx->ox && xoff + size > ctx->ox + ctx->sx) {
474 1.1.1.10 christos /* Both left and right not visible. */
475 1.1.1.10 christos i = ctx->ox;
476 1.1.1.10 christos x = 0;
477 1.1.1.10 christos width = ctx->sx;
478 1.1.1.10 christos } else if (xoff < ctx->ox) {
479 1.1.1.10 christos /* Left not visible. */
480 1.1.1.10 christos i = ctx->ox - xoff;
481 1.1.1.10 christos x = 0;
482 1.1.1.10 christos width = size - i;
483 1.1.1.10 christos } else {
484 1.1.1.10 christos /* Right not visible. */
485 1.1.1.10 christos i = 0;
486 1.1.1.10 christos x = xoff - ctx->ox;
487 1.1.1.10 christos width = size - x;
488 1.1.1.10 christos }
489 1.1.1.10 christos
490 1.1.1.11 christos if (ctx->statustop)
491 1.1.1.11 christos yoff += ctx->statuslines;
492 1.1.1.12 christos tty_draw_line(tty, s, i, 0, width, x, yoff - ctx->oy,
493 1.1.1.12 christos &grid_default_cell, NULL);
494 1.1.1.7 christos }
495 1.1.1.7 christos tty_cursor(tty, 0, 0);
496 1.1.1.7 christos }
497 1.1.1.7 christos
498 1.1.1.7 christos /* Update status line and change flags if unchanged. */
499 1.1.1.10 christos static int
500 1.1.1.10 christos screen_redraw_update(struct client *c, int flags)
501 1.1.1.7 christos {
502 1.1.1.13 wiz struct window *w = c->session->curw->window;
503 1.1.1.13 wiz struct window_pane *wp;
504 1.1.1.13 wiz struct options *wo = w->options;
505 1.1.1.13 wiz int redraw;
506 1.1.1.13 wiz enum pane_lines lines;
507 1.1.1.13 wiz struct screen_redraw_ctx ctx;
508 1.1.1.7 christos
509 1.1.1.7 christos if (c->message_string != NULL)
510 1.1.1.7 christos redraw = status_message_redraw(c);
511 1.1.1.7 christos else if (c->prompt_string != NULL)
512 1.1.1.7 christos redraw = status_prompt_redraw(c);
513 1.1.1.7 christos else
514 1.1.1.7 christos redraw = status_redraw(c);
515 1.1.1.10 christos if (!redraw && (~flags & CLIENT_REDRAWSTATUSALWAYS))
516 1.1.1.10 christos flags &= ~CLIENT_REDRAWSTATUS;
517 1.1.1.7 christos
518 1.1.1.11 christos if (c->overlay_draw != NULL)
519 1.1.1.11 christos flags |= CLIENT_REDRAWOVERLAY;
520 1.1.1.11 christos
521 1.1.1.11 christos if (options_get_number(wo, "pane-border-status") != PANE_STATUS_OFF) {
522 1.1.1.12 christos screen_redraw_set_context(c, &ctx);
523 1.1.1.12 christos lines = options_get_number(wo, "pane-border-lines");
524 1.1.1.7 christos redraw = 0;
525 1.1.1.7 christos TAILQ_FOREACH(wp, &w->panes, entry) {
526 1.1.1.12 christos if (screen_redraw_make_pane_status(c, wp, &ctx, lines))
527 1.1.1.7 christos redraw = 1;
528 1.1.1.7 christos }
529 1.1.1.7 christos if (redraw)
530 1.1.1.10 christos flags |= CLIENT_REDRAWBORDERS;
531 1.1.1.7 christos }
532 1.1.1.10 christos return (flags);
533 1.1.1.3 christos }
534 1.1.1.3 christos
535 1.1.1.10 christos /* Set up redraw context. */
536 1.1.1.10 christos static void
537 1.1.1.10 christos screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
538 1.1 jmmv {
539 1.1.1.10 christos struct session *s = c->session;
540 1.1.1.10 christos struct options *oo = s->options;
541 1.1.1.10 christos struct window *w = s->curw->window;
542 1.1.1.10 christos struct options *wo = w->options;
543 1.1.1.11 christos u_int lines;
544 1.1.1.2 jmmv
545 1.1.1.10 christos memset(ctx, 0, sizeof *ctx);
546 1.1.1.10 christos ctx->c = c;
547 1.1.1.9 christos
548 1.1.1.11 christos lines = status_line_size(c);
549 1.1.1.9 christos if (c->message_string != NULL || c->prompt_string != NULL)
550 1.1.1.11 christos lines = (lines == 0) ? 1 : lines;
551 1.1.1.11 christos if (lines != 0 && options_get_number(oo, "status-position") == 0)
552 1.1.1.11 christos ctx->statustop = 1;
553 1.1.1.11 christos ctx->statuslines = lines;
554 1.1.1.11 christos
555 1.1.1.10 christos ctx->pane_status = options_get_number(wo, "pane-border-status");
556 1.1.1.12 christos ctx->pane_lines = options_get_number(wo, "pane-border-lines");
557 1.1.1.9 christos
558 1.1.1.10 christos tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy);
559 1.1.1.10 christos
560 1.1.1.10 christos log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__, c->name,
561 1.1.1.11 christos w->id, ctx->ox, ctx->oy, ctx->sx, ctx->sy, ctx->statuslines,
562 1.1.1.11 christos ctx->statustop);
563 1.1.1.10 christos }
564 1.1.1.10 christos
565 1.1.1.10 christos /* Redraw entire screen. */
566 1.1.1.10 christos void
567 1.1.1.10 christos screen_redraw_screen(struct client *c)
568 1.1.1.10 christos {
569 1.1.1.10 christos struct screen_redraw_ctx ctx;
570 1.1.1.10 christos int flags;
571 1.1.1.9 christos
572 1.1.1.10 christos if (c->flags & CLIENT_SUSPENDED)
573 1.1.1.10 christos return;
574 1.1.1.9 christos
575 1.1.1.10 christos flags = screen_redraw_update(c, c->flags);
576 1.1.1.12 christos if ((flags & CLIENT_ALLREDRAWFLAGS) == 0)
577 1.1.1.12 christos return;
578 1.1.1.12 christos
579 1.1.1.10 christos screen_redraw_set_context(c, &ctx);
580 1.1.1.12 christos tty_sync_start(&c->tty);
581 1.1.1.12 christos tty_update_mode(&c->tty, c->tty.mode, NULL);
582 1.1.1.3 christos
583 1.1.1.10 christos if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) {
584 1.1.1.12 christos log_debug("%s: redrawing borders", c->name);
585 1.1.1.11 christos if (ctx.pane_status != PANE_STATUS_OFF)
586 1.1.1.10 christos screen_redraw_draw_pane_status(&ctx);
587 1.1.1.9 christos screen_redraw_draw_borders(&ctx);
588 1.1.1.7 christos }
589 1.1.1.12 christos if (flags & CLIENT_REDRAWWINDOW) {
590 1.1.1.12 christos log_debug("%s: redrawing panes", c->name);
591 1.1.1.9 christos screen_redraw_draw_panes(&ctx);
592 1.1.1.12 christos }
593 1.1.1.11 christos if (ctx.statuslines != 0 &&
594 1.1.1.12 christos (flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))) {
595 1.1.1.12 christos log_debug("%s: redrawing status", c->name);
596 1.1.1.9 christos screen_redraw_draw_status(&ctx);
597 1.1.1.12 christos }
598 1.1.1.12 christos if (c->overlay_draw != NULL && (flags & CLIENT_REDRAWOVERLAY)) {
599 1.1.1.12 christos log_debug("%s: redrawing overlay", c->name);
600 1.1.1.13 wiz c->overlay_draw(c, c->overlay_data, &ctx);
601 1.1.1.12 christos }
602 1.1.1.12 christos
603 1.1.1.10 christos tty_reset(&c->tty);
604 1.1.1.3 christos }
605 1.1 jmmv
606 1.1.1.10 christos /* Redraw a single pane. */
607 1.1.1.3 christos void
608 1.1.1.3 christos screen_redraw_pane(struct client *c, struct window_pane *wp)
609 1.1.1.3 christos {
610 1.1.1.10 christos struct screen_redraw_ctx ctx;
611 1.1.1.3 christos
612 1.1.1.13 wiz if (!window_pane_visible(wp))
613 1.1 jmmv return;
614 1.1 jmmv
615 1.1.1.10 christos screen_redraw_set_context(c, &ctx);
616 1.1.1.12 christos tty_sync_start(&c->tty);
617 1.1.1.12 christos tty_update_mode(&c->tty, c->tty.mode, NULL);
618 1.1.1.7 christos
619 1.1.1.10 christos screen_redraw_draw_pane(&ctx, wp);
620 1.1.1.12 christos
621 1.1.1.3 christos tty_reset(&c->tty);
622 1.1.1.3 christos }
623 1.1.1.3 christos
624 1.1.1.12 christos /* Get border cell style. */
625 1.1.1.12 christos static const struct grid_cell *
626 1.1.1.12 christos screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x,
627 1.1.1.12 christos u_int y, struct window_pane *wp)
628 1.1.1.12 christos {
629 1.1.1.12 christos struct client *c = ctx->c;
630 1.1.1.12 christos struct session *s = c->session;
631 1.1.1.12 christos struct window *w = s->curw->window;
632 1.1.1.12 christos struct window_pane *active = server_client_get_pane(c);
633 1.1.1.12 christos struct options *oo = w->options;
634 1.1.1.12 christos struct format_tree *ft;
635 1.1.1.12 christos
636 1.1.1.12 christos if (wp->border_gc_set)
637 1.1.1.12 christos return (&wp->border_gc);
638 1.1.1.12 christos wp->border_gc_set = 1;
639 1.1.1.12 christos
640 1.1.1.12 christos ft = format_create_defaults(NULL, c, s, s->curw, wp);
641 1.1.1.12 christos if (screen_redraw_check_is(x, y, ctx->pane_status, active))
642 1.1.1.12 christos style_apply(&wp->border_gc, oo, "pane-active-border-style", ft);
643 1.1.1.12 christos else
644 1.1.1.12 christos style_apply(&wp->border_gc, oo, "pane-border-style", ft);
645 1.1.1.12 christos format_free(ft);
646 1.1.1.12 christos
647 1.1.1.12 christos return (&wp->border_gc);
648 1.1.1.12 christos }
649 1.1.1.12 christos
650 1.1.1.9 christos /* Draw a border cell. */
651 1.1.1.9 christos static void
652 1.1.1.12 christos screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
653 1.1.1.10 christos {
654 1.1.1.10 christos struct client *c = ctx->c;
655 1.1.1.10 christos struct session *s = c->session;
656 1.1.1.13 wiz struct window *w = s->curw->window;
657 1.1.1.13 wiz struct options *oo = w->options;
658 1.1.1.10 christos struct tty *tty = &c->tty;
659 1.1.1.13 wiz struct format_tree *ft;
660 1.1.1.13 wiz struct window_pane *wp, *active = server_client_get_pane(c);
661 1.1.1.12 christos struct grid_cell gc;
662 1.1.1.12 christos const struct grid_cell *tmp;
663 1.1.1.13 wiz struct overlay_ranges r;
664 1.1.1.13 wiz u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
665 1.1.1.13 wiz int arrows = 0, border;
666 1.1.1.13 wiz int pane_status = ctx->pane_status, isolates;
667 1.1.1.9 christos
668 1.1.1.13 wiz if (c->overlay_check != NULL) {
669 1.1.1.13 wiz c->overlay_check(c, c->overlay_data, x, y, 1, &r);
670 1.1.1.13 wiz if (r.nx[0] + r.nx[1] == 0)
671 1.1.1.13 wiz return;
672 1.1.1.13 wiz }
673 1.1.1.9 christos
674 1.1.1.12 christos cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
675 1.1.1.12 christos if (cell_type == CELL_INSIDE)
676 1.1.1.12 christos return;
677 1.1.1.12 christos
678 1.1.1.13 wiz if (wp == NULL) {
679 1.1.1.13 wiz if (!ctx->no_pane_gc_set) {
680 1.1.1.13 wiz ft = format_create_defaults(NULL, c, s, s->curw, NULL);
681 1.1.1.13 wiz memcpy(&ctx->no_pane_gc, &grid_default_cell, sizeof gc);
682 1.1.1.13 wiz style_add(&ctx->no_pane_gc, oo, "pane-border-style",
683 1.1.1.13 wiz ft);
684 1.1.1.13 wiz format_free(ft);
685 1.1.1.13 wiz ctx->no_pane_gc_set = 1;
686 1.1.1.13 wiz }
687 1.1.1.13 wiz memcpy(&gc, &ctx->no_pane_gc, sizeof gc);
688 1.1.1.13 wiz } else {
689 1.1.1.12 christos tmp = screen_redraw_draw_borders_style(ctx, x, y, wp);
690 1.1.1.12 christos if (tmp == NULL)
691 1.1.1.12 christos return;
692 1.1.1.12 christos memcpy(&gc, tmp, sizeof gc);
693 1.1.1.12 christos
694 1.1.1.12 christos if (server_is_marked(s, s->curw, marked_pane.wp) &&
695 1.1.1.12 christos screen_redraw_check_is(x, y, pane_status, marked_pane.wp))
696 1.1.1.12 christos gc.attr ^= GRID_ATTR_REVERSE;
697 1.1.1.12 christos }
698 1.1.1.13 wiz screen_redraw_border_set(w, wp, ctx->pane_lines, cell_type, &gc);
699 1.1.1.12 christos
700 1.1.1.12 christos if (cell_type == CELL_TOPBOTTOM &&
701 1.1.1.12 christos (c->flags & CLIENT_UTF8) &&
702 1.1.1.12 christos tty_term_has(tty->term, TTYC_BIDI))
703 1.1.1.12 christos isolates = 1;
704 1.1.1.9 christos else
705 1.1.1.12 christos isolates = 0;
706 1.1.1.12 christos
707 1.1.1.11 christos if (ctx->statustop)
708 1.1.1.11 christos tty_cursor(tty, i, ctx->statuslines + j);
709 1.1.1.9 christos else
710 1.1.1.10 christos tty_cursor(tty, i, j);
711 1.1.1.12 christos if (isolates)
712 1.1.1.12 christos tty_puts(tty, END_ISOLATE);
713 1.1.1.13 wiz
714 1.1.1.13 wiz switch (options_get_number(oo, "pane-border-indicators")) {
715 1.1.1.13 wiz case PANE_BORDER_ARROWS:
716 1.1.1.13 wiz case PANE_BORDER_BOTH:
717 1.1.1.13 wiz arrows = 1;
718 1.1.1.13 wiz break;
719 1.1.1.13 wiz }
720 1.1.1.13 wiz
721 1.1.1.13 wiz if (wp != NULL && arrows) {
722 1.1.1.13 wiz border = screen_redraw_pane_border(active, x, y, pane_status);
723 1.1.1.13 wiz if (((i == wp->xoff + 1 &&
724 1.1.1.13 wiz (cell_type == CELL_LEFTRIGHT ||
725 1.1.1.13 wiz (cell_type == CELL_TOPJOIN &&
726 1.1.1.13 wiz border == SCREEN_REDRAW_BORDER_BOTTOM) ||
727 1.1.1.13 wiz (cell_type == CELL_BOTTOMJOIN &&
728 1.1.1.13 wiz border == SCREEN_REDRAW_BORDER_TOP))) ||
729 1.1.1.13 wiz (j == wp->yoff + 1 &&
730 1.1.1.13 wiz (cell_type == CELL_TOPBOTTOM ||
731 1.1.1.13 wiz (cell_type == CELL_LEFTJOIN &&
732 1.1.1.13 wiz border == SCREEN_REDRAW_BORDER_RIGHT) ||
733 1.1.1.13 wiz (cell_type == CELL_RIGHTJOIN &&
734 1.1.1.13 wiz border == SCREEN_REDRAW_BORDER_LEFT)))) &&
735 1.1.1.13 wiz screen_redraw_check_is(x, y, pane_status, active)) {
736 1.1.1.13 wiz gc.attr |= GRID_ATTR_CHARSET;
737 1.1.1.13 wiz utf8_set(&gc.data, BORDER_MARKERS[border]);
738 1.1.1.13 wiz }
739 1.1.1.13 wiz }
740 1.1.1.13 wiz
741 1.1.1.14 wiz tty_cell(tty, &gc, &grid_default_cell, NULL, NULL);
742 1.1.1.12 christos if (isolates)
743 1.1.1.12 christos tty_puts(tty, START_ISOLATE);
744 1.1.1.9 christos }
745 1.1.1.9 christos
746 1.1.1.3 christos /* Draw the borders. */
747 1.1.1.7 christos static void
748 1.1.1.9 christos screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
749 1.1.1.3 christos {
750 1.1.1.9 christos struct client *c = ctx->c;
751 1.1.1.5 christos struct session *s = c->session;
752 1.1.1.5 christos struct window *w = s->curw->window;
753 1.1.1.12 christos struct window_pane *wp;
754 1.1.1.10 christos u_int i, j;
755 1.1.1.10 christos
756 1.1.1.10 christos log_debug("%s: %s @%u", __func__, c->name, w->id);
757 1.1.1.3 christos
758 1.1.1.12 christos TAILQ_FOREACH(wp, &w->panes, entry)
759 1.1.1.12 christos wp->border_gc_set = 0;
760 1.1.1.12 christos
761 1.1.1.12 christos for (j = 0; j < c->tty.sy - ctx->statuslines; j++) {
762 1.1.1.12 christos for (i = 0; i < c->tty.sx; i++)
763 1.1.1.12 christos screen_redraw_draw_borders_cell(ctx, i, j);
764 1.1 jmmv }
765 1.1.1.3 christos }
766 1.1 jmmv
767 1.1.1.3 christos /* Draw the panes. */
768 1.1.1.7 christos static void
769 1.1.1.9 christos screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
770 1.1.1.3 christos {
771 1.1.1.9 christos struct client *c = ctx->c;
772 1.1.1.3 christos struct window *w = c->session->curw->window;
773 1.1.1.3 christos struct window_pane *wp;
774 1.1 jmmv
775 1.1.1.10 christos log_debug("%s: %s @%u", __func__, c->name, w->id);
776 1.1.1.10 christos
777 1.1 jmmv TAILQ_FOREACH(wp, &w->panes, entry) {
778 1.1.1.11 christos if (window_pane_visible(wp))
779 1.1.1.11 christos screen_redraw_draw_pane(ctx, wp);
780 1.1 jmmv }
781 1.1 jmmv }
782 1.1 jmmv
783 1.1.1.3 christos /* Draw the status line. */
784 1.1.1.7 christos static void
785 1.1.1.9 christos screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
786 1.1 jmmv {
787 1.1.1.9 christos struct client *c = ctx->c;
788 1.1.1.10 christos struct window *w = c->session->curw->window;
789 1.1.1.3 christos struct tty *tty = &c->tty;
790 1.1.1.10 christos struct screen *s = c->status.active;
791 1.1.1.9 christos u_int i, y;
792 1.1 jmmv
793 1.1.1.10 christos log_debug("%s: %s @%u", __func__, c->name, w->id);
794 1.1.1.10 christos
795 1.1.1.11 christos if (ctx->statustop)
796 1.1.1.9 christos y = 0;
797 1.1.1.3 christos else
798 1.1.1.11 christos y = c->tty.sy - ctx->statuslines;
799 1.1.1.12 christos for (i = 0; i < ctx->statuslines; i++) {
800 1.1.1.12 christos tty_draw_line(tty, s, 0, i, UINT_MAX, 0, y + i,
801 1.1.1.12 christos &grid_default_cell, NULL);
802 1.1.1.12 christos }
803 1.1.1.10 christos }
804 1.1.1.10 christos
805 1.1.1.10 christos /* Draw one pane. */
806 1.1.1.10 christos static void
807 1.1.1.10 christos screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
808 1.1.1.10 christos {
809 1.1.1.13 wiz struct client *c = ctx->c;
810 1.1.1.13 wiz struct window *w = c->session->curw->window;
811 1.1.1.13 wiz struct tty *tty = &c->tty;
812 1.1.1.13 wiz struct screen *s = wp->screen;
813 1.1.1.13 wiz struct colour_palette *palette = &wp->palette;
814 1.1.1.13 wiz struct grid_cell defaults;
815 1.1.1.13 wiz u_int i, j, top, x, y, width;
816 1.1.1.10 christos
817 1.1.1.10 christos log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id);
818 1.1.1.10 christos
819 1.1.1.10 christos if (wp->xoff + wp->sx <= ctx->ox || wp->xoff >= ctx->ox + ctx->sx)
820 1.1.1.10 christos return;
821 1.1.1.11 christos if (ctx->statustop)
822 1.1.1.11 christos top = ctx->statuslines;
823 1.1.1.10 christos else
824 1.1.1.10 christos top = 0;
825 1.1.1.10 christos for (j = 0; j < wp->sy; j++) {
826 1.1.1.10 christos if (wp->yoff + j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy)
827 1.1.1.10 christos continue;
828 1.1.1.10 christos y = top + wp->yoff + j - ctx->oy;
829 1.1.1.10 christos
830 1.1.1.10 christos if (wp->xoff >= ctx->ox &&
831 1.1.1.10 christos wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
832 1.1.1.10 christos /* All visible. */
833 1.1.1.10 christos i = 0;
834 1.1.1.10 christos x = wp->xoff - ctx->ox;
835 1.1.1.10 christos width = wp->sx;
836 1.1.1.10 christos } else if (wp->xoff < ctx->ox &&
837 1.1.1.10 christos wp->xoff + wp->sx > ctx->ox + ctx->sx) {
838 1.1.1.10 christos /* Both left and right not visible. */
839 1.1.1.10 christos i = ctx->ox;
840 1.1.1.10 christos x = 0;
841 1.1.1.10 christos width = ctx->sx;
842 1.1.1.10 christos } else if (wp->xoff < ctx->ox) {
843 1.1.1.10 christos /* Left not visible. */
844 1.1.1.10 christos i = ctx->ox - wp->xoff;
845 1.1.1.10 christos x = 0;
846 1.1.1.10 christos width = wp->sx - i;
847 1.1.1.10 christos } else {
848 1.1.1.10 christos /* Right not visible. */
849 1.1.1.10 christos i = 0;
850 1.1.1.10 christos x = wp->xoff - ctx->ox;
851 1.1.1.10 christos width = ctx->sx - x;
852 1.1.1.10 christos }
853 1.1.1.10 christos log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
854 1.1.1.10 christos __func__, c->name, wp->id, i, j, x, y, width);
855 1.1.1.10 christos
856 1.1.1.12 christos tty_default_colours(&defaults, wp);
857 1.1.1.13 wiz tty_draw_line(tty, s, i, j, width, x, y, &defaults, palette);
858 1.1.1.10 christos }
859 1.1.1.14 wiz
860 1.1.1.14 wiz #ifdef ENABLE_SIXEL
861 1.1.1.14 wiz tty_draw_images(c, wp, s);
862 1.1.1.14 wiz #endif
863 1.1 jmmv }
864