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