Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam 2016-07-15 04:01:12 +01:00
commit d4eeeb5498
10 changed files with 468 additions and 475 deletions

View File

@ -67,7 +67,7 @@ colour_find_rgb(u_char r, u_char g, u_char b)
/* If we have hit the colour exactly, return early. */ /* If we have hit the colour exactly, return early. */
if (cr == r && cg == g && cb == b) if (cr == r && cg == g && cb == b)
return (16 + (36 * qr) + (6 * qg) + qb); return ((16 + (36 * qr) + (6 * qg) + qb) | COLOUR_FLAG_256);
/* Work out the closest grey (average of RGB). */ /* Work out the closest grey (average of RGB). */
grey_avg = (r + g + b) / 3; grey_avg = (r + g + b) / 3;
@ -83,25 +83,25 @@ colour_find_rgb(u_char r, u_char g, u_char b)
idx = 232 + grey_idx; idx = 232 + grey_idx;
else else
idx = 16 + (36 * qr) + (6 * qg) + qb; idx = 16 + (36 * qr) + (6 * qg) + qb;
return (idx); return (idx | COLOUR_FLAG_256);
} }
/* Set grid cell foreground colour. */ /* Join RGB into a colour. */
void int
colour_set_fg(struct grid_cell *gc, int c) colour_join_rgb(u_char r, u_char g, u_char b)
{ {
if (c & 0x100) return ((((int)((r) & 0xff)) << 16) |
gc->flags |= GRID_FLAG_FG256; (((int)((g) & 0xff)) << 8) |
gc->fg = c; (((int)((b) & 0xff))) | COLOUR_FLAG_RGB);
} }
/* Set grid cell background colour. */ /* Split colour into RGB. */
void void
colour_set_bg(struct grid_cell *gc, int c) colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
{ {
if (c & 0x100) *r = (c >> 16) & 0xff;
gc->flags |= GRID_FLAG_BG256; *g = (c >> 8) & 0xff;
gc->bg = c; *b = c & 0xff;
} }
/* Convert colour to a string. */ /* Convert colour to a string. */
@ -109,9 +109,16 @@ const char *
colour_tostring(int c) colour_tostring(int c)
{ {
static char s[32]; static char s[32];
u_char r, g, b;
if (c & 0x100) { if (c & COLOUR_FLAG_RGB) {
xsnprintf(s, sizeof s, "colour%d", c & ~0x100); colour_split_rgb(c, &r, &g, &b);
xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
return (s);
}
if (c & COLOUR_FLAG_256) {
xsnprintf(s, sizeof s, "colour%u", c & 0xff);
return (s); return (s);
} }
@ -171,14 +178,14 @@ colour_fromstring(const char *s)
n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b); n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
if (n != 3) if (n != 3)
return (-1); return (-1);
return (colour_find_rgb(r, g, b) | 0x100); return (colour_join_rgb(r, g, b));
} }
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) { if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr); n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
if (errstr != NULL) if (errstr != NULL)
return (-1); return (-1);
return (n | 0x100); return (n | COLOUR_FLAG_256);
} }
if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0) if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)

74
grid.c
View File

