mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Don't update cells in each block of data read from a pane immediately,
instead track them as change (dirty) and update them once at the end, saves much time if repeatedly writing the same cell. Also fix comparison of cells being equal in a few places (memcmp is not enough).
This commit is contained in:
parent
1fd6ca2260
commit
0f73af876f
74
grid.c
74
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;
|
||||
|
284
screen-write.c
284
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. */
|
||||
|
4
screen.c
4
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);
|
||||
|
70
tmux.h
70
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 *);
|
||||
|
310
tty.c
310
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);
|
||||
}
|
||||
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 (-1);
|
||||
|
||||
fallback:
|
||||
xsnprintf(s, sizeof s, "\033[%s;5;%hhum", type, colour);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user