xref: /openbsd-src/usr.bin/tmux/tty.c (revision aa997e528a848ca5596493c2a801bdd6fb26ae61)
1 /* $OpenBSD: tty.c,v 1.300 2018/02/04 10:10:39 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2007 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 #include <sys/ioctl.h>
21 
22 #include <netinet/in.h>
23 
24 #include <curses.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <resolv.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <termios.h>
31 #include <unistd.h>
32 
33 #include "tmux.h"
34 
35 static int	tty_log_fd = -1;
36 
37 static int	tty_client_ready(struct client *, struct window_pane *);
38 
39 static void	tty_set_italics(struct tty *);
40 static int	tty_try_colour(struct tty *, int, const char *);
41 static void	tty_force_cursor_colour(struct tty *, const char *);
42 static void	tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int,
43 		    u_int);
44 static void	tty_cursor_pane_unless_wrap(struct tty *,
45 		    const struct tty_ctx *, u_int, u_int);
46 static void	tty_invalidate(struct tty *);
47 static void	tty_colours(struct tty *, const struct grid_cell *);
48 static void	tty_check_fg(struct tty *, const struct window_pane *,
49 		    struct grid_cell *);
50 static void	tty_check_bg(struct tty *, const struct window_pane *,
51 		    struct grid_cell *);
52 static void	tty_colours_fg(struct tty *, const struct grid_cell *);
53 static void	tty_colours_bg(struct tty *, const struct grid_cell *);
54 
55 static void	tty_region_pane(struct tty *, const struct tty_ctx *, u_int,
56 		    u_int);
57 static void	tty_region(struct tty *, u_int, u_int);
58 static void	tty_margin_pane(struct tty *, const struct tty_ctx *);
59 static void	tty_margin(struct tty *, u_int, u_int);
60 static int	tty_large_region(struct tty *, const struct tty_ctx *);
61 static int	tty_fake_bce(const struct tty *, const struct window_pane *,
62 		    u_int);
63 static void	tty_redraw_region(struct tty *, const struct tty_ctx *);
64 static void	tty_emulate_repeat(struct tty *, enum tty_code_code,
65 		    enum tty_code_code, u_int);
66 static void	tty_repeat_space(struct tty *, u_int);
67 static void	tty_cell(struct tty *, const struct grid_cell *,
68 		    const struct window_pane *);
69 static void	tty_default_colours(struct grid_cell *,
70 		    const struct window_pane *);
71 static void	tty_default_attributes(struct tty *, const struct window_pane *,
72 		    u_int);
73 
74 #define tty_use_margin(tty) \
75 	((tty)->term_type == TTY_VT420)
76 
77 #define tty_pane_full_width(tty, ctx) \
78 	((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
79 
80 #define TTY_BLOCK_INTERVAL (100000 /* 100 milliseconds */)
81 #define TTY_BLOCK_START(tty) (1 + ((tty)->sx * (tty)->sy) * 8)
82 #define TTY_BLOCK_STOP(tty) (1 + ((tty)->sx * (tty)->sy) / 8)
83 
84 void
85 tty_create_log(void)
86 {
87 	char	name[64];
88 
89 	xsnprintf(name, sizeof name, "tmux-out-%ld.log", (long)getpid());
90 
91 	tty_log_fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644);
92 	if (tty_log_fd != -1 && fcntl(tty_log_fd, F_SETFD, FD_CLOEXEC) == -1)
93 		fatal("fcntl failed");
94 }
95 
96 int
97 tty_init(struct tty *tty, struct client *c, int fd, char *term)
98 {
99 	if (!isatty(fd))
100 		return (-1);
101 
102 	memset(tty, 0, sizeof *tty);
103 
104 	if (term == NULL || *term == '\0')
105 		tty->term_name = xstrdup("unknown");
106 	else
107 		tty->term_name = xstrdup(term);
108 
109 	tty->fd = fd;
110 	tty->client = c;
111 
112 	tty->cstyle = 0;
113 	tty->ccolour = xstrdup("");
114 
115 	tty->flags = 0;
116 
117 	tty->term_flags = 0;
118 	tty->term_type = TTY_UNKNOWN;
119 
120 	return (0);
121 }
122 
123 void
124 tty_resize(struct tty *tty)
125 {
126 	struct client	*c = tty->client;
127 	struct winsize	 ws;
128 	u_int		 sx, sy;
129 
130 	if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) {
131 		sx = ws.ws_col;
132 		if (sx == 0)
133 			sx = 80;
134 		sy = ws.ws_row;
135 		if (sy == 0)
136 			sy = 24;
137 	} else {
138 		sx = 80;
139 		sy = 24;
140 	}
141 	log_debug("%s: %s now %ux%u", __func__, c->name, sx, sy);
142 	tty_set_size(tty, sx, sy);
143 	tty_invalidate(tty);
144 }
145 
146 void
147 tty_set_size(struct tty *tty, u_int sx, u_int sy)
148 {
149 	tty->sx = sx;
150 	tty->sy = sy;
151 }
152 
153 static void
154 tty_read_callback(__unused int fd, __unused short events, void *data)
155 {
156 	struct tty	*tty = data;
157 	struct client	*c = tty->client;
158 	size_t		 size = EVBUFFER_LENGTH(tty->in);
159 	int		 nread;
160 
161 	nread = evbuffer_read(tty->in, tty->fd, -1);
162 	if (nread == 0 || nread == -1) {
163 		event_del(&tty->event_in);
164 		server_client_lost(tty->client);
165 		return;
166 	}
167 	log_debug("%s: read %d bytes (already %zu)", c->name, nread, size);
168 
169 	while (tty_keys_next(tty))
170 		;
171 }
172 
173 static void
174 tty_timer_callback(__unused int fd, __unused short events, void *data)
175 {
176 	struct tty	*tty = data;
177 	struct client	*c = tty->client;
178 	struct timeval	 tv = { .tv_usec = TTY_BLOCK_INTERVAL };
179 
180 	log_debug("%s: %zu discarded", c->name, tty->discarded);
181 
182 	c->flags |= CLIENT_REDRAW;
183 	c->discarded += tty->discarded;
184 
185 	if (tty->discarded < TTY_BLOCK_STOP(tty)) {
186 		tty->flags &= ~TTY_BLOCK;
187 		tty_invalidate(tty);
188 		return;
189 	}
190 	tty->discarded = 0;
191 	evtimer_add(&tty->timer, &tv);
192 }
193 
194 static int
195 tty_block_maybe(struct tty *tty)
196 {
197 	struct client	*c = tty->client;
198 	size_t		 size = EVBUFFER_LENGTH(tty->out);
199 	struct timeval	 tv = { .tv_usec = TTY_BLOCK_INTERVAL };
200 
201 	if (size < TTY_BLOCK_START(tty))
202 		return (0);
203 
204 	if (tty->flags & TTY_BLOCK)
205 		return (1);
206 	tty->flags |= TTY_BLOCK;
207 
208 	log_debug("%s: can't keep up, %zu discarded", c->name, size);
209 
210 	evbuffer_drain(tty->out, size);
211 	c->discarded += size;
212 
213 	tty->discarded = 0;
214 	evtimer_add(&tty->timer, &tv);
215 	return (1);
216 }
217 
218 static void
219 tty_write_callback(__unused int fd, __unused short events, void *data)
220 {
221 	struct tty	*tty = data;
222 	struct client	*c = tty->client;
223 	size_t		 size = EVBUFFER_LENGTH(tty->out);
224 	int		 nwrite;
225 
226 	nwrite = evbuffer_write(tty->out, tty->fd);
227 	if (nwrite == -1)
228 		return;
229 	log_debug("%s: wrote %d bytes (of %zu)", c->name, nwrite, size);
230 
231 	if (c->redraw > 0) {
232 		if ((size_t)nwrite >= c->redraw)
233 			c->redraw = 0;
234 		else
235 			c->redraw -= nwrite;
236 		log_debug("%s: waiting for redraw, %zu bytes left", c->name,
237 		    c->redraw);
238 	} else if (tty_block_maybe(tty))
239 		return;
240 
241 	if (EVBUFFER_LENGTH(tty->out) != 0)
242 		event_add(&tty->event_out, NULL);
243 }
244 
245 int
246 tty_open(struct tty *tty, char **cause)
247 {
248 	tty->term = tty_term_find(tty->term_name, tty->fd, cause);
249 	if (tty->term == NULL) {
250 		tty_close(tty);
251 		return (-1);
252 	}
253 	tty->flags |= TTY_OPENED;
254 
255 	tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_BLOCK|TTY_TIMER);
256 
257 	event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ,
258 	    tty_read_callback, tty);
259 	tty->in = evbuffer_new();
260 
261 	event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty);
262 	tty->out = evbuffer_new();
263 
264 	evtimer_set(&tty->timer, tty_timer_callback, tty);
265 
266 	tty_start_tty(tty);
267 
268 	tty_keys_build(tty);
269 
270 	return (0);
271 }
272 
273 void
274 tty_start_tty(struct tty *tty)
275 {
276 	struct client	*c = tty->client;
277 	struct termios	 tio;
278 
279 	if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) {
280 		setblocking(tty->fd, 0);
281 		event_add(&tty->event_in, NULL);
282 
283 		memcpy(&tio, &tty->tio, sizeof tio);
284 		tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
285 		tio.c_iflag |= IGNBRK;
286 		tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
287 		tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
288 		    ECHOPRT|ECHOKE|ISIG);
289 		tio.c_cc[VMIN] = 1;
290 		tio.c_cc[VTIME] = 0;
291 		if (tcsetattr(tty->fd, TCSANOW, &tio) == 0)
292 			tcflush(tty->fd, TCIOFLUSH);
293 	}
294 
295 	tty_putcode(tty, TTYC_SMCUP);
296 
297 	tty_putcode(tty, TTYC_SMKX);
298 	tty_putcode(tty, TTYC_CLEAR);
299 
300 	if (tty_acs_needed(tty)) {
301 		log_debug("%s: using capabilities for ACS", c->name);
302 		tty_putcode(tty, TTYC_ENACS);
303 	} else
304 		log_debug("%s: using UTF-8 for ACS", c->name);
305 
306 	tty_putcode(tty, TTYC_CNORM);
307 	if (tty_term_has(tty->term, TTYC_KMOUS))
308 		tty_puts(tty, "\033[?1000l\033[?1002l\033[?1006l\033[?1005l");
309 
310 	if (tty_term_flag(tty->term, TTYC_XT)) {
311 		if (options_get_number(global_options, "focus-events")) {
312 			tty->flags |= TTY_FOCUS;
313 			tty_puts(tty, "\033[?1004h");
314 		}
315 		tty_puts(tty, "\033[c");
316 	}
317 
318 	tty->flags |= TTY_STARTED;
319 	tty_invalidate(tty);
320 
321 	tty_force_cursor_colour(tty, "");
322 
323 	tty->mouse_drag_flag = 0;
324 	tty->mouse_drag_update = NULL;
325 	tty->mouse_drag_release = NULL;
326 }
327 
328 void
329 tty_stop_tty(struct tty *tty)
330 {
331 	struct winsize	ws;
332 
333 	if (!(tty->flags & TTY_STARTED))
334 		return;
335 	tty->flags &= ~TTY_STARTED;
336 
337 	event_del(&tty->timer);
338 	tty->flags &= ~TTY_BLOCK;
339 
340 	event_del(&tty->event_in);
341 	event_del(&tty->event_out);
342 
343 	/*
344 	 * Be flexible about error handling and try not kill the server just
345 	 * because the fd is invalid. Things like ssh -t can easily leave us
346 	 * with a dead tty.
347 	 */
348 	if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1)
349 		return;
350 	if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1)
351 		return;
352 
353 	tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
354 	if (tty_acs_needed(tty))
355 		tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
356 	tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
357 	tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
358 	tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
359 	if (tty_term_has(tty->term, TTYC_SS) && tty->cstyle != 0) {
360 		if (tty_term_has(tty->term, TTYC_SE))
361 			tty_raw(tty, tty_term_string(tty->term, TTYC_SE));
362 		else
363 			tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0));
364 	}
365 	if (tty->mode & MODE_BRACKETPASTE)
366 		tty_raw(tty, "\033[?2004l");
367 	tty_raw(tty, tty_term_string(tty->term, TTYC_CR));
368 
369 	tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM));
370 	if (tty_term_has(tty->term, TTYC_KMOUS))
371 		tty_raw(tty, "\033[?1000l\033[?1002l\033[?1006l\033[?1005l");
372 
373 	if (tty_term_flag(tty->term, TTYC_XT)) {
374 		if (tty->flags & TTY_FOCUS) {
375 			tty->flags &= ~TTY_FOCUS;
376 			tty_raw(tty, "\033[?1004l");
377 		}
378 	}
379 
380 	if (tty_use_margin(tty))
381 		tty_raw(tty, "\033[?69l"); /* DECLRMM */
382 	tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
383 
384 	setblocking(tty->fd, 1);
385 }
386 
387 void
388 tty_close(struct tty *tty)
389 {
390 	if (event_initialized(&tty->key_timer))
391 		evtimer_del(&tty->key_timer);
392 	tty_stop_tty(tty);
393 
394 	if (tty->flags & TTY_OPENED) {
395 		evbuffer_free(tty->in);
396 		event_del(&tty->event_in);
397 		evbuffer_free(tty->out);
398 		event_del(&tty->event_out);
399 
400 		tty_term_free(tty->term);
401 		tty_keys_free(tty);
402 
403 		tty->flags &= ~TTY_OPENED;
404 	}
405 
406 	if (tty->fd != -1) {
407 		close(tty->fd);
408 		tty->fd = -1;
409 	}
410 }
411 
412 void
413 tty_free(struct tty *tty)
414 {
415 	tty_close(tty);
416 
417 	free(tty->ccolour);
418 	free(tty->term_name);
419 }
420 
421 void
422 tty_set_type(struct tty *tty, int type)
423 {
424 	tty->term_type = type;
425 
426 	if (tty_use_margin(tty))
427 		tty_puts(tty, "\033[?69h"); /* DECLRMM */
428 }
429 
430 void
431 tty_raw(struct tty *tty, const char *s)
432 {
433 	ssize_t	n, slen;
434 	u_int	i;
435 
436 	slen = strlen(s);
437 	for (i = 0; i < 5; i++) {
438 		n = write(tty->fd, s, slen);
439 		if (n >= 0) {
440 			s += n;
441 			slen -= n;
442 			if (slen == 0)
443 				break;
444 		} else if (n == -1 && errno != EAGAIN)
445 			break;
446 		usleep(100);
447 	}
448 }
449 
450 void
451 tty_putcode(struct tty *tty, enum tty_code_code code)
452 {
453 	tty_puts(tty, tty_term_string(tty->term, code));
454 }
455 
456 void
457 tty_putcode1(struct tty *tty, enum tty_code_code code, int a)
458 {
459 	if (a < 0)
460 		return;
461 	tty_puts(tty, tty_term_string1(tty->term, code, a));
462 }
463 
464 void
465 tty_putcode2(struct tty *tty, enum tty_code_code code, int a, int b)
466 {
467 	if (a < 0 || b < 0)
468 		return;
469 	tty_puts(tty, tty_term_string2(tty->term, code, a, b));
470 }
471 
472 void
473 tty_putcode3(struct tty *tty, enum tty_code_code code, int a, int b, int c)
474 {
475 	if (a < 0 || b < 0 || c < 0)
476 		return;
477 	tty_puts(tty, tty_term_string3(tty->term, code, a, b, c));
478 }
479 
480 void
481 tty_putcode_ptr1(struct tty *tty, enum tty_code_code code, const void *a)
482 {
483 	if (a != NULL)
484 		tty_puts(tty, tty_term_ptr1(tty->term, code, a));
485 }
486 
487 void
488 tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a,
489     const void *b)
490 {
491 	if (a != NULL && b != NULL)
492 		tty_puts(tty, tty_term_ptr2(tty->term, code, a, b));
493 }
494 
495 static void
496 tty_add(struct tty *tty, const char *buf, size_t len)
497 {
498 	struct client	*c = tty->client;
499 
500 	if (tty->flags & TTY_BLOCK) {
501 		tty->discarded += len;
502 		return;
503 	}
504 
505 	evbuffer_add(tty->out, buf, len);
506 	log_debug("%s: %.*s", c->name, (int)len, buf);
507 	c->written += len;
508 
509 	if (tty_log_fd != -1)
510 		write(tty_log_fd, buf, len);
511 	if (tty->flags & TTY_STARTED)
512 		event_add(&tty->event_out, NULL);
513 }
514 
515 void
516 tty_puts(struct tty *tty, const char *s)
517 {
518 	if (*s != '\0')
519 		tty_add(tty, s, strlen(s));
520 }
521 
522 void
523 tty_putc(struct tty *tty, u_char ch)
524 {
525 	const char	*acs;
526 
527 	if (tty->cell.attr & GRID_ATTR_CHARSET) {
528 		acs = tty_acs_get(tty, ch);
529 		if (acs != NULL)
530 			tty_add(tty, acs, strlen(acs));
531 		else
532 			tty_add(tty, &ch, 1);
533 	} else
534 		tty_add(tty, &ch, 1);
535 
536 	if (ch >= 0x20 && ch != 0x7f) {
537 		if (tty->cx >= tty->sx) {
538 			tty->cx = 1;
539 			if (tty->cy != tty->rlower)
540 				tty->cy++;
541 
542 			/*
543 			 * On !xenl terminals, force the cursor position to
544 			 * where we think it should be after a line wrap - this
545 			 * means it works on sensible terminals as well.
546 			 */
547 			if (tty->term->flags & TERM_EARLYWRAP)
548 				tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx);
549 		} else
550 			tty->cx++;
551 	}
552 }
553 
554 void
555 tty_putn(struct tty *tty, const void *buf, size_t len, u_int width)
556 {
557 	tty_add(tty, buf, len);
558 	if (tty->cx + width > tty->sx) {
559 		tty->cx = (tty->cx + width) - tty->sx;
560 		if (tty->cx <= tty->sx)
561 			tty->cy++;
562 		else
563 			tty->cx = tty->cy = UINT_MAX;
564 	} else
565 		tty->cx += width;
566 }
567 
568 static void
569 tty_set_italics(struct tty *tty)
570 {
571 	const char	*s;
572 
573 	if (tty_term_has(tty->term, TTYC_SITM)) {
574 		s = options_get_string(global_options, "default-terminal");
575 		if (strcmp(s, "screen") != 0 && strncmp(s, "screen-", 7) != 0) {
576 			tty_putcode(tty, TTYC_SITM);
577 			return;
578 		}
579 	}
580 	tty_putcode(tty, TTYC_SMSO);
581 }
582 
583 void
584 tty_set_title(struct tty *tty, const char *title)
585 {
586 	if (!tty_term_has(tty->term, TTYC_TSL) ||
587 	    !tty_term_has(tty->term, TTYC_FSL))
588 		return;
589 
590 	tty_putcode(tty, TTYC_TSL);
591 	tty_puts(tty, title);
592 	tty_putcode(tty, TTYC_FSL);
593 }
594 
595 static void
596 tty_force_cursor_colour(struct tty *tty, const char *ccolour)
597 {
598 	if (*ccolour == '\0')
599 		tty_putcode(tty, TTYC_CR);
600 	else
601 		tty_putcode_ptr1(tty, TTYC_CS, ccolour);
602 	free(tty->ccolour);
603 	tty->ccolour = xstrdup(ccolour);
604 }
605 
606 void
607 tty_update_mode(struct tty *tty, int mode, struct screen *s)
608 {
609 	int	changed;
610 
611 	if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0)
612 		tty_force_cursor_colour(tty, s->ccolour);
613 
614 	if (tty->flags & TTY_NOCURSOR)
615 		mode &= ~MODE_CURSOR;
616 
617 	changed = mode ^ tty->mode;
618 	if (changed & MODE_BLINKING) {
619 		if (tty_term_has(tty->term, TTYC_CVVIS))
620 			tty_putcode(tty, TTYC_CVVIS);
621 		else
622 			tty_putcode(tty, TTYC_CNORM);
623 		changed |= MODE_CURSOR;
624 	}
625 	if (changed & MODE_CURSOR) {
626 		if (mode & MODE_CURSOR)
627 			tty_putcode(tty, TTYC_CNORM);
628 		else
629 			tty_putcode(tty, TTYC_CIVIS);
630 	}
631 	if (s != NULL && tty->cstyle != s->cstyle) {
632 		if (tty_term_has(tty->term, TTYC_SS)) {
633 			if (s->cstyle == 0 &&
634 			    tty_term_has(tty->term, TTYC_SE))
635 				tty_putcode(tty, TTYC_SE);
636 			else
637 				tty_putcode1(tty, TTYC_SS, s->cstyle);
638 		}
639 		tty->cstyle = s->cstyle;
640 	}
641 	if (changed & ALL_MOUSE_MODES) {
642 		if (mode & ALL_MOUSE_MODES) {
643 			/*
644 			 * Enable the SGR (1006) extension unconditionally, as
645 			 * it is safe from misinterpretation.
646 			 */
647 			tty_puts(tty, "\033[?1006h");
648 			if (mode & MODE_MOUSE_ALL)
649 				tty_puts(tty, "\033[?1003h");
650 			else if (mode & MODE_MOUSE_BUTTON)
651 				tty_puts(tty, "\033[?1002h");
652 			else if (mode & MODE_MOUSE_STANDARD)
653 				tty_puts(tty, "\033[?1000h");
654 		} else {
655 			if (tty->mode & MODE_MOUSE_ALL)
656 				tty_puts(tty, "\033[?1003l");
657 			else if (tty->mode & MODE_MOUSE_BUTTON)
658 				tty_puts(tty, "\033[?1002l");
659 			else if (tty->mode & MODE_MOUSE_STANDARD)
660 				tty_puts(tty, "\033[?1000l");
661 			tty_puts(tty, "\033[?1006l");
662 		}
663 	}
664 	if (changed & MODE_BRACKETPASTE) {
665 		if (mode & MODE_BRACKETPASTE)
666 			tty_puts(tty, "\033[?2004h");
667 		else
668 			tty_puts(tty, "\033[?2004l");
669 	}
670 	tty->mode = mode;
671 }
672 
673 static void
674 tty_emulate_repeat(struct tty *tty, enum tty_code_code code,
675     enum tty_code_code code1, u_int n)
676 {
677 	if (tty_term_has(tty->term, code))
678 		tty_putcode1(tty, code, n);
679 	else {
680 		while (n-- > 0)
681 			tty_putcode(tty, code1);
682 	}
683 }
684 
685 static void
686 tty_repeat_space(struct tty *tty, u_int n)
687 {
688 	static char s[500];
689 
690 	if (*s != ' ')
691 		memset(s, ' ', sizeof s);
692 
693 	while (n > sizeof s) {
694 		tty_putn(tty, s, sizeof s, sizeof s);
695 		n -= sizeof s;
696 	}
697 	if (n != 0)
698 		tty_putn(tty, s, n, n);
699 }
700 
701 /*
702  * Is the region large enough to be worth redrawing once later rather than
703  * probably several times now? Currently yes if it is more than 50% of the
704  * pane.
705  */
706 static int
707 tty_large_region(__unused struct tty *tty, const struct tty_ctx *ctx)
708 {
709 	struct window_pane	*wp = ctx->wp;
710 
711 	return (ctx->orlower - ctx->orupper >= screen_size_y(wp->screen) / 2);
712 }
713 
714 /*
715  * Return if BCE is needed but the terminal doesn't have it - it'll need to be
716  * emulated.
717  */
718 static int
719 tty_fake_bce(const struct tty *tty, const struct window_pane *wp, u_int bg)
720 {
721 	struct grid_cell	gc;
722 
723 	if (tty_term_flag(tty->term, TTYC_BCE))
724 		return (0);
725 
726 	memcpy(&gc, &grid_default_cell, sizeof gc);
727 	if (wp != NULL)
728 		tty_default_colours(&gc, wp);
729 
730 	if (bg != 8 || gc.bg != 8)
731 		return (1);
732 	return (0);
733 }
734 
735 /*
736  * Redraw scroll region using data from screen (already updated). Used when
737  * CSR not supported, or window is a pane that doesn't take up the full
738  * width of the terminal.
739  */
740 static void
741 tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
742 {
743 	struct window_pane	*wp = ctx->wp;
744 	struct screen		*s = wp->screen;
745 	u_int			 i;
746 
747 	/*
748 	 * If region is large, schedule a window redraw. In most cases this is
749 	 * likely to be followed by some more scrolling.
750 	 */
751 	if (tty_large_region(tty, ctx)) {
752 		wp->flags |= PANE_REDRAW;
753 		return;
754 	}
755 
756 	if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) {
757 		for (i = ctx->ocy; i < screen_size_y(s); i++)
758 			tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff);
759 	} else {
760 		for (i = ctx->orupper; i <= ctx->orlower; i++)
761 			tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff);
762 	}
763 }
764 
765 static void
766 tty_clear_line(struct tty *tty, const struct window_pane *wp, u_int py,
767     u_int px, u_int nx, u_int bg)
768 {
769 	log_debug("%s: %u at %u,%u", __func__, nx, px, py);
770 
771 	/* Nothing to clear. */
772 	if (nx == 0)
773 		return;
774 
775 	/* If genuine BCE is available, can try escape sequences. */
776 	if (!tty_fake_bce(tty, wp, bg)) {
777 		/* Off the end of the line, use EL if available. */
778 		if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) {
779 			tty_cursor(tty, px, py);
780 			tty_putcode(tty, TTYC_EL);
781 			return;
782 		}
783 
784 		/* At the start of the line. Use EL1. */
785 		if (px == 0 && tty_term_has(tty->term, TTYC_EL1)) {
786 			tty_cursor(tty, px + nx - 1, py);
787 			tty_putcode(tty, TTYC_EL1);
788 			return;
789 		}
790 
791 		/* Section of line. Use ECH if possible. */
792 		if (tty_term_has(tty->term, TTYC_ECH)) {
793 			tty_cursor(tty, px, py);
794 			tty_putcode1(tty, TTYC_ECH, nx);
795 			return;
796 		}
797 	}
798 
799 	/* Couldn't use an escape sequence, use spaces. */
800 	tty_cursor(tty, px, py);
801 	tty_repeat_space(tty, nx);
802 }
803 
804 static void
805 tty_clear_area(struct tty *tty, const struct window_pane *wp, u_int py,
806     u_int ny, u_int px, u_int nx, u_int bg)
807 {
808 	u_int	yy;
809 	char	tmp[64];
810 
811 	log_debug("%s: %u,%u at %u,%u", __func__, nx, ny, px, py);
812 
813 	/* Nothing to clear. */
814 	if (nx == 0 || ny == 0)
815 		return;
816 
817 	/* If genuine BCE is available, can try escape sequences. */
818 	if (!tty_fake_bce(tty, wp, bg)) {
819 		/* Use ED if clearing off the bottom of the terminal. */
820 		if (px == 0 &&
821 		    px + nx >= tty->sx &&
822 		    py + ny >= tty->sy &&
823 		    tty_term_has(tty->term, TTYC_ED)) {
824 			tty_cursor(tty, 0, py);
825 			tty_putcode(tty, TTYC_ED);
826 			return;
827 		}
828 
829 		/*
830 		 * On VT420 compatible terminals we can use DECFRA if the
831 		 * background colour isn't default (because it doesn't work
832 		 * after SGR 0).
833 		 */
834 		if (tty->term_type == TTY_VT420 && bg != 8) {
835 			xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x",
836 			    py + 1, px + 1, py + ny, px + nx);
837 			tty_puts(tty, tmp);
838 			return;
839 		}
840 
841 		/* Full lines can be scrolled away to clear them. */
842 		if (px == 0 &&
843 		    px + nx >= tty->sx &&
844 		    ny > 2 &&
845 		    tty_term_has(tty->term, TTYC_CSR) &&
846 		    tty_term_has(tty->term, TTYC_INDN)) {
847 			tty_region(tty, py, py + ny - 1);
848 			tty_margin_off(tty);
849 			tty_putcode1(tty, TTYC_INDN, ny);
850 			return;
851 		}
852 
853 		/*
854 		 * If margins are supported, can just scroll the area off to
855 		 * clear it.
856 		 */
857 		if (nx > 2 &&
858 		    ny > 2 &&
859 		    tty_term_has(tty->term, TTYC_CSR) &&
860 		    tty_use_margin(tty) &&
861 		    tty_term_has(tty->term, TTYC_INDN)) {
862 			tty_region(tty, py, py + ny - 1);
863 			tty_margin(tty, px, px + nx - 1);
864 			tty_putcode1(tty, TTYC_INDN, ny);
865 			return;
866 		}
867 	}
868 
869 	/* Couldn't use an escape sequence, loop over the lines. */
870 	for (yy = py; yy < py + ny; yy++)
871 		tty_clear_line(tty, wp, yy, px, nx, bg);
872 }
873 
874 void
875 tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox,
876     u_int oy)
877 {
878 	tty_draw_line(tty, wp, wp->screen, py, ox, oy);
879 }
880 
881 static const struct grid_cell *
882 tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
883 {
884 	static struct grid_cell	new;
885 	u_int			n;
886 
887 	/* Characters less than 0x7f are always fine, no matter what. */
888 	if (gc->data.size == 1 && *gc->data.data < 0x7f)
889 		return (gc);
890 
891 	/* UTF-8 terminal and a UTF-8 character - fine. */
892 	if (tty->flags & TTY_UTF8)
893 		return (gc);
894 
895 	/* Replace by the right number of underscores. */
896 	n = gc->data.width;
897 	if (n > UTF8_SIZE)
898 		n = UTF8_SIZE;
899 	memcpy(&new, gc, sizeof new);
900 	new.data.size = n;
901 	memset(new.data.data, '_', n);
902 	return (&new);
903 }
904 
905 void
906 tty_draw_line(struct tty *tty, const struct window_pane *wp,
907     struct screen *s, u_int py, u_int ox, u_int oy)
908 {
909 	struct grid		*gd = s->grid;
910 	struct grid_cell	 gc, last;
911 	const struct grid_cell	*gcp;
912 	u_int			 i, j, ux, sx, nx, width;
913 	int			 flags, cleared = 0;
914 	char			 buf[512];
915 	size_t			 len, old_len;
916 
917 	flags = (tty->flags & TTY_NOCURSOR);
918 	tty->flags |= TTY_NOCURSOR;
919 	tty_update_mode(tty, tty->mode, s);
920 
921 	tty_region_off(tty);
922 	tty_margin_off(tty);
923 
924 	/*
925 	 * Clamp the width to cellsize - note this is not cellused, because
926 	 * there may be empty background cells after it (from BCE).
927 	 */
928 	sx = screen_size_x(s);
929 	if (sx > gd->linedata[gd->hsize + py].cellsize)
930 		sx = gd->linedata[gd->hsize + py].cellsize;
931 	if (sx > tty->sx)
932 		sx = tty->sx;
933 	ux = 0;
934 
935 	if (wp == NULL ||
936 	    py == 0 ||
937 	    (~gd->linedata[gd->hsize + py - 1].flags & GRID_LINE_WRAPPED) ||
938 	    ox != 0 ||
939 	    tty->cx < tty->sx ||
940 	    screen_size_x(s) < tty->sx) {
941 		if (screen_size_x(s) < tty->sx &&
942 		    ox == 0 &&
943 		    sx != screen_size_x(s) &&
944 		    tty_term_has(tty->term, TTYC_EL1) &&
945 		    !tty_fake_bce(tty, wp, 8)) {
946 			tty_default_attributes(tty, wp, 8);
947 			tty_cursor(tty, screen_size_x(s) - 1, oy + py);
948 			tty_putcode(tty, TTYC_EL1);
949 			cleared = 1;
950 		}
951 		if (sx != 0)
952 			tty_cursor(tty, ox, oy + py);
953 	} else
954 		log_debug("%s: wrapped line %u", __func__, oy + py);
955 
956 	memcpy(&last, &grid_default_cell, sizeof last);
957 	len = 0;
958 	width = 0;
959 
960 	for (i = 0; i < sx; i++) {
961 		grid_view_get_cell(gd, i, py, &gc);
962 		gcp = tty_check_codeset(tty, &gc);
963 		if (len != 0 &&
964 		    ((gcp->attr & GRID_ATTR_CHARSET) ||
965 		    gcp->flags != last.flags ||
966 		    gcp->attr != last.attr ||
967 		    gcp->fg != last.fg ||
968 		    gcp->bg != last.bg ||
969 		    ux + width + gcp->data.width >= screen_size_x(s) ||
970 		    (sizeof buf) - len < gcp->data.size)) {
971 			tty_attributes(tty, &last, wp);
972 			tty_putn(tty, buf, len, width);
973 			ux += width;
974 
975 			len = 0;
976 			width = 0;
977 		}
978 
979 		if (gcp->flags & GRID_FLAG_SELECTED)
980 			screen_select_cell(s, &last, gcp);
981 		else
982 			memcpy(&last, gcp, sizeof last);
983 		if (ux + gcp->data.width > screen_size_x(s)) {
984 			tty_attributes(tty, &last, wp);
985 			for (j = 0; j < gcp->data.width; j++) {
986 				if (ux + j > screen_size_x(s))
987 					break;
988 				tty_putc(tty, ' ');
989 				ux++;
990 			}
991 		} else if (gcp->attr & GRID_ATTR_CHARSET) {
992 			tty_attributes(tty, &last, wp);
993 			for (j = 0; j < gcp->data.size; j++)
994 				tty_putc(tty, gcp->data.data[j]);
995 			ux += gc.data.width;
996 		} else {
997 			memcpy(buf + len, gcp->data.data, gcp->data.size);
998 			len += gcp->data.size;
999 			width += gcp->data.width;
1000 		}
1001 	}
1002 	if (len != 0) {
1003 		if (grid_cells_equal(&last, &grid_default_cell)) {
1004 			old_len = len;
1005 			while (len > 0 && buf[len - 1] == ' ') {
1006 				len--;
1007 				width--;
1008 			}
1009 			log_debug("%s: trimmed %zu spaces", __func__,
1010 			    old_len - len);
1011 		}
1012 		if (len != 0) {
1013 			tty_attributes(tty, &last, wp);
1014 			tty_putn(tty, buf, len, width);
1015 			ux += width;
1016 		}
1017 	}
1018 
1019 	if (!cleared && ux < screen_size_x(s)) {
1020 		nx = screen_size_x(s) - ux;
1021 		tty_default_attributes(tty, wp, 8);
1022 		tty_clear_line(tty, wp, oy + py, ox + ux, nx, 8);
1023 	}
1024 
1025 	tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags;
1026 	tty_update_mode(tty, tty->mode, s);
1027 }
1028 
1029 static int
1030 tty_client_ready(struct client *c, struct window_pane *wp)
1031 {
1032 	if (c->session == NULL || c->tty.term == NULL)
1033 		return (0);
1034 	if (c->flags & (CLIENT_REDRAW|CLIENT_SUSPENDED))
1035 		return (0);
1036 	if (c->tty.flags & TTY_FREEZE)
1037 		return (0);
1038 	if (c->session->curw->window != wp->window)
1039 		return (0);
1040 	return (1);
1041 }
1042 
1043 void
1044 tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
1045     struct tty_ctx *ctx)
1046 {
1047 	struct window_pane	*wp = ctx->wp;
1048 	struct client		*c;
1049 
1050 	/* wp can be NULL if updating the screen but not the terminal. */
1051 	if (wp == NULL)
1052 		return;
1053 
1054 	if ((wp->flags & (PANE_REDRAW|PANE_DROP)) || !window_pane_visible(wp))
1055 		return;
1056 
1057 	TAILQ_FOREACH(c, &clients, entry) {
1058 		if (!tty_client_ready(c, wp))
1059 			continue;
1060 
1061 		ctx->xoff = wp->xoff;
1062 		ctx->yoff = wp->yoff;
1063 		if (status_at_line(c) == 0)
1064 			ctx->yoff += status_line_size(c->session);
1065 
1066 		cmdfn(&c->tty, ctx);
1067 	}
1068 }
1069 
1070 void
1071 tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
1072 {
1073 	struct window_pane	*wp = ctx->wp;
1074 
1075 	if (!tty_pane_full_width(tty, ctx) ||
1076 	    tty_fake_bce(tty, wp, ctx->bg) ||
1077 	    (!tty_term_has(tty->term, TTYC_ICH) &&
1078 	    !tty_term_has(tty->term, TTYC_ICH1))) {
1079 		tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
1080 		return;
1081 	}
1082 
1083 	tty_default_attributes(tty, wp, ctx->bg);
1084 
1085 	tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
1086 
1087 	tty_emulate_repeat(tty, TTYC_ICH, TTYC_ICH1, ctx->num);
1088 }
1089 
1090 void
1091 tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
1092 {
1093 	struct window_pane	*wp = ctx->wp;
1094 
1095 	if (!tty_pane_full_width(tty, ctx) ||
1096 	    tty_fake_bce(tty, wp, ctx->bg) ||
1097 	    (!tty_term_has(tty->term, TTYC_DCH) &&
1098 	    !tty_term_has(tty->term, TTYC_DCH1))) {
1099 		tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
1100 		return;
1101 	}
1102 
1103 	tty_default_attributes(tty, wp, ctx->bg);
1104 
1105 	tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
1106 
1107 	tty_emulate_repeat(tty, TTYC_DCH, TTYC_DCH1, ctx->num);
1108 }
1109 
1110 void
1111 tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
1112 {
1113 	tty_default_attributes(tty, ctx->wp, ctx->bg);
1114 
1115 	tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
1116 
1117 	if (tty_term_has(tty->term, TTYC_ECH) &&
1118 	    !tty_fake_bce(tty, ctx->wp, 8))
1119 		tty_putcode1(tty, TTYC_ECH, ctx->num);
1120 	else
1121 		tty_repeat_space(tty, ctx->num);
1122 }
1123 
1124 void
1125 tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
1126 {
1127 	if (!tty_pane_full_width(tty, ctx) ||
1128 	    tty_fake_bce(tty, ctx->wp, ctx->bg) ||
1129 	    !tty_term_has(tty->term, TTYC_CSR) ||
1130 	    !tty_term_has(tty->term, TTYC_IL1)) {
1131 		tty_redraw_region(tty, ctx);
1132 		return;
1133 	}
1134 
1135 	tty_default_attributes(tty, ctx->wp, ctx->bg);
1136 
1137 	tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
1138 	tty_margin_off(tty);
1139 	tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
1140 
1141 	tty_emulate_repeat(tty, TTYC_IL, TTYC_IL1, ctx->num);
1142 	tty->cx = tty->cy = UINT_MAX;
1143 }
1144 
1145 void
1146 tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
1147 {
1148 	if (!tty_pane_full_width(tty, ctx) ||
1149 	    tty_fake_bce(tty, ctx->wp, ctx->bg) ||
1150 	    !tty_term_has(tty->term, TTYC_CSR) ||
1151 	    !tty_term_has(tty->term, TTYC_DL1)) {
1152 		tty_redraw_region(tty, ctx);
1153 		return;
1154 	}
1155 
1156 	tty_default_attributes(tty, ctx->wp, ctx->bg);
1157 
1158 	tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
1159 	tty_margin_off(tty);
1160 	tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
1161 
1162 	tty_emulate_repeat(tty, TTYC_DL, TTYC_DL1, ctx->num);
1163 	tty->cx = tty->cy = UINT_MAX;
1164 }
1165 
1166 void
1167 tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
1168 {
1169 	struct window_pane	*wp = ctx->wp;
1170 	u_int			 nx, py = ctx->yoff + ctx->ocy;
1171 
1172 	tty_default_attributes(tty, wp, ctx->bg);
1173 
1174 	nx = screen_size_x(wp->screen);
1175 	tty_clear_line(tty, wp, py, ctx->xoff, nx, ctx->bg);
1176 }
1177 
1178 void
1179 tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
1180 {
1181 	struct window_pane	*wp = ctx->wp;
1182 	u_int			 nx, py = ctx->yoff + ctx->ocy;
1183 
1184 	tty_default_attributes(tty, wp, ctx->bg);
1185 
1186 	nx = screen_size_x(wp->screen) - ctx->ocx;
1187 	tty_clear_line(tty, wp, py, ctx->xoff + ctx->ocx, nx, ctx->bg);
1188 }
1189 
1190 void
1191 tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
1192 {
1193 	struct window_pane	*wp = ctx->wp;
1194 	u_int			 py = ctx->yoff + ctx->ocy;
1195 
1196 	tty_default_attributes(tty, wp, ctx->bg);
1197 
1198 	tty_clear_line(tty, wp, py, ctx->xoff, ctx->ocx + 1, ctx->bg);
1199 }
1200 
1201 void
1202 tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
1203 {
1204 	struct window_pane	*wp = ctx->wp;
1205 
1206 	if (ctx->ocy != ctx->orupper)
1207 		return;
1208 
1209 	if (!tty_pane_full_width(tty, ctx) ||
1210 	    tty_fake_bce(tty, wp, 8) ||
1211 	    !tty_term_has(tty->term, TTYC_CSR) ||
1212 	    !tty_term_has(tty->term, TTYC_RI)) {
1213 		tty_redraw_region(tty, ctx);
1214 		return;
1215 	}
1216 
1217 	tty_default_attributes(tty, wp, ctx->bg);
1218 
1219 	tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
1220 	tty_margin_off(tty);
1221 	tty_cursor_pane(tty, ctx, ctx->ocx, ctx->orupper);
1222 
1223 	tty_putcode(tty, TTYC_RI);
1224 }
1225 
1226 void
1227 tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
1228 {
1229 	struct window_pane	*wp = ctx->wp;
1230 
1231 	if (ctx->ocy != ctx->orlower)
1232 		return;
1233 
1234 	if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
1235 	    tty_fake_bce(tty, wp, 8) ||
1236 	    !tty_term_has(tty->term, TTYC_CSR)) {
1237 		tty_redraw_region(tty, ctx);
1238 		return;
1239 	}
1240 
1241 	tty_default_attributes(tty, wp, ctx->bg);
1242 
1243 	tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
1244 	tty_margin_pane(tty, ctx);
1245 
1246 	/*
1247 	 * If we want to wrap a pane, the cursor needs to be exactly on the
1248 	 * right of the region. But if the pane isn't on the right, it may be
1249 	 * off the edge - if so, move the cursor back to the right.
1250 	 */
1251 	if (ctx->xoff + ctx->ocx > tty->rright)
1252 		tty_cursor(tty, tty->rright, ctx->yoff + ctx->ocy);
1253 	else
1254 		tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
1255 
1256 	tty_putc(tty, '\n');
1257 }
1258 
1259 void
1260 tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
1261 {
1262 	struct window_pane	*wp = ctx->wp;
1263 	u_int			 i;
1264 
1265 	if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
1266 	    tty_fake_bce(tty, wp, 8) ||
1267 	    !tty_term_has(tty->term, TTYC_CSR)) {
1268 		tty_redraw_region(tty, ctx);
1269 		return;
1270 	}
1271 
1272 	tty_default_attributes(tty, wp, ctx->bg);
1273 
1274 	tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
1275 	tty_margin_pane(tty, ctx);
1276 
1277 	if (ctx->num == 1 || !tty_term_has(tty->term, TTYC_INDN)) {
1278 		tty_cursor(tty, tty->rright, tty->rlower);
1279 		for (i = 0; i < ctx->num; i++)
1280 			tty_putc(tty, '\n');
1281 	} else
1282 		tty_putcode1(tty, TTYC_INDN, ctx->num);
1283 }
1284 
1285 void
1286 tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
1287 {
1288 	struct window_pane	*wp = ctx->wp;
1289 	u_int			 px, py, nx, ny;
1290 
1291 	tty_default_attributes(tty, wp, ctx->bg);
1292 
1293 	tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
1294 	tty_margin_off(tty);
1295 
1296 	px = ctx->xoff;
1297 	nx = screen_size_x(wp->screen);
1298 	py = ctx->yoff + ctx->ocy + 1;
1299 	ny = screen_size_y(wp->screen) - ctx->ocy - 1;
1300 
1301 	tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
1302 
1303 	px = ctx->xoff + ctx->ocx;
1304 	nx = screen_size_x(wp->screen) - ctx->ocx;
1305 	py = ctx->yoff + ctx->ocy;
1306 
1307 	tty_clear_line(tty, wp, py, px, nx, ctx->bg);
1308 }
1309 
1310 void
1311 tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
1312 {
1313 	struct window_pane	*wp = ctx->wp;
1314 	u_int			 px, py, nx, ny;
1315 
1316 	tty_default_attributes(tty, wp, ctx->bg);
1317 
1318 	tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
1319 	tty_margin_off(tty);
1320 
1321 	px = ctx->xoff;
1322 	nx = screen_size_x(wp->screen);
1323 	py = ctx->yoff;
1324 	ny = ctx->ocy - 1;
1325 
1326 	tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
1327 
1328 	px = ctx->xoff;
1329 	nx = ctx->ocx + 1;
1330 	py = ctx->yoff + ctx->ocy;
1331 
1332 	tty_clear_line(tty, wp, py, px, nx, ctx->bg);
1333 }
1334 
1335 void
1336 tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
1337 {
1338 	struct window_pane	*wp = ctx->wp;
1339 	u_int			 px, py, nx, ny;
1340 
1341 	tty_default_attributes(tty, wp, ctx->bg);
1342 
1343 	tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
1344 	tty_margin_off(tty);
1345 
1346 	px = ctx->xoff;
1347 	nx = screen_size_x(wp->screen);
1348 	py = ctx->yoff;
1349 	ny = screen_size_y(wp->screen);
1350 
1351 	tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
1352 }
1353 
1354 void
1355 tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
1356 {
1357 	struct window_pane	*wp = ctx->wp;
1358 	struct screen		*s = wp->screen;
1359 	u_int			 i, j;
1360 
1361 	tty_attributes(tty, &grid_default_cell, wp);
1362 
1363 	tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
1364 	tty_margin_off(tty);
1365 
1366 	for (j = 0; j < screen_size_y(s); j++) {
1367 		tty_cursor_pane(tty, ctx, 0, j);
1368 		for (i = 0; i < screen_size_x(s); i++)
1369 			tty_putc(tty, 'E');
1370 	}
1371 }
1372 
1373 void
1374 tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
1375 {
1376 	if (ctx->xoff + ctx->ocx > tty->sx - 1 && ctx->ocy == ctx->orlower) {
1377 		if (tty_pane_full_width(tty, ctx))
1378 			tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
1379 		else
1380 			tty_margin_off(tty);
1381 	}
1382 
1383 	tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
1384 
1385 	tty_cell(tty, ctx->cell, ctx->wp);
1386 }
1387 
1388 void
1389 tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
1390 {
1391 	tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
1392 
1393 	tty_attributes(tty, ctx->cell, ctx->wp);
1394 	tty_putn(tty, ctx->ptr, ctx->num, ctx->num);
1395 }
1396 
1397 void
1398 tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx)
1399 {
1400 	char	*buf;
1401 	size_t	 off;
1402 
1403 	if (!tty_term_has(tty->term, TTYC_MS))
1404 		return;
1405 
1406 	off = 4 * ((ctx->num + 2) / 3) + 1; /* storage for base64 */
1407 	buf = xmalloc(off);
1408 
1409 	b64_ntop(ctx->ptr, ctx->num, buf, off);
1410 	tty_putcode_ptr2(tty, TTYC_MS, "", buf);
1411 
1412 	free(buf);
1413 }
1414 
1415 void
1416 tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
1417 {
1418 	tty_add(tty, ctx->ptr, ctx->num);
1419 	tty_invalidate(tty);
1420 }
1421 
1422 static void
1423 tty_cell(struct tty *tty, const struct grid_cell *gc,
1424     const struct window_pane *wp)
1425 {
1426 	const struct grid_cell	*gcp;
1427 
1428 	/* Skip last character if terminal is stupid. */
1429 	if ((tty->term->flags & TERM_EARLYWRAP) &&
1430 	    tty->cy == tty->sy - 1 &&
1431 	    tty->cx == tty->sx - 1)
1432 		return;
1433 
1434 	/* If this is a padding character, do nothing. */
1435 	if (gc->flags & GRID_FLAG_PADDING)
1436 		return;
1437 
1438 	/* Set the attributes. */
1439 	tty_attributes(tty, gc, wp);
1440 
1441 	/* Get the cell and if ASCII write with putc to do ACS translation. */
1442 	gcp = tty_check_codeset(tty, gc);
1443 	if (gcp->data.size == 1) {
1444 		if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f)
1445 			return;
1446 		tty_putc(tty, *gcp->data.data);
1447 		return;
1448 	}
1449 
1450 	/* Write the data. */
1451 	tty_putn(tty, gcp->data.data, gcp->data.size, gcp->data.width);
1452 }
1453 
1454 void
1455 tty_reset(struct tty *tty)
1456 {
1457 	struct grid_cell	*gc = &tty->cell;
1458 
1459 	if (!grid_cells_equal(gc, &grid_default_cell)) {
1460 		if ((gc->attr & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
1461 			tty_putcode(tty, TTYC_RMACS);
1462 		tty_putcode(tty, TTYC_SGR0);
1463 		memcpy(gc, &grid_default_cell, sizeof *gc);
1464 	}
1465 
1466 	memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell);
1467 	tty->last_wp = -1;
1468 }
1469 
1470 static void
1471 tty_invalidate(struct tty *tty)
1472 {
1473 	memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
1474 
1475 	memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell);
1476 	tty->last_wp = -1;
1477 
1478 	tty->cx = tty->cy = UINT_MAX;
1479 
1480 	tty->rupper = tty->rleft = UINT_MAX;
1481 	tty->rlower = tty->rright = UINT_MAX;
1482 
1483 	if (tty->flags & TTY_STARTED) {
1484 		tty_putcode(tty, TTYC_SGR0);
1485 
1486 		tty->mode = ALL_MODES;
1487 		tty_update_mode(tty, MODE_CURSOR, NULL);
1488 
1489 		tty_cursor(tty, 0, 0);
1490 		tty_region_off(tty);
1491 		tty_margin_off(tty);
1492 	} else
1493 		tty->mode = MODE_CURSOR;
1494 }
1495 
1496 /* Turn off margin. */
1497 void
1498 tty_region_off(struct tty *tty)
1499 {
1500 	tty_region(tty, 0, tty->sy - 1);
1501 }
1502 
1503 /* Set region inside pane. */
1504 static void
1505 tty_region_pane(struct tty *tty, const struct tty_ctx *ctx, u_int rupper,
1506     u_int rlower)
1507 {
1508 	tty_region(tty, ctx->yoff + rupper, ctx->yoff + rlower);
1509 }
1510 
1511 /* Set region at absolute position. */
1512 static void
1513 tty_region(struct tty *tty, u_int rupper, u_int rlower)
1514 {
1515 	if (tty->rlower == rlower && tty->rupper == rupper)
1516 		return;
1517 	if (!tty_term_has(tty->term, TTYC_CSR))
1518 		return;
1519 
1520 	tty->rupper = rupper;
1521 	tty->rlower = rlower;
1522 
1523 	/*
1524 	 * Some terminals (such as PuTTY) do not correctly reset the cursor to
1525 	 * 0,0 if it is beyond the last column (they do not reset their wrap
1526 	 * flag so further output causes a line feed). As a workaround, do an
1527 	 * explicit move to 0 first.
1528 	 */
1529 	if (tty->cx >= tty->sx)
1530 		tty_cursor(tty, 0, tty->cy);
1531 
1532 	tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower);
1533 	tty->cx = tty->cy = UINT_MAX;
1534 }
1535 
1536 /* Turn off margin. */
1537 void
1538 tty_margin_off(struct tty *tty)
1539 {
1540 	tty_margin(tty, 0, tty->sx - 1);
1541 }
1542 
1543 /* Set margin inside pane. */
1544 static void
1545 tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
1546 {
1547 	tty_margin(tty, ctx->xoff, ctx->xoff + ctx->wp->sx - 1);
1548 }
1549 
1550 /* Set margin at absolute position. */
1551 static void
1552 tty_margin(struct tty *tty, u_int rleft, u_int rright)
1553 {
1554 	char s[64];
1555 
1556 	if (!tty_use_margin(tty))
1557 		return;
1558 	if (tty->rleft == rleft && tty->rright == rright)
1559 		return;
1560 
1561 	tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower);
1562 
1563 	tty->rleft = rleft;
1564 	tty->rright = rright;
1565 
1566 	if (rleft == 0 && rright == tty->sx - 1)
1567 		snprintf(s, sizeof s, "\033[s");
1568 	else
1569 		snprintf(s, sizeof s, "\033[%u;%us", rleft + 1, rright + 1);
1570 	tty_puts(tty, s);
1571 	tty->cx = tty->cy = UINT_MAX;
1572 }
1573 
1574 /*
1575  * Move the cursor, unless it would wrap itself when the next character is
1576  * printed.
1577  */
1578 static void
1579 tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
1580     u_int cx, u_int cy)
1581 {
1582 	if (!ctx->wrapped ||
1583 	    !tty_pane_full_width(tty, ctx) ||
1584 	    (tty->term->flags & TERM_EARLYWRAP) ||
1585 	    ctx->xoff + cx != 0 ||
1586 	    ctx->yoff + cy != tty->cy + 1 ||
1587 	    tty->cx < tty->sx ||
1588 	    tty->cy == tty->rlower)
1589 		tty_cursor_pane(tty, ctx, cx, cy);
1590 	else
1591 		log_debug("%s: will wrap at %u,%u", __func__, tty->cx, tty->cy);
1592 }
1593 
1594 /* Move cursor inside pane. */
1595 static void
1596 tty_cursor_pane(struct tty *tty, const struct tty_ctx *ctx, u_int cx, u_int cy)
1597 {
1598 	tty_cursor(tty, ctx->xoff + cx, ctx->yoff + cy);
1599 }
1600 
1601 /* Move cursor to absolute position. */
1602 void
1603 tty_cursor(struct tty *tty, u_int cx, u_int cy)
1604 {
1605 	struct tty_term	*term = tty->term;
1606 	u_int		 thisx, thisy;
1607 	int		 change;
1608 
1609 	if (cx > tty->sx - 1)
1610 		cx = tty->sx - 1;
1611 
1612 	thisx = tty->cx;
1613 	thisy = tty->cy;
1614 
1615 	/* No change. */
1616 	if (cx == thisx && cy == thisy)
1617 		return;
1618 
1619 	/* Very end of the line, just use absolute movement. */
1620 	if (thisx > tty->sx - 1)
1621 		goto absolute;
1622 
1623 	/* Move to home position (0, 0). */
1624 	if (cx == 0 && cy == 0 && tty_term_has(term, TTYC_HOME)) {
1625 		tty_putcode(tty, TTYC_HOME);
1626 		goto out;
1627 	}
1628 
1629 	/* Zero on the next line. */
1630 	if (cx == 0 && cy == thisy + 1 && thisy != tty->rlower &&
1631 	    (!tty_use_margin(tty) || tty->rleft == 0)) {
1632 		tty_putc(tty, '\r');
1633 		tty_putc(tty, '\n');
1634 		goto out;
1635 	}
1636 
1637 	/* Moving column or row. */
1638 	if (cy == thisy) {
1639 		/*
1640 		 * Moving column only, row staying the same.
1641 		 */
1642 
1643 		/* To left edge. */
1644 		if (cx == 0 && (!tty_use_margin(tty) || tty->rleft == 0)) {
1645 			tty_putc(tty, '\r');
1646 			goto out;
1647 		}
1648 
1649 		/* One to the left. */
1650 		if (cx == thisx - 1 && tty_term_has(term, TTYC_CUB1)) {
1651 			tty_putcode(tty, TTYC_CUB1);
1652 			goto out;
1653 		}
1654 
1655 		/* One to the right. */
1656 		if (cx == thisx + 1 && tty_term_has(term, TTYC_CUF1)) {
1657 			tty_putcode(tty, TTYC_CUF1);
1658 			goto out;
1659 		}
1660 
1661 		/* Calculate difference. */
1662 		change = thisx - cx;	/* +ve left, -ve right */
1663 
1664 		/*
1665 		 * Use HPA if change is larger than absolute, otherwise move
1666 		 * the cursor with CUB/CUF.
1667 		 */
1668 		if ((u_int) abs(change) > cx && tty_term_has(term, TTYC_HPA)) {
1669 			tty_putcode1(tty, TTYC_HPA, cx);
1670 			goto out;
1671 		} else if (change > 0 && tty_term_has(term, TTYC_CUB)) {
1672 			if (change == 2 && tty_term_has(term, TTYC_CUB1)) {
1673 				tty_putcode(tty, TTYC_CUB1);
1674 				tty_putcode(tty, TTYC_CUB1);
1675 				goto out;
1676 			}
1677 			tty_putcode1(tty, TTYC_CUB, change);
1678 			goto out;
1679 		} else if (change < 0 && tty_term_has(term, TTYC_CUF)) {
1680 			tty_putcode1(tty, TTYC_CUF, -change);
1681 			goto out;
1682 		}
1683 	} else if (cx == thisx) {
1684 		/*
1685 		 * Moving row only, column staying the same.
1686 		 */
1687 
1688 		/* One above. */
1689 		if (thisy != tty->rupper &&
1690 		    cy == thisy - 1 && tty_term_has(term, TTYC_CUU1)) {
1691 			tty_putcode(tty, TTYC_CUU1);
1692 			goto out;
1693 		}
1694 
1695 		/* One below. */
1696 		if (thisy != tty->rlower &&
1697 		    cy == thisy + 1 && tty_term_has(term, TTYC_CUD1)) {
1698 			tty_putcode(tty, TTYC_CUD1);
1699 			goto out;
1700 		}
1701 
1702 		/* Calculate difference. */
1703 		change = thisy - cy;	/* +ve up, -ve down */
1704 
1705 		/*
1706 		 * Try to use VPA if change is larger than absolute or if this
1707 		 * change would cross the scroll region, otherwise use CUU/CUD.
1708 		 */
1709 		if ((u_int) abs(change) > cy ||
1710 		    (change < 0 && cy - change > tty->rlower) ||
1711 		    (change > 0 && cy - change < tty->rupper)) {
1712 			    if (tty_term_has(term, TTYC_VPA)) {
1713 				    tty_putcode1(tty, TTYC_VPA, cy);
1714 				    goto out;
1715 			    }
1716 		} else if (change > 0 && tty_term_has(term, TTYC_CUU)) {
1717 			tty_putcode1(tty, TTYC_CUU, change);
1718 			goto out;
1719 		} else if (change < 0 && tty_term_has(term, TTYC_CUD)) {
1720 			tty_putcode1(tty, TTYC_CUD, -change);
1721 			goto out;
1722 		}
1723 	}
1724 
1725 absolute:
1726 	/* Absolute movement. */
1727 	tty_putcode2(tty, TTYC_CUP, cy, cx);
1728 
1729 out:
1730 	tty->cx = cx;
1731 	tty->cy = cy;
1732 }
1733 
1734 void
1735 tty_attributes(struct tty *tty, const struct grid_cell *gc,
1736     const struct window_pane *wp)
1737 {
1738 	struct grid_cell	*tc = &tty->cell, gc2;
1739 	int			 changed;
1740 
1741 	/* Ignore cell if it is the same as the last one. */
1742 	if (wp != NULL &&
1743 	    (int)wp->id == tty->last_wp &&
1744 	    ~(wp->window->flags & WINDOW_STYLECHANGED) &&
1745 	    gc->attr == tty->last_cell.attr &&
1746 	    gc->fg == tty->last_cell.fg &&
1747 	    gc->bg == tty->last_cell.bg)
1748 		return;
1749 	tty->last_wp = (wp != NULL ? (int)wp->id : -1);
1750 	memcpy(&tty->last_cell, gc, sizeof tty->last_cell);
1751 
1752 	/* Copy cell and update default colours. */
1753 	memcpy(&gc2, gc, sizeof gc2);
1754 	if (wp != NULL)
1755 		tty_default_colours(&gc2, wp);
1756 
1757 	/*
1758 	 * If no setab, try to use the reverse attribute as a best-effort for a
1759 	 * non-default background. This is a bit of a hack but it doesn't do
1760 	 * any serious harm and makes a couple of applications happier.
1761 	 */
1762 	if (!tty_term_has(tty->term, TTYC_SETAB)) {
1763 		if (gc2.attr & GRID_ATTR_REVERSE) {
1764 			if (gc2.fg != 7 && gc2.fg != 8)
1765 				gc2.attr &= ~GRID_ATTR_REVERSE;
1766 		} else {
1767 			if (gc2.bg != 0 && gc2.bg != 8)
1768 				gc2.attr |= GRID_ATTR_REVERSE;
1769 		}
1770 	}
1771 
1772 	/* Fix up the colours if necessary. */
1773 	tty_check_fg(tty, wp, &gc2);
1774 	tty_check_bg(tty, wp, &gc2);
1775 
1776 	/* If any bits are being cleared, reset everything. */
1777 	if (tc->attr & ~gc2.attr)
1778 		tty_reset(tty);
1779 
1780 	/*
1781 	 * Set the colours. This may call tty_reset() (so it comes next) and
1782 	 * may add to (NOT remove) the desired attributes by changing new_attr.
1783 	 */
1784 	tty_colours(tty, &gc2);
1785 
1786 	/* Filter out attribute bits already set. */
1787 	changed = gc2.attr & ~tc->attr;
1788 	tc->attr = gc2.attr;
1789 
1790 	/* Set the attributes. */
1791 	if (changed & GRID_ATTR_BRIGHT)
1792 		tty_putcode(tty, TTYC_BOLD);
1793 	if (changed & GRID_ATTR_DIM)
1794 		tty_putcode(tty, TTYC_DIM);
1795 	if (changed & GRID_ATTR_ITALICS)
1796 		tty_set_italics(tty);
1797 	if (changed & GRID_ATTR_UNDERSCORE)
1798 		tty_putcode(tty, TTYC_SMUL);
1799 	if (changed & GRID_ATTR_BLINK)
1800 		tty_putcode(tty, TTYC_BLINK);
1801 	if (changed & GRID_ATTR_REVERSE) {
1802 		if (tty_term_has(tty->term, TTYC_REV))
1803 			tty_putcode(tty, TTYC_REV);
1804 		else if (tty_term_has(tty->term, TTYC_SMSO))
1805 			tty_putcode(tty, TTYC_SMSO);
1806 	}
1807 	if (changed & GRID_ATTR_HIDDEN)
1808 		tty_putcode(tty, TTYC_INVIS);
1809 	if (changed & GRID_ATTR_STRIKETHROUGH)
1810 		tty_putcode(tty, TTYC_SMXX);
1811 	if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
1812 		tty_putcode(tty, TTYC_SMACS);
1813 }
1814 
1815 static void
1816 tty_colours(struct tty *tty, const struct grid_cell *gc)
1817 {
1818 	struct grid_cell	*tc = &tty->cell;
1819 	int			 have_ax;
1820 
1821 	/* No changes? Nothing is necessary. */
1822 	if (gc->fg == tc->fg && gc->bg == tc->bg)
1823 		return;
1824 
1825 	/*
1826 	 * Is either the default colour? This is handled specially because the
1827 	 * best solution might be to reset both colours to default, in which
1828 	 * case if only one is default need to fall onward to set the other
1829 	 * colour.
1830 	 */
1831 	if (gc->fg == 8 || gc->bg == 8) {
1832 		/*
1833 		 * If don't have AX but do have op, send sgr0 (op can't
1834 		 * actually be used because it is sometimes the same as sgr0
1835 		 * and sometimes isn't). This resets both colours to default.
1836 		 *
1837 		 * Otherwise, try to set the default colour only as needed.
1838 		 */
1839 		have_ax = tty_term_flag(tty->term, TTYC_AX);
1840 		if (!have_ax && tty_term_has(tty->term, TTYC_OP))
1841 			tty_reset(tty);
1842 		else {
1843 			if (gc->fg == 8 && tc->fg != 8) {
1844 				if (have_ax)
1845 					tty_puts(tty, "\033[39m");
1846 				else if (tc->fg != 7)
1847 					tty_putcode1(tty, TTYC_SETAF, 7);
1848 				tc->fg = 8;
1849 			}
1850 			if (gc->bg == 8 && tc->bg != 8) {
1851 				if (have_ax)
1852 					tty_puts(tty, "\033[49m");
1853 				else if (tc->bg != 0)
1854 					tty_putcode1(tty, TTYC_SETAB, 0);
1855 				tc->bg = 8;
1856 			}
1857 		}
1858 	}
1859 
1860 	/* Set the foreground colour. */
1861 	if (gc->fg != 8 && gc->fg != tc->fg)
1862 		tty_colours_fg(tty, gc);
1863 
1864 	/*
1865 	 * Set the background colour. This must come after the foreground as
1866 	 * tty_colour_fg() can call tty_reset().
1867 	 */
1868 	if (gc->bg != 8 && gc->bg != tc->bg)
1869 		tty_colours_bg(tty, gc);
1870 }
1871 
1872 static void
1873 tty_check_fg(struct tty *tty, const struct window_pane *wp,
1874     struct grid_cell *gc)
1875 {
1876 	u_char	r, g, b;
1877 	u_int	colours;
1878 	int	c;
1879 
1880 	/*
1881 	 * Perform substitution if this pane has a palette. If the bright
1882 	 * attribute is set, use the bright entry in the palette by changing to
1883 	 * the aixterm colour.
1884 	 */
1885 	if (~gc->flags & GRID_FLAG_NOPALETTE) {
1886 		c = gc->fg;
1887 		if (c < 8 && gc->attr & GRID_ATTR_BRIGHT)
1888 			c += 90;
1889 		if ((c = window_pane_get_palette(wp, c)) != -1)
1890 			gc->fg = c;
1891 	}
1892 
1893 	/* Is this a 24-bit colour? */
1894 	if (gc->fg & COLOUR_FLAG_RGB) {
1895 		/* Not a 24-bit terminal? Translate to 256-colour palette. */
1896 		if (!tty_term_has(tty->term, TTYC_SETRGBF)) {
1897 			colour_split_rgb(gc->fg, &r, &g, &b);
1898 			gc->fg = colour_find_rgb(r, g, b);
1899 		} else
1900 			return;
1901 	}
1902 
1903 	/* How many colours does this terminal have? */
1904 	if ((tty->term->flags|tty->term_flags) & TERM_256COLOURS)
1905 		colours = 256;
1906 	else
1907 		colours = tty_term_number(tty->term, TTYC_COLORS);
1908 
1909 	/* Is this a 256-colour colour? */
1910 	if (gc->fg & COLOUR_FLAG_256) {
1911 		/* And not a 256 colour mode? */
1912 		if (colours != 256) {
1913 			gc->fg = colour_256to16(gc->fg);
1914 			if (gc->fg & 8) {
1915 				gc->fg &= 7;
1916 				if (colours >= 16)
1917 					gc->fg += 90;
1918 				else
1919 					gc->attr |= GRID_ATTR_BRIGHT;
1920 			} else
1921 				gc->attr &= ~GRID_ATTR_BRIGHT;
1922 		}
1923 		return;
1924 	}
1925 
1926 	/* Is this an aixterm colour? */
1927 	if (gc->fg >= 90 && gc->fg <= 97 && colours < 16) {
1928 		gc->fg -= 90;
1929 		gc->attr |= GRID_ATTR_BRIGHT;
1930 	}
1931 }
1932 
1933 static void
1934 tty_check_bg(struct tty *tty, const struct window_pane *wp,
1935     struct grid_cell *gc)
1936 {
1937 	u_char	r, g, b;
1938 	u_int	colours;
1939 	int	c;
1940 
1941 	/* Perform substitution if this pane has a palette. */
1942 	if (~gc->flags & GRID_FLAG_NOPALETTE) {
1943 		if ((c = window_pane_get_palette(wp, gc->bg)) != -1)
1944 			gc->bg = c;
1945 	}
1946 
1947 	/* Is this a 24-bit colour? */
1948 	if (gc->bg & COLOUR_FLAG_RGB) {
1949 		/* Not a 24-bit terminal? Translate to 256-colour palette. */
1950 		if (!tty_term_has(tty->term, TTYC_SETRGBB)) {
1951 			colour_split_rgb(gc->bg, &r, &g, &b);
1952 			gc->bg = colour_find_rgb(r, g, b);
1953 		} else
1954 			return;
1955 	}
1956 
1957 	/* How many colours does this terminal have? */
1958 	if ((tty->term->flags|tty->term_flags) & TERM_256COLOURS)
1959 		colours = 256;
1960 	else
1961 		colours = tty_term_number(tty->term, TTYC_COLORS);
1962 
1963 	/* Is this a 256-colour colour? */
1964 	if (gc->bg & COLOUR_FLAG_256) {
1965 		/*
1966 		 * And not a 256 colour mode? Translate to 16-colour
1967 		 * palette. Bold background doesn't exist portably, so just
1968 		 * discard the bold bit if set.
1969 		 */
1970 		if (colours != 256) {
1971 			gc->bg = colour_256to16(gc->bg);
1972 			if (gc->bg & 8) {
1973 				gc->bg &= 7;
1974 				if (colours >= 16)
1975 					gc->fg += 90;
1976 			}
1977 		}
1978 		return;
1979 	}
1980 
1981 	/* Is this an aixterm colour? */
1982 	if (gc->bg >= 90 && gc->bg <= 97 && colours < 16)
1983 		gc->bg -= 90;
1984 }
1985 
1986 static void
1987 tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
1988 {
1989 	struct grid_cell	*tc = &tty->cell;
1990 	char			 s[32];
1991 
1992 	/* Is this a 24-bit or 256-colour colour? */
1993 	if (gc->fg & COLOUR_FLAG_RGB ||
1994 	    gc->fg & COLOUR_FLAG_256) {
1995 		if (tty_try_colour(tty, gc->fg, "38") == 0)
1996 			goto save_fg;
1997 		/* Should not get here, already converted in tty_check_fg. */
1998 		return;
1999 	}
2000 
2001 	/* Is this an aixterm bright colour? */
2002 	if (gc->fg >= 90 && gc->fg <= 97) {
2003 		xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
2004 		tty_puts(tty, s);
2005 		goto save_fg;
2006 	}
2007 
2008 	/* Otherwise set the foreground colour. */
2009 	tty_putcode1(tty, TTYC_SETAF, gc->fg);
2010 
2011 save_fg:
2012 	/* Save the new values in the terminal current cell. */
2013 	tc->fg = gc->fg;
2014 }
2015 
2016 static void
2017 tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
2018 {
2019 	struct grid_cell	*tc = &tty->cell;
2020 	char			 s[32];
2021 
2022 	/* Is this a 24-bit or 256-colour colour? */
2023 	if (gc->bg & COLOUR_FLAG_RGB ||
2024 	    gc->bg & COLOUR_FLAG_256) {
2025 		if (tty_try_colour(tty, gc->bg, "48") == 0)
2026 			goto save_bg;
2027 		/* Should not get here, already converted in tty_check_bg. */
2028 		return;
2029 	}
2030 
2031 	/* Is this an aixterm bright colour? */
2032 	if (gc->bg >= 90 && gc->bg <= 97) {
2033 		xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
2034 		tty_puts(tty, s);
2035 		goto save_bg;
2036 	}
2037 
2038 	/* Otherwise set the background colour. */
2039 	tty_putcode1(tty, TTYC_SETAB, gc->bg);
2040 
2041 save_bg:
2042 	/* Save the new values in the terminal current cell. */
2043 	tc->bg = gc->bg;
2044 }
2045 
2046 static int
2047 tty_try_colour(struct tty *tty, int colour, const char *type)
2048 {
2049 	u_char	r, g, b;
2050 	char	s[32];
2051 
2052 	if (colour & COLOUR_FLAG_256) {
2053 		/*
2054 		 * If the user has specified -2 to the client (meaning
2055 		 * TERM_256COLOURS is set), setaf and setab may not work (or
2056 		 * they may not want to use them), so send the usual sequence.
2057 		 *
2058 		 * Also if RGB is set, setaf and setab do not support the 256
2059 		 * colour palette so use the sequences directly there too.
2060 		 */
2061 		if ((tty->term_flags & TERM_256COLOURS) ||
2062 		    tty_term_has(tty->term, TTYC_RGB))
2063 			goto fallback_256;
2064 
2065 		/*
2066 		 * If the terminfo entry has 256 colours and setaf and setab
2067 		 * exist, assume that they work correctly.
2068 		 */
2069 		if (tty->term->flags & TERM_256COLOURS) {
2070 			if (*type == '3') {
2071 				if (!tty_term_has(tty->term, TTYC_SETAF))
2072 					goto fallback_256;
2073 				tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
2074 			} else {
2075 				if (!tty_term_has(tty->term, TTYC_SETAB))
2076 					goto fallback_256;
2077 				tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
2078 			}
2079 			return (0);
2080 		}
2081 		goto fallback_256;
2082 	}
2083 
2084 	if (colour & COLOUR_FLAG_RGB) {
2085 		if (*type == '3') {
2086 			if (!tty_term_has(tty->term, TTYC_SETRGBF))
2087 				return (-1);
2088 			colour_split_rgb(colour & 0xffffff, &r, &g, &b);
2089 			tty_putcode3(tty, TTYC_SETRGBF, r, g, b);
2090 		} else {
2091 			if (!tty_term_has(tty->term, TTYC_SETRGBB))
2092 				return (-1);
2093 			colour_split_rgb(colour & 0xffffff, &r, &g, &b);
2094 			tty_putcode3(tty, TTYC_SETRGBB, r, g, b);
2095 		}
2096 		return (0);
2097 	}
2098 
2099 	return (-1);
2100 
2101 fallback_256:
2102 	xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
2103 	log_debug("%s: 256 colour fallback: %s", tty->client->name, s);
2104 	tty_puts(tty, s);
2105 	return (0);
2106 }
2107 
2108 static void
2109 tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
2110 {
2111 	struct window		*w = wp->window;
2112 	struct options		*oo = w->options;
2113 	const struct grid_cell	*agc, *pgc, *wgc;
2114 	int			 c;
2115 
2116 	if (w->flags & WINDOW_STYLECHANGED) {
2117 		w->flags &= ~WINDOW_STYLECHANGED;
2118 		agc = options_get_style(oo, "window-active-style");
2119 		memcpy(&w->active_style, agc, sizeof w->active_style);
2120 		wgc = options_get_style(oo, "window-style");
2121 		memcpy(&w->style, wgc, sizeof w->style);
2122 	} else {
2123 		agc = &w->active_style;
2124 		wgc = &w->style;
2125 	}
2126 	pgc = &wp->colgc;
2127 
2128 	if (gc->fg == 8) {
2129 		if (pgc->fg != 8)
2130 			gc->fg = pgc->fg;
2131 		else if (wp == w->active && agc->fg != 8)
2132 			gc->fg = agc->fg;
2133 		else
2134 			gc->fg = wgc->fg;
2135 
2136 		if (gc->fg != 8 &&
2137 		    (c = window_pane_get_palette(wp, gc->fg)) != -1)
2138 			gc->fg = c;
2139 	}
2140 
2141 	if (gc->bg == 8) {
2142 		if (pgc->bg != 8)
2143 			gc->bg = pgc->bg;
2144 		else if (wp == w->active && agc->bg != 8)
2145 			gc->bg = agc->bg;
2146 		else
2147 			gc->bg = wgc->bg;
2148 
2149 		if (gc->bg != 8 &&
2150 		    (c = window_pane_get_palette(wp, gc->bg)) != -1)
2151 			gc->bg = c;
2152 	}
2153 }
2154 
2155 static void
2156 tty_default_attributes(struct tty *tty, const struct window_pane *wp, u_int bg)
2157 {
2158 	static struct grid_cell gc;
2159 
2160 	memcpy(&gc, &grid_default_cell, sizeof gc);
2161 	gc.bg = bg;
2162 	tty_attributes(tty, &gc, wp);
2163 }
2164