xref: /openbsd-src/usr.bin/tmux/screen-write.c (revision c0dd97bfcad3dab6c31ec12b9de1274fd2d2f993)
1 /* $OpenBSD: screen-write.c,v 1.131 2017/10/05 08:12:24 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 void	screen_write_initctx(struct screen_write_ctx *,
27 		    struct tty_ctx *);
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 *);
31 static void	screen_write_collect_flush(struct screen_write_ctx *, int);
32 
33 static int	screen_write_overwrite(struct screen_write_ctx *,
34 		    struct grid_cell *, u_int);
35 static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
36 		    const struct utf8_data *, u_int *);
37 
38 static const struct grid_cell screen_write_pad_cell = {
39 	GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
40 };
41 
42 struct screen_write_collect_item {
43 	u_int			 x;
44 	int			 wrapped;
45 
46 	u_int			 used;
47 	char			 data[256];
48 
49 	struct grid_cell	 gc;
50 
51 	TAILQ_ENTRY(screen_write_collect_item) entry;
52 };
53 struct screen_write_collect_line {
54 	TAILQ_HEAD(, screen_write_collect_item) items;
55 };
56 
57 /* Initialize writing with a window. */
58 void
59 screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
60     struct screen *s)
61 {
62 	char	tmp[16];
63 	u_int	y;
64 
65 	memset(ctx, 0, sizeof *ctx);
66 
67 	ctx->wp = wp;
68 	if (wp != NULL && s == NULL)
69 		ctx->s = wp->screen;
70 	else
71 		ctx->s = s;
72 
73 	ctx->list = xcalloc(screen_size_y(ctx->s), sizeof *ctx->list);
74 	for (y = 0; y < screen_size_y(ctx->s); y++)
75 		TAILQ_INIT(&ctx->list[y].items);
76 	ctx->item = xcalloc(1, sizeof *ctx->item);
77 
78 	ctx->scrolled = 0;
79 	ctx->bg = 8;
80 
81 	if (wp != NULL)
82 		snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
83 	log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
84 	    screen_size_y(ctx->s), wp == NULL ? "no pane" : tmp);
85 }
86 
87 /* Finish writing. */
88 void
89 screen_write_stop(struct screen_write_ctx *ctx)
90 {
91 	screen_write_collect_end(ctx);
92 	screen_write_collect_flush(ctx, 0);
93 
94 	log_debug("%s: %u cells (%u written, %u skipped)", __func__,
95 	    ctx->cells, ctx->written, ctx->skipped);
96 
97 	free(ctx->item);
98 	free(ctx->list); /* flush will have emptied */
99 }
100 
101 /* Reset screen state. */
102 void
103 screen_write_reset(struct screen_write_ctx *ctx)
104 {
105 	struct screen	*s = ctx->s;
106 
107 	screen_reset_tabs(s);
108 	screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1);
109 
110 	s->mode &= ~(MODE_INSERT|MODE_KCURSOR|MODE_KKEYPAD|MODE_FOCUSON);
111 	s->mode &= ~(ALL_MOUSE_MODES|MODE_MOUSE_UTF8|MODE_MOUSE_SGR);
112 
113 	screen_write_clearscreen(ctx, 8);
114 	screen_write_cursormove(ctx, 0, 0);
115 }
116 
117 /* Write character. */
118 void
119 screen_write_putc(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
120     u_char ch)
121 {
122 	struct grid_cell	gc;
123 
124 	memcpy(&gc, gcp, sizeof gc);
125 
126 	utf8_set(&gc.data, ch);
127 	screen_write_cell(ctx, &gc);
128 }
129 
130 /* Calculate string length, with embedded formatting. */
131 size_t
132 screen_write_cstrlen(const char *fmt, ...)
133 {
134 	va_list	ap;
135 	char   *msg, *msg2, *ptr, *ptr2;
136 	size_t	size;
137 
138 	va_start(ap, fmt);
139 	xvasprintf(&msg, fmt, ap);
140 	va_end(ap);
141 	msg2 = xmalloc(strlen(msg) + 1);
142 
143 	ptr = msg;
144 	ptr2 = msg2;
145 	while (*ptr != '\0') {
146 		if (ptr[0] == '#' && ptr[1] == '[') {
147 			while (*ptr != ']' && *ptr != '\0')
148 				ptr++;
149 			if (*ptr == ']')
150 				ptr++;
151 			continue;
152 		}
153 		*ptr2++ = *ptr++;
154 	}
155 	*ptr2 = '\0';
156 
157 	size = screen_write_strlen("%s", msg2);
158 
159 	free(msg);
160 	free(msg2);
161 
162 	return (size);
163 }
164 
165 /* Calculate string length. */
166 size_t
167 screen_write_strlen(const char *fmt, ...)
168 {
169 	va_list			ap;
170 	char   	       	       *msg;
171 	struct utf8_data	ud;
172 	u_char 	      	       *ptr;
173 	size_t			left, size = 0;
174 	enum utf8_state		more;
175 
176 	va_start(ap, fmt);
177 	xvasprintf(&msg, fmt, ap);
178 	va_end(ap);
179 
180 	ptr = msg;
181 	while (*ptr != '\0') {
182 		if (*ptr > 0x7f && utf8_open(&ud, *ptr) == UTF8_MORE) {
183 			ptr++;
184 
185 			left = strlen(ptr);
186 			if (left < (size_t)ud.size - 1)
187 				break;
188 			while ((more = utf8_append(&ud, *ptr)) == UTF8_MORE)
189 				ptr++;
190 			ptr++;
191 
192 			if (more == UTF8_DONE)
193 				size += ud.width;
194 		} else {
195 			if (*ptr > 0x1f && *ptr < 0x7f)
196 				size++;
197 			ptr++;
198 		}
199 	}
200 
201 	free(msg);
202 	return (size);
203 }
204 
205 /* Write simple string (no UTF-8 or maximum length). */
206 void
207 screen_write_puts(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
208     const char *fmt, ...)
209 {
210 	va_list	ap;
211 
212 	va_start(ap, fmt);
213 	screen_write_vnputs(ctx, -1, gcp, fmt, ap);
214 	va_end(ap);
215 }
216 
217 /* Write string with length limit (-1 for unlimited). */
218 void
219 screen_write_nputs(struct screen_write_ctx *ctx, ssize_t maxlen,
220     const struct grid_cell *gcp, const char *fmt, ...)
221 {
222 	va_list	ap;
223 
224 	va_start(ap, fmt);
225 	screen_write_vnputs(ctx, maxlen, gcp, fmt, ap);
226 	va_end(ap);
227 }
228 
229 void
230 screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
231     const struct grid_cell *gcp, const char *fmt, va_list ap)
232 {
233 	struct grid_cell	gc;
234 	struct utf8_data       *ud = &gc.data;
235 	char   		       *msg;
236 	u_char 		       *ptr;
237 	size_t		 	left, size = 0;
238 	enum utf8_state		more;
239 
240 	memcpy(&gc, gcp, sizeof gc);
241 	xvasprintf(&msg, fmt, ap);
242 
243 	ptr = msg;
244 	while (*ptr != '\0') {
245 		if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
246 			ptr++;
247 
248 			left = strlen(ptr);
249 			if (left < (size_t)ud->size - 1)
250 				break;
251 			while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
252 				ptr++;
253 			ptr++;
254 
255 			if (more != UTF8_DONE)
256 				continue;
257 			if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
258 				while (size < (size_t)maxlen) {
259 					screen_write_putc(ctx, &gc, ' ');
260 					size++;
261 				}
262 				break;
263 			}
264 			size += ud->width;
265 			screen_write_cell(ctx, &gc);
266 		} else {
267 			if (maxlen > 0 && size + 1 > (size_t)maxlen)
268 				break;
269 
270 			if (*ptr == '\001')
271 				gc.attr ^= GRID_ATTR_CHARSET;
272 			else if (*ptr > 0x1f && *ptr < 0x7f) {
273 				size++;
274 				screen_write_putc(ctx, &gc, *ptr);
275 			}
276 			ptr++;
277 		}
278 	}
279 
280 	free(msg);
281 }
282 
283 /* Write string, similar to nputs, but with embedded formatting (#[]). */
284 void
285 screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
286     const struct grid_cell *gcp, const char *fmt, ...)
287 {
288 	struct grid_cell	 gc;
289 	struct utf8_data	*ud = &gc.data;
290 	va_list			 ap;
291 	char			*msg;
292 	u_char 			*ptr, *last;
293 	size_t			 left, size = 0;
294 	enum utf8_state		 more;
295 
296 	memcpy(&gc, gcp, sizeof gc);
297 
298 	va_start(ap, fmt);
299 	xvasprintf(&msg, fmt, ap);
300 	va_end(ap);
301 
302 	ptr = msg;
303 	while (*ptr != '\0') {
304 		if (ptr[0] == '#' && ptr[1] == '[') {
305 			ptr += 2;
306 			last = ptr + strcspn(ptr, "]");
307 			if (*last == '\0') {
308 				/* No ]. Not much point in doing anything. */
309 				break;
310 			}
311 			*last = '\0';
312 
313 			style_parse(gcp, &gc, ptr);
314 			ptr = last + 1;
315 			continue;
316 		}
317 
318 		if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
319 			ptr++;
320 
321 			left = strlen(ptr);
322 			if (left < (size_t)ud->size - 1)
323 				break;
324 			while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
325 				ptr++;
326 			ptr++;
327 
328 			if (more != UTF8_DONE)
329 				continue;
330 			if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
331 				while (size < (size_t)maxlen) {
332 					screen_write_putc(ctx, &gc, ' ');
333 					size++;
334 				}
335 				break;
336 			}
337 			size += ud->width;
338 			screen_write_cell(ctx, &gc);
339 		} else {
340 			if (maxlen > 0 && size + 1 > (size_t)maxlen)
341 				break;
342 
343 			if (*ptr > 0x1f && *ptr < 0x7f) {
344 				size++;
345 				screen_write_putc(ctx, &gc, *ptr);
346 			}
347 			ptr++;
348 		}
349 	}
350 
351 	free(msg);
352 }
353 
354 /* Copy from another screen. */
355 void
356 screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px,
357     u_int py, u_int nx, u_int ny, bitstr_t *markbs,
358     const struct grid_cell *markgc)
359 {
360 	struct screen		*s = ctx->s;
361 	struct grid		*gd = src->grid;
362 	struct grid_cell	 gc;
363 	u_int		 	 xx, yy, cx, cy, b;
364 
365 	if (nx == 0 || ny == 0)
366 		return;
367 
368 	cx = s->cx;
369 	cy = s->cy;
370 
371 	for (yy = py; yy < py + ny; yy++) {
372 		for (xx = px; xx < px + nx; xx++) {
373 			grid_get_cell(gd, xx, yy, &gc);
374 			if (markbs != NULL) {
375 				b = (yy * screen_size_x(src)) + xx;
376 				if (bit_test(markbs, b)) {
377 					gc.attr = markgc->attr;
378 					gc.fg = markgc->fg;
379 					gc.bg = markgc->bg;
380 				}
381 			}
382 			screen_write_cell(ctx, &gc);
383 		}
384 
385 		cy++;
386 		screen_write_cursormove(ctx, cx, cy);
387 	}
388 }
389 
390 /* Draw a horizontal line on screen. */
391 void
392 screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right)
393 {
394 	struct screen		*s = ctx->s;
395 	struct grid_cell	 gc;
396 	u_int			 cx, cy, i;
397 
398 	cx = s->cx;
399 	cy = s->cy;
400 
401 	memcpy(&gc, &grid_default_cell, sizeof gc);
402 	gc.attr |= GRID_ATTR_CHARSET;
403 
404 	screen_write_putc(ctx, &gc, left ? 't' : 'q');
405 	for (i = 1; i < nx - 1; i++)
406 		screen_write_putc(ctx, &gc, 'q');
407 	screen_write_putc(ctx, &gc, right ? 'u' : 'q');
408 
409 	screen_write_cursormove(ctx, cx, cy);
410 }
411 
412 /* Draw a horizontal line on screen. */
413 void
414 screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom)
415 {
416 	struct screen		*s = ctx->s;
417 	struct grid_cell	 gc;
418 	u_int			 cx, cy, i;
419 
420 	cx = s->cx;
421 	cy = s->cy;
422 
423 	memcpy(&gc, &grid_default_cell, sizeof gc);
424 	gc.attr |= GRID_ATTR_CHARSET;
425 
426 	screen_write_putc(ctx, &gc, top ? 'w' : 'x');
427 	for (i = 1; i < ny - 1; i++) {
428 		screen_write_cursormove(ctx, cx, cy + i);
429 		screen_write_putc(ctx, &gc, 'x');
430 	}
431 	screen_write_cursormove(ctx, cx, cy + ny);
432 	screen_write_putc(ctx, &gc, bottom ? 'v' : 'x');
433 
434 	screen_write_cursormove(ctx, cx, cy);
435 }
436 
437 /* Draw a box on screen. */
438 void
439 screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny)
440 {
441 	struct screen		*s = ctx->s;
442 	struct grid_cell	 gc;
443 	u_int			 cx, cy, i;
444 
445 	cx = s->cx;
446 	cy = s->cy;
447 
448 	memcpy(&gc, &grid_default_cell, sizeof gc);
449 	gc.attr |= GRID_ATTR_CHARSET;
450 
451 	screen_write_putc(ctx, &gc, 'l');
452 	for (i = 1; i < nx - 1; i++)
453 		screen_write_putc(ctx, &gc, 'q');
454 	screen_write_putc(ctx, &gc, 'k');
455 
456 	screen_write_cursormove(ctx, cx, cy + ny - 1);
457 	screen_write_putc(ctx, &gc, 'm');
458 	for (i = 1; i < nx - 1; i++)
459 		screen_write_putc(ctx, &gc, 'q');
460 	screen_write_putc(ctx, &gc, 'j');
461 
462 	for (i = 1; i < ny - 1; i++) {
463 		screen_write_cursormove(ctx, cx, cy + i);
464 		screen_write_putc(ctx, &gc, 'x');
465 	}
466 	for (i = 1; i < ny - 1; i++) {
467 		screen_write_cursormove(ctx, cx + nx - 1, cy + i);
468 		screen_write_putc(ctx, &gc, 'x');
469 	}
470 
471 	screen_write_cursormove(ctx, cx, cy);
472 }
473 
474 /* Write a preview version of a window. */
475 void
476 screen_write_preview(struct screen_write_ctx *ctx, struct screen *src, u_int nx,
477     u_int ny)
478 {
479 	struct screen		*s = ctx->s;
480 	struct grid_cell	 gc;
481 	u_int			 cx, cy, px, py;
482 
483 	cx = s->cx;
484 	cy = s->cy;
485 
486 	/*
487 	 * If the cursor is on, pick the area around the cursor, otherwise use
488 	 * the top left.
489 	 */
490 	if (src->mode & MODE_CURSOR) {
491 		px = src->cx;
492 		if (px < nx / 3)
493 			px = 0;
494 		else
495 			px = px - nx / 3;
496 		if (px + nx > screen_size_x(src)) {
497 			if (nx > screen_size_x(src))
498 				px = 0;
499 			else
500 				px = screen_size_x(src) - nx;
501 		}
502 		py = src->cy;
503 		if (py < ny / 3)
504 			py = 0;
505 		else
506 			py = py - ny / 3;
507 		if (py + ny > screen_size_y(src)) {
508 			if (ny > screen_size_y(src))
509 				py = 0;
510 			else
511 				py = screen_size_y(src) - ny;
512 		}
513 	} else {
514 		px = 0;
515 		py = 0;
516 	}
517 
518 	screen_write_copy(ctx, src, px, src->grid->hsize + py, nx, ny, NULL,
519 	    NULL);
520 
521 	if (src->mode & MODE_CURSOR) {
522 		grid_view_get_cell(src->grid, src->cx, src->cy, &gc);
523 		gc.attr |= GRID_ATTR_REVERSE;
524 		screen_write_cursormove(ctx, cx + (src->cx - px),
525 		    cy + (src->cy - py));
526 		screen_write_cell(ctx, &gc);
527 	}
528 }
529 
530 /* Set up context for TTY command. */
531 static void
532 screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
533 {
534 	struct screen	*s = ctx->s;
535 
536 	memset(ttyctx, 0, sizeof *ttyctx);
537 
538 	ttyctx->wp = ctx->wp;
539 
540 	ttyctx->ocx = s->cx;
541 	ttyctx->ocy = s->cy;
542 
543 	ttyctx->orlower = s->rlower;
544 	ttyctx->orupper = s->rupper;
545 }
546 
547 /* Set a mode. */
548 void
549 screen_write_mode_set(struct screen_write_ctx *ctx, int mode)
550 {
551 	struct screen	*s = ctx->s;
552 
553 	s->mode |= mode;
554 }
555 
556 /* Clear a mode. */
557 void
558 screen_write_mode_clear(struct screen_write_ctx *ctx, int mode)
559 {
560 	struct screen	*s = ctx->s;
561 
562 	s->mode &= ~mode;
563 }
564 
565 /* Cursor up by ny. */
566 void
567 screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
568 {
569 	struct screen	*s = ctx->s;
570 
571 	if (ny == 0)
572 		ny = 1;
573 
574 	if (s->cy < s->rupper) {
575 		/* Above region. */
576 		if (ny > s->cy)
577 			ny = s->cy;
578 	} else {
579 		/* Below region. */
580 		if (ny > s->cy - s->rupper)
581 			ny = s->cy - s->rupper;
582 	}
583 	if (s->cx == screen_size_x(s))
584 	    s->cx--;
585 	if (ny == 0)
586 		return;
587 
588 	s->cy -= ny;
589 }
590 
591 /* Cursor down by ny. */
592 void
593 screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
594 {
595 	struct screen	*s = ctx->s;
596 
597 	if (ny == 0)
598 		ny = 1;
599 
600 	if (s->cy > s->rlower) {
601 		/* Below region. */
602 		if (ny > screen_size_y(s) - 1 - s->cy)
603 			ny = screen_size_y(s) - 1 - s->cy;
604 	} else {
605 		/* Above region. */
606 		if (ny > s->rlower - s->cy)
607 			ny = s->rlower - s->cy;
608 	}
609 	if (s->cx == screen_size_x(s))
610 	    s->cx--;
611 	if (ny == 0)
612 		return;
613 
614 	s->cy += ny;
615 }
616 
617 /* Cursor right by nx. */
618 void
619 screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
620 {
621 	struct screen	*s = ctx->s;
622 
623 	if (nx == 0)
624 		nx = 1;
625 
626 	if (nx > screen_size_x(s) - 1 - s->cx)
627 		nx = screen_size_x(s) - 1 - s->cx;
628 	if (nx == 0)
629 		return;
630 
631 	s->cx += nx;
632 }
633 
634 /* Cursor left by nx. */
635 void
636 screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
637 {
638 	struct screen	*s = ctx->s;
639 
640 	if (nx == 0)
641 		nx = 1;
642 
643 	if (nx > s->cx)
644 		nx = s->cx;
645 	if (nx == 0)
646 		return;
647 
648 	s->cx -= nx;
649 }
650 
651 /* Backspace; cursor left unless at start of wrapped line when can move up. */
652 void
653 screen_write_backspace(struct screen_write_ctx *ctx)
654 {
655 	struct screen		*s = ctx->s;
656 	struct grid_line	*gl;
657 
658 	if (s->cx == 0) {
659 		if (s->cy == 0)
660 			return;
661 		gl = &s->grid->linedata[s->grid->hsize + s->cy - 1];
662 		if (gl->flags & GRID_LINE_WRAPPED) {
663 			s->cy--;
664 			s->cx = screen_size_x(s) - 1;
665 		}
666 	} else
667 		s->cx--;
668 }
669 
670 /* VT100 alignment test. */
671 void
672 screen_write_alignmenttest(struct screen_write_ctx *ctx)
673 {
674 	struct screen		*s = ctx->s;
675 	struct tty_ctx	 	 ttyctx;
676 	struct grid_cell       	 gc;
677 	u_int			 xx, yy;
678 
679 	screen_write_initctx(ctx, &ttyctx);
680 
681 	memcpy(&gc, &grid_default_cell, sizeof gc);
682 	utf8_set(&gc.data, 'E');
683 
684 	for (yy = 0; yy < screen_size_y(s); yy++) {
685 		for (xx = 0; xx < screen_size_x(s); xx++)
686 			grid_view_set_cell(s->grid, xx, yy, &gc);
687 	}
688 
689 	s->cx = 0;
690 	s->cy = 0;
691 
692 	s->rupper = 0;
693 	s->rlower = screen_size_y(s) - 1;
694 
695 	screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1);
696 	tty_write(tty_cmd_alignmenttest, &ttyctx);
697 }
698 
699 /* Insert nx characters. */
700 void
701 screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
702 {
703 	struct screen	*s = ctx->s;
704 	struct tty_ctx	 ttyctx;
705 
706 	if (nx == 0)
707 		nx = 1;
708 
709 	if (nx > screen_size_x(s) - s->cx)
710 		nx = screen_size_x(s) - s->cx;
711 	if (nx == 0)
712 		return;
713 
714 	if (s->cx > screen_size_x(s) - 1)
715 		return;
716 
717 	screen_write_initctx(ctx, &ttyctx);
718 	ttyctx.bg = bg;
719 
720 	grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);
721 
722 	screen_write_collect_flush(ctx, 0);
723 	ttyctx.num = nx;
724 	tty_write(tty_cmd_insertcharacter, &ttyctx);
725 }
726 
727 /* Delete nx characters. */
728 void
729 screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
730 {
731 	struct screen	*s = ctx->s;
732 	struct tty_ctx	 ttyctx;
733 
734 	if (nx == 0)
735 		nx = 1;
736 
737 	if (nx > screen_size_x(s) - s->cx)
738 		nx = screen_size_x(s) - s->cx;
739 	if (nx == 0)
740 		return;
741 
742 	if (s->cx > screen_size_x(s) - 1)
743 		return;
744 
745 	screen_write_initctx(ctx, &ttyctx);
746 	ttyctx.bg = bg;
747 
748 	grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);
749 
750 	screen_write_collect_flush(ctx, 0);
751 	ttyctx.num = nx;
752 	tty_write(tty_cmd_deletecharacter, &ttyctx);
753 }
754 
755 /* Clear nx characters. */
756 void
757 screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
758 {
759 	struct screen	*s = ctx->s;
760 	struct tty_ctx	 ttyctx;
761 
762 	if (nx == 0)
763 		nx = 1;
764 
765 	if (nx > screen_size_x(s) - s->cx)
766 		nx = screen_size_x(s) - s->cx;
767 	if (nx == 0)
768 		return;
769 
770 	if (s->cx > screen_size_x(s) - 1)
771 		return;
772 
773 	screen_write_initctx(ctx, &ttyctx);
774 	ttyctx.bg = bg;
775 
776 	grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg);
777 
778 	screen_write_collect_flush(ctx, 0);
779 	ttyctx.num = nx;
780 	tty_write(tty_cmd_clearcharacter, &ttyctx);
781 }
782 
783 /* Insert ny lines. */
784 void
785 screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
786 {
787 	struct screen	*s = ctx->s;
788 	struct grid	*gd = s->grid;
789 	struct tty_ctx	 ttyctx;
790 
791 	if (ny == 0)
792 		ny = 1;
793 
794 	if (s->cy < s->rupper || s->cy > s->rlower) {
795 		if (ny > screen_size_y(s) - s->cy)
796 			ny = screen_size_y(s) - s->cy;
797 		if (ny == 0)
798 			return;
799 
800 		screen_write_initctx(ctx, &ttyctx);
801 		ttyctx.bg = bg;
802 
803 		grid_view_insert_lines(gd, s->cy, ny, bg);
804 
805 		screen_write_collect_flush(ctx, 0);
806 		ttyctx.num = ny;
807 		tty_write(tty_cmd_insertline, &ttyctx);
808 		return;
809 	}
810 
811 	if (ny > s->rlower + 1 - s->cy)
812 		ny = s->rlower + 1 - s->cy;
813 	if (ny == 0)
814 		return;
815 
816 	screen_write_initctx(ctx, &ttyctx);
817 	ttyctx.bg = bg;
818 
819 	if (s->cy < s->rupper || s->cy > s->rlower)
820 		grid_view_insert_lines(gd, s->cy, ny, bg);
821 	else
822 		grid_view_insert_lines_region(gd, s->rlower, s->cy, ny, bg);
823 
824 	screen_write_collect_flush(ctx, 0);
825 	ttyctx.num = ny;
826 	tty_write(tty_cmd_insertline, &ttyctx);
827 }
828 
829 /* Delete ny lines. */
830 void
831 screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
832 {
833 	struct screen	*s = ctx->s;
834 	struct grid	*gd = s->grid;
835 	struct tty_ctx	 ttyctx;
836 
837 	if (ny == 0)
838 		ny = 1;
839 
840 	if (s->cy < s->rupper || s->cy > s->rlower) {
841 		if (ny > screen_size_y(s) - s->cy)
842 			ny = screen_size_y(s) - s->cy;
843 		if (ny == 0)
844 			return;
845 
846 		screen_write_initctx(ctx, &ttyctx);
847 		ttyctx.bg = bg;
848 
849 		grid_view_delete_lines(gd, s->cy, ny, bg);
850 
851 		screen_write_collect_flush(ctx, 0);
852 		ttyctx.num = ny;
853 		tty_write(tty_cmd_deleteline, &ttyctx);
854 		return;
855 	}
856 
857 	if (ny > s->rlower + 1 - s->cy)
858 		ny = s->rlower + 1 - s->cy;
859 	if (ny == 0)
860 		return;
861 
862 	screen_write_initctx(ctx, &ttyctx);
863 	ttyctx.bg = bg;
864 
865 	if (s->cy < s->rupper || s->cy > s->rlower)
866 		grid_view_delete_lines(gd, s->cy, ny, bg);
867 	else
868 		grid_view_delete_lines_region(gd, s->rlower, s->cy, ny, bg);
869 
870 	screen_write_collect_flush(ctx, 0);
871 	ttyctx.num = ny;
872 	tty_write(tty_cmd_deleteline, &ttyctx);
873 }
874 
875 /* Clear line at cursor. */
876 void
877 screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
878 {
879 	struct screen		*s = ctx->s;
880 	struct grid_line	*gl;
881 	struct tty_ctx		 ttyctx;
882 	u_int			 sx = screen_size_x(s);
883 
884 	gl = &s->grid->linedata[s->grid->hsize + s->cy];
885 	if (gl->cellsize == 0 && bg == 8)
886 		return;
887 
888 	screen_write_initctx(ctx, &ttyctx);
889 	ttyctx.bg = bg;
890 
891 	grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
892 
893 	screen_write_collect_clear(ctx, s->cy, 1);
894 	screen_write_collect_flush(ctx, 0);
895 	tty_write(tty_cmd_clearline, &ttyctx);
896 }
897 
898 /* Clear to end of line from cursor. */
899 void
900 screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
901 {
902 	struct screen		*s = ctx->s;
903 	struct grid_line	*gl;
904 	struct tty_ctx		 ttyctx;
905 	u_int			 sx = screen_size_x(s);
906 
907 	gl = &s->grid->linedata[s->grid->hsize + s->cy];
908 	if (s->cx > sx - 1 || (s->cx >= gl->cellsize && bg == 8))
909 		return;
910 
911 	screen_write_initctx(ctx, &ttyctx);
912 	ttyctx.bg = bg;
913 
914 	grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
915 
916 	if (s->cx == 0)
917 		screen_write_collect_clear(ctx, s->cy, 1);
918 	screen_write_collect_flush(ctx, 0);
919 	tty_write(tty_cmd_clearendofline, &ttyctx);
920 }
921 
922 /* Clear to start of line from cursor. */
923 void
924 screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
925 {
926 	struct screen	*s = ctx->s;
927 	struct tty_ctx	 ttyctx;
928 	u_int		 sx = screen_size_x(s);
929 
930 	screen_write_initctx(ctx, &ttyctx);
931 	ttyctx.bg = bg;
932 
933 	if (s->cx > sx - 1)
934 		grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
935 	else
936 		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
937 
938 	if (s->cx > sx - 1)
939 		screen_write_collect_clear(ctx, s->cy, 1);
940 	screen_write_collect_flush(ctx, 0);
941 	tty_write(tty_cmd_clearstartofline, &ttyctx);
942 }
943 
944 /* Move cursor to px,py. */
945 void
946 screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py)
947 {
948 	struct screen	*s = ctx->s;
949 
950 	if (px > screen_size_x(s) - 1)
951 		px = screen_size_x(s) - 1;
952 	if (py > screen_size_y(s) - 1)
953 		py = screen_size_y(s) - 1;
954 
955 	s->cx = px;
956 	s->cy = py;
957 }
958 
959 /* Reverse index (up with scroll). */
960 void
961 screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
962 {
963 	struct screen	*s = ctx->s;
964 	struct tty_ctx	 ttyctx;
965 
966 	screen_write_initctx(ctx, &ttyctx);
967 	ttyctx.bg = bg;
968 
969 	if (s->cy == s->rupper)
970 		grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
971 	else if (s->cy > 0)
972 		s->cy--;
973 
974 	screen_write_collect_flush(ctx, 0);
975 	tty_write(tty_cmd_reverseindex, &ttyctx);
976 }
977 
978 /* Set scroll region. */
979 void
980 screen_write_scrollregion(struct screen_write_ctx *ctx, u_int rupper,
981     u_int rlower)
982 {
983 	struct screen	*s = ctx->s;
984 
985 	if (rupper > screen_size_y(s) - 1)
986 		rupper = screen_size_y(s) - 1;
987 	if (rlower > screen_size_y(s) - 1)
988 		rlower = screen_size_y(s) - 1;
989 	if (rupper >= rlower)	/* cannot be one line */
990 		return;
991 
992 	screen_write_collect_flush(ctx, 0);
993 
994 	/* Cursor moves to top-left. */
995 	s->cx = 0;
996 	s->cy = 0;
997 
998 	s->rupper = rupper;
999 	s->rlower = rlower;
1000 }
1001 
1002 /* Line feed. */
1003 void
1004 screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
1005 {
1006 	struct screen		*s = ctx->s;
1007 	struct grid		*gd = s->grid;
1008 	struct grid_line	*gl;
1009 
1010 	gl = &gd->linedata[gd->hsize + s->cy];
1011 	if (wrapped)
1012 		gl->flags |= GRID_LINE_WRAPPED;
1013 	else
1014 		gl->flags &= ~GRID_LINE_WRAPPED;
1015 
1016 	log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
1017 	    s->rupper, s->rlower);
1018 
1019 	if (bg != ctx->bg) {
1020 		screen_write_collect_flush(ctx, 1);
1021 		ctx->bg = bg;
1022 	}
1023 
1024 	if (s->cy == s->rlower) {
1025 		grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
1026 		screen_write_collect_scroll(ctx);
1027 		ctx->scrolled++;
1028 	} else if (s->cy < screen_size_y(s) - 1)
1029 		s->cy++;
1030 }
1031 
1032 /* Scroll up. */
1033 void
1034 screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
1035 {
1036 	struct screen	*s = ctx->s;
1037 	struct grid	*gd = s->grid;
1038 	u_int		 i;
1039 
1040 	if (lines == 0)
1041 		lines = 1;
1042 	else if (lines > s->rlower - s->rupper + 1)
1043 		lines = s->rlower - s->rupper + 1;
1044 
1045 	if (bg != ctx->bg) {
1046 		screen_write_collect_flush(ctx, 1);
1047 		ctx->bg = bg;
1048 	}
1049 
1050 	for (i = 0; i < lines; i++) {
1051 		grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
1052 		screen_write_collect_scroll(ctx);
1053 	}
1054 	ctx->scrolled += lines;
1055 }
1056 
1057 /* Carriage return (cursor to start of line). */
1058 void
1059 screen_write_carriagereturn(struct screen_write_ctx *ctx)
1060 {
1061 	struct screen	*s = ctx->s;
1062 
1063 	s->cx = 0;
1064 }
1065 
1066 /* Clear to end of screen from cursor. */
1067 void
1068 screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
1069 {
1070 	struct screen	*s = ctx->s;
1071 	struct grid	*gd = s->grid;
1072 	struct tty_ctx	 ttyctx;
1073 	u_int		 sx = screen_size_x(s), sy = screen_size_y(s);
1074 
1075 	screen_write_initctx(ctx, &ttyctx);
1076 	ttyctx.bg = bg;
1077 
1078 	/* Scroll into history if it is enabled and clearing entire screen. */
1079 	if (s->cx == 0 && s->cy == 0 && (gd->flags & GRID_HISTORY))
1080 		grid_view_clear_history(gd, bg);
1081 	else {
1082 		if (s->cx <= sx - 1)
1083 			grid_view_clear(gd, s->cx, s->cy, sx - s->cx, 1, bg);
1084 		grid_view_clear(gd, 0, s->cy + 1, sx, sy - (s->cy + 1), bg);
1085 	}
1086 
1087 	screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
1088 	screen_write_collect_flush(ctx, 0);
1089 	tty_write(tty_cmd_clearendofscreen, &ttyctx);
1090 }
1091 
1092 /* Clear to start of screen. */
1093 void
1094 screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
1095 {
1096 	struct screen	*s = ctx->s;
1097 	struct tty_ctx	 ttyctx;
1098 	u_int		 sx = screen_size_x(s);
1099 
1100 	screen_write_initctx(ctx, &ttyctx);
1101 	ttyctx.bg = bg;
1102 
1103 	if (s->cy > 0)
1104 		grid_view_clear(s->grid, 0, 0, sx, s->cy, bg);
1105 	if (s->cx > sx - 1)
1106 		grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
1107 	else
1108 		grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
1109 
1110 	screen_write_collect_clear(ctx, 0, s->cy);
1111 	screen_write_collect_flush(ctx, 0);
1112 	tty_write(tty_cmd_clearstartofscreen, &ttyctx);
1113 }
1114 
1115 /* Clear entire screen. */
1116 void
1117 screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
1118 {
1119 	struct screen	*s = ctx->s;
1120 	struct tty_ctx	 ttyctx;
1121 	u_int		 sx = screen_size_x(s), sy = screen_size_y(s);
1122 
1123 	screen_write_initctx(ctx, &ttyctx);
1124 	ttyctx.bg = bg;
1125 
1126 	/* Scroll into history if it is enabled. */
1127 	if (s->grid->flags & GRID_HISTORY)
1128 		grid_view_clear_history(s->grid, bg);
1129 	else
1130 		grid_view_clear(s->grid, 0, 0, sx, sy, bg);
1131 
1132 	screen_write_collect_clear(ctx, 0, sy);
1133 	tty_write(tty_cmd_clearscreen, &ttyctx);
1134 }
1135 
1136 /* Clear entire history. */
1137 void
1138 screen_write_clearhistory(struct screen_write_ctx *ctx)
1139 {
1140 	struct screen	*s = ctx->s;
1141 	struct grid	*gd = s->grid;
1142 
1143 	grid_move_lines(gd, 0, gd->hsize, gd->sy, 8);
1144 	gd->hscrolled = gd->hsize = 0;
1145 }
1146 
1147 /* Clear a collected line. */
1148 static void
1149 screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
1150 {
1151 	struct screen_write_collect_item	*ci, *tmp;
1152 	u_int					 i;
1153 	size_t					 size;
1154 
1155 	for (i = y ; i < y + n; i++) {
1156 		if (TAILQ_EMPTY(&ctx->list[i].items))
1157 			continue;
1158 		size = 0;
1159 		TAILQ_FOREACH_SAFE(ci, &ctx->list[i].items, entry, tmp) {
1160 			size += ci->used;
1161 			TAILQ_REMOVE(&ctx->list[i].items, ci, entry);
1162 			free(ci);
1163 		}
1164 		ctx->skipped += size;
1165 		log_debug("%s: dropped %zu bytes (line %u)", __func__, size, i);
1166 	}
1167 }
1168 
1169 /* Scroll collected lines up. */
1170 static void
1171 screen_write_collect_scroll(struct screen_write_ctx *ctx)
1172 {
1173 	struct screen				*s = ctx->s;
1174 	struct screen_write_collect_line	*cl;
1175 	u_int					 y;
1176 
1177 	log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
1178 	    s->rupper, s->rlower);
1179 
1180 	screen_write_collect_clear(ctx, s->rupper, 1);
1181 	for (y = s->rupper; y < s->rlower; y++) {
1182 		cl = &ctx->list[y + 1];
1183 		TAILQ_CONCAT(&ctx->list[y].items, &cl->items, entry);
1184 		TAILQ_INIT(&cl->items);
1185 	}
1186 }
1187 
1188 /* Flush collected lines. */
1189 static void
1190 screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only)
1191 {
1192 	struct screen				*s = ctx->s;
1193 	struct screen_write_collect_item	*ci, *tmp;
1194 	u_int					 y, cx, cy, items = 0;
1195 	struct tty_ctx				 ttyctx;
1196 	size_t					 written = 0;
1197 
1198 	if (ctx->scrolled != 0) {
1199 		log_debug("%s: scrolled %u (region %u-%u)", __func__,
1200 		    ctx->scrolled, s->rupper, s->rlower);
1201 		if (ctx->scrolled > s->rlower - s->rupper + 1)
1202 			ctx->scrolled = s->rlower - s->rupper + 1;
1203 
1204 		screen_write_initctx(ctx, &ttyctx);
1205 		ttyctx.num = ctx->scrolled;
1206 		ttyctx.bg = ctx->bg;
1207 		tty_write(tty_cmd_scrollup, &ttyctx);
1208 	}
1209 	ctx->scrolled = 0;
1210 	ctx->bg = 8;
1211 
1212 	if (scroll_only)
1213 		return;
1214 
1215 	cx = s->cx; cy = s->cy;
1216 	for (y = 0; y < screen_size_y(s); y++) {
1217 		TAILQ_FOREACH_SAFE(ci, &ctx->list[y].items, entry, tmp) {
1218 			screen_write_cursormove(ctx, ci->x, y);
1219 			screen_write_initctx(ctx, &ttyctx);
1220 			ttyctx.cell = &ci->gc;
1221 			ttyctx.wrapped = ci->wrapped;
1222 			ttyctx.ptr = ci->data;
1223 			ttyctx.num = ci->used;
1224 			tty_write(tty_cmd_cells, &ttyctx);
1225 
1226 			items++;
1227 			written += ci->used;
1228 
1229 			TAILQ_REMOVE(&ctx->list[y].items, ci, entry);
1230 			free(ci);
1231 		}
1232 	}
1233 	s->cx = cx; s->cy = cy;
1234 
1235 	log_debug("%s: flushed %u items (%zu bytes)", __func__, items, written);
1236 	ctx->written += written;
1237 }
1238 
1239 /* Finish and store collected cells. */
1240 void
1241 screen_write_collect_end(struct screen_write_ctx *ctx)
1242 {
1243 	struct screen				*s = ctx->s;
1244 	struct screen_write_collect_item	*ci = ctx->item;
1245 	struct grid_cell			 gc;
1246 	u_int					 xx;
1247 
1248 	if (ci->used == 0)
1249 		return;
1250 	ci->data[ci->used] = '\0';
1251 
1252 	ci->x = s->cx;
1253 	TAILQ_INSERT_TAIL(&ctx->list[s->cy].items, ci, entry);
1254 	ctx->item = xcalloc(1, sizeof *ctx->item);
1255 
1256 	log_debug("%s: %u %s (at %u,%u)", __func__, ci->used, ci->data, s->cx,
1257 	    s->cy);
1258 
1259 	if (s->cx != 0) {
1260 		for (xx = s->cx; xx > 0; xx--) {
1261 			grid_view_get_cell(s->grid, xx, s->cy, &gc);
1262 			if (~gc.flags & GRID_FLAG_PADDING)
1263 				break;
1264 			grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
1265 		}
1266 		if (gc.data.width > 1)
1267 			grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
1268 	}
1269 
1270 	memcpy(&gc, &ci->gc, sizeof gc);
1271 	grid_view_set_cells(s->grid, s->cx, s->cy, &gc, ci->data, ci->used);
1272 	s->cx += ci->used;
1273 
1274 	for (xx = s->cx; xx < screen_size_x(s); xx++) {
1275 		grid_view_get_cell(s->grid, xx, s->cy, &gc);
1276 		if (~gc.flags & GRID_FLAG_PADDING)
1277 			break;
1278 		grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
1279 	}
1280 }
1281 
1282 /* Write cell data, collecting if necessary. */
1283 void
1284 screen_write_collect_add(struct screen_write_ctx *ctx,
1285     const struct grid_cell *gc)
1286 {
1287 	struct screen				*s = ctx->s;
1288 	struct screen_write_collect_item	*ci;
1289 	u_int					 sx = screen_size_x(s);
1290 	int					 collect;
1291 
1292 	/*
1293 	 * Don't need to check that the attributes and whatnot are still the
1294 	 * same - input_parse will end the collection when anything that isn't
1295 	 * a plain character is encountered. Also nothing should make it here
1296 	 * that isn't a single ASCII character.
1297 	 */
1298 
1299 	collect = 1;
1300 	if (gc->data.width != 1 || gc->data.size != 1)
1301 		collect = 0;
1302 	else if (gc->attr & GRID_ATTR_CHARSET)
1303 		collect = 0;
1304 	else if (~s->mode & MODE_WRAP)
1305 		collect = 0;
1306 	else if (s->mode & MODE_INSERT)
1307 		collect = 0;
1308 	else if (s->sel.flag)
1309 		collect = 0;
1310 	if (!collect) {
1311 		screen_write_collect_end(ctx);
1312 		screen_write_collect_flush(ctx, 0);
1313 		screen_write_cell(ctx, gc);
1314 		return;
1315 	}
1316 	ctx->cells++;
1317 
1318 	if (s->cx > sx - 1 || ctx->item->used > sx - 1 - s->cx)
1319 		screen_write_collect_end(ctx);
1320 	ci = ctx->item; /* may have changed */
1321 
1322 	if (s->cx > sx - 1) {
1323 		log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
1324 		ci->wrapped = 1;
1325 		screen_write_linefeed(ctx, 1, 8);
1326 		s->cx = 0;
1327 	}
1328 
1329 	if (ci->used == 0)
1330 		memcpy(&ci->gc, gc, sizeof ci->gc);
1331 	ci->data[ci->used++] = gc->data.data[0];
1332 	if (ci->used == (sizeof ci->data) - 1)
1333 		screen_write_collect_end(ctx);
1334 }
1335 
1336 /* Write cell data. */
1337 void
1338 screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
1339 {
1340 	struct screen		*s = ctx->s;
1341 	struct grid		*gd = s->grid;
1342 	struct grid_line	*gl;
1343 	struct grid_cell_entry	*gce;
1344 	struct grid_cell 	 tmp_gc, now_gc;
1345 	struct tty_ctx		 ttyctx;
1346 	u_int			 sx = screen_size_x(s), sy = screen_size_y(s);
1347 	u_int		 	 width = gc->data.width, xx, last, cx, cy;
1348 	int			 selected, skip = 1;
1349 
1350 	/* Ignore padding cells. */
1351 	if (gc->flags & GRID_FLAG_PADDING)
1352 		return;
1353 	ctx->cells++;
1354 
1355 	/* If the width is zero, combine onto the previous character. */
1356 	if (width == 0) {
1357 		screen_write_collect_flush(ctx, 0);
1358 		if ((gc = screen_write_combine(ctx, &gc->data, &xx)) != 0) {
1359 			cx = s->cx; cy = s->cy;
1360 			screen_write_cursormove(ctx, xx, s->cy);
1361 			screen_write_initctx(ctx, &ttyctx);
1362 			ttyctx.cell = gc;
1363 			tty_write(tty_cmd_cell, &ttyctx);
1364 			s->cx = cx; s->cy = cy;
1365 		}
1366 		return;
1367 	}
1368 
1369 	/* Flush any existing scrolling. */
1370 	screen_write_collect_flush(ctx, 1);
1371 
1372 	/* If this character doesn't fit, ignore it. */
1373 	if ((~s->mode & MODE_WRAP) &&
1374 	    width > 1 &&
1375 	    (width > sx || (s->cx != sx && s->cx > sx - width)))
1376 		return;
1377 
1378 	/* If in insert mode, make space for the cells. */
1379 	if (s->mode & MODE_INSERT) {
1380 		grid_view_insert_cells(s->grid, s->cx, s->cy, width, 8);
1381 		skip = 0;
1382 	}
1383 
1384 	/* Check this will fit on the current line and wrap if not. */
1385 	if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
1386 		log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
1387 		screen_write_linefeed(ctx, 1, 8);
1388 		s->cx = 0;
1389 		screen_write_collect_flush(ctx, 1);
1390 	}
1391 
1392 	/* Sanity check cursor position. */
1393 	if (s->cx > sx - width || s->cy > sy - 1)
1394 		return;
1395 	screen_write_initctx(ctx, &ttyctx);
1396 
1397 	/* Handle overwriting of UTF-8 characters. */
1398 	gl = &s->grid->linedata[s->grid->hsize + s->cy];
1399 	if (gl->flags & GRID_LINE_EXTENDED) {
1400 		grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
1401 		if (screen_write_overwrite(ctx, &now_gc, width))
1402 			skip = 0;
1403 	}
1404 
1405 	/*
1406 	 * If the new character is UTF-8 wide, fill in padding cells. Have
1407 	 * already ensured there is enough room.
1408 	 */
1409 	for (xx = s->cx + 1; xx < s->cx + width; xx++) {
1410 		log_debug("%s: new padding at %u,%u", __func__, xx, s->cy);
1411 		grid_view_set_cell(gd, xx, s->cy, &screen_write_pad_cell);
1412 		skip = 0;
1413 	}
1414 
1415 	/* If no change, do not draw. */
1416 	if (skip) {
1417 		if (s->cx >= gl->cellsize)
1418 			skip = grid_cells_equal(gc, &grid_default_cell);
1419 		else {
1420 			gce = &gl->celldata[s->cx];
1421 			if (gce->flags & GRID_FLAG_EXTENDED)
1422 				skip = 0;
1423 			else if (gc->flags != gce->flags)
1424 				skip = 0;
1425 			else if (gc->attr != gce->data.attr)
1426 				skip = 0;
1427 			else if (gc->fg != gce->data.fg)
1428 				skip = 0;
1429 			else if (gc->bg != gce->data.bg)
1430 				skip = 0;
1431 			else if (gc->data.width != 1)
1432 				skip = 0;
1433 			else if (gc->data.size != 1)
1434 				skip = 0;
1435 			else if (gce->data.data != gc->data.data[0])
1436 				skip = 0;
1437 		}
1438 	}
1439 
1440 	/* Update the selected flag and set the cell. */
1441 	selected = screen_check_selection(s, s->cx, s->cy);
1442 	if (selected && (~gc->flags & GRID_FLAG_SELECTED)) {
1443 		memcpy(&tmp_gc, gc, sizeof tmp_gc);
1444 		tmp_gc.flags |= GRID_FLAG_SELECTED;
1445 		grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
1446 	} else if (!selected && (gc->flags & GRID_FLAG_SELECTED)) {
1447 		memcpy(&tmp_gc, gc, sizeof tmp_gc);
1448 		tmp_gc.flags &= ~GRID_FLAG_SELECTED;
1449 		grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
1450 	} else if (!skip)
1451 		grid_view_set_cell(gd, s->cx, s->cy, gc);
1452 	if (selected)
1453 		skip = 0;
1454 
1455 	/*
1456 	 * Move the cursor. If not wrapping, stick at the last character and
1457 	 * replace it.
1458 	 */
1459 	last = !(s->mode & MODE_WRAP);
1460 	if (s->cx <= sx - last - width)
1461 		s->cx += width;
1462 	else
1463 		s->cx = sx - last;
1464 
1465 	/* Create space for character in insert mode. */
1466 	if (s->mode & MODE_INSERT) {
1467 		screen_write_collect_flush(ctx, 0);
1468 		ttyctx.num = width;
1469 		tty_write(tty_cmd_insertcharacter, &ttyctx);
1470 	}
1471 
1472 	/* Write to the screen. */
1473 	if (!skip) {
1474 		if (selected) {
1475 			screen_select_cell(s, &tmp_gc, gc);
1476 			ttyctx.cell = &tmp_gc;
1477 		} else
1478 			ttyctx.cell = gc;
1479 		tty_write(tty_cmd_cell, &ttyctx);
1480 		ctx->written++;
1481 	} else
1482 		ctx->skipped++;
1483 }
1484 
1485 /* Combine a UTF-8 zero-width character onto the previous. */
1486 static const struct grid_cell *
1487 screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud,
1488     u_int *xx)
1489 {
1490 	struct screen		*s = ctx->s;
1491 	struct grid		*gd = s->grid;
1492 	static struct grid_cell	 gc;
1493 	u_int			 n;
1494 
1495 	/* Can't combine if at 0. */
1496 	if (s->cx == 0)
1497 		return (NULL);
1498 
1499 	/* Empty data is out. */
1500 	if (ud->size == 0)
1501 		fatalx("UTF-8 data empty");
1502 
1503 	/* Retrieve the previous cell. */
1504 	for (n = 1; n <= s->cx; n++) {
1505 		grid_view_get_cell(gd, s->cx - n, s->cy, &gc);
1506 		if (~gc.flags & GRID_FLAG_PADDING)
1507 			break;
1508 	}
1509 	if (n > s->cx)
1510 		return (NULL);
1511 	*xx = s->cx - n;
1512 
1513 	/* Check there is enough space. */
1514 	if (gc.data.size + ud->size > sizeof gc.data.data)
1515 		return (NULL);
1516 
1517 	log_debug("%s: %.*s onto %.*s at %u,%u", __func__, (int)ud->size,
1518 	    ud->data, (int)gc.data.size, gc.data.data, *xx, s->cy);
1519 
1520 	/* Append the data. */
1521 	memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
1522 	gc.data.size += ud->size;
1523 
1524 	/* Set the new cell. */
1525 	grid_view_set_cell(gd, *xx, s->cy, &gc);
1526 
1527 	return (&gc);
1528 }
1529 
1530 /*
1531  * UTF-8 wide characters are a bit of an annoyance. They take up more than one
1532  * cell on the screen, so following cells must not be drawn by marking them as
1533  * padding.
1534  *
1535  * So far, so good. The problem is, when overwriting a padding cell, or a UTF-8
1536  * character, it is necessary to also overwrite any other cells which covered
1537  * by the same character.
1538  */
1539 static int
1540 screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc,
1541     u_int width)
1542 {
1543 	struct screen		*s = ctx->s;
1544 	struct grid		*gd = s->grid;
1545 	struct grid_cell	 tmp_gc;
1546 	u_int			 xx;
1547 	int			 done = 0;
1548 
1549 	if (gc->flags & GRID_FLAG_PADDING) {
1550 		/*
1551 		 * A padding cell, so clear any following and leading padding
1552 		 * cells back to the character. Don't overwrite the current
1553 		 * cell as that happens later anyway.
1554 		 */
1555 		xx = s->cx + 1;
1556 		while (--xx > 0) {
1557 			grid_view_get_cell(gd, xx, s->cy, &tmp_gc);
1558 			if (~tmp_gc.flags & GRID_FLAG_PADDING)
1559 				break;
1560 			log_debug("%s: padding at %u,%u", __func__, xx, s->cy);
1561 			grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
1562 		}
1563 
1564 		/* Overwrite the character at the start of this padding. */
1565 		log_debug("%s: character at %u,%u", __func__, xx, s->cy);
1566 		grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
1567 		done = 1;
1568 	}
1569 
1570 	/*
1571 	 * Overwrite any padding cells that belong to any UTF-8 characters
1572 	 * we'll be overwriting with the current character.
1573 	 */
1574 	if (width != 1 ||
1575 	    gc->data.width != 1 ||
1576 	    gc->flags & GRID_FLAG_PADDING) {
1577 		xx = s->cx + width - 1;
1578 		while (++xx < screen_size_x(s)) {
1579 			grid_view_get_cell(gd, xx, s->cy, &tmp_gc);
1580 			if (~tmp_gc.flags & GRID_FLAG_PADDING)
1581 				break;
1582 			log_debug("%s: overwrite at %u,%u", __func__, xx, s->cy);
1583 			grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
1584 			done = 1;
1585 		}
1586 	}
1587 
1588 	return (done);
1589 }
1590 
1591 /* Set external clipboard. */
1592 void
1593 screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
1594 {
1595 	struct tty_ctx	ttyctx;
1596 
1597 	screen_write_initctx(ctx, &ttyctx);
1598 	ttyctx.ptr = str;
1599 	ttyctx.num = len;
1600 
1601 	tty_write(tty_cmd_setselection, &ttyctx);
1602 }
1603 
1604 /* Write unmodified string. */
1605 void
1606 screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
1607 {
1608 	struct tty_ctx	ttyctx;
1609 
1610 	screen_write_initctx(ctx, &ttyctx);
1611 	ttyctx.ptr = str;
1612 	ttyctx.num = len;
1613 
1614 	tty_write(tty_cmd_rawstring, &ttyctx);
1615 }
1616