xref: /openbsd-src/usr.bin/tmux/screen-write.c (revision 24bb5fcea3ed904bc467217bdaadb5dfc618d5bf)
1 /* $OpenBSD: screen-write.c,v 1.194 2021/06/10 07:43:44 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 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "tmux.h"
25 
26 static struct screen_write_citem *screen_write_collect_trim(
27 		    struct screen_write_ctx *, u_int, u_int, u_int, int *);
28 static void	screen_write_collect_clear(struct screen_write_ctx *, u_int,
29 		    u_int);
30 static void	screen_write_collect_scroll(struct screen_write_ctx *, u_int);
31 static void	screen_write_collect_flush(struct screen_write_ctx *, int,
32 		    const char *);
33 
34 static int	screen_write_overwrite(struct screen_write_ctx *,
35 		    struct grid_cell *, u_int);
36 static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
37 		    const struct utf8_data *, u_int *);
38 
39 struct screen_write_citem {
40 	u_int				x;
41 	int				wrapped;
42 
43 	enum { TEXT, CLEAR }		type;
44 	u_int				used;
45 	u_int				bg;
46 
47 	struct grid_cell		gc;
48 
49 	TAILQ_ENTRY(screen_write_citem) entry;
50 };
51 struct screen_write_cline {
52 	char				*data;
53 	TAILQ_HEAD(, screen_write_citem) items;
54 };
55 TAILQ_HEAD(, screen_write_citem)  screen_write_citem_freelist =
56     TAILQ_HEAD_INITIALIZER(screen_write_citem_freelist);
57 
58 static struct screen_write_citem *
59 screen_write_get_citem(void)
60 {
61     struct screen_write_citem	*ci;
62 
63     ci = TAILQ_FIRST(&screen_write_citem_freelist);
64     if (ci != NULL) {
65         TAILQ_REMOVE(&screen_write_citem_freelist, ci, entry);
66         memset(ci, 0, sizeof *ci);
67         return (ci);
68     }
69     return (xcalloc(1, sizeof *ci));
70 }
71 
72 static void
73 screen_write_free_citem(struct screen_write_citem *ci)
74 {
75     TAILQ_INSERT_TAIL(&screen_write_citem_freelist, ci, entry);
76 }
77 
78 static void
79 screen_write_offset_timer(__unused int fd, __unused short events, void *data)
80 {
81 	struct window	*w = data;
82 
83 	tty_update_window_offset(w);
84 }
85 
86 /* Set cursor position. */
87 static void
88 screen_write_set_cursor(struct screen_write_ctx *ctx, int cx, int cy)
89 {
90 	struct window_pane	*wp = ctx->wp;
91 	struct window		*w;
92 	struct screen		*s = ctx->s;
93 	struct timeval		 tv = { .tv_usec = 10000 };
94 
95 	if (cx != -1 && (u_int)cx == s->cx && cy != -1 && (u_int)cy == s->cy)
96 		return;
97 
98 	if (cx != -1) {
99 		if ((u_int)cx > screen_size_x(s)) /* allow last column */
100 			cx = screen_size_x(s) - 1;
101 		s->cx = cx;
102 	}
103 	if (cy != -1) {
104 		if ((u_int)cy > screen_size_y(s) - 1)
105 			cy = screen_size_y(s) - 1;
106 		s->cy = cy;
107 	}
108 
109 	if (wp == NULL)
110 		return;
111 	w = wp->window;
112 
113 	if (!event_initialized(&w->offset_timer))
114 		evtimer_set(&w->offset_timer, screen_write_offset_timer, w);
115 	if (!evtimer_pending(&w->offset_timer, NULL))
116 		evtimer_add(&w->offset_timer, &tv);
117 }
118 
119 /* Do a full redraw. */
120 static void
121 screen_write_redraw_cb(const struct tty_ctx *ttyctx)
122 {
123 	struct window_pane	*wp = ttyctx->arg;
124 
125 	if (wp != NULL)
126 		wp->flags |= PANE_REDRAW;
127 }
128 
129 /* Update context for client. */
130 static int
131 screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
132 {
133 	struct window_pane	*wp = ttyctx->arg;
134 
135 	if (c->session->curw->window != wp->window)
136 		return (0);
137 	if (wp->layout_cell == NULL)
138 		return (0);
139 
140 	if (wp->flags & (PANE_REDRAW|PANE_DROP))
141 		return (-1);
142 	if (c->flags & CLIENT_REDRAWPANES) {
143 		/*
144 		 * Redraw is already deferred to redraw another pane - redraw
145 		 * this one also when that happens.
146 		 */
147 		log_debug("%s: adding %%%u to deferred redraw", __func__,
148 		    wp->id);
149 		wp->flags |= PANE_REDRAW;
150 		return (-1);
151 	}
152 
153 	ttyctx->bigger = tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy,
154 	    &ttyctx->wsx, &ttyctx->wsy);
155 
156 	ttyctx->xoff = ttyctx->rxoff = wp->xoff;
157 	ttyctx->yoff = ttyctx->ryoff = wp->yoff;
158 
159 	if (status_at_line(c) == 0)
160 		ttyctx->yoff += status_line_size(c);
161 
162 	return (1);
163 }
164 
165 /* Set up context for TTY command. */
166 static void
167 screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
168     int sync)
169 {
170 	struct screen	*s = ctx->s;
171 
172 	memset(ttyctx, 0, sizeof *ttyctx);
173 
174 	if (ctx->wp != NULL) {
175 		tty_default_colours(&ttyctx->defaults, ctx->wp);
176 		ttyctx->palette = ctx->wp->palette;
177 	} else {
178 		memcpy(&ttyctx->defaults, &grid_default_cell,
179 		    sizeof ttyctx->defaults);
180 		ttyctx->palette = NULL;
181 	}
182 
183 	ttyctx->s = s;
184 	ttyctx->sx = screen_size_x(s);
185 	ttyctx->sy = screen_size_y(s);
186 
187 	ttyctx->ocx = s->cx;
188 	ttyctx->ocy = s->cy;
189 	ttyctx->orlower = s->rlower;
190 	ttyctx->orupper = s->rupper;
191 
192 	if (ctx->init_ctx_cb != NULL)
193 		ctx->init_ctx_cb(ctx, ttyctx);
194 	else {
195 		ttyctx->redraw_cb = screen_write_redraw_cb;
196 		if (ctx->wp == NULL)
197 			ttyctx->set_client_cb = NULL;
198 		else
199 			ttyctx->set_client_cb = screen_write_set_client_cb;
200 		ttyctx->arg = ctx->wp;
201 	}
202 
203 	if (ctx->wp != NULL &&
204 	    (~ctx->flags & SCREEN_WRITE_SYNC) &&
205 	    (sync || ctx->wp != ctx->wp->window->active)) {
206 		tty_write(tty_cmd_syncstart, ttyctx);
207 		ctx->flags |= SCREEN_WRITE_SYNC;
208 	}
209 }
210 
211 /* Make write list. */
212 void
213 screen_write_make_list(struct screen *s)
214 {
215 	u_int	y;
216 
217 	s->write_list = xcalloc(screen_size_y(s), sizeof *s->write_list);
218 	for (y = 0; y < screen_size_y(s); y++)
219 		TAILQ_INIT(&s->write_list[y].items);
220 }
221 
222 /* Free write list. */
223 void
224 screen_write_free_list(struct screen *s)
225 {
226 	u_int	y;
227 
228 	for (y = 0; y < screen_size_y(s); y++)
229 		free(s->write_list[y].data);
230 	free(s->write_list);
231 }
232 
233 /* Set up for writing. */
234 static void
235 screen_write_init(struct screen_write_ctx *ctx, struct screen *s)
236 {
237 	memset(ctx, 0, sizeof *ctx);
238 
239 	ctx->s = s;
240 
241 	if (ctx->s->write_list == NULL)
242 		screen_write_make_list(ctx->s);
243 	ctx->item = screen_write_get_citem();
244 
245 	ctx->scrolled = 0;
246 	ctx->bg = 8;
247 }
248 
249 /* Initialize writing with a pane. */
250 void
251 screen_write_start_pane(struct screen_write_ctx *ctx, struct window_pane *wp,
252     struct screen *s)
253 {
254 	if (s == NULL)
255 		s = wp->screen;
256 	screen_write_init(ctx, s);
257 	ctx->wp = wp;
258 
259 	if (log_get_level() != 0) {
260 		log_debug("%s: size %ux%u, pane %%%u (at %u,%u)",
261 		    __func__, screen_size_x(ctx->s), screen_size_y(ctx->s),
262 		    wp->id, wp->xoff, wp->yoff);
263 	}
264 }
265 
266 /* Initialize writing with a callback. */
267 void
268 screen_write_start_callback(struct screen_write_ctx *ctx, struct screen *s,
269     screen_write_init_ctx_cb cb, void *arg)
270 {
271 	screen_write_init(ctx, s);
272 
273 	ctx->init_ctx_cb = cb;
274 	ctx->arg = arg;
275 
276 	if (log_get_level() != 0) {
277 		log_debug("%s: size %ux%u, with callback", __func__,
278 		    screen_size_x(ctx->s), screen_size_y(ctx->s));
279 	}
280 }
281 
282 /* Initialize writing. */
283 void
284 screen_write_start(struct screen_write_ctx *ctx, struct screen *s)
285 {
286 	screen_write_init(ctx, s);
287 
288 	if (log_get_level() != 0) {
289 		log_debug("%s: size %ux%u, no pane", __func__,
290 		    screen_size_x(ctx->s), screen_size_y(ctx->s));
291 	}
292 }
293 
294 /* Finish writing. */
295 void
296 screen_write_stop(struct screen_write_ctx *ctx)
297 {
298 	screen_write_collect_end(ctx);
299 	screen_write_collect_flush(ctx, 0, __func__);
300 
301 	screen_write_free_citem(ctx->item);
302 }
303 
304 /* Reset screen state. */
305 void
306 screen_write_reset(struct screen_write_ctx *ctx)
307 {
308 	struct screen	*s = ctx->s;
309 
310 	screen_reset_tabs(s);
311 	screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1);
312 
313 	s->mode = MODE_CURSOR | MODE_WRAP;
314 
315 	screen_write_clearscreen(ctx, 8);
316 	screen_write_set_cursor(ctx, 0, 0);
317 }
318 
319 /* Write character. */
320 void
321 screen_write_putc(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
322     u_char ch)
323 {
324 	struct grid_cell	gc;
325 
326 	memcpy(&gc, gcp, sizeof gc);
327 
328 	utf8_set(&gc.data, ch);
329 	screen_write_cell(ctx, &gc);
330 }
331 
332 /* Calculate string length. */
333 size_t
334 screen_write_strlen(const char *fmt, ...)
335 {
336 	va_list			ap;
337 	char   	       	       *msg;
338 	struct utf8_data	ud;
339 	u_char 	      	       *ptr;
340 	size_t			left, size = 0;
341 	enum utf8_state		more;
342 
343 	va_start(ap, fmt);
344 	xvasprintf(&msg, fmt, ap);
345 	va_end(ap);
346 
347 	ptr = msg;
348 	while (*ptr != '\0') {
349 		if (*ptr > 0x7f && utf8_open(&ud, *ptr) == UTF8_MORE) {
350 			ptr++;
351 
352 			left = strlen(ptr);
353 			if (left < (size_t)ud.size - 1)
354 				break;
355 			while ((more = utf8_append(&ud, *ptr)) == UTF8_MORE)
356 				ptr++;
357 			ptr++;
358 
359 			if (more == UTF8_DONE)
360 				size += ud.width;
361 		} else {
362 			if (*ptr > 0x1f && *ptr < 0x7f)
363 				size++;
364 			ptr++;
365 		}
366 	}
367 
368 	free(msg);
369 	return (size);
370 }
371 
372 /* Write string wrapped over lines. */
373 int
374 screen_write_text(struct screen_write_ctx *ctx, u_int cx, u_int width,
375     u_int lines, int more, const struct grid_cell *gcp, const char *fmt, ...)
376 {
377 	struct screen		*s = ctx->s;
378 	va_list			 ap;
379 	char			*tmp;
380 	u_int			 cy = s->cy, i, end, next, idx = 0, at, left;
381 	struct utf8_data	*text;
382 	struct grid_cell	 gc;
383 
384 	memcpy(&gc, gcp, sizeof gc);
385 
386 	va_start(ap, fmt);
387 	xvasprintf(&tmp, fmt, ap);
388 	va_end(ap);
389 
390 	text = utf8_fromcstr(tmp);
391 	free(tmp);
392 
393 	left = (cx + width) - s->cx;
394 	for (;;) {
395 		/* Find the end of what can fit on the line. */
396 		at = 0;
397 		for (end = idx; text[end].size != 0; end++) {
398 			if (text[end].size == 1 && text[end].data[0] == '\n')
399 				break;
400 			if (at + text[end].width > left)
401 				break;
402 			at += text[end].width;
403 		}
404 
405 		/*
406 		 * If we're on a space, that's the end. If not, walk back to
407 		 * try and find one.
408 		 */
409 		if (text[end].size == 0)
410 			next = end;
411 		else if (text[end].size == 1 && text[end].data[0] == '\n')
412 			next = end + 1;
413 		else if (text[end].size == 1 && text[end].data[0] == ' ')
414 			next = end + 1;
415 		else {
416 			for (i = end; i > idx; i--) {
417 				if (text[i].size == 1 && text[i].data[0] == ' ')
418 					break;
419 			}
420 			if (i != idx) {
421 				next = i + 1;
422 				end = i;
423 			} else
424 				next = end;
425 		}
426 
427 		/* Print the line. */
428 		for (i = idx; i < end; i++) {
429 			utf8_copy(&gc.data, &text[i]);
430 			screen_write_cell(ctx, &gc);
431 		}
432 
433 		/* If at the bottom, stop. */
434 		idx = next;
435 		if (s->cy == cy + lines - 1 || text[idx].size == 0)
436 			break;
437 
438 		screen_write_cursormove(ctx, cx, s->cy + 1, 0);
439 		left = width;
440 	}
441 
442 	/*
443 	 * Fail if on the last line and there is more to come or at the end, or
444 	 * if the text was not entirely consumed.
445 	 */
446 	if ((s->cy == cy + lines - 1 && (!more || s->cx == cx + width)) ||
447 	    text[idx].size != 0) {
448 		free(text);
449 		return (0);
450 	}
451 	free(text);
452 
453 	/*
454 	 * If no more to come, move to the next line. Otherwise, leave on
455 	 * the same line (except if at the end).
456 	 */
457 	if (!more || s->cx == cx + width)
458 		screen_write_cursormove(ctx, cx, s->cy + 1, 0);
459 	return (1);
460 }
461 
462 /* Write simple string (no maximum length). */
463 void
464 screen_write_puts(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
465     const char *fmt, ...)
466 {
467 	va_list	ap;
468 
469 	va_start(ap, fmt);
470 	screen_write_vnputs(ctx, -1, gcp, fmt, ap);
471 	va_end(ap);
472 }
473 
474 /* Write string with length limit (-1 for unlimited). */
475 void
476 screen_write_nputs(struct screen_write_ctx *ctx, ssize_t maxlen,
477     const struct grid_cell *gcp, const char *fmt, ...)
478 {
479 	va_list	ap;
480 
481 	va_start(ap, fmt);
482 	screen_write_vnputs(ctx, maxlen, gcp, fmt, ap);
483 	va_end(ap);
484 }
485 
486 void
487 screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
488     const struct grid_cell *gcp, const char *fmt, va_list ap)
489 {
490 	struct grid_cell	gc;
491 	struct utf8_data       *ud = &gc.data;
492 	char   		       *msg;
493 	u_char 		       *ptr;
494 	size_t		 	left, size = 0;
495 	enum utf8_state		more;
496 
497 	memcpy(&gc, gcp, sizeof gc);
498 	xvasprintf(&msg, fmt, ap);
499 
500 	ptr = msg;
501 	while (*ptr != '\0') {
502 		if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
503 			ptr++;
504 
505 			left = strlen(ptr);
506 			if (left < (size_t)ud->size - 1)
507 				break;
508 			while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
509 				ptr++;
510 			ptr++;
511 
512 			if (more != UTF8_DONE)
513 				continue;
514 			if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
515 				while (size < (size_t)maxlen) {
516 					screen_write_putc(ctx, &gc, ' ');
517 					size++;
518 				}
519 				break;
520 			}
521 			size += ud->width;
522 			screen_write_cell(ctx, &gc);
523 		} else {
524 			if (maxlen > 0 && size + 1 > (size_t)maxlen)
525 				break;
526 
527 			if (*ptr == '\001')
528 				gc.attr ^= GRID_ATTR_CHARSET;
529 			else if (*ptr == '\n') {
530 				screen_write_linefeed(ctx, 0, 8);
531 				screen_write_carriagereturn(ctx);
532 			} else if (*ptr > 0x1f && *ptr < 0x7f) {
533 				size++;
534 				screen_write_putc(ctx, &gc, *ptr);
535 			}
536 			ptr++;
537 		}
538 	}
539 
540 	free(msg);
541 }
542 
543 /*
544  * Copy from another screen but without the selection stuff. Assumes the target
545  * region is already big enough.
546  */
547 void
548 screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
549     u_int px, u_int py, u_int nx, u_int ny)
550 {
551 	struct screen		*s = ctx->s;
552 	struct grid		*gd = src->grid;
553 	struct grid_cell	 gc;
554 	u_int		 	 xx, yy, cx, cy;
555 
556 	if (nx == 0 || ny == 0)
557 		return;
558 
559 	cy = s->cy;
560 	for (yy = py; yy < py + ny; yy++) {
561 		if (yy >= gd->hsize + gd->sy)
562 			break;
563 		cx = s->cx;
564 		for (xx = px; xx < px + nx; xx++) {
565 			if (xx >= grid_get_line(gd, yy)->cellsize)
566 				break;
567 			grid_get_cell(gd, xx, yy, &gc);
568 			if (xx + gc.data.width > px + nx)
569 				break;
570 			grid_view_set_cell(ctx->s->grid, cx, cy, &gc);
571 			cx++;
572 		}
573 		cy++;
574 	}
575 }
576 
577 /* Draw a horizontal line on screen. */
578 void
579 screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right)
580 {
581 	struct screen		*s = ctx->s;
582 	struct grid_cell	 gc;
583 	u_int			 cx, cy, i;
584 
585 	cx = s->cx;
586 	cy = s->cy;
587 
588 	memcpy(&gc, &grid_default_cell, sizeof gc);
589 	gc.attr |= GRID_ATTR_CHARSET;
590 
591 	screen_write_putc(ctx, &gc, left ? 't' : 'q');
592 	for (i = 1; i < nx - 1; i++)
593 		screen_write_putc(ctx, &gc, 'q');
594 	screen_write_putc(ctx, &gc, right ? 'u' : 'q');
595 
596 	screen_write_set_cursor(ctx, cx, cy);
597 }
598 
599 /* Draw a horizontal line on screen. */
600 void
601 screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom)
602 {
603 	struct screen		*s = ctx->s;
604 	struct grid_cell	 gc;
605 	u_int			 cx, cy, i;
606 
607 	cx = s->cx;
608 	cy = s->cy;
609 
610 	memcpy(&gc, &grid_default_cell, sizeof gc);
611 	gc.attr |= GRID_ATTR_CHARSET;
612 
613 	screen_write_putc(ctx, &gc, top ? 'w' : 'x');
614 	for (i = 1; i < ny - 1; i++) {
615 		screen_write_set_cursor(ctx, cx, cy + i);
616 		screen_write_putc(ctx, &gc, 'x');
617 	}
618 	screen_write_set_cursor(ctx, cx, cy + ny - 1);
619 	screen_write_putc(ctx, &gc, bottom ? 'v' : 'x');
620 
621 	screen_write_set_cursor(ctx, cx, cy);
622 }
623 
624 /* Draw a menu on screen. */
625 void
626 screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu,
627     int choice, const struct grid_cell *choice_gc)
628 {
629 	struct screen		*s = ctx->s;
630 	struct grid_cell	 default_gc;
631 	const struct grid_cell	*gc = &default_gc;
632 	u_int			 cx, cy, i, j;
633 	const char		*name;
634 
635 	cx = s->cx;
636 	cy = s->cy;
637 
638 	memcpy(&default_gc, &grid_default_cell, sizeof default_gc);
639 
640 	screen_write_box(ctx, menu->width + 4, menu->count + 2);
641 	screen_write_cursormove(ctx, cx + 2, cy, 0);
642 	format_draw(ctx, &default_gc, menu->width, menu->title, NULL);
643 
644 	for (i = 0; i < menu->count; i++) {
645 		name = menu->items[i].name;
646 		if (name == NULL) {
647 			screen_write_cursormove(ctx, cx, cy + 1 + i, 0);
648 			screen_write_hline(ctx, menu->width + 4, 1, 1);
649 		} else {
650 			if (choice >= 0 && i == (u_int)choice && *name != '-')
651 				gc = choice_gc;
652 			screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0);
653 			for (j = 0; j < menu->width; j++)
654 				screen_write_putc(ctx, gc, ' ');
655 			screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0);
656 			if (*name == '-') {
657 				name++;
658 				default_gc.attr |= GRID_ATTR_DIM;
659 				format_draw(ctx, gc, menu->width, name, NULL);
660 				default_gc.attr &= ~GRID_ATTR_DIM;
661 			} else
662 				format_draw(ctx, gc, menu->width, name, NULL);
663 			gc = &default_gc;
664 		}
665 	}
666 
667 	screen_write_set_cursor(ctx, cx, cy);
668 }
669 
670 /* Draw a box on screen. */
671 void
672 screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny)
673 {
674 	struct screen		*s = ctx->s;
675 	struct grid_cell	 gc;
676 	u_int			 cx, cy, i;
677 
678 	cx = s->cx;
679 	cy = s->cy;
680 
681 	memcpy(&gc, &grid_default_cell, sizeof gc);
682 	gc.attr |= GRID_ATTR_CHARSET;
683 
684 	screen_write_putc(ctx, &gc, 'l');
685 	for (i = 1; i < nx - 1; i++)
686 		screen_write_putc(ctx, &gc, 'q');
687 	screen_write_putc(ctx, &gc, 'k');
688 
689 	screen_write_set_cursor(ctx, cx, cy + ny - 1);
690 	screen_write_putc(ctx, &gc, 'm');
691 	for (i = 1; i < nx - 1; i++)
692 		screen_write_putc(ctx, &gc, 'q');
693 	screen_write_putc(ctx, &gc, 'j');
694 
695 	for (i = 1; i < ny - 1; i++) {
696 		screen_write_set_cursor(ctx, cx, cy + i);
697 		screen_write_putc(ctx, &gc, 'x');
698 	}
699 	for (i = 1; i < ny - 1; i++) {
700 		screen_write_set_cursor(ctx, cx + nx - 1, cy + i);
701 		screen_write_putc(ctx, &gc, 'x');
702 	}
703 
704 	screen_write_set_cursor(ctx, cx, cy);
705 }
706 
707 /*
708  * Write a preview version of a window. Assumes target area is big enough and
709  * already cleared.
710  */
711 void
712 screen_write_preview(struct screen_write_ctx *ctx, struct screen *src, u_int nx,
713     u_int ny)
714 {
715 	struct screen		*s = ctx->s;
716 	struct grid_cell	 gc;
717 	u_int			 cx, cy, px, py;
718 
719 	cx = s->cx;
720 	cy = s->cy;
721 
722 	/*
723 	 * If the cursor is on, pick the area around the cursor, otherwise use
724 	 * the top left.
725 	 */
726 	if (src->mode & MODE_CURSOR) {
727 		px = src->cx;
728 		if (px < nx / 3)
729 			px = 0;
730 		else
731 			px = px - nx / 3;
732 		if (px + nx > screen_size_x(src)) {
733 			if (nx > screen_size_x(src))
734 				px = 0;
735 			else
736 				px = screen_size_x(src) - nx;
737 		}
738 		py = src->cy;
739 		if (py < ny / 3)
740 			py = 0;
741 		else
742 			py = py - ny / 3;
743 		if (py + ny > screen_size_y(src)) {
744 			if (ny > screen_size_y(src))
745 				py = 0;
746 			else
747 				py = screen_size_y(src) - ny;
748 		}
749 	} else {
750 		px = 0;
751 		py = 0;
752 	}
753 
754 	screen_write_fast_copy(ctx, src, px, src->grid->hsize + py, nx, ny);
755 
756 	if (src->mode & MODE_CURSOR) {
757 		grid_view_get_cell(src->grid, src->cx, src->cy, &gc);
758 		gc.attr |= GRID_ATTR_REVERSE;
759 		screen_write_set_cursor(ctx, cx + (src->cx - px),
760 		    cy + (src->cy - py));
761 		screen_write_cell(ctx, &gc);
762 	}
763 }
764 
765 /* Set a mode. */
766 void
767 screen_write_mode_set(struct screen_write_ctx *ctx, int mode)
768 {
769 	struct screen	*s = ctx->s;
770 
771 	s->mode |= mode;
772 
773 	if (log_get_level() != 0)
774 		log_debug("%s: %s", __func__, screen_mode_to_string(mode));
775 }
776 
777 /* Clear a mode. */
778 void
779 screen_write_mode_clear(struct screen_write_ctx *ctx, int mode)
780 {
781 	struct screen	*s = ctx->s;
782 
783 	s->mode &= ~mode;
784 
785 	if (log_get_level() != 0)
786 		log_debug("%s: %s", __func__, screen_mode_to_string(mode));
787 }
788 
789 /* Cursor up by ny. */
790 void
791 screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
792 {
793 	struct screen	*s = ctx->s;
794 	u_int		 cx = s->cx, cy = s->cy;
795 
796 	if (ny == 0)
797 		ny = 1;
798 
799 	if (cy < s->rupper) {
800 		/* Above region. */
801 		if (ny > cy)
802 			ny = cy;
803 	} else {
804 		/* Below region. */
805 		if (ny > cy - s->rupper)
806 			ny = cy - s->rupper;
807 	}
808 	if (cx == screen_size_x(s))
809 		cx--;
810 
811 	cy -= ny;
812 
813 	screen_write_set_cursor(ctx, cx, cy);
814 }
815 
816 /* Cursor down by ny. */
817 void
818 screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
819 {
820 	struct screen	*s = ctx->s;
821 	u_int		 cx = s->cx, cy = s->cy;
822 
823 	if (ny == 0)
824 		ny = 1;
825 
826 	if (cy > s->rlower) {
827 		/* Below region. */
828 		if (ny > screen_size_y(s) - 1 - cy)
829 			ny = screen_size_y(s) - 1 - cy;
830 	} else {
831 		/* Above region. */
832 		if (ny > s->rlower - cy)
833 			ny = s->rlower - cy;
834 	}
835 	if (cx == screen_size_x(s))
836 	    cx--;
837 	else if (ny == 0)
838 		return;
839 
840 	cy += ny;
841 
842 	screen_write_set_cursor(ctx, cx, cy);
843 }
844 
845 /* Cursor right by nx. */
846 void
847 screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
848 {
849 	struct screen	*s = ctx->s;
850 	u_int		 cx = s->cx, cy = s->cy;
851 
852 	if (nx == 0)
853 		nx = 1;
854 
855 	if (nx > screen_size_x(s) - 1 - cx)
856 		nx = screen_size_x(s) - 1 - cx;
857 	if (nx == 0)
858 		return;
859 
860 	cx += nx;
861 
862 	screen_write_set_cursor(ctx, cx, cy);
863 }
864 
865 /* Cursor left by nx. */
866 void
867 screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
868 {
869 	struct screen	*s = ctx->s;
870 	u_int		 cx = s->cx, cy = s->cy;
871 
872 	if (nx == 0)
873 		nx = 1;
874 
875 	if (nx > cx)
876 		nx = cx;
877 	if (nx == 0)
878 		return;
879 
880 	cx -= nx;
881 
882 	screen_write_set_cursor(ctx, cx, cy);
883 }
884 
885 /* Backspace; cursor left unless at start of wrapped line when can move up. */
886 void
887 screen_write_backspace(struct screen_write_ctx *ctx)
888 {
889 	struct screen		*s = ctx->s;
890 	struct grid_line	*gl;
891 	u_int			 cx = s->cx, cy = s->cy;
892 
893 	if (cx == 0) {
894 		if (cy == 0)
895 			return;
896 		gl = grid_get_line(s->grid, s->grid->hsize + cy - 1);
897 		if (gl->flags & GRID_LINE_WRAPPED) {
898 			cy--;
899 			cx = screen_size_x(s) - 1;
900 		}
901 	} else
902 		cx--;
903 
904 	screen_write_set_cursor(ctx, cx, cy);
905 }
906 
907 /* VT100 alignment test. */
908 void
909 screen_write_alignmenttest(struct screen_write_ctx *ctx)
910 {
911 	struct screen		*s = ctx->s;
912 	struct tty_ctx	 	 ttyctx;
913 	struct grid_cell       	 gc;
914 	u_int			 xx, yy;
915 
916 	memcpy(&gc, &grid_default_cell, sizeof gc);
917 	utf8_set(&gc.data, 'E');
918 
919 	for (yy = 0; yy < screen_size_y(s); yy++) {
920 		for (xx = 0; xx < screen_size_x(s); xx++)
921 			grid_view_set_cell(s->grid, xx, yy, &gc);
922 	}
923 
924 	screen_write_set_cursor(ctx, 0, 0);
925 
926 	s->rupper = 0;
927 	s->rlower = screen_size_y(s) - 1;
928 
929 	screen_write_initctx(ctx, &ttyctx, 1);
930 
931 	screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1);
932 	tty_write(tty_cmd_alignmenttest, &ttyctx);
933 }
934 
935 /* Insert nx characters. */
936 void
937 screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
938 {
939 	struct screen	*s = ctx->s;
940 	struct tty_ctx	 ttyctx;
941 
942 	if (nx == 0)
943 		nx = 1;
944 
945 	if (nx > screen_size_x(s) - s->cx)
946 		nx = screen_size_x(s) - s->cx;
947 	if (nx == 0)
948 		return;
949 
950 	if (s->cx > screen_size_x(s) - 1)
951 		return;
952 
953 	screen_write_initctx(ctx, &ttyctx, 0);
954 	ttyctx.bg = bg;
955 
956 	grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);
957 
958 	screen_write_collect_flush(ctx, 0, __func__);
959 	ttyctx.num = nx;
960 	tty_write(tty_cmd_insertcharacter, &ttyctx);
961 }
962 
963 /* Delete nx characters. */
964 void
965 screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
966 {
967 	struct screen	*s = ctx->s;
968 	struct tty_ctx	 ttyctx;
969 
970 	if (nx == 0)
971 		nx = 1;
972 
973 	if (nx > screen_size_x(s) - s->cx)
974 		nx = screen_size_x(s) - s->cx;
975 	if (nx == 0)
976 		return;
977 
978 	if (s->cx > screen_size_x(s) - 1)
979 		return;
980 
981 	screen_write_initctx(ctx, &ttyctx, 0);
982 	ttyctx.bg = bg;
983 
984 	grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);
985 
986 	screen_write_collect_flush(ctx, 0, __func__);
987 	ttyctx.num = nx;
988 	tty_write(tty_cmd_deletecharacter, &ttyctx);
989 }
990 
991 /* Clear nx characters. */
992 void
993 screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
994 {
995 	struct screen	*s = ctx->s;
996 	struct tty_ctx	 ttyctx;
997 
998 	if (nx == 0)
999 		nx = 1;
1000 
1001 	if (nx > screen_size_x(s) - s->cx)
1002 		nx = screen_size_x(s) - s->cx;
1003 	if (nx == 0)
1004 		return;
1005 
1006 	if (s->cx > screen_size_x(s) - 1)
1007 		return;
1008 
1009 	screen_write_initctx(ctx, &ttyctx, 0);
1010 	ttyctx.bg = bg;
1011 
1012 	grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg);
1013 
1014 	screen_write_collect_flush(ctx, 0, __func__);
1015 	ttyctx.num = nx;
1016 	tty_write(tty_cmd_clearcharacter, &ttyctx);
1017 }
1018 
1019 /* Insert ny lines. */
1020 void
1021 screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
1022 {
1023 	struct screen	*s = ctx->s;
1024 	struct grid	*gd = s->grid;
1025 	struct tty_ctx	 ttyctx;
1026 
1027 	if (ny == 0)
1028 		ny = 1;
1029 
1030 	if (s->cy < s->rupper || s->cy > s->rlower) {
1031 		if (ny > screen_size_y(s) - s->cy)
1032 			ny = screen_size_y(s) - s->cy;
1033 		if (ny == 0)
1034 			return;
1035 
1036 		screen_write_initctx(ctx, &ttyctx, 1);
1037 		ttyctx.bg = bg;
1038 
1039 		grid_view_insert_lines(gd, s->cy, ny, bg);
1040 
1041 		screen_write_collect_flush(ctx, 0, __func__);
1042 		ttyctx.num = ny;
1043 		tty_write(tty_cmd_insertline, &ttyctx);
1044 		return;
1045 	}
1046 
1047 	if (ny > s->rlower + 1 - s->cy)
1048 		ny = s->rlower + 1 - s->cy;
1049 	if (ny == 0)
1050 		return;
1051 
1052 	screen_write_initctx(ctx, &ttyctx, 1);
1053 	ttyctx.bg = bg;
1054 
1055 	if (s->cy < s->rupper || s->cy > s->rlower)
1056 		grid_view_insert_lines(gd, s->cy, ny, bg);
1057 	else
1058 		grid_view_insert_lines_region(gd, s->rlower, s->cy, ny, bg);
1059 
1060 	screen_write_collect_flush(ctx, 0, __func__);
1061 
1062 	ttyctx.num = ny;
1063 	tty_write(tty_cmd_insertline, &ttyctx);
1064 }
1065 
1066 /* Delete ny lines. */
1067 void
1068 screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
1069 {
1070 	struct screen	*s = ctx->s;
1071 	struct grid	*gd = s->grid;
1072 	struct tty_ctx	 ttyctx;
1073 
1074 	if (ny == 0)
1075 		ny = 1;
1076 
1077 	if (s->cy < s->rupper || s->cy > s->rlower) {
1078 		if (ny > screen_size_y(s) - s->cy)
1079 			ny = screen_size_y(s) - s->cy;
1080 		if (ny == 0)
1081 			return;
1082 
1083 		screen_write_initctx(ctx, &ttyctx, 1);
1084 		ttyctx.bg = bg;
1085 
1086 		grid_view_delete_lines(gd, s->cy, ny, bg);
1087 
1088 		screen_write_collect_flush(ctx, 0, __func__);
1089 		ttyctx.num = ny;
1090 		tty_write(tty_cmd_deleteline, &ttyctx);
1091 		return;
1092 	}
1093 
1094 	if (ny > s->rlower + 1 - s->cy)
1095 		ny = s->rlower + 1 - s->cy;
1096 	if (ny == 0)
1097 		return;
1098 
1099 	screen_write_initctx(ctx, &ttyctx, 1);
1100 	ttyctx.bg = bg;
1101 
1102 	if (s->cy < s->rupper || s->cy > s->rlower)
1103 		grid_view_delete_lines(gd, s->cy, ny, bg);
1104 	else
1105 		grid_view_delete_lines_region(gd, s->rlower, s->cy, ny, bg);
1106 
1107 	screen_write_collect_flush(ctx, 0, __func__);
1108 	ttyctx.num = ny;
1109 	tty_write(tty_cmd_deleteline, &ttyctx);
1110 }
1111 
1112 /* Clear line at cursor. */
1113 void
1114 screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
1115 {
1116 	struct screen			*s = ctx->s;
1117 	struct grid_line		*gl;
1118 	u_int				 sx = screen_size_x(s);
1119 	struct screen_write_citem	*ci = ctx->item;
1120 
1121 	gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
1122 	if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
1123 		return;
1124 
1125 	grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
1126 
1127 	screen_write_collect_clear(ctx, s->cy, 1);
1128 	ci->x = 0;
1129 	ci->used = sx;
1130 	ci->type = CLEAR;
1131 	ci->bg = bg;
1132 	TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
1133 	ctx->item = screen_write_get_citem();
1134 }
1135 
1136 /* Clear to end of line from cursor. */
1137 void
1138 screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
1139 {
1140 	struct screen			*s = ctx->s;
1141 	struct grid_line		*gl;
1142 	u_int				 sx = screen_size_x(s);
1143 	struct screen_write_citem	*ci = ctx->item, *before;
1144 
1145 	if (s->cx == 0) {
1146 		screen_write_clearline(ctx, bg);
1147 		return;
1148 	}
1149 
1150 	gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
1151 	if (s->cx > sx - 1 || (s->cx >= gl->cellsize && COLOUR_DEFAULT(bg)))
1152 		return;
1153 
1154 	grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
1155 
1156  	before = screen_write_collect_trim(ctx, s->cy, s->cx, sx - s->cx, NULL);
1157 	ci->x = s->cx;
1158 	ci->used = sx - s->cx;
1159 	ci->type = CLEAR;
1160 	ci->bg = bg;
1161 	if (before == NULL)
1162 		TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
1163 	else
1164 		TAILQ_INSERT_BEFORE(before, ci, entry);
1165 	ctx->item = screen_write_get_citem();
1166 }
1167 
1168 /* Clear to start of line from cursor. */
1169 void
1170 screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
1171 {
1172 	struct screen			 *s = ctx->s;
1173 	u_int				 sx = screen_size_x(s);
1174 	struct screen_write_citem	*ci = ctx->item, *before;
1175 
1176 	if (s->cx >= sx - 1) {
1177 		screen_write_clearline(ctx, bg);
1178 		return;
1179 	}
1180 
1181 	if (s->cx > sx - 1)
1182 		grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
1183 	else
1184 		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
1185 
1186 	before = screen_write_collect_trim(ctx, s->cy, 0, s->cx + 1, NULL);
1187 	ci->x = 0;
1188 	ci->used = s->cx + 1;
1189 	ci->type = CLEAR;
1190 	ci->bg = bg;
1191 	if (before == NULL)
1192 		TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
1193 	else
1194 		TAILQ_INSERT_BEFORE(before, ci, entry);
1195 	ctx->item = screen_write_get_citem();
1196 }
1197 
1198 /* Move cursor to px,py. */
1199 void
1200 screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py,
1201     int origin)
1202 {
1203 	struct screen	*s = ctx->s;
1204 
1205 	if (origin && py != -1 && (s->mode & MODE_ORIGIN)) {
1206 		if ((u_int)py > s->rlower - s->rupper)
1207 			py = s->rlower;
1208 		else
1209 			py += s->rupper;
1210 	}
1211 
1212 	if (px != -1 && (u_int)px > screen_size_x(s) - 1)
1213 		px = screen_size_x(s) - 1;
1214 	if (py != -1 && (u_int)py > screen_size_y(s) - 1)
1215 		py = screen_size_y(s) - 1;
1216 
1217 	log_debug("%s: from %u,%u to %u,%u", __func__, s->cx, s->cy, px, py);
1218 	screen_write_set_cursor(ctx, px, py);
1219 }
1220 
1221 /* Reverse index (up with scroll). */
1222 void
1223 screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
1224 {
1225 	struct screen	*s = ctx->s;
1226 	struct tty_ctx	 ttyctx;
1227 
1228 	if (s->cy == s->rupper) {
1229 		grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
1230 		screen_write_collect_flush(ctx, 0, __func__);
1231 
1232 		screen_write_initctx(ctx, &ttyctx, 1);
1233 		ttyctx.bg = bg;
1234 
1235 		tty_write(tty_cmd_reverseindex, &ttyctx);
1236 	} else if (s->cy > 0)
1237 		screen_write_set_cursor(ctx, -1, s->cy - 1);
1238 
1239 }
1240 
1241 /* Set scroll region. */
1242 void
1243 screen_write_scrollregion(struct screen_write_ctx *ctx, u_int rupper,
1244     u_int rlower)
1245 {
1246 	struct screen	*s = ctx->s;
1247 
1248 	if (rupper > screen_size_y(s) - 1)
1249 		rupper = screen_size_y(s) - 1;
1250 	if (rlower > screen_size_y(s) - 1)
1251 		rlower = screen_size_y(s) - 1;
1252 	if (rupper >= rlower)	/* cannot be one line */
1253 		return;
1254 
1255 	screen_write_collect_flush(ctx, 0, __func__);
1256 
1257 	/* Cursor moves to top-left. */
1258 	screen_write_set_cursor(ctx, 0, 0);
1259 
1260 	s->rupper = rupper;
1261 	s->rlower = rlower;
1262 }
1263 
1264 /* Line feed. */
1265 void
1266 screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
1267 {
1268 	struct screen		*s = ctx->s;
1269 	struct grid		*gd = s->grid;
1270 	struct grid_line	*gl;
1271 
1272 	gl = grid_get_line(gd, gd->hsize + s->cy);
1273 	if (wrapped)
1274 		gl->flags |= GRID_LINE_WRAPPED;
1275 
1276 	log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
1277 	    s->rupper, s->rlower);
1278 
1279 	if (bg != ctx->bg) {
1280 		screen_write_collect_flush(ctx, 1, __func__);
1281 		ctx->bg = bg;
1282 	}
1283 
1284 	if (s->cy == s->rlower) {
1285 		grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
1286 		screen_write_collect_scroll(ctx, bg);
1287 		ctx->scrolled++;
1288 	} else if (s->cy < screen_size_y(s) - 1)
1289 		screen_write_set_cursor(ctx, -1, s->cy + 1);
1290 }
1291 
1292 /* Scroll up. */
1293 void
1294 screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
1295 {
1296 	struct screen	*s = ctx->s;
1297 	struct grid	*gd = s->grid;
1298 	u_int		 i;
1299 
1300 	if (lines == 0)
1301 		lines = 1;
1302 	else if (lines > s->rlower - s->rupper + 1)
1303 		lines = s->rlower - s->rupper + 1;
1304 
1305 	if (bg != ctx->bg) {
1306 		screen_write_collect_flush(ctx, 1, __func__);
1307 		ctx->bg = bg;
1308 	}
1309 
1310 	for (i = 0; i < lines; i++) {
1311 		grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
1312 		screen_write_collect_scroll(ctx, bg);
1313 	}
1314 	ctx->scrolled += lines;
1315 }
1316 
1317 /* Scroll down. */
1318 void
1319 screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg)
1320 {
1321 	struct screen	*s = ctx->s;
1322 	struct grid	*gd = s->grid;
1323 	struct tty_ctx	 ttyctx;
1324 	u_int		 i;
1325 
1326 	screen_write_initctx(ctx, &ttyctx, 1);
1327 	ttyctx.bg = bg;
1328 
1329 	if (lines == 0)
1330 		lines = 1;
1331 	else if (lines > s->rlower - s->rupper + 1)
1332 		lines = s->rlower - s->rupper + 1;
1333 
1334 	for (i = 0; i < lines; i++)
1335 		grid_view_scroll_region_down(gd, s->rupper, s->rlower, bg);
1336 
1337 	screen_write_collect_flush(ctx, 0, __func__);
1338 	ttyctx.num = lines;
1339 	tty_write(tty_cmd_scrolldown, &ttyctx);
1340 }
1341 
1342 /* Carriage return (cursor to start of line). */
1343 void
1344 screen_write_carriagereturn(struct screen_write_ctx *ctx)
1345 {
1346 	screen_write_set_cursor(ctx, 0, -1);
1347 }
1348 
1349 /* Clear to end of screen from cursor. */
1350 void
1351 screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
1352 {
1353 	struct screen	*s = ctx->s;
1354 	struct grid	*gd = s->grid;
1355 	struct tty_ctx	 ttyctx;
1356 	u_int		 sx = screen_size_x(s), sy = screen_size_y(s);
1357 
1358 	screen_write_initctx(ctx, &ttyctx, 1);
1359 	ttyctx.bg = bg;
1360 
1361 	/* Scroll into history if it is enabled and clearing entire screen. */
1362 	if (s->cx == 0 && s->cy == 0 && (gd->flags & GRID_HISTORY))
1363 		grid_view_clear_history(gd, bg);
1364 	else {
1365 		if (s->cx <= sx - 1)
1366 			grid_view_clear(gd, s->cx, s->cy, sx - s->cx, 1, bg);
1367 		grid_view_clear(gd, 0, s->cy + 1, sx, sy - (s->cy + 1), bg);
1368 	}
1369 
1370 	screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
1371 	screen_write_collect_flush(ctx, 0, __func__);
1372 	tty_write(tty_cmd_clearendofscreen, &ttyctx);
1373 }
1374 
1375 /* Clear to start of screen. */
1376 void
1377 screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
1378 {
1379 	struct screen	*s = ctx->s;
1380 	struct tty_ctx	 ttyctx;
1381 	u_int		 sx = screen_size_x(s);
1382 
1383 	screen_write_initctx(ctx, &ttyctx, 1);
1384 	ttyctx.bg = bg;
1385 
1386 	if (s->cy > 0)
1387 		grid_view_clear(s->grid, 0, 0, sx, s->cy, bg);
1388 	if (s->cx > sx - 1)
1389 		grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
1390 	else
1391 		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
1392 
1393 	screen_write_collect_clear(ctx, 0, s->cy);
1394 	screen_write_collect_flush(ctx, 0, __func__);
1395 	tty_write(tty_cmd_clearstartofscreen, &ttyctx);
1396 }
1397 
1398 /* Clear entire screen. */
1399 void
1400 screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
1401 {
1402 	struct screen	*s = ctx->s;
1403 	struct tty_ctx	 ttyctx;
1404 	u_int		 sx = screen_size_x(s), sy = screen_size_y(s);
1405 
1406 	screen_write_initctx(ctx, &ttyctx, 1);
1407 	ttyctx.bg = bg;
1408 
1409 	/* Scroll into history if it is enabled. */
1410 	if (s->grid->flags & GRID_HISTORY)
1411 		grid_view_clear_history(s->grid, bg);
1412 	else
1413 		grid_view_clear(s->grid, 0, 0, sx, sy, bg);
1414 
1415 	screen_write_collect_clear(ctx, 0, sy);
1416 	tty_write(tty_cmd_clearscreen, &ttyctx);
1417 }
1418 
1419 /* Clear entire history. */
1420 void
1421 screen_write_clearhistory(struct screen_write_ctx *ctx)
1422 {
1423 	grid_clear_history(ctx->s->grid);
1424 }
1425 
1426 /* Trim collected items. */
1427 static struct screen_write_citem *
1428 screen_write_collect_trim(struct screen_write_ctx *ctx, u_int y, u_int x,
1429     u_int used, int *wrapped)
1430 {
1431 	struct screen_write_cline	*cl = &ctx->s->write_list[y];
1432 	struct screen_write_citem	*ci, *ci2, *tmp, *before = NULL;
1433 	u_int				 sx = x, ex = x + used - 1;
1434 	u_int				 csx, cex;
1435 
1436 	if (TAILQ_EMPTY(&cl->items))
1437 		return (NULL);
1438 	TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
1439 		csx = ci->x;
1440 		cex = ci->x + ci->used - 1;
1441 
1442 		/* Item is entirely before. */
1443 		if (cex < sx) {
1444 			log_debug("%s: %p %u-%u before %u-%u", __func__, ci,
1445 			    csx, cex, sx, ex);
1446 			continue;
1447 		}
1448 
1449 		/* Item is entirely after. */
1450 		if (csx > ex) {
1451 			log_debug("%s: %p %u-%u after %u-%u", __func__, ci,
1452 			    csx, cex, sx, ex);
1453 			before = ci;
1454 			break;
1455 		}
1456 
1457 		/* Item is entirely inside. */
1458 		if (csx >= sx && cex <= ex) {
1459 			log_debug("%s: %p %u-%u inside %u-%u", __func__, ci,
1460 			    csx, cex, sx, ex);
1461 			TAILQ_REMOVE(&cl->items, ci, entry);
1462 			screen_write_free_citem(ci);
1463 			if (csx == 0 && ci->wrapped && wrapped != NULL)
1464 				*wrapped = 1;
1465 			continue;
1466 		}
1467 
1468 		/* Item under the start. */
1469 		if (csx < sx && cex >= sx && cex <= ex) {
1470 			log_debug("%s: %p %u-%u start %u-%u", __func__, ci,
1471 			    csx, cex, sx, ex);
1472 			ci->used = sx - csx;
1473 			log_debug("%s: %p now %u-%u", __func__, ci, ci->x,
1474 			    ci->x + ci->used + 1);
1475 			continue;
1476 		}
1477 
1478 		/* Item covers the end. */
1479 		if (cex > ex && csx >= sx && csx <= ex) {
1480 			log_debug("%s: %p %u-%u end %u-%u", __func__, ci,
1481 			    csx, cex, sx, ex);
1482 			ci->x = ex + 1;
1483 			ci->used = cex - ex;
1484 			log_debug("%s: %p now %u-%u", __func__, ci, ci->x,
1485 			    ci->x + ci->used + 1);
1486 			before = ci;
1487 			break;
1488 		}
1489 
1490 		/* Item must cover both sides. */
1491 		log_debug("%s: %p %u-%u under %u-%u", __func__, ci,
1492 		    csx, cex, sx, ex);
1493 		ci2 = screen_write_get_citem();
1494 		ci2->type = ci->type;
1495 		ci2->bg = ci->bg;
1496 		memcpy(&ci2->gc, &ci->gc, sizeof ci2->gc);
1497 		TAILQ_INSERT_AFTER(&cl->items, ci, ci2, entry);
1498 
1499 		ci->used = sx - csx;
1500 		ci2->x = ex + 1;
1501 		ci2->used = cex - ex;
1502 
1503 		log_debug("%s: %p now %u-%u (%p) and %u-%u (%p)", __func__, ci,
1504 		    ci->x, ci->x + ci->used - 1, ci, ci2->x,
1505 		    ci2->x + ci2->used - 1, ci2);
1506 		before = ci2;
1507 		break;
1508 	}
1509 	return (before);
1510 }
1511 
1512 /* Clear collected lines. */
1513 static void
1514 screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
1515 {
1516 	struct screen_write_cline	*cl;
1517 	u_int				 i;
1518 
1519 	for (i = y; i < y + n; i++) {
1520 		cl = &ctx->s->write_list[i];
1521 		TAILQ_CONCAT(&screen_write_citem_freelist, &cl->items, entry);
1522 	}
1523 }
1524 
1525 /* Scroll collected lines up. */
1526 static void
1527 screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
1528 {
1529 	struct screen			*s = ctx->s;
1530 	struct screen_write_cline	*cl;
1531 	u_int				 y;
1532 	char				*saved;
1533 	struct screen_write_citem	*ci;
1534 
1535 	log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
1536 	    s->rupper, s->rlower);
1537 
1538 	screen_write_collect_clear(ctx, s->rupper, 1);
1539 	saved = ctx->s->write_list[s->rupper].data;
1540 	for (y = s->rupper; y < s->rlower; y++) {
1541 		cl = &ctx->s->write_list[y + 1];
1542 		TAILQ_CONCAT(&ctx->s->write_list[y].items, &cl->items, entry);
1543 		ctx->s->write_list[y].data = cl->data;
1544 	}
1545 	ctx->s->write_list[s->rlower].data = saved;
1546 
1547 	ci = screen_write_get_citem();
1548 	ci->x = 0;
1549 	ci->used = screen_size_x(s);
1550 	ci->type = CLEAR;
1551 	ci->bg = bg;
1552 	TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
1553 }
1554 
1555 /* Flush collected lines. */
1556 static void
1557 screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
1558     const char *from)
1559 {
1560 	struct screen			*s = ctx->s;
1561 	struct screen_write_citem	*ci, *tmp;
1562 	struct screen_write_cline	*cl;
1563 	u_int				 y, cx, cy, last, items = 0;
1564 	struct tty_ctx			 ttyctx;
1565 
1566 	if (ctx->scrolled != 0) {
1567 		log_debug("%s: scrolled %u (region %u-%u)", __func__,
1568 		    ctx->scrolled, s->rupper, s->rlower);
1569 		if (ctx->scrolled > s->rlower - s->rupper + 1)
1570 			ctx->scrolled = s->rlower - s->rupper + 1;
1571 
1572 		screen_write_initctx(ctx, &ttyctx, 1);
1573 		ttyctx.num = ctx->scrolled;
1574 		ttyctx.bg = ctx->bg;
1575 		tty_write(tty_cmd_scrollup, &ttyctx);
1576 	}
1577 	ctx->scrolled = 0;
1578 	ctx->bg = 8;
1579 
1580 	if (scroll_only)
1581 		return;
1582 
1583 	cx = s->cx; cy = s->cy;
1584 	for (y = 0; y < screen_size_y(s); y++) {
1585 		cl = &ctx->s->write_list[y];
1586 		last = UINT_MAX;
1587 		TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
1588 			if (last != UINT_MAX && ci->x <= last) {
1589 				fatalx("collect list not in order: %u <= %u",
1590 				    ci->x, last);
1591 			}
1592 			screen_write_set_cursor(ctx, ci->x, y);
1593 			if (ci->type == CLEAR) {
1594 				screen_write_initctx(ctx, &ttyctx, 1);
1595 				ttyctx.bg = ci->bg;
1596 				ttyctx.num = ci->used;
1597 				tty_write(tty_cmd_clearcharacter, &ttyctx);
1598 			} else {
1599 				screen_write_initctx(ctx, &ttyctx, 0);
1600 				ttyctx.cell = &ci->gc;
1601 				ttyctx.wrapped = ci->wrapped;
1602 				ttyctx.ptr = cl->data + ci->x;
1603 				ttyctx.num = ci->used;
1604 				tty_write(tty_cmd_cells, &ttyctx);
1605 			}
1606 			items++;
1607 
1608 			TAILQ_REMOVE(&cl->items, ci, entry);
1609 			screen_write_free_citem(ci);
1610 			last = ci->x;
1611 		}
1612 	}
1613 	s->cx = cx; s->cy = cy;
1614 
1615 	log_debug("%s: flushed %u items (%s)", __func__, items, from);
1616 }
1617 
1618 /* Finish and store collected cells. */
1619 void
1620 screen_write_collect_end(struct screen_write_ctx *ctx)
1621 {
1622 	struct screen			*s = ctx->s;
1623 	struct screen_write_citem	*ci = ctx->item, *before;
1624 	struct screen_write_cline	*cl = &s->write_list[s->cy];
1625 	struct grid_cell		 gc;
1626 	u_int				 xx;
1627 	int				 wrapped = ci->wrapped;
1628 
1629 	if (ci->used == 0)
1630 		return;
1631 
1632 	before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
1633 	    &wrapped);
1634 	ci->x = s->cx;
1635 	ci->wrapped = wrapped;
1636 	if (before == NULL)
1637 		TAILQ_INSERT_TAIL(&cl->items, ci, entry);
1638 	else
1639 		TAILQ_INSERT_BEFORE(before, ci, entry);
1640 	ctx->item = screen_write_get_citem();
1641 
1642 	log_debug("%s: %u %.*s (at %u,%u)", __func__, ci->used,
1643 	    (int)ci->used, cl->data + ci->x, s->cx, s->cy);
1644 
1645 	if (s->cx != 0) {
1646 		for (xx = s->cx; xx > 0; xx--) {
1647 			grid_view_get_cell(s->grid, xx, s->cy, &gc);
1648 			if (~gc.flags & GRID_FLAG_PADDING)
1649 				break;
1650 			grid_view_set_cell(s->grid, xx, s->cy,
1651 			    &grid_default_cell);
1652 		}
1653 		if (gc.data.width > 1) {
1654 			grid_view_set_cell(s->grid, xx, s->cy,
1655 			    &grid_default_cell);
1656 		}
1657 	}
1658 
1659 	grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
1660 	    ci->used);
1661 	screen_write_set_cursor(ctx, s->cx + ci->used, -1);
1662 
1663 	for (xx = s->cx; xx < screen_size_x(s); xx++) {
1664 		grid_view_get_cell(s->grid, xx, s->cy, &gc);
1665 		if (~gc.flags & GRID_FLAG_PADDING)
1666 			break;
1667 		grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
1668 	}
1669 }
1670 
1671 /* Write cell data, collecting if necessary. */
1672 void
1673 screen_write_collect_add(struct screen_write_ctx *ctx,
1674     const struct grid_cell *gc)
1675 {
1676 	struct screen			*s = ctx->s;
1677 	struct screen_write_citem	*ci;
1678 	u_int				 sx = screen_size_x(s);
1679 	int				 collect;
1680 
1681 	/*
1682 	 * Don't need to check that the attributes and whatnot are still the
1683 	 * same - input_parse will end the collection when anything that isn't
1684 	 * a plain character is encountered.
1685 	 */
1686 
1687 	collect = 1;
1688 	if (gc->data.width != 1 || gc->data.size != 1 || *gc->data.data >= 0x7f)
1689 		collect = 0;
1690 	else if (gc->attr & GRID_ATTR_CHARSET)
1691 		collect = 0;
1692 	else if (~s->mode & MODE_WRAP)
1693 		collect = 0;
1694 	else if (s->mode & MODE_INSERT)
1695 		collect = 0;
1696 	else if (s->sel != NULL)
1697 		collect = 0;
1698 	if (!collect) {
1699 		screen_write_collect_end(ctx);
1700 		screen_write_collect_flush(ctx, 0, __func__);
1701 		screen_write_cell(ctx, gc);
1702 		return;
1703 	}
1704 
1705 	if (s->cx > sx - 1 || ctx->item->used > sx - 1 - s->cx)
1706 		screen_write_collect_end(ctx);
1707 	ci = ctx->item; /* may have changed */
1708 
1709 	if (s->cx > sx - 1) {
1710 		log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
1711 		ci->wrapped = 1;
1712 		screen_write_linefeed(ctx, 1, 8);
1713 		screen_write_set_cursor(ctx, 0, -1);
1714 	}
1715 
1716 	if (ci->used == 0)
1717 		memcpy(&ci->gc, gc, sizeof ci->gc);
1718 	if (ctx->s->write_list[s->cy].data == NULL)
1719 		ctx->s->write_list[s->cy].data = xmalloc(screen_size_x(ctx->s));
1720 	ctx->s->write_list[s->cy].data[s->cx + ci->used++] = gc->data.data[0];
1721 }
1722 
1723 /* Write cell data. */
1724 void
1725 screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
1726 {
1727 	struct screen		*s = ctx->s;
1728 	struct grid		*gd = s->grid;
1729 	struct grid_line	*gl;
1730 	struct grid_cell_entry	*gce;
1731 	struct grid_cell 	 tmp_gc, now_gc;
1732 	struct tty_ctx		 ttyctx;
1733 	u_int			 sx = screen_size_x(s), sy = screen_size_y(s);
1734 	u_int		 	 width = gc->data.width, xx, last, cx, cy;
1735 	int			 selected, skip = 1;
1736 
1737 	/* Ignore padding cells. */
1738 	if (gc->flags & GRID_FLAG_PADDING)
1739 		return;
1740 
1741 	/* If the width is zero, combine onto the previous character. */
1742 	if (width == 0) {
1743 		screen_write_collect_flush(ctx, 0, __func__);
1744 		if ((gc = screen_write_combine(ctx, &gc->data, &xx)) != 0) {
1745 			cx = s->cx; cy = s->cy;
1746 			screen_write_set_cursor(ctx, xx, s->cy);
1747 			screen_write_initctx(ctx, &ttyctx, 0);
1748 			ttyctx.cell = gc;
1749 			tty_write(tty_cmd_cell, &ttyctx);
1750 			s->cx = cx; s->cy = cy;
1751 		}
1752 		return;
1753 	}
1754 
1755 	/* Flush any existing scrolling. */
1756 	screen_write_collect_flush(ctx, 1, __func__);
1757 
1758 	/* If this character doesn't fit, ignore it. */
1759 	if ((~s->mode & MODE_WRAP) &&
1760 	    width > 1 &&
1761 	    (width > sx || (s->cx != sx && s->cx > sx - width)))
1762 		return;
1763 
1764 	/* If in insert mode, make space for the cells. */
1765 	if (s->mode & MODE_INSERT) {
1766 		grid_view_insert_cells(s->grid, s->cx, s->cy, width, 8);
1767 		skip = 0;
1768 	}
1769 
1770 	/* Check this will fit on the current line and wrap if not. */
1771 	if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
1772 		log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
1773 		screen_write_linefeed(ctx, 1, 8);
1774 		screen_write_set_cursor(ctx, 0, -1);
1775 		screen_write_collect_flush(ctx, 1, __func__);
1776 	}
1777 
1778 	/* Sanity check cursor position. */
1779 	if (s->cx > sx - width || s->cy > sy - 1)
1780 		return;
1781 	screen_write_initctx(ctx, &ttyctx, 0);
1782 
1783 	/* Handle overwriting of UTF-8 characters. */
1784 	gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
1785 	if (gl->flags & GRID_LINE_EXTENDED) {
1786 		grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
1787 		if (screen_write_overwrite(ctx, &now_gc, width))
1788 			skip = 0;
1789 	}
1790 
1791 	/*
1792 	 * If the new character is UTF-8 wide, fill in padding cells. Have
1793 	 * already ensured there is enough room.
1794 	 */
1795 	for (xx = s->cx + 1; xx < s->cx + width; xx++) {
1796 		log_debug("%s: new padding at %u,%u", __func__, xx, s->cy);
1797 		grid_view_set_padding(gd, xx, s->cy);
1798 		skip = 0;
1799 	}
1800 
1801 	/* If no change, do not draw. */
1802 	if (skip) {
1803 		if (s->cx >= gl->cellsize)
1804 			skip = grid_cells_equal(gc, &grid_default_cell);
1805 		else {
1806 			gce = &gl->celldata[s->cx];
1807 			if (gce->flags & GRID_FLAG_EXTENDED)
1808 				skip = 0;
1809 			else if (gc->flags != gce->flags)
1810 				skip = 0;
1811 			else if (gc->attr != gce->data.attr)
1812 				skip = 0;
1813 			else if (gc->fg != gce->data.fg)
1814 				skip = 0;
1815 			else if (gc->bg != gce->data.bg)
1816 				skip = 0;
1817 			else if (gc->data.width != 1)
1818 				skip = 0;
1819 			else if (gc->data.size != 1)
1820 				skip = 0;
1821 			else if (gce->data.data != gc->data.data[0])
1822 				skip = 0;
1823 		}
1824 	}
1825 
1826 	/* Update the selected flag and set the cell. */
1827 	selected = screen_check_selection(s, s->cx, s->cy);
1828 	if (selected && (~gc->flags & GRID_FLAG_SELECTED)) {
1829 		memcpy(&tmp_gc, gc, sizeof tmp_gc);
1830 		tmp_gc.flags |= GRID_FLAG_SELECTED;
1831 		grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
1832 	} else if (!selected && (gc->flags & GRID_FLAG_SELECTED)) {
1833 		memcpy(&tmp_gc, gc, sizeof tmp_gc);
1834 		tmp_gc.flags &= ~GRID_FLAG_SELECTED;
1835 		grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
1836 	} else if (!skip)
1837 		grid_view_set_cell(gd, s->cx, s->cy, gc);
1838 	if (selected)
1839 		skip = 0;
1840 
1841 	/*
1842 	 * Move the cursor. If not wrapping, stick at the last character and
1843 	 * replace it.
1844 	 */
1845 	last = !(s->mode & MODE_WRAP);
1846 	if (s->cx <= sx - last - width)
1847 		screen_write_set_cursor(ctx, s->cx + width, -1);
1848 	else
1849 		screen_write_set_cursor(ctx,  sx - last, -1);
1850 
1851 	/* Create space for character in insert mode. */
1852 	if (s->mode & MODE_INSERT) {
1853 		screen_write_collect_flush(ctx, 0, __func__);
1854 		ttyctx.num = width;
1855 		tty_write(tty_cmd_insertcharacter, &ttyctx);
1856 	}
1857 
1858 	/* Write to the screen. */
1859 	if (!skip) {
1860 		if (selected) {
1861 			screen_select_cell(s, &tmp_gc, gc);
1862 			ttyctx.cell = &tmp_gc;
1863 		} else
1864 			ttyctx.cell = gc;
1865 		tty_write(tty_cmd_cell, &ttyctx);
1866 	}
1867 }
1868 
1869 /* Combine a UTF-8 zero-width character onto the previous. */
1870 static const struct grid_cell *
1871 screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud,
1872     u_int *xx)
1873 {
1874 	struct screen		*s = ctx->s;
1875 	struct grid		*gd = s->grid;
1876 	static struct grid_cell	 gc;
1877 	u_int			 n;
1878 
1879 	/* Can't combine if at 0. */
1880 	if (s->cx == 0)
1881 		return (NULL);
1882 
1883 	/* Empty data is out. */
1884 	if (ud->size == 0)
1885 		fatalx("UTF-8 data empty");
1886 
1887 	/* Retrieve the previous cell. */
1888 	for (n = 1; n <= s->cx; n++) {
1889 		grid_view_get_cell(gd, s->cx - n, s->cy, &gc);
1890 		if (~gc.flags & GRID_FLAG_PADDING)
1891 			break;
1892 	}
1893 	if (n > s->cx)
1894 		return (NULL);
1895 	*xx = s->cx - n;
1896 
1897 	/* Check there is enough space. */
1898 	if (gc.data.size + ud->size > sizeof gc.data.data)
1899 		return (NULL);
1900 
1901 	log_debug("%s: %.*s onto %.*s at %u,%u", __func__, (int)ud->size,
1902 	    ud->data, (int)gc.data.size, gc.data.data, *xx, s->cy);
1903 
1904 	/* Append the data. */
1905 	memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
1906 	gc.data.size += ud->size;
1907 
1908 	/* Set the new cell. */
1909 	grid_view_set_cell(gd, *xx, s->cy, &gc);
1910 
1911 	return (&gc);
1912 }
1913 
1914 /*
1915  * UTF-8 wide characters are a bit of an annoyance. They take up more than one
1916  * cell on the screen, so following cells must not be drawn by marking them as
1917  * padding.
1918  *
1919  * So far, so good. The problem is, when overwriting a padding cell, or a UTF-8
1920  * character, it is necessary to also overwrite any other cells which covered
1921  * by the same character.
1922  */
1923 static int
1924 screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc,
1925     u_int width)
1926 {
1927 	struct screen		*s = ctx->s;
1928 	struct grid		*gd = s->grid;
1929 	struct grid_cell	 tmp_gc;
1930 	u_int			 xx;
1931 	int			 done = 0;
1932 
1933 	if (gc->flags & GRID_FLAG_PADDING) {
1934 		/*
1935 		 * A padding cell, so clear any following and leading padding
1936 		 * cells back to the character. Don't overwrite the current
1937 		 * cell as that happens later anyway.
1938 		 */
1939 		xx = s->cx + 1;
1940 		while (--xx > 0) {
1941 			grid_view_get_cell(gd, xx, s->cy, &tmp_gc);
1942 			if (~tmp_gc.flags & GRID_FLAG_PADDING)
1943 				break;
1944 			log_debug("%s: padding at %u,%u", __func__, xx, s->cy);
1945 			grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
1946 		}
1947 
1948 		/* Overwrite the character at the start of this padding. */
1949 		log_debug("%s: character at %u,%u", __func__, xx, s->cy);
1950 		grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
1951 		done = 1;
1952 	}
1953 
1954 	/*
1955 	 * Overwrite any padding cells that belong to any UTF-8 characters
1956 	 * we'll be overwriting with the current character.
1957 	 */
1958 	if (width != 1 ||
1959 	    gc->data.width != 1 ||
1960 	    gc->flags & GRID_FLAG_PADDING) {
1961 		xx = s->cx + width - 1;
1962 		while (++xx < screen_size_x(s)) {
1963 			grid_view_get_cell(gd, xx, s->cy, &tmp_gc);
1964 			if (~tmp_gc.flags & GRID_FLAG_PADDING)
1965 				break;
1966 			log_debug("%s: overwrite at %u,%u", __func__, xx,
1967 			    s->cy);
1968 			grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
1969 			done = 1;
1970 		}
1971 	}
1972 
1973 	return (done);
1974 }
1975 
1976 /* Set external clipboard. */
1977 void
1978 screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
1979 {
1980 	struct tty_ctx	ttyctx;
1981 
1982 	screen_write_initctx(ctx, &ttyctx, 0);
1983 	ttyctx.ptr = str;
1984 	ttyctx.num = len;
1985 
1986 	tty_write(tty_cmd_setselection, &ttyctx);
1987 }
1988 
1989 /* Write unmodified string. */
1990 void
1991 screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
1992 {
1993 	struct tty_ctx	ttyctx;
1994 
1995 	screen_write_initctx(ctx, &ttyctx, 0);
1996 	ttyctx.ptr = str;
1997 	ttyctx.num = len;
1998 
1999 	tty_write(tty_cmd_rawstring, &ttyctx);
2000 }
2001 
2002 /* Turn alternate screen on. */
2003 void
2004 screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
2005     int cursor)
2006 {
2007 	struct tty_ctx		 ttyctx;
2008 	struct window_pane	*wp = ctx->wp;
2009 
2010 	if (wp != NULL && !options_get_number(wp->options, "alternate-screen"))
2011 		return;
2012 
2013 	screen_write_collect_flush(ctx, 0, __func__);
2014 	screen_alternate_on(ctx->s, gc, cursor);
2015 
2016 	screen_write_initctx(ctx, &ttyctx, 1);
2017 	ttyctx.redraw_cb(&ttyctx);
2018 }
2019 
2020 /* Turn alternate screen off. */
2021 void
2022 screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
2023     int cursor)
2024 {
2025 	struct tty_ctx		 ttyctx;
2026 	struct window_pane	*wp = ctx->wp;
2027 
2028 	if (wp != NULL && !options_get_number(wp->options, "alternate-screen"))
2029 		return;
2030 
2031 	screen_write_collect_flush(ctx, 0, __func__);
2032 	screen_alternate_off(ctx->s, gc, cursor);
2033 
2034 	screen_write_initctx(ctx, &ttyctx, 1);
2035 	ttyctx.redraw_cb(&ttyctx);
2036 }
2037