@ -37,14 +37,12 @@
/* Default grid cell data. */ /* Default grid cell data. */
const struct grid_cell grid_default_cell = { 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 = { const struct grid_cell_entry grid_default_entry = {
0, { .data = { 0, 8, 8, ' ' } } 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, void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *l,
u_int, u_int); u_int, u_int);
void grid_reflow_join(struct grid *, u_int *, struct grid_line *, 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. */ /* Check grid y position. */
int static int
grid_check_y(struct grid *gd, u_int py) grid_check_y(struct grid *gd, u_int py)
{ {
if ((py) >= (gd)->hsize + (gd)->sy) { if ((py) >= (gd)->hsize + (gd)->sy) {
@ -74,6 +72,21 @@ grid_check_y(struct grid *gd, u_int py)
return (0); 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. */ /* Create a new grid. */
struct grid * struct grid *
grid_create(u_int sx, u_int sy, u_int hlimit) 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++) { for (xx = 0; xx < gla->cellsize; xx++) {
grid_get_cell(ga, xx, yy, &gca); grid_get_cell(ga, xx, yy, &gca);
grid_get_cell(gb, xx, yy, &gcb); grid_get_cell(gb, xx, yy, &gcb);
if (memcmp(&gca, &gcb, sizeof (struct grid_cell)) != 0) if (!grid_cells_equal(&gca, &gcb))
return (1); return (1);
} }
} }
@ -270,10 +283,14 @@ grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
return; return;
} }
gc->flags = gce->flags & ~GRID_FLAG_EXTENDED; gc->flags = gce->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
gc->attr = gce->data.attr; gc->attr = gce->data.attr;
gc->fg = gce->data.fg; gc->fg = gce->data.fg;
if (gce->flags & GRID_FLAG_FG256)
gc->fg |= COLOUR_FLAG_256;
gc->bg = gce->data.bg; gc->bg = gce->data.bg;
if (gce->flags & GRID_FLAG_BG256)
gc->bg |= COLOUR_FLAG_256;
utf8_set(&gc->data, gce->data.data); 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); extended = (gce->flags & GRID_FLAG_EXTENDED);
if (!extended && (gc->data.size != 1 || gc->data.width != 1)) if (!extended && (gc->data.size != 1 || gc->data.width != 1))
extended = 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; extended = 1;
if (extended) { if (extended) {
gl->flags |= GRID_LINE_EXTENDED;
if (~gce->flags & GRID_FLAG_EXTENDED) { if (~gce->flags & GRID_FLAG_EXTENDED) {
gl->extddata = xreallocarray(gl->extddata, gl->extddata = xreallocarray(gl->extddata,
gl->extdsize + 1, sizeof *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; return;
} }
gce->flags = gc->flags & ~GRID_FLAG_EXTENDED; gce->flags = gc->flags;
gce->data.attr = gc->attr; gce->data.attr = gc->attr;
gce->data.fg = gc->fg; gce->data.fg = gc->fg & 0xff;
gce->data.bg = gc->bg; 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]; gce->data.data = gc->data.data[0];
} }
@ -446,18 +470,20 @@ size_t
grid_string_cells_fg(const struct grid_cell *gc, int *values) grid_string_cells_fg(const struct grid_cell *gc, int *values)
{ {
size_t n; size_t n;
u_char r, g, b;
n = 0; n = 0;
if (gc->flags & GRID_FLAG_FG256) { if (gc->fg & COLOUR_FLAG_256) {
values[n++] = 38; values[n++] = 38;
values[n++] = 5; values[n++] = 5;
values[n++] = gc->fg; values[n++] = gc->fg & 0xff;
} else if (gc->flags & GRID_FLAG_FGRGB) { } else if (gc->fg & COLOUR_FLAG_RGB) {
values[n++] = 38; values[n++] = 38;
values[n++] = 2; values[n++] = 2;
values[n++] = gc->fg_rgb.r; colour_split_rgb(gc->fg, &r, &g, &b);
values[n++] = gc->fg_rgb.g; values[n++] = r;
values[n++] = gc->fg_rgb.b; values[n++] = g;
values[n++] = b;
} else { } else {
switch (gc->fg) { switch (gc->fg) {
case 0: case 0:
@ -493,18 +519,20 @@ size_t
grid_string_cells_bg(const struct grid_cell *gc, int *values) grid_string_cells_bg(const struct grid_cell *gc, int *values)
{ {
size_t n; size_t n;
u_char r, g, b;
n = 0; n = 0;
if (gc->flags & GRID_FLAG_BG256) { if (gc->bg & COLOUR_FLAG_256) {
values[n++] = 48; values[n++] = 48;
values[n++] = 5; values[n++] = 5;
values[n++] = gc->bg; values[n++] = gc->bg & 0xff;
} else if (gc->flags & GRID_FLAG_BGRGB) { } else if (gc->bg & COLOUR_FLAG_RGB) {
values[n++] = 48; values[n++] = 48;
values[n++] = 2; values[n++] = 2;
values[n++] = gc->bg_rgb.r; colour_split_rgb(gc->bg, &r, &g, &b);
values[n++] = gc->bg_rgb.g; values[n++] = r;
values[n++] = gc->bg_rgb.b; values[n++] = g;
values[n++] = b;
} else { } else {
switch (gc->bg) { switch (gc->bg) {
case 0: case 0:
@ -525,7 +553,7 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values)
case 102: case 102:
case 103: case 103:
case 104: case 104:
case 105: case 105:
case 106: case 106:
case 107: case 107:
values[n++] = gc->bg - 10; values[n++] = gc->bg - 10;

43
input.c
View File

@ -1628,23 +1628,15 @@ input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
(*i)++; (*i)++;
c = input_get(ictx, *i, 0, -1); c = input_get(ictx, *i, 0, -1);
if (c == -1) { if (c == -1) {
if (fgbg == 38) { if (fgbg == 38)
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = 8; gc->fg = 8;
} else if (fgbg == 48) { else if (fgbg == 48)
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = 8; gc->bg = 8;
}
} else { } else {
if (fgbg == 38) { if (fgbg == 38)
gc->flags |= GRID_FLAG_FG256; gc->fg = c | COLOUR_FLAG_256;
gc->flags &= ~GRID_FLAG_FGRGB; else if (fgbg == 48)
gc->fg = c; gc->bg = c | COLOUR_FLAG_256;
} else if (fgbg == 48) {
gc->flags |= GRID_FLAG_BG256;
gc->flags &= ~GRID_FLAG_BGRGB;
gc->bg = c;
}
} }
} }
@ -1668,19 +1660,10 @@ input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
if (b == -1 || b > 255) if (b == -1 || b > 255)
return; return;
if (fgbg == 38) { if (fgbg == 38)
gc->flags &= ~GRID_FLAG_FG256; gc->fg = colour_join_rgb(r, g, b);
gc->flags |= GRID_FLAG_FGRGB; else if (fgbg == 48)
gc->fg_rgb.r = r; gc->bg = colour_join_rgb(r, g, b);
gc->fg_rgb.g = g;
gc->fg_rgb.b = b;
} else if (fgbg == 48) {
gc->flags &= ~GRID_FLAG_BG256;
gc->flags |= GRID_FLAG_BGRGB;
gc->bg_rgb.r = r;
gc->bg_rgb.g = g;
gc->bg_rgb.b = b;
}
} }
/* Handle CSI SGR. */ /* Handle CSI SGR. */
@ -1761,11 +1744,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 35: case 35:
case 36: case 36:
case 37: case 37:
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = n - 30; gc->fg = n - 30;
break; break;
case 39: case 39:
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = 8; gc->fg = 8;
break; break;
case 40: case 40:
@ -1776,11 +1757,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 45: case 45:
case 46: case 46:
case 47: case 47:
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = n - 40; gc->bg = n - 40;
break; break;
case 49: case 49:
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = 8; gc->bg = 8;
break; break;
case 90: case 90:
@ -1791,7 +1770,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 95: case 95:
case 96: case 96:
case 97: case 97:
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = n; gc->fg = n;
break; break;
case 100: case 100:
@ -1802,7 +1780,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 105: case 105:
case 106: case 106:
case 107: case 107:
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = n - 10; gc->bg = n - 10;
break; break;
} }

View File

@ -552,9 +552,9 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp) if (w->active == wp)
colour_set_bg(&gc, active_colour); gc.bg = active_colour;
else else
colour_set_bg(&gc, colour); gc.bg = colour;
tty_attributes(tty, &gc, wp); tty_attributes(tty, &gc, wp);
for (ptr = buf; *ptr != '\0'; ptr++) { for (ptr = buf; *ptr != '\0'; ptr++) {
if (*ptr < '0' || *ptr > '9') if (*ptr < '0' || *ptr > '9')
@ -579,9 +579,9 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
draw_text: draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp) if (w->active == wp)
colour_set_fg(&gc, active_colour); gc.fg = active_colour;
else else
colour_set_fg(&gc, colour); gc.fg = colour;
tty_attributes(tty, &gc, wp); tty_attributes(tty, &gc, wp);
tty_puts(tty, buf); tty_puts(tty, buf);

View File

@ -27,6 +27,7 @@ static void screen_write_initctx(struct screen_write_ctx *,
struct tty_ctx *); struct tty_ctx *);
static void screen_write_save_last(struct screen_write_ctx *, static void screen_write_save_last(struct screen_write_ctx *,
struct tty_ctx *); struct tty_ctx *);
static void screen_write_flush(struct screen_write_ctx *);
static int screen_write_overwrite(struct screen_write_ctx *, static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int); struct grid_cell *, u_int);
@ -34,25 +35,103 @@ static int screen_write_combine(struct screen_write_ctx *,
const struct utf8_data *); const struct utf8_data *);
static const struct grid_cell screen_write_pad_cell = { 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 void
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp, screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
struct screen *s) struct screen *s)
{ {
u_int size;
char tmp[16];
const char *cp = tmp;
ctx->wp = wp; ctx->wp = wp;
if (wp != NULL && s == NULL) if (wp != NULL && s == NULL)
ctx->s = wp->screen; ctx->s = wp->screen;
else else
ctx->s = s; 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. */ /* Finish writing. */
void 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. */ /* 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) if (~gc.flags & GRID_FLAG_PADDING)
break; break;
} }
ttyctx->last_width = xx;
memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell); 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 tty_ctx ttyctx;
struct grid_cell gc; struct grid_cell gc;
u_int xx, yy; u_int xx, yy;
u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
utf8_set(&gc.data, 'E'); utf8_set(&gc.data, 'E');
@ -532,7 +613,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
s->cy = 0; s->cy = 0;
s->rupper = 0; s->rupper = 0;
s->rlower = screen_size_y(s) - 1; s->rlower = screen_size_y(s) - 1;
tty_write(tty_cmd_alignmenttest, &ttyctx); tty_write(tty_cmd_alignmenttest, &ttyctx);
@ -553,6 +633,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0) if (nx == 0)
return; return;
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1) 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) if (nx == 0)
return; return;
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1) 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); 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); grid_view_clear(s->grid, s->cx, s->cy, nx, 1);
} else
return;
ttyctx.num = nx; ttyctx.num = nx;
tty_write(tty_cmd_clearcharacter, &ttyctx); tty_write(tty_cmd_clearcharacter, &ttyctx);
@ -626,6 +711,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0) if (ny == 0)
return; return;
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
grid_view_insert_lines(s->grid, s->cy, ny); 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) if (ny == 0)
return; return;
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower) 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) if (ny == 0)
return; return;
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
grid_view_delete_lines(s->grid, s->cy, ny); 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) if (ny == 0)
return; return;
screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower) 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 void
screen_write_clearline(struct screen_write_ctx *ctx) screen_write_clearline(struct screen_write_ctx *ctx)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct grid_line *gl;
struct tty_ctx ttyctx;
u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx); 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); tty_write(tty_cmd_clearline, &ttyctx);
} }
@ -710,16 +806,19 @@ screen_write_clearline(struct screen_write_ctx *ctx)
void void
screen_write_clearendofline(struct screen_write_ctx *ctx) screen_write_clearendofline(struct screen_write_ctx *ctx)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct grid_line *gl;
u_int sx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
sx = screen_size_x(s); gl = &s->grid->linedata[s->grid->hsize + s->cy];
if (s->cx <= sx - 1 && s->cx < gl->cellsize) {
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); grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
} else
return;
tty_write(tty_cmd_clearendofline, &ttyctx); tty_write(tty_cmd_clearendofline, &ttyctx);
} }
@ -730,16 +829,17 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx; u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
sx = screen_size_x(s); if (s->cx > sx - 1) {
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
if (s->cx > sx - 1)
grid_view_clear(s->grid, 0, s->cy, sx, 1); 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); grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
}
tty_write(tty_cmd_clearstartofline, &ttyctx); tty_write(tty_cmd_clearstartofline, &ttyctx);
} }
@ -768,9 +868,10 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
screen_write_initctx(ctx, &ttyctx); 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); grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
else if (s->cy > 0) } else if (s->cy > 0)
s->cy--; s->cy--;
tty_write(tty_cmd_reverseindex, &ttyctx); 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 screen *s = ctx->s;
struct grid_line *gl; struct grid_line *gl;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
@ -814,9 +916,11 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
else else
gl->flags &= ~GRID_LINE_WRAPPED; 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); 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++; s->cy++;
ttyctx.num = wrapped; ttyctx.num = wrapped;
@ -838,19 +942,20 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; 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); 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. */ /* 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); grid_view_clear_history(s->grid);
else { } else {
if (s->cx <= sx - 1) 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); 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)); 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 screen *s = ctx->s;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx; u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
sx = screen_size_x(s); if (s->cy > 0) {
screen_dirty_clear(s, 0, 0, sx - 1, s->cy);
if (s->cy > 0)
grid_view_clear(s->grid, 0, 0, sx, 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); 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); grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
}
tty_write(tty_cmd_clearstartofscreen, &ttyctx); tty_write(tty_cmd_clearstartofscreen, &ttyctx);
} }
@ -885,11 +993,12 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s); u_int sx = screen_size_x(s), sy = screen_size_y(s);
u_int sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
/* Scroll into history if it is enabled. */ /* Scroll into history if it is enabled. */
if (s->grid->flags & GRID_HISTORY) if (s->grid->flags & GRID_HISTORY)
grid_view_clear_history(s->grid); 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 grid *gd = s->grid;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int width, xx, last; 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; 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. */ /* Ignore padding. */
if (gc->flags & GRID_FLAG_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 * If this is a wide character and there is no room on the screen, for
* the entire character, don't print it. * the entire character, don't print it.
*/ */
if (!(s->mode & MODE_WRAP) if (!(s->mode & MODE_WRAP) && (width > 1 &&
&& (width > 1 && (width > screen_size_x(s) || (width > sx || (s->cx != sx && s->cx > sx - width))))
(s->cx != screen_size_x(s)
&& s->cx > screen_size_x(s) - width))))
return; return;
/* /*
@ -952,8 +1064,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
screen_write_initctx(ctx, &ttyctx); screen_write_initctx(ctx, &ttyctx);
/* If in insert mode, make space for the cells. */ /* If in insert mode, make space for the cells. */
if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) { if ((s->mode & MODE_INSERT) && s->cx <= sx - width) {
xx = screen_size_x(s) - s->cx - width; xx = sx - s->cx - width;
grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx); grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
insert = 1; insert = 1;
} else } else
@ -961,20 +1073,26 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
skip = !insert; skip = !insert;
/* Check this will fit on the current line and wrap if not. */ /* 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); screen_write_linefeed(ctx, 1);
s->cx = 0; /* carriage return */ s->cx = 0; /* carriage return */
skip = 0; skip = 0;
wrapped = 1;
} }
/* Sanity check cursor position. */ /* 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; return;
/* Handle overwriting of UTF-8 characters. */ /* Handle overwriting of UTF-8 characters. */
grid_view_get_cell(gd, s->cx, s->cy, &now_gc); gl = &s->grid->linedata[s->grid->hsize + s->cy];
if (screen_write_overwrite(ctx, &now_gc, width)) if (gl->flags & GRID_LINE_EXTENDED) {
skip = 0; 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 * 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 no change, do not draw. */
if (skip) if (skip) {
skip = (memcmp(&now_gc, gc, sizeof now_gc) == 0); 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. */ /* Update the selection the flag and set the cell. */
selected = screen_check_selection(s, s->cx, s->cy); 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. * replace it.
*/ */
last = !(s->mode & MODE_WRAP); last = !(s->mode & MODE_WRAP);
if (s->cx <= screen_size_x(s) - last - width) if (s->cx <= sx - last - width)
s->cx += width; s->cx += width;
else else
s->cx = screen_size_x(s) - last; s->cx = sx - last;
/* Create space for character in insert mode. */ /* Create space for character in insert mode. */
if (insert) { if (insert) {
if (!wrapped)
screen_write_flush(ctx);
ttyctx.num = width; ttyctx.num = width;
tty_write(tty_cmd_insertcharacter, &ttyctx); 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. */ /* Write to the screen. */
if (selected) { if (selected) {
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); 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 = tmp_gc.attr & ~GRID_ATTR_CHARSET;
tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET; tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
tmp_gc.flags = gc->flags; tmp_gc.flags = gc->flags;
tmp_gc.flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_BGRGB); screen_write_flush(ctx);
tmp_gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
tmp_gc.flags |= s->sel.cell.flags &
(GRID_FLAG_FG256|GRID_FLAG_BG256);
ttyctx.cell = &tmp_gc; ttyctx.cell = &tmp_gc;
tty_write(tty_cmd_cell, &ttyctx); tty_write(tty_cmd_cell, &ttyctx);
ctx->written++;
} else if (!skip) { } else if (!skip) {
ttyctx.cell = gc; if (wrapped) {
tty_write(tty_cmd_cell, &ttyctx); 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. */ /* Combine a UTF-8 zero-width character onto the previous. */

View File

@ -38,6 +38,9 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
s->ccolour = xstrdup(""); s->ccolour = xstrdup("");
s->tabs = NULL; s->tabs = NULL;
s->dirty = NULL;
s->dirtysize = 0;
screen_reinit(s); screen_reinit(s);
} }
@ -64,6 +67,7 @@ screen_reinit(struct screen *s)
void void
screen_free(struct screen *s) screen_free(struct screen *s)
{ {
free(s->dirty);
free(s->tabs); free(s->tabs);
free(s->title); free(s->title);
free(s->ccolour); free(s->ccolour);

105
style.c
View File

@ -33,7 +33,8 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
char tmp[32]; char tmp[32];
int val; int val;
size_t end; size_t end;
u_char fg, bg, attr, flags; int fg, bg;
u_char attr, flags;
if (*in == '\0') if (*in == '\0')
return (0); return (0);
@ -56,38 +57,20 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
fg = defgc->fg; fg = defgc->fg;
bg = defgc->bg; bg = defgc->bg;
attr = defgc->attr; attr = defgc->attr;
flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256); flags = defgc->flags;
flags |=
defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) { } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
if ((val = colour_fromstring(tmp + 3)) == -1) if ((val = colour_fromstring(tmp + 3)) == -1)
goto error; goto error;
if (*in == 'f' || *in == 'F') { if (*in == 'f' || *in == 'F') {
if (val != 8) { if (val != 8)
if (val & 0x100) {
flags |= GRID_FLAG_FG256;
val &= ~0x100;
} else
flags &= ~GRID_FLAG_FG256;
fg = val; fg = val;
} else { else
fg = defgc->fg; fg = defgc->fg;
flags &= ~GRID_FLAG_FG256;
flags |= defgc->flags & GRID_FLAG_FG256;
}
} else if (*in == 'b' || *in == 'B') { } else if (*in == 'b' || *in == 'B') {
if (val != 8) { if (val != 8)
if (val & 0x100) {
flags |= GRID_FLAG_BG256;
val &= ~0x100;
} else
flags &= ~GRID_FLAG_BG256;
bg = val; bg = val;
} else { else
bg = defgc->bg; bg = defgc->bg;
flags &= ~GRID_FLAG_BG256;
flags |= defgc->flags & GRID_FLAG_BG256;
}
} else } else
goto error; goto error;
} else if (strcasecmp(tmp, "none") == 0) } else if (strcasecmp(tmp, "none") == 0)
@ -120,27 +103,19 @@ error:
const char * const char *
style_tostring(struct grid_cell *gc) style_tostring(struct grid_cell *gc)
{ {
int c, off = 0, comma = 0; int off = 0, comma = 0;
static char s[256]; static char s[256];
*s = '\0'; *s = '\0';
if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) { if (gc->fg != 8) {
if (gc->flags & GRID_FLAG_FG256) off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(gc->fg));
c = gc->fg | 0x100;
else
c = gc->fg;
off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
comma = 1; comma = 1;
} }
if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) { if (gc->bg != 8) {
if (gc->flags & GRID_FLAG_BG256)
c = gc->bg | 0x100;
else
c = gc->bg;
off += xsnprintf(s + off, sizeof s - off, "%sbg=%s", off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
comma ? "," : "", colour_tostring(c)); comma ? "," : "", colour_tostring(gc->bg));
comma = 1; comma = 1;
} }
@ -177,9 +152,9 @@ style_update_new(struct options *oo, const char *name, const char *newname)
value = o->num; value = o->num;
if (strstr(name, "-bg") != NULL) if (strstr(name, "-bg") != NULL)
colour_set_bg(gc, value); gc->bg = value;
else if (strstr(name, "-fg") != NULL) else if (strstr(name, "-fg") != NULL)
colour_set_fg(gc, value); gc->fg = value;
else if (strstr(name, "-attr") != NULL) else if (strstr(name, "-attr") != NULL)
gc->attr = value; gc->attr = value;
} }
@ -189,23 +164,15 @@ void
style_update_old(struct options *oo, const char *name, struct grid_cell *gc) style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
{ {
char newname[128]; char newname[128];
int c, size; int size;
size = strrchr(name, '-') - name; size = strrchr(name, '-') - name;
if (gc->flags & GRID_FLAG_BG256)
c = gc->bg | 0x100;
else
c = gc->bg;
xsnprintf(newname, sizeof newname, "%.*s-bg", size, name); xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
options_set_number(oo, newname, c); options_set_number(oo, newname, gc->bg);
if (gc->flags & GRID_FLAG_FG256)
c = gc->fg | 0x100;
else
c = gc->fg;
xsnprintf(newname, sizeof newname, "%.*s-fg", size, name); xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
options_set_number(oo, newname, c); options_set_number(oo, newname, gc->fg);
xsnprintf(newname, sizeof newname, "%.*s-attr", size, name); xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
options_set_number(oo, newname, gc->attr); options_set_number(oo, newname, gc->attr);
@ -219,14 +186,8 @@ style_apply(struct grid_cell *gc, struct options *oo, const char *name)
memcpy(gc, &grid_default_cell, sizeof *gc); memcpy(gc, &grid_default_cell, sizeof *gc);
gcp = options_get_style(oo, name); gcp = options_get_style(oo, name);
if (gcp->flags & GRID_FLAG_FG256) gc->fg = gcp->fg;
colour_set_fg(gc, gcp->fg | 0x100); gc->bg = gcp->bg;
else
colour_set_fg(gc, gcp->fg);
if (gcp->flags & GRID_FLAG_BG256)
colour_set_bg(gc, gcp->bg | 0x100);
else
colour_set_bg(gc, gcp->bg);
gc->attr |= gcp->attr; gc->attr |= gcp->attr;
} }
@ -237,18 +198,10 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
struct grid_cell *gcp; struct grid_cell *gcp;
gcp = options_get_style(oo, name); gcp = options_get_style(oo, name);
if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) { if (gcp->fg != 8)
if (gcp->flags & GRID_FLAG_FG256) gc->fg = gcp->fg;
colour_set_fg(gc, gcp->fg | 0x100); if (gcp->bg != 8)
else gc->bg = gcp->bg;
colour_set_fg(gc, gcp->fg);
}
if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) {
if (gcp->flags & GRID_FLAG_BG256)
colour_set_bg(gc, gcp->bg | 0x100);
else
colour_set_bg(gc, gcp->bg);
}
if (gcp->attr != 0) if (gcp->attr != 0)
gc->attr |= gcp->attr; gc->attr |= gcp->attr;
} }
@ -257,10 +210,10 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
int int
style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2) style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
{ {
return gc1->fg == gc2->fg && return (gc1->fg == gc2->fg &&
gc1->bg == gc2->bg && gc1->bg == gc2->bg &&
(gc1->flags & ~GRID_FLAG_PADDING) == (gc1->flags & ~GRID_FLAG_PADDING) ==
(gc2->flags & ~GRID_FLAG_PADDING) && (gc2->flags & ~GRID_FLAG_PADDING) &&
(gc1->attr & ~GRID_ATTR_CHARSET) == (gc1->attr & ~GRID_ATTR_CHARSET) ==
(gc2->attr & ~GRID_ATTR_CHARSET); (gc2->attr & ~GRID_ATTR_CHARSET));
} }

