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