tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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