70
tmux.h
View File

@ -62,7 +62,7 @@ struct tmuxproc;
#define NAME_INTERVAL 500000 #define NAME_INTERVAL 500000
/* The maximum amount of data to hold from a pty (the event high watermark). */ /* 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. */ /* Attribute to make gcc check printf-like arguments. */
#define printflike(a, b) __attribute__ ((format (printf, a, b))) #define printflike(a, b) __attribute__ ((format (printf, a, b)))
@ -627,6 +627,10 @@ enum utf8_state {
UTF8_ERROR UTF8_ERROR
}; };
/* Colour flags. */
#define COLOUR_FLAG_256 0x01000000
#define COLOUR_FLAG_RGB 0x02000000
/* Grid attributes. */ /* Grid attributes. */
#define GRID_ATTR_BRIGHT 0x1 #define GRID_ATTR_BRIGHT 0x1
#define GRID_ATTR_DIM 0x2 #define GRID_ATTR_DIM 0x2
@ -642,32 +646,18 @@ enum utf8_state {
#define GRID_FLAG_BG256 0x2 #define GRID_FLAG_BG256 0x2
#define GRID_FLAG_PADDING 0x4 #define GRID_FLAG_PADDING 0x4
#define GRID_FLAG_EXTENDED 0x8 #define GRID_FLAG_EXTENDED 0x8
#define GRID_FLAG_FGRGB 0x10 #define GRID_FLAG_SELECTED 0x10
#define GRID_FLAG_BGRGB 0x20
#define GRID_FLAG_SELECTED 0x40
/* Grid line flags. */ /* Grid line flags. */
#define GRID_LINE_WRAPPED 0x1 #define GRID_LINE_WRAPPED 0x1
#define GRID_LINE_EXTENDED 0x2
/* Grid cell RGB colours. */
struct grid_cell_rgb {
u_char r;
u_char g;
u_char b;
};
/* Grid cell data. */ /* Grid cell data. */
struct grid_cell { struct grid_cell {
u_char flags; u_char flags;
u_char attr; u_char attr;
union { int fg;
u_char fg; int bg;
struct grid_cell_rgb fg_rgb;
};
union {
u_char bg;
struct grid_cell_rgb bg_rgb;
};
struct utf8_data data; struct utf8_data data;
}; };
@ -782,30 +772,38 @@ struct screen_sel {
/* Virtual screen. */ /* Virtual screen. */
struct screen { struct screen {
char *title; char *title;
struct grid *grid; /* grid data */ struct grid *grid; /* grid data */
u_int cx; /* cursor x */ u_int cx; /* cursor x */
u_int cy; /* cursor y */ u_int cy; /* cursor y */
u_int cstyle; /* cursor style */ u_int cstyle; /* cursor style */
char *ccolour; /* cursor colour string */ char *ccolour; /* cursor colour string */
u_int rupper; /* scroll region top */ u_int rupper; /* scroll region top */
u_int rlower; /* scroll region bottom */ 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. */ /* Screen write context. */
struct screen_write_ctx { struct screen_write_ctx {
struct window_pane *wp; struct window_pane *wp;
struct screen *s; struct screen *s;
u_int dirty;
u_int cells;
u_int written;
u_int skipped;
}; };
/* Screen size. */ /* Screen size. */
@ -1211,7 +1209,6 @@ struct tty_ctx {
/* Saved last cell on line. */ /* Saved last cell on line. */
struct grid_cell last_cell; struct grid_cell last_cell;
u_int last_width;
}; };
/* Saved message entry. */ /* Saved message entry. */
@ -1983,10 +1980,10 @@ int xterm_keys_find(const char *, size_t, size_t *, key_code *);
/* colour.c */ /* colour.c */
int colour_find_rgb(u_char, u_char, u_char); int colour_find_rgb(u_char, u_char, u_char);
void colour_set_fg(struct grid_cell *, int); int colour_join_rgb(u_char, u_char, u_char);
void colour_set_bg(struct grid_cell *, int); void colour_split_rgb(int, u_char *, u_char *, u_char *);
const char *colour_tostring(int); const char *colour_tostring(int);
int colour_fromstring(const char *); int colour_fromstring(const char *s);
u_char colour_256to16(u_char); u_char colour_256to16(u_char);
/* attributes.c */ /* attributes.c */
@ -1995,6 +1992,7 @@ int attributes_fromstring(const char *);
/* grid.c */ /* grid.c */
extern const struct grid_cell grid_default_cell; 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); struct grid *grid_create(u_int, u_int, u_int);
void grid_destroy(struct grid *); void grid_destroy(struct grid *);
int grid_compare(struct grid *, struct grid *); int grid_compare(struct grid *, struct grid *);

310
tty.c
View File

@ -36,17 +36,10 @@ static int tty_log_fd = -1;
void tty_read_callback(struct bufferevent *, void *); void tty_read_callback(struct bufferevent *, void *);
void tty_error_callback(struct bufferevent *, short, 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 *); static int tty_client_ready(struct client *, struct window_pane *);
void tty_set_italics(struct tty *); void tty_set_italics(struct tty *);
int tty_try_256(struct tty *, u_char, const char *); int tty_try_colour(struct tty *, int, const char *);
int tty_try_rgb(struct tty *, const struct grid_cell_rgb *, const char *);
void tty_colours(struct tty *, const struct grid_cell *); void tty_colours(struct tty *, const struct grid_cell *);
void tty_check_fg(struct tty *, 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) \ #define tty_pane_full_width(tty, ctx) \
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) ((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 void
tty_create_log(void) tty_create_log(void)
{ {
@ -679,7 +604,7 @@ tty_fake_bce(const struct tty *tty, const struct window_pane *wp)
if (wp != NULL) if (wp != NULL)
tty_default_colours(&gc, wp); tty_default_colours(&gc, wp);
if (gc.bg == 8 && !(gc.flags & GRID_FLAG_BG256)) if (gc.bg == 8)
return (0); return (0);
return (!tty_term_flag(tty->term, TTYC_BCE)); 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 window_pane *wp = ctx->wp;
struct screen *s = wp->screen; struct screen *s = wp->screen;
u_int i; u_int i;
/* /*
* If region is large, schedule a window redraw. In most cases this is * 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++) { for (i = 0; i < sx; i++) {
grid_view_get_cell(s->grid, i, py, &gc); 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); 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 window_pane *wp = ctx->wp;
struct screen *s = wp->screen; struct screen *s = wp->screen;
u_int i, j; u_int i, j;
tty_attributes(tty, &grid_default_cell, wp); 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 window_pane *wp = ctx->wp;
struct screen *s = wp->screen; struct screen *s = wp->screen;
u_int i, j; u_int i, j;
tty_attributes(tty, &grid_default_cell, wp); 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 window_pane *wp = ctx->wp;
struct screen *s = wp->screen; struct screen *s = wp->screen;
u_int i, j; u_int i, j;
tty_attributes(tty, &grid_default_cell, wp); tty_attributes(tty, &grid_default_cell, wp);
@ -1255,7 +1175,7 @@ tty_reset(struct tty *tty)
{ {
struct grid_cell *gc = &tty->cell; struct grid_cell *gc = &tty->cell;
if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0) if (grid_cells_equal(gc, &grid_default_cell))
return; return;
if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty)) 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) tty_colours(struct tty *tty, const struct grid_cell *gc)
{ {
struct grid_cell *tc = &tty->cell; struct grid_cell *tc = &tty->cell;
int have_ax, fg_default, bg_default; int have_ax;
/* No changes? Nothing is necessary. */ /* No changes? Nothing is necessary. */
if (tty_same_colours(gc, tc)) if (gc->fg == tc->fg && gc->bg == tc->bg)
return; 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 * case if only one is default need to fall onward to set the other
* colour. * colour.
*/ */
fg_default = tty_is_fg(gc, 8); if (gc->fg == 8 || gc->bg == 8) {
bg_default = tty_is_bg(gc, 8);
if (fg_default || bg_default) {
/* /*
* If don't have AX but do have op, send sgr0 (op can't * 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 * 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)) if (!have_ax && tty_term_has(tty->term, TTYC_OP))
tty_reset(tty); tty_reset(tty);
else { else {
if (fg_default && !tty_is_fg(tc, 8)) { if (gc->fg == 8 && tc->fg != 8) {
if (have_ax) if (have_ax)
tty_puts(tty, "\033[39m"); tty_puts(tty, "\033[39m");
else if (!tty_is_fg(tc, 7)) else if (tc->fg != 7)
tty_putcode1(tty, TTYC_SETAF, 7); tty_putcode1(tty, TTYC_SETAF, 7);
tc->fg = 8; 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) if (have_ax)
tty_puts(tty, "\033[49m"); tty_puts(tty, "\033[49m");
else if (!tty_is_bg(tc, 0)) else if (tc->bg != 0)
tty_putcode1(tty, TTYC_SETAB, 0); tty_putcode1(tty, TTYC_SETAB, 0);
tc->bg = 8; tc->bg = 8;
tc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
} }
} }
} }
/* Set the foreground colour. */ /* 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); tty_colours_fg(tty, gc);
/* /*
* Set the background colour. This must come after the foreground as * Set the background colour. This must come after the foreground as
* tty_colour_fg() can call tty_reset(). * 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); tty_colours_bg(tty, gc);
} }
void void
tty_check_fg(struct tty *tty, struct grid_cell *gc) tty_check_fg(struct tty *tty, struct grid_cell *gc)
{ {
struct grid_cell_rgb *rgb = &gc->fg_rgb; u_char r, g, b;
u_int colours; u_int colours;
/* Is this a 24-bit colour? */ /* 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. */ /* Not a 24-bit terminal? Translate to 256-colour palette. */
if (!tty_term_flag(tty->term, TTYC_TC)) { if (!tty_term_flag(tty->term, TTYC_TC)) {
gc->flags &= ~GRID_FLAG_FGRGB; colour_split_rgb(gc->fg, &r, &g, &b);
gc->flags |= GRID_FLAG_FG256; gc->fg = colour_find_rgb(r, g, b);
gc->fg = colour_find_rgb(rgb->r, rgb->g, rgb->b); } else
}
else
return; return;
} }
colours = tty_term_number(tty->term, TTYC_COLORS); colours = tty_term_number(tty->term, TTYC_COLORS);
/* Is this a 256-colour colour? */ /* Is this a 256-colour colour? */
if (gc->flags & GRID_FLAG_FG256) { if (gc->fg & COLOUR_FLAG_256) {
/* And not a 256 colour mode? */ /* And not a 256 colour mode? */
if (!(tty->term->flags & TERM_256COLOURS) && if (!(tty->term->flags & TERM_256COLOURS) &&
!(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; gc->attr |= GRID_ATTR_BRIGHT;
} else } else
gc->attr &= ~GRID_ATTR_BRIGHT; gc->attr &= ~GRID_ATTR_BRIGHT;
gc->flags &= ~GRID_FLAG_FG256;
} }
return; return;
} }
@ -1612,24 +1525,22 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
void void
tty_check_bg(struct tty *tty, struct grid_cell *gc) tty_check_bg(struct tty *tty, struct grid_cell *gc)
{ {
struct grid_cell_rgb *rgb = &gc->bg_rgb; u_char r, g, b;
u_int colours; u_int colours;
/* Is this a 24-bit colour? */ /* 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. */ /* Not a 24-bit terminal? Translate to 256-colour palette. */
if (!tty_term_flag(tty->term, TTYC_TC)) { if (!tty_term_flag(tty->term, TTYC_TC)) {
gc->flags &= ~GRID_FLAG_BGRGB; colour_split_rgb(gc->bg, &r, &g, &b);
gc->flags |= GRID_FLAG_BG256; gc->bg = colour_find_rgb(r, g, b);
gc->bg = colour_find_rgb(rgb->r, rgb->g, rgb->b); } else
}
else
return; return;
} }
colours = tty_term_number(tty->term, TTYC_COLORS); colours = tty_term_number(tty->term, TTYC_COLORS);
/* Is this a 256-colour colour? */ /* 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 * And not a 256 colour mode? Translate to 16-colour
* palette. Bold background doesn't exist portably, so just * 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) if (colours >= 16)
gc->fg += 90; gc->fg += 90;
} }
gc->flags &= ~GRID_FLAG_BG256;
} }
return; return;
} }
@ -1657,137 +1567,111 @@ void
tty_colours_fg(struct tty *tty, const struct grid_cell *gc) tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
{ {
struct grid_cell *tc = &tty->cell; struct grid_cell *tc = &tty->cell;
u_char fg = gc->fg;
char s[32]; char s[32];
tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB); /* Is this a 24-bit or 256-colour colour? */
if (gc->fg & COLOUR_FLAG_RGB ||
/* Is this a 24-bit colour? */ gc->fg & COLOUR_FLAG_256) {
if (gc->flags & GRID_FLAG_FGRGB) { if (tty_try_colour(tty, gc->fg, "38") == 0)
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)
goto save_fg; goto save_fg;
/* Should not get here, already converted in tty_check_fg. */ /* Should not get here, already converted in tty_check_fg. */
return; return;
} }
/* Is this an aixterm bright colour? */ /* Is this an aixterm bright colour? */
if (fg >= 90 && fg <= 97) { if (gc->fg >= 90 && gc->fg <= 97) {
xsnprintf(s, sizeof s, "\033[%dm", fg); xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
tty_puts(tty, s); tty_puts(tty, s);
goto save_fg; goto save_fg;
} }
/* Otherwise set the foreground colour. */ /* Otherwise set the foreground colour. */
tty_putcode1(tty, TTYC_SETAF, fg); tty_putcode1(tty, TTYC_SETAF, gc->fg);
save_fg: save_fg:
/* Save the new values in the terminal current cell. */ /* Save the new values in the terminal current cell. */
if (gc->flags & GRID_FLAG_FGRGB) tc->fg = gc->fg;
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));
} }
void void
tty_colours_bg(struct tty *tty, const struct grid_cell *gc) tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
{ {
struct grid_cell *tc = &tty->cell; struct grid_cell *tc = &tty->cell;
u_char bg = gc->bg;
char s[32]; char s[32];
/* Is this a 24-bit colour? */ /* Is this a 24-bit or 256-colour colour? */
if (gc->flags & GRID_FLAG_BGRGB) { if (gc->bg & COLOUR_FLAG_RGB ||
if (tty_try_rgb(tty, &gc->bg_rgb, "48") == 0) gc->bg & COLOUR_FLAG_256) {
goto save_bg; if (tty_try_colour(tty, gc->bg, "48") == 0)
/* 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)
goto save_bg; goto save_bg;
/* Should not get here, already converted in tty_check_bg. */ /* Should not get here, already converted in tty_check_bg. */
return; return;
} }
/* Is this an aixterm bright colour? */ /* Is this an aixterm bright colour? */
if (bg >= 90 && bg <= 97) { if (gc->bg >= 90 && gc->bg <= 97) {
xsnprintf(s, sizeof s, "\033[%dm", bg + 10); xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
tty_puts(tty, s); tty_puts(tty, s);
goto save_bg; goto save_bg;
} }
/* Otherwise set the background colour. */ /* Otherwise set the background colour. */
tty_putcode1(tty, TTYC_SETAB, bg); tty_putcode1(tty, TTYC_SETAB, gc->bg);
save_bg: save_bg:
/* Save the new values in the terminal current cell. */ /* Save the new values in the terminal current cell. */
if (gc->flags & GRID_FLAG_BGRGB) tc->bg = gc->bg;
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));
} }
int 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]; char s[32];
/* 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 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
if (tty->term_flags & TERM_256COLOURS) * usual sequence.
goto fallback; */
if (tty->term_flags & TERM_256COLOURS)
goto fallback_256;
/* /*
* If the terminfo entry has 256 colours and setaf and setab exist, * If the terminfo entry has 256 colours and setaf and setab
* assume that they work correctly. * exist, assume that they work correctly.
*/ */
if (tty->term->flags & TERM_256COLOURS) { if (tty->term->flags & TERM_256COLOURS) {
if (*type == '3') { if (*type == '3') {
if (!tty_term_has(tty->term, TTYC_SETAF)) if (!tty_term_has(tty->term, TTYC_SETAF))
goto fallback; goto fallback_256;
tty_putcode1(tty, TTYC_SETAF, colour); tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
} else { } else {
if (!tty_term_has(tty->term, TTYC_SETAB)) if (!tty_term_has(tty->term, TTYC_SETAB))
goto fallback; goto fallback_256;
tty_putcode1(tty, TTYC_SETAB, colour); tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
}
return (0);
} }
goto fallback_256;
}
if (colour & COLOUR_FLAG_RGB) {
if (!tty_term_flag(tty->term, TTYC_TC))
return (-1);
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); return (0);
} }
return (-1); return (-1);
fallback: fallback_256:
xsnprintf(s, sizeof s, "\033[%s;5;%hhum", type, colour); xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
tty_puts(tty, s);
return (0);
}
int
tty_try_rgb(struct tty *tty, const struct grid_cell_rgb *rgb, const char *type)
{
char s[32];
if (!tty_term_flag(tty->term, TTYC_TC))
return (-1);
xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type, rgb->r,
rgb->g, rgb->b);
tty_puts(tty, s); tty_puts(tty, s);
return (0); return (0);
} }
@ -1811,31 +1695,21 @@ tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
} }
pgc = &wp->colgc; pgc = &wp->colgc;
if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) { if (gc->fg == 8) {
if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) { if (pgc->fg != 8)
gc->fg = pgc->fg; gc->fg = pgc->fg;
gc->flags |= (pgc->flags & GRID_FLAG_FG256); else if (wp == w->active && agc->fg != 8)
} else if (wp == w->active &&
(agc->fg != 8 || (agc->flags & GRID_FLAG_FG256))) {
gc->fg = agc->fg; gc->fg = agc->fg;
gc->flags |= (agc->flags & GRID_FLAG_FG256); else
} else {
gc->fg = wgc->fg; gc->fg = wgc->fg;
gc->flags |= (wgc->flags & GRID_FLAG_FG256);
}
} }
if (gc->bg == 8 && !(gc->flags & GRID_FLAG_BG256)) { if (gc->bg == 8) {
if (pgc->bg != 8 || (pgc->flags & GRID_FLAG_BG256)) { if (pgc->bg != 8)
gc->bg = pgc->bg; gc->bg = pgc->bg;
gc->flags |= (pgc->flags & GRID_FLAG_BG256); else if (wp == w->active && agc->bg != 8)
} else if (wp == w->active &&
(agc->bg != 8 || (agc->flags & GRID_FLAG_BG256))) {
gc->bg = agc->bg; gc->bg = agc->bg;
gc->flags |= (agc->flags & GRID_FLAG_BG256); else
} else {
gc->bg = wgc->bg; gc->bg = wgc->bg;
gc->flags |= (wgc->flags & GRID_FLAG_BG256);
}
} }
} }

View File

@ -230,7 +230,7 @@ window_clock_draw_screen(struct window_pane *wp)
screen_write_cursormove(&ctx, x, y); screen_write_cursormove(&ctx, x, y);
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_fg(&gc, colour); gc.fg = colour;
screen_write_puts(&ctx, &gc, "%s", tim); screen_write_puts(&ctx, &gc, "%s", tim);
} }
@ -242,7 +242,7 @@ window_clock_draw_screen(struct window_pane *wp)
y = (screen_size_y(s) / 2) - 3; y = (screen_size_y(s) / 2) - 3;
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_bg(&gc, colour); gc.bg = colour;
for (ptr = tim; *ptr != '\0'; ptr++) { for (ptr = tim; *ptr != '\0'; ptr++) {
if (*ptr >= '0' && *ptr <= '9') if (*ptr >= '0' && *ptr <= '9')
idx = *ptr - '0'; idx = *ptr - '0';