aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--grid.c74
-rw-r--r--screen-write.c284
-rw-r--r--screen.c4
-rw-r--r--tmux.h70
-rw-r--r--tty.c310
5 files changed, 399 insertions, 343 deletions
diff --git a/grid.c b/grid.c
index 0be0254f..f0eda7e0 100644
--- a/grid.c
+++ b/grid.c
@@ -37,14 +37,12 @@
/* Default grid cell data. */
const struct grid_cell grid_default_cell = {
- 0, 0, { .fg = 8 }, { .bg = 8 }, { { ' ' }, 0, 1, 1 }
+ 0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
};
const struct grid_cell_entry grid_default_entry = {
0, { .data = { 0, 8, 8, ' ' } }
};
-int grid_check_y(struct grid *, u_int);
-
void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *l,
u_int, u_int);
void grid_reflow_join(struct grid *, u_int *, struct grid_line *, u_int);
@@ -64,7 +62,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py)
}
/* Check grid y position. */
-int
+static int
grid_check_y(struct grid *gd, u_int py)
{
if ((py) >= (gd)->hsize + (gd)->sy) {
@@ -74,6 +72,21 @@ grid_check_y(struct grid *gd, u_int py)
return (0);
}
+/* Compare grid cells. Return 1 if equal, 0 if not. */
+int
+grid_cells_equal(const struct grid_cell *gca, const struct grid_cell *gcb)
+{
+ if (gca->fg != gcb->fg || gca->bg != gcb->bg)
+ return (0);
+ if (gca->attr != gcb->attr || gca->flags != gcb->flags)
+ return (0);
+ if (gca->data.width != gcb->data.width)
+ return (0);
+ if (gca->data.size != gcb->data.size)
+ return (0);
+ return (memcmp(gca->data.data, gcb->data.data, gca->data.size) == 0);
+}
+
/* Create a new grid. */
struct grid *
grid_create(u_int sx, u_int sy, u_int hlimit)
@@ -131,7 +144,7 @@ grid_compare(struct grid *ga, struct grid *gb)
for (xx = 0; xx < gla->cellsize; xx++) {
grid_get_cell(ga, xx, yy, &gca);
grid_get_cell(gb, xx, yy, &gcb);
- if (memcmp(&gca, &gcb, sizeof (struct grid_cell)) != 0)
+ if (!grid_cells_equal(&gca, &gcb))
return (1);
}
}
@@ -270,10 +283,14 @@ grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
return;
}
- gc->flags = gce->flags & ~GRID_FLAG_EXTENDED;
+ gc->flags = gce->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
gc->attr = gce->data.attr;
gc->fg = gce->data.fg;
+ if (gce->flags & GRID_FLAG_FG256)
+ gc->fg |= COLOUR_FLAG_256;
gc->bg = gce->data.bg;
+ if (gce->flags & GRID_FLAG_BG256)
+ gc->bg |= COLOUR_FLAG_256;
utf8_set(&gc->data, gce->data.data);
}
@@ -297,9 +314,12 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
extended = (gce->flags & GRID_FLAG_EXTENDED);
if (!extended && (gc->data.size != 1 || gc->data.width != 1))
extended = 1;
- if (!extended && (gc->flags & (GRID_FLAG_FGRGB|GRID_FLAG_BGRGB)))
+ if (!extended && ((gc->fg & COLOUR_FLAG_RGB) ||
+ (gc->bg & COLOUR_FLAG_RGB)))
extended = 1;
if (extended) {
+ gl->flags |= GRID_LINE_EXTENDED;
+
if (~gce->flags & GRID_FLAG_EXTENDED) {
gl->extddata = xreallocarray(gl->extddata,
gl->extdsize + 1, sizeof *gl->extddata);
@@ -314,10 +334,14 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
return;
}
- gce->flags = gc->flags & ~GRID_FLAG_EXTENDED;
+ gce->flags = gc->flags;
gce->data.attr = gc->attr;
- gce->data.fg = gc->fg;
- gce->data.bg = gc->bg;
+ gce->data.fg = gc->fg & 0xff;
+ if (gc->fg & COLOUR_FLAG_256)
+ gce->flags |= GRID_FLAG_FG256;
+ gce->data.bg = gc->bg & 0xff;
+ if (gc->bg & COLOUR_FLAG_256)
+ gce->flags |= GRID_FLAG_BG256;
gce->data.data = gc->data.data[0];
}
@@ -446,18 +470,20 @@ size_t
grid_string_cells_fg(const struct grid_cell *gc, int *values)
{
size_t n;
+ u_char r, g, b;
n = 0;
- if (gc->flags & GRID_FLAG_FG256) {
+ if (gc->fg & COLOUR_FLAG_256) {
values[n++] = 38;
values[n++] = 5;
- values[n++] = gc->fg;
- } else if (gc->flags & GRID_FLAG_FGRGB) {
+ values[n++] = gc->fg & 0xff;
+ } else if (gc->fg & COLOUR_FLAG_RGB) {
values[n++] = 38;
values[n++] = 2;
- values[n++] = gc->fg_rgb.r;
- values[n++] = gc->fg_rgb.g;
- values[n++] = gc->fg_rgb.b;
+ colour_split_rgb(gc->fg, &r, &g, &b);
+ values[n++] = r;
+ values[n++] = g;
+ values[n++] = b;
} else {
switch (gc->fg) {
case 0:
@@ -493,18 +519,20 @@ size_t
grid_string_cells_bg(const struct grid_cell *gc, int *values)
{
size_t n;
+ u_char r, g, b;
n = 0;
- if (gc->flags & GRID_FLAG_BG256) {
+ if (gc->bg & COLOUR_FLAG_256) {
values[n++] = 48;
values[n++] = 5;
- values[n++] = gc->bg;
- } else if (gc->flags & GRID_FLAG_BGRGB) {
+ values[n++] = gc->bg & 0xff;
+ } else if (gc->bg & COLOUR_FLAG_RGB) {
values[n++] = 48;
values[n++] = 2;
- values[n++] = gc->bg_rgb.r;
- values[n++] = gc->bg_rgb.g;
- values[n++] = gc->bg_rgb.b;
+ colour_split_rgb(gc->bg, &r, &g, &b);
+ values[n++] = r;
+ values[n++] = g;
+ values[n++] = b;
} else {
switch (gc->bg) {
case 0:
@@ -525,7 +553,7 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values)
case 102:
case 103:
case 104:
- case 105:
+ case 105:
case 106:
case 107:
values[n++] = gc->bg - 10;
diff --git a/screen-write.c b/screen-write.c
index 48af1383..3c4d2758 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -27,6 +27,7 @@ static void screen_write_initctx(struct screen_write_ctx *,
struct tty_ctx *);
static void screen_write_save_last(struct screen_write_ctx *,
struct tty_ctx *);
+static void screen_write_flush(struct screen_write_ctx *);
static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int);
@@ -34,25 +35,103 @@ static int screen_write_combine(struct screen_write_ctx *,
const struct utf8_data *);
static const struct grid_cell screen_write_pad_cell = {
- GRID_FLAG_PADDING, 0, { .fg = 8 }, { .bg = 8 }, { { 0 }, 0, 0, 0 }
+ GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
};
-/* Initialise writing with a window. */
+#define screen_dirty_bit(s, x, y) (((y) * screen_size_x(s)) + (x))
+#define screen_dirty_clear(s, sx, sy, ex, ey) \
+ do { \
+ if (s->dirty != NULL) { \
+ bit_nclear(s->dirty, \
+ screen_dirty_bit(s, sx, sy), \
+ screen_dirty_bit(s, ex, ey)); \
+ } \
+ } while (0)
+
+/* Initialize writing with a window. */
void
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
struct screen *s)
{
+ u_int size;
+ char tmp[16];
+ const char *cp = tmp;
+
ctx->wp = wp;
if (wp != NULL && s == NULL)
ctx->s = wp->screen;
else
ctx->s = s;
+
+ size = screen_size_x(ctx->s) * screen_size_y(ctx->s);
+ if (ctx->s->dirtysize != size) {
+ free(ctx->s->dirty);
+ ctx->s->dirty = NULL;
+ ctx->s->dirtysize = size;
+ }
+ ctx->dirty = 0;
+
+ ctx->cells = ctx->written = ctx->skipped = 0;
+
+ if (wp == NULL)
+ cp = "no pane";
+ else
+ snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
+ log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
+ screen_size_y(ctx->s), cp);
}
/* Finish writing. */
void
-screen_write_stop(__unused struct screen_write_ctx *ctx)
+screen_write_stop(struct screen_write_ctx *ctx)
+{
+ screen_write_flush(ctx);
+
+ log_debug("%s: %u of %u written (dirty %u, skipped %u)", __func__,
+ ctx->written, ctx->cells, ctx->cells - ctx->written, ctx->skipped);
+}
+
+/* Flush outstanding cell writes. */
+static void
+screen_write_flush(struct screen_write_ctx *ctx)
{
+ struct screen *s = ctx->s;
+ struct tty_ctx ttyctx;
+ u_int x, y, offset, cx, cy, dirty;
+ struct grid_cell gc;
+
+ if (ctx->dirty == 0)
+ return;
+ dirty = 0;
+
+ cx = s->cx;
+ cy = s->cy;
+
+ offset = 0;
+ for (y = 0; y < screen_size_y(s); y++) {
+ for (x = 0; x < screen_size_x(s); x++) {
+ offset++;
+ if (!bit_test(s->dirty, offset - 1))
+ continue;
+ bit_clear(s->dirty, offset - 1);
+
+ screen_write_cursormove(ctx, x, y);
+ grid_view_get_cell(s->grid, x, y, &gc);
+
+ screen_write_initctx(ctx, &ttyctx);
+ ttyctx.cell = &gc;
+ tty_write(tty_cmd_cell, &ttyctx);
+ ctx->written++;
+
+ if (++dirty == ctx->dirty)
+ break;
+ }
+ if (dirty == ctx->dirty)
+ break;
+ }
+
+ s->cx = cx;
+ s->cy = cy;
}
/* Reset screen state. */
@@ -382,7 +461,6 @@ screen_write_save_last(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
if (~gc.flags & GRID_FLAG_PADDING)
break;
}
- ttyctx->last_width = xx;
memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell);
}
@@ -517,9 +595,12 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
struct tty_ctx ttyctx;
struct grid_cell gc;
u_int xx, yy;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
+ screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
+
memcpy(&gc, &grid_default_cell, sizeof gc);
utf8_set(&gc.data, 'E');
@@ -532,7 +613,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
s->cy = 0;
s->rupper = 0;
-
s->rlower = screen_size_y(s) - 1;
tty_write(tty_cmd_alignmenttest, &ttyctx);
@@ -553,6 +633,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1)
@@ -577,6 +658,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1)
@@ -603,8 +685,11 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
screen_write_initctx(ctx, &ttyctx);
- if (s->cx <= screen_size_x(s) - 1)
+ if (s->cx <= screen_size_x(s) - 1) {
+ screen_dirty_clear(s, s->cx, s->cy, s->cx + nx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, nx, 1);
+ } else
+ return;
ttyctx.num = nx;
tty_write(tty_cmd_clearcharacter, &ttyctx);
@@ -626,6 +711,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
grid_view_insert_lines(s->grid, s->cy, ny);
@@ -640,6 +726,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower)
@@ -667,6 +754,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
grid_view_delete_lines(s->grid, s->cy, ny);
@@ -681,6 +769,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower)
@@ -696,12 +785,19 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
void
screen_write_clearline(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
- struct tty_ctx ttyctx;
+ struct screen *s = ctx->s;
+ struct grid_line *gl;
+ struct tty_ctx ttyctx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
+ gl = &s->grid->linedata[s->grid->hsize + s->cy];
+ if (gl->cellsize != 0) {
+ screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
+ grid_view_clear(s->grid, 0, s->cy, sx, 1);
+ } else
+ return;
tty_write(tty_cmd_clearline, &ttyctx);
}
@@ -710,16 +806,19 @@ screen_write_clearline(struct screen_write_ctx *ctx)
void
screen_write_clearendofline(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
- struct tty_ctx ttyctx;
- u_int sx;
+ struct screen *s = ctx->s;
+ struct grid_line *gl;
+ struct tty_ctx ttyctx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
-
- if (s->cx <= sx - 1)
+ gl = &s->grid->linedata[s->grid->hsize + s->cy];
+ if (s->cx <= sx - 1 && s->cx < gl->cellsize) {
+ screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ } else
+ return;
tty_write(tty_cmd_clearendofline, &ttyctx);
}
@@ -730,16 +829,17 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
-
- if (s->cx > sx - 1)
+ if (s->cx > sx - 1) {
+ screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
- else
+ } else {
+ screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
+ }
tty_write(tty_cmd_clearstartofline, &ttyctx);
}
@@ -768,9 +868,10 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
screen_write_initctx(ctx, &ttyctx);
- if (s->cy == s->rupper)
+ if (s->cy == s->rupper) {
+ screen_write_flush(ctx);
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
- else if (s->cy > 0)
+ } else if (s->cy > 0)
s->cy--;
tty_write(tty_cmd_reverseindex, &ttyctx);
@@ -805,6 +906,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
struct screen *s = ctx->s;
struct grid_line *gl;
struct tty_ctx ttyctx;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
@@ -814,9 +916,11 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
else
gl->flags &= ~GRID_LINE_WRAPPED;
- if (s->cy == s->rlower)
+ if (s->cy == s->rlower) {
+ screen_dirty_clear(s, 0, s->rupper, sx - 1, s->rupper);
+ screen_write_flush(ctx);
grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
- else if (s->cy < screen_size_y(s) - 1)
+ } else if (s->cy < sy - 1)
s->cy++;
ttyctx.num = wrapped;
@@ -838,19 +942,20 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx, sy;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
- sy = screen_size_y(s);
-
/* Scroll into history if it is enabled and clearing entire screen. */
- if (s->cy == 0 && s->grid->flags & GRID_HISTORY)
+ if (s->cy == 0 && s->grid->flags & GRID_HISTORY) {
+ screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
grid_view_clear_history(s->grid);
- else {
- if (s->cx <= sx - 1)
+ } else {
+ if (s->cx <= sx - 1) {
+ screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ }
+ screen_dirty_clear(s, 0, s->cy + 1, sx - 1, sy - 1);
grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
}
@@ -863,18 +968,21 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
-
- if (s->cy > 0)
+ if (s->cy > 0) {
+ screen_dirty_clear(s, 0, 0, sx - 1, s->cy);
grid_view_clear(s->grid, 0, 0, sx, s->cy);
- if (s->cx > sx - 1)
+ }
+ if (s->cx > sx - 1) {
+ screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
- else
+ } else {
+ screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
+ }
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
}
@@ -885,11 +993,12 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx = screen_size_x(s);
- u_int sy = screen_size_y(s);
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
+ screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
+
/* Scroll into history if it is enabled. */
if (s->grid->flags & GRID_HISTORY)
grid_view_clear_history(s->grid);
@@ -918,8 +1027,13 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
struct grid *gd = s->grid;
struct tty_ctx ttyctx;
u_int width, xx, last;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
+ struct grid_line *gl;
struct grid_cell tmp_gc, now_gc;
- int insert, skip, selected;
+ struct grid_cell_entry *gce;
+ int insert, skip, selected, wrapped = 0;
+
+ ctx->cells++;
/* Ignore padding. */
if (gc->flags & GRID_FLAG_PADDING)
@@ -930,10 +1044,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* If this is a wide character and there is no room on the screen, for
* the entire character, don't print it.
*/
- if (!(s->mode & MODE_WRAP)
- && (width > 1 && (width > screen_size_x(s) ||
- (s->cx != screen_size_x(s)
- && s->cx > screen_size_x(s) - width))))
+ if (!(s->mode & MODE_WRAP) && (width > 1 &&
+ (width > sx || (s->cx != sx && s->cx > sx - width))))
return;
/*
@@ -952,8 +1064,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
screen_write_initctx(ctx, &ttyctx);
/* If in insert mode, make space for the cells. */
- if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) {
- xx = screen_size_x(s) - s->cx - width;
+ if ((s->mode & MODE_INSERT) && s->cx <= sx - width) {
+ xx = sx - s->cx - width;
grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
insert = 1;
} else
@@ -961,20 +1073,26 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
skip = !insert;
/* Check this will fit on the current line and wrap if not. */
- if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
+ if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
+ screen_write_flush(ctx);
+ screen_write_save_last(ctx, &ttyctx);
screen_write_linefeed(ctx, 1);
s->cx = 0; /* carriage return */
skip = 0;
+ wrapped = 1;
}
/* Sanity check cursor position. */
- if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1)
+ if (s->cx > sx - width || s->cy > sy - 1)
return;
/* Handle overwriting of UTF-8 characters. */
- grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
- if (screen_write_overwrite(ctx, &now_gc, width))
- skip = 0;
+ gl = &s->grid->linedata[s->grid->hsize + s->cy];
+ if (gl->flags & GRID_LINE_EXTENDED) {
+ grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
+ if (screen_write_overwrite(ctx, &now_gc, width))
+ skip = 0;
+ }
/*
* If the new character is UTF-8 wide, fill in padding cells. Have
@@ -986,8 +1104,25 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
}
/* If no change, do not draw. */
- if (skip)
- skip = (memcmp(&now_gc, gc, sizeof now_gc) == 0);
+ if (skip) {
+ if (s->cx >= gl->cellsize)
+ skip = grid_cells_equal(gc, &grid_default_cell);
+ else {
+ gce = &gl->celldata[s->cx];
+ if (gce->flags & GRID_FLAG_EXTENDED)
+ skip = 0;
+ else if (gc->flags != (gce->flags & ~GRID_FLAG_EXTENDED))
+ skip = 0;
+ else if (gc->attr != gce->data.attr)
+ skip = 0;
+ else if (gc->fg != gce->data.fg)
+ skip = 0;
+ else if (gc->bg != gce->data.bg)
+ skip = 0;
+ else if (gc->data.width != 1 || gce->data.data != gc->data.data[0])
+ skip = 0;
+ }
+ }
/* Update the selection the flag and set the cell. */
selected = screen_check_selection(s, s->cx, s->cy);
@@ -1009,21 +1144,19 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* replace it.
*/
last = !(s->mode & MODE_WRAP);
- if (s->cx <= screen_size_x(s) - last - width)
+ if (s->cx <= sx - last - width)
s->cx += width;
else
- s->cx = screen_size_x(s) - last;
+ s->cx = sx - last;
/* Create space for character in insert mode. */
if (insert) {
+ if (!wrapped)
+ screen_write_flush(ctx);
ttyctx.num = width;
tty_write(tty_cmd_insertcharacter, &ttyctx);
}
- /* Save last cell if it will be needed. */
- if (!skip && ctx->wp != NULL && ttyctx.ocx > ctx->wp->sx - width)
- screen_write_save_last(ctx, &ttyctx);
-
/* Write to the screen. */
if (selected) {
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
@@ -1031,16 +1164,35 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
tmp_gc.flags = gc->flags;
- tmp_gc.flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_BGRGB);
- tmp_gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
- tmp_gc.flags |= s->sel.cell.flags &
- (GRID_FLAG_FG256|GRID_FLAG_BG256);
+ screen_write_flush(ctx);
ttyctx.cell = &tmp_gc;
tty_write(tty_cmd_cell, &ttyctx);
+ ctx->written++;
} else if (!skip) {
- ttyctx.cell = gc;
- tty_write(tty_cmd_cell, &ttyctx);
- }
+ if (wrapped) {
+ ttyctx.cell = gc;
+ tty_write(tty_cmd_cell, &ttyctx);
+ ctx->written++;
+ } else {
+ /*
+ * If wp is NULL, we are not updating the terminal and
+ * don't care about actually writing the cells
+ * (tty_write will just return). So don't even bother
+ * allocating the dirty array.
+ */
+ if (ctx->wp != NULL && s->dirty == NULL) {
+ log_debug("%s: allocating %u bits", __func__,
+ s->dirtysize);
+ s->dirty = bit_alloc(s->dirtysize);
+ }
+ if (s->dirty != NULL) {
+ bit_set(s->dirty, screen_dirty_bit(s,
+ ttyctx.ocx, ttyctx.ocy));
+ ctx->dirty++;
+ }
+ }
+ } else
+ ctx->skipped++;
}
/* Combine a UTF-8 zero-width character onto the previous. */
diff --git a/screen.c b/screen.c
index 4fa8e4c9..f5f39d37 100644
--- a/screen.c
+++ b/screen.c
@@ -38,6 +38,9 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
s->ccolour = xstrdup("");
s->tabs = NULL;
+ s->dirty = NULL;
+ s->dirtysize = 0;
+
screen_reinit(s);
}
@@ -64,6 +67,7 @@ screen_reinit(struct screen *s)
void
screen_free(struct screen *s)
{
+ free(s->dirty);
free(s->tabs);
free(s->title);
free(s->ccolour);
diff --git a/tmux.h b/tmux.h
index f6588afe..f461c495 100644
--- a/tmux.h
+++ b/tmux.h
@@ -60,7 +60,7 @@ struct tmuxproc;
#define NAME_INTERVAL 500000
/* The maximum amount of data to hold from a pty (the event high watermark). */
-#define READ_SIZE 128
+#define READ_SIZE 4096
/* Attribute to make gcc check printf-like arguments. */
#define printflike(a, b) __attribute__ ((format (printf, a, b)))
@@ -625,6 +625,10 @@ enum utf8_state {
UTF8_ERROR
};
+/* Colour flags. */
+#define COLOUR_FLAG_256 0x01000000
+#define COLOUR_FLAG_RGB 0x02000000
+
/* Grid attributes. */
#define GRID_ATTR_BRIGHT 0x1
#define GRID_ATTR_DIM 0x2
@@ -640,32 +644,18 @@ enum utf8_state {
#define GRID_FLAG_BG256 0x2
#define GRID_FLAG_PADDING 0x4
#define GRID_FLAG_EXTENDED 0x8
-#define GRID_FLAG_FGRGB 0x10
-#define GRID_FLAG_BGRGB 0x20
-#define GRID_FLAG_SELECTED 0x40
+#define GRID_FLAG_SELECTED 0x10
/* Grid line flags. */
#define GRID_LINE_WRAPPED 0x1
-
-/* Grid cell RGB colours. */
-struct grid_cell_rgb {
- u_char r;
- u_char g;
- u_char b;
-};
+#define GRID_LINE_EXTENDED 0x2
/* Grid cell data. */
struct grid_cell {
u_char flags;
u_char attr;
- union {
- u_char fg;
- struct grid_cell_rgb fg_rgb;
- };
- union {
- u_char bg;
- struct grid_cell_rgb bg_rgb;
- };
+ int fg;
+ int bg;
struct utf8_data data;
};
@@ -780,30 +770,38 @@ struct screen_sel {
/* Virtual screen. */
struct screen {
- char *title;
+ char *title;
- struct grid *grid; /* grid data */
+ struct grid *grid; /* grid data */
- u_int cx; /* cursor x */
- u_int cy; /* cursor y */
+ u_int cx; /* cursor x */
+ u_int cy; /* cursor y */
- u_int cstyle; /* cursor style */
- char *ccolour; /* cursor colour string */
+ u_int cstyle; /* cursor style */
+ char *ccolour; /* cursor colour string */
- u_int rupper; /* scroll region top */
- u_int rlower; /* scroll region bottom */
+ u_int rupper; /* scroll region top */
+ u_int rlower; /* scroll region bottom */
- int mode;
+ int mode;
- bitstr_t *tabs;
+ bitstr_t *tabs;
- struct screen_sel sel;
+ bitstr_t *dirty;
+ u_int dirtysize;
+
+ struct screen_sel sel;
};
/* Screen write context. */
struct screen_write_ctx {
- struct window_pane *wp;
- struct screen *s;
+ struct window_pane *wp;
+ struct screen *s;
+ u_int dirty;
+
+ u_int cells;
+ u_int written;
+ u_int skipped;
};
/* Screen size. */
@@ -1209,7 +1207,6 @@ struct tty_ctx {
/* Saved last cell on line. */
struct grid_cell last_cell;
- u_int last_width;
};
/* Saved message entry. */
@@ -1981,10 +1978,10 @@ int xterm_keys_find(const char *, size_t, size_t *, key_code *);
/* colour.c */
int colour_find_rgb(u_char, u_char, u_char);
-void colour_set_fg(struct grid_cell *, int);
-void colour_set_bg(struct grid_cell *, int);
+int colour_join_rgb(u_char, u_char, u_char);
+void colour_split_rgb(int, u_char *, u_char *, u_char *);
const char *colour_tostring(int);
-int colour_fromstring(const char *);
+int colour_fromstring(const char *s);
u_char colour_256to16(u_char);
/* attributes.c */
@@ -1993,6 +1990,7 @@ int attributes_fromstring(const char *);
/* grid.c */
extern const struct grid_cell grid_default_cell;
+int grid_cells_equal(const struct grid_cell *, const struct grid_cell *);
struct grid *grid_create(u_int, u_int, u_int);
void grid_destroy(struct grid *);
int grid_compare(struct grid *, struct grid *);
diff --git a/tty.c b/tty.c
index 64c60a5b..b94a18b6 100644
--- a/tty.c
+++ b/tty.c
@@ -36,17 +36,10 @@ static int tty_log_fd = -1;
void tty_read_callback(struct bufferevent *, void *);
void tty_error_callback(struct bufferevent *, short, void *);
-static int tty_same_fg(const struct grid_cell *, const struct grid_cell *);
-static int tty_same_bg(const struct grid_cell *, const struct grid_cell *);
-static int tty_same_colours(const struct grid_cell *, const struct grid_cell *);
-static int tty_is_fg(const struct grid_cell *, int);
-static int tty_is_bg(const struct grid_cell *, int);
-
static int tty_client_ready(struct client *, struct window_pane *);
void tty_set_italics(struct tty *);
-int tty_try_256(struct tty *, u_char, const char *);
-int tty_try_rgb(struct tty *, const struct grid_cell_rgb *, const char *);
+int tty_try_colour(struct tty *, int, const char *);
void tty_colours(struct tty *, const struct grid_cell *);
void tty_check_fg(struct tty *, struct grid_cell *);
@@ -70,74 +63,6 @@ void tty_default_colours(struct grid_cell *, const struct window_pane *);
#define tty_pane_full_width(tty, ctx) \
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
-static int
-tty_same_fg(const struct grid_cell *gc1, const struct grid_cell *gc2)
-{
- int flags1, flags2;
-
- flags1 = (gc1->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
- flags2 = (gc2->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
-
- if (flags1 != flags2)
- return (0);
-
- if (flags1 & GRID_FLAG_FGRGB) {
- if (gc1->fg_rgb.r != gc2->fg_rgb.r)
- return (0);
- if (gc1->fg_rgb.g != gc2->fg_rgb.g)
- return (0);
- if (gc1->fg_rgb.b != gc2->fg_rgb.b)
- return (0);
- return (1);
- }
- return (gc1->fg == gc2->fg);
-}
-
-static int
-tty_same_bg(const struct grid_cell *gc1, const struct grid_cell *gc2)
-{
- int flags1, flags2;
-
- flags1 = (gc1->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
- flags2 = (gc2->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
-
- if (flags1 != flags2)
- return (0);
-
- if (flags1 & GRID_FLAG_BGRGB) {
- if (gc1->bg_rgb.r != gc2->bg_rgb.r)
- return (0);
- if (gc1->bg_rgb.g != gc2->bg_rgb.g)
- return (0);
- if (gc1->bg_rgb.b != gc2->bg_rgb.b)
- return (0);
- return (1);
- }
- return (gc1->bg == gc2->bg);
-}
-
-static int
-tty_same_colours(const struct grid_cell *gc1, const struct grid_cell *gc2)
-{
- return (tty_same_fg(gc1, gc2) && tty_same_bg(gc1, gc2));
-}
-
-static int
-tty_is_fg(const struct grid_cell *gc, int c)
-{
- if (gc->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB))
- return (0);
- return (gc->fg == c);
-}
-
-static int
-tty_is_bg(const struct grid_cell *gc, int c)
-{
- if (gc->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB))
- return (0);
- return (gc->bg == c);
-}
-
void
tty_create_log(void)
{
@@ -679,7 +604,7 @@ tty_fake_bce(const struct tty *tty, const struct window_pane *wp)
if (wp != NULL)
tty_default_colours(&gc, wp);
- if (gc.bg == 8 && !(gc.flags & GRID_FLAG_BG256))
+ if (gc.bg == 8)
return (0);
return (!tty_term_flag(tty->term, TTYC_BCE));
}
@@ -694,7 +619,7 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
- u_int i;
+ u_int i;
/*
* If region is large, schedule a window redraw. In most cases this is
@@ -754,11 +679,6 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
for (i = 0; i < sx; i++) {
grid_view_get_cell(s->grid, i, py, &gc);
- if (screen_check_selection(s, i, py)) {
- gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
- gc.flags |= s->sel.cell.flags &
- (GRID_FLAG_FG256|GRID_FLAG_BG256);
- }
tty_cell(tty, &gc, wp);
}
@@ -1025,7 +945,7 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
- u_int i, j;
+ u_int i, j;
tty_attributes(tty, &grid_default_cell, wp);
@@ -1059,7 +979,7 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
- u_int i, j;
+ u_int i, j;
tty_attributes(tty, &grid_default_cell, wp);
@@ -1087,7 +1007,7 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
- u_int i, j;
+ u_int i, j;
tty_attributes(tty, &grid_default_cell, wp);
@@ -1255,7 +1175,7 @@ tty_reset(struct tty *tty)
{
struct grid_cell *gc = &tty->cell;
- if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
+ if (grid_cells_equal(gc, &grid_default_cell))
return;
if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty))
@@ -1507,10 +1427,10 @@ void
tty_colours(struct tty *tty, const struct grid_cell *gc)
{
struct grid_cell *tc = &tty->cell;
- int have_ax, fg_default, bg_default;
+ int have_ax;
/* No changes? Nothing is necessary. */
- if (tty_same_colours(gc, tc))
+ if (gc->fg == tc->fg && gc->bg == tc->bg)
return;
/*
@@ -1519,9 +1439,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
* case if only one is default need to fall onward to set the other
* colour.
*/
- fg_default = tty_is_fg(gc, 8);
- bg_default = tty_is_bg(gc, 8);
- if (fg_default || bg_default) {
+ if (gc->fg == 8 || gc->bg == 8) {
/*
* If don't have AX but do have op, send sgr0 (op can't
* actually be used because it is sometimes the same as sgr0
@@ -1533,58 +1451,54 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
if (!have_ax && tty_term_has(tty->term, TTYC_OP))
tty_reset(tty);
else {
- if (fg_default && !tty_is_fg(tc, 8)) {
+ if (gc->fg == 8 && tc->fg != 8) {
if (have_ax)
tty_puts(tty, "\033[39m");
- else if (!tty_is_fg(tc, 7))
+ else if (tc->fg != 7)
tty_putcode1(tty, TTYC_SETAF, 7);
tc->fg = 8;
- tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
}
- if (bg_default && !tty_is_bg(tc, 8)) {
+ if (gc->bg == 8 && tc->bg != 8) {
if (have_ax)
tty_puts(tty, "\033[49m");
- else if (!tty_is_bg(tc, 0))
+ else if (tc->bg != 0)
tty_putcode1(tty, TTYC_SETAB, 0);
tc->bg = 8;
- tc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
}
}
}
/* Set the foreground colour. */
- if (!fg_default && !tty_same_fg(gc, tc))
+ if (gc->fg != 8 && gc->fg != tc->fg)
tty_colours_fg(tty, gc);
/*
* Set the background colour. This must come after the foreground as
* tty_colour_fg() can call tty_reset().
*/
- if (!bg_default && !tty_same_bg(gc, tc))
+ if (gc->bg != 8 && gc->bg != tc->bg)
tty_colours_bg(tty, gc);
}
void
tty_check_fg(struct tty *tty, struct grid_cell *gc)
{
- struct grid_cell_rgb *rgb = &gc->fg_rgb;
- u_int colours;
+ u_char r, g, b;
+ u_int colours;
/* Is this a 24-bit colour? */
- if (gc->flags & GRID_FLAG_FGRGB) {
+ if (gc->fg & COLOUR_FLAG_RGB) {
/* Not a 24-bit terminal? Translate to 256-colour palette. */
if (!tty_term_flag(tty->term, TTYC_TC)) {
- gc->flags &= ~GRID_FLAG_FGRGB;
- gc->flags |= GRID_FLAG_FG256;
- gc->fg = colour_find_rgb(rgb->r, rgb->g, rgb->b);
- }
- else
+ colour_split_rgb(gc->fg, &r, &g, &b);
+ gc->fg = colour_find_rgb(r, g, b);
+ } else
return;
}
colours = tty_term_number(tty->term, TTYC_COLORS);
/* Is this a 256-colour colour? */
- if (gc->flags & GRID_FLAG_FG256) {
+ if (gc->fg & COLOUR_FLAG_256) {
/* And not a 256 colour mode? */
if (!(tty->term->flags & TERM_256COLOURS) &&
!(tty->term_flags & TERM_256COLOURS)) {
@@ -1597,7 +1511,6 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
gc->attr |= GRID_ATTR_BRIGHT;
} else
gc->attr &= ~GRID_ATTR_BRIGHT;
- gc->flags &= ~GRID_FLAG_FG256;
}
return;
}
@@ -1612,24 +1525,22 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
void
tty_check_bg(struct tty *tty, struct grid_cell *gc)
{
- struct grid_cell_rgb *rgb = &gc->bg_rgb;
- u_int colours;
+ u_char r, g, b;
+ u_int colours;
/* Is this a 24-bit colour? */
- if (gc->flags & GRID_FLAG_BGRGB) {
+ if (gc->bg & COLOUR_FLAG_RGB) {
/* Not a 24-bit terminal? Translate to 256-colour palette. */
if (!tty_term_flag(tty->term, TTYC_TC)) {
- gc->flags &= ~GRID_FLAG_BGRGB;
- gc->flags |= GRID_FLAG_BG256;
- gc->bg = colour_find_rgb(rgb->r, rgb->g, rgb->b);
- }
- else
+ colour_split_rgb(gc->bg, &r, &g, &b);
+ gc->bg = colour_find_rgb(r, g, b);
+ } else
return;
}
colours = tty_term_number(tty->term, TTYC_COLORS);
/* Is this a 256-colour colour? */
- if (gc->flags & GRID_FLAG_BG256) {
+ if (gc->bg & COLOUR_FLAG_256) {
/*
* And not a 256 colour mode? Translate to 16-colour
* palette. Bold background doesn't exist portably, so just
@@ -1643,7 +1554,6 @@ tty_check_bg(struct tty *tty, struct grid_cell *gc)
if (colours >= 16)
gc->fg += 90;
}
- gc->flags &= ~GRID_FLAG_BG256;
}
return;
}
@@ -1657,137 +1567,111 @@ void
tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
{
struct grid_cell *tc = &tty->cell;
- u_char fg = gc->fg;
char s[32];
- tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
-
- /* Is this a 24-bit colour? */
- if (gc->flags & GRID_FLAG_FGRGB) {
- if (tty_try_rgb(tty, &gc->fg_rgb, "38") == 0)
- goto save_fg;
- /* Should not get here, already converted in tty_check_fg. */
- return;
- }
-
- /* Is this a 256-colour colour? */
- if (gc->flags & GRID_FLAG_FG256) {
- if (tty_try_256(tty, fg, "38") == 0)
+ /* Is this a 24-bit or 256-colour colour? */
+ if (gc->fg & COLOUR_FLAG_RGB ||
+ gc->fg & COLOUR_FLAG_256) {
+ if (tty_try_colour(tty, gc->fg, "38") == 0)
goto save_fg;
/* Should not get here, already converted in tty_check_fg. */
return;
}
/* Is this an aixterm bright colour? */
- if (fg >= 90 && fg <= 97) {
- xsnprintf(s, sizeof s, "\033[%dm", fg);
+ if (gc->fg >= 90 && gc->fg <= 97) {
+ xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
tty_puts(tty, s);
goto save_fg;
}
/* Otherwise set the foreground colour. */
- tty_putcode1(tty, TTYC_SETAF, fg);
+ tty_putcode1(tty, TTYC_SETAF, gc->fg);
save_fg:
/* Save the new values in the terminal current cell. */
- if (gc->flags & GRID_FLAG_FGRGB)
- memcpy(&tc->fg_rgb, &gc->fg_rgb, sizeof tc->fg_rgb);
- else
- tc->fg = fg;
- tc->flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_FG256);
- tc->flags |= (gc->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
+ tc->fg = gc->fg;
}
void
tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
{
struct grid_cell *tc = &tty->cell;
- u_char bg = gc->bg;
char s[32];
- /* Is this a 24-bit colour? */
- if (gc->flags & GRID_FLAG_BGRGB) {
- if (tty_try_rgb(tty, &gc->bg_rgb, "48") == 0)
- goto save_bg;
- /* Should not get here, already converted in tty_check_bg. */
- return;
- }
-
- /* Is this a 256-colour colour? */
- if (gc->flags & GRID_FLAG_BG256) {
- if (tty_try_256(tty, bg, "48") == 0)
+ /* Is this a 24-bit or 256-colour colour? */
+ if (gc->bg & COLOUR_FLAG_RGB ||
+ gc->bg & COLOUR_FLAG_256) {
+ if (tty_try_colour(tty, gc->bg, "48") == 0)
goto save_bg;
/* Should not get here, already converted in tty_check_bg. */
return;
}
/* Is this an aixterm bright colour? */
- if (bg >= 90 && bg <= 97) {
- xsnprintf(s, sizeof s, "\033[%dm", bg + 10);
+ if (gc->bg >= 90 && gc->bg <= 97) {
+ xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
tty_puts(tty, s);
goto save_bg;
}
/* Otherwise set the background colour. */
- tty_putcode1(tty, TTYC_SETAB, bg);
+ tty_putcode1(tty, TTYC_SETAB, gc->bg);
save_bg:
/* Save the new values in the terminal current cell. */
- if (gc->flags & GRID_FLAG_BGRGB)
- memcpy(&tc->bg_rgb, &gc->bg_rgb, sizeof tc->bg_rgb);
- else
- tc->bg = bg;
- tc->flags &= ~(GRID_FLAG_BGRGB|GRID_FLAG_BG256);
- tc->flags |= (gc->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
+ tc->bg = gc->bg;
}
int
-tty_try_256(struct tty *tty, u_char colour, const char *type)
+tty_try_colour(struct tty *tty, int colour, const char *type)
{
+ u_char r, g, b;
char s[32];
- /*
- * If the user has specified -2 to the client, setaf and setab may not
- * work (or they may not want to use them), so send the usual sequence.
- */
- if (tty->term_flags & TERM_256COLOURS)
- goto fallback;
+ if (colour & COLOUR_FLAG_256) {
+ /*
+ * If the user has specified -2 to the client, setaf and setab
+ * may not work (or they may not want to use them), so send the
+ * usual sequence.
+ */
+ if (tty->term_flags & TERM_256COLOURS)
+ goto fallback_256;
- /*
- * If the terminfo entry has 256 colours and setaf and setab exist,
- * assume that they work correctly.
- */
- if (tty->term->flags & TERM_256COLOURS) {
- if (*type == '3') {
- if (!tty_term_has(tty->term, TTYC_SETAF))
- goto fallback;
- tty_putcode1(tty, TTYC_SETAF, colour);
- } else {
- if (!tty_term_has(tty->term, TTYC_SETAB))
- goto fallback;
- tty_putcode1(tty, TTYC_SETAB, colour);
+ /*
+ * If the terminfo entry has 256 colours and setaf and setab
+ * exist, assume that they work correctly.
+ */
+ if (tty->term->flags & TERM_256COLOURS) {
+ if (*type == '3') {
+ if (!tty_term_has(tty->term, TTYC_SETAF))
+ goto fallback_256;
+ tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
+ } else {
+ if (!tty_term_has(tty->term, TTYC_SETAB))
+ goto fallback_256;
+ tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
+ }
+ return (0);
}
- return (0);
+ goto fallback_256;
}
- return (-1);
-
-fallback:
- xsnprintf(s, sizeof s, "\033[%s;5;%hhum", type, colour);
- tty_puts(tty, s);
- return (0);
-}
+ if (colour & COLOUR_FLAG_RGB) {
+ if (!tty_term_flag(tty->term, TTYC_TC))
+ return (-1);
-int
-tty_try_rgb(struct tty *tty, const struct grid_cell_rgb *rgb, const char *type)
-{
- char s[32];
+ colour_split_rgb(colour & 0xffffff, &r, &g, &b);
+ xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type,
+ r, g, b);
+ tty_puts(tty, s);
+ return (0);
+ }
- if (!tty_term_flag(tty->term, TTYC_TC))
- return (-1);
+ return (-1);
- xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type, rgb->r,
- rgb->g, rgb->b);
+fallback_256:
+ xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
tty_puts(tty, s);
return (0);
}
@@ -1811,31 +1695,21 @@ tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
}
pgc = &wp->colgc;
- if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) {
- if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) {
+ if (gc->fg == 8) {
+ if (pgc->fg != 8)
gc->fg = pgc->fg;
- gc->flags |= (pgc->flags & GRID_FLAG_FG256);
- } else if (wp == w->active &&
- (agc->fg != 8 || (agc->flags & GRID_FLAG_FG256))) {
+ else if (wp == w->active && agc->fg != 8)
gc->fg = agc->fg;
- gc->flags |= (agc->flags & GRID_FLAG_FG256);
- } else {
+ else
gc->fg = wgc->fg;
- gc->flags |= (wgc->flags & GRID_FLAG_FG256);
- }
}
- if (gc->bg == 8 && !(gc->flags & GRID_FLAG_BG256)) {
- if (pgc->bg != 8 || (pgc->flags & GRID_FLAG_BG256)) {
+ if (gc->bg == 8) {
+ if (pgc->bg != 8)
gc->bg = pgc->bg;
- gc->flags |= (pgc->flags & GRID_FLAG_BG256);
- } else if (wp == w->active &&
- (agc->bg != 8 || (agc->flags & GRID_FLAG_BG256))) {
+ else if (wp == w->active && agc->bg != 8)
gc->bg = agc->bg;
- gc->flags |= (agc->flags & GRID_FLAG_BG256);
- } else {
+ else
gc->bg = wgc->bg;
- gc->flags |= (wgc->flags & GRID_FLAG_BG256);
- }
}
}