summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--colour.c41
-rw-r--r--grid.c74
-rw-r--r--input.c43
-rw-r--r--screen-redraw.c8
-rw-r--r--screen-write.c284
-rw-r--r--screen.c4
-rw-r--r--style.c105
-rw-r--r--tmux.h70
-rw-r--r--tty.c310
-rw-r--r--window-clock.c4
10 files changed, 468 insertions, 475 deletions
diff --git a/colour.c b/colour.c
index 99b2b3b0..f29663f2 100644
--- a/colour.c
+++ b/colour.c
@@ -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 (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). */
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;
else
idx = 16 + (36 * qr) + (6 * qg) + qb;
- return (idx);
+ return (idx | COLOUR_FLAG_256);
}
-/* Set grid cell foreground colour. */
-void
-colour_set_fg(struct grid_cell *gc, int c)
+/* Join RGB into a colour. */
+int
+colour_join_rgb(u_char r, u_char g, u_char b)
{
- if (c & 0x100)
- gc->flags |= GRID_FLAG_FG256;
- gc->fg = c;
+ return ((((int)((r) & 0xff)) << 16) |
+ (((int)((g) & 0xff)) << 8) |
+ (((int)((b) & 0xff))) | COLOUR_FLAG_RGB);
}
-/* Set grid cell background colour. */
+/* Split colour into RGB. */
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)
- gc->flags |= GRID_FLAG_BG256;
- gc->bg = c;
+ *r = (c >> 16) & 0xff;
+ *g = (c >> 8) & 0xff;
+ *b = c & 0xff;
}
/* Convert colour to a string. */
@@ -109,9 +109,16 @@ const char *
colour_tostring(int c)
{
static char s[32];
+ u_char r, g, b;
+
+ if (c & COLOUR_FLAG_RGB) {
+ colour_split_rgb(c, &r, &g, &b);
+ xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
+ return (s);
+ }
- if (c & 0x100) {
- xsnprintf(s, sizeof s, "colour%d", c & ~0x100);
+ if (c & COLOUR_FLAG_256) {
+ xsnprintf(s, sizeof s, "colour%u", c & 0xff);
return (s);
}
@@ -171,14 +178,14 @@ colour_fromstring(const char *s)
n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
if (n != 3)
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) {
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
if (errstr != NULL)
return (-1);
- return (n | 0x100);
+ return (n | COLOUR_FLAG_256);
}
if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
diff --git a/grid.c b/grid.c
index 0be0254f..f0eda7e0 100644
--- a/grid.c
+++ b/grid.c
@@ -37,14 +37,12 @@
/* Default grid cell data. */
const struct grid_cell grid_default_cell = {
- 0, 0, { .fg = 8 }, { .bg = 8 }, { { ' ' }, 0, 1, 1 }
+ 0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
};
const struct grid_cell_entry grid_default_entry = {
0, { .data = { 0, 8, 8, ' ' } }
};
-int grid_check_y(struct grid *, u_int);
-
void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *l,
u_int, u_int);
void grid_reflow_join(struct grid *, u_int *, struct grid_line *, u_int);
@@ -64,7 +62,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py)
}
/* Check grid y position. */
-int
+static int
grid_check_y(struct grid *gd, u_int py)
{
if ((py) >= (gd)->hsize + (gd)->sy) {
@@ -74,6 +72,21 @@ grid_check_y(struct grid *gd, u_int py)
return (0);
}
+/* Compare grid cells. Return 1 if equal, 0 if not. */
+int
+grid_cells_equal(const struct grid_cell *gca, const struct grid_cell *gcb)
+{
+ if (gca->fg != gcb->fg || gca->bg != gcb->bg)
+ return (0);
+ if (gca->attr != gcb->attr || gca->flags != gcb->flags)
+ return (0);
+ if (gca->data.width != gcb->data.width)
+ return (0);
+ if (gca->data.size != gcb->data.size)
+ return (0);
+ return (memcmp(gca->data.data, gcb->data.data, gca->data.size) == 0);
+}
+
/* Create a new grid. */
struct grid *
grid_create(u_int sx, u_int sy, u_int hlimit)
@@ -131,7 +144,7 @@ grid_compare(struct grid *ga, struct grid *gb)
for (xx = 0; xx < gla->cellsize; xx++) {
grid_get_cell(ga, xx, yy, &gca);
grid_get_cell(gb, xx, yy, &gcb);
- if (memcmp(&gca, &gcb, sizeof (struct grid_cell)) != 0)
+ if (!grid_cells_equal(&gca, &gcb))
return (1);
}
}
@@ -270,10 +283,14 @@ grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
return;
}
- gc->flags = gce->flags & ~GRID_FLAG_EXTENDED;
+ gc->flags = gce->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
gc->attr = gce->data.attr;
gc->fg = gce->data.fg;
+ if (gce->flags & GRID_FLAG_FG256)
+ gc->fg |= COLOUR_FLAG_256;
gc->bg = gce->data.bg;
+ if (gce->flags & GRID_FLAG_BG256)
+ gc->bg |= COLOUR_FLAG_256;
utf8_set(&gc->data, gce->data.data);
}
@@ -297,9 +314,12 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
extended = (gce->flags & GRID_FLAG_EXTENDED);
if (!extended && (gc->data.size != 1 || gc->data.width != 1))
extended = 1;
- if (!extended && (gc->flags & (GRID_FLAG_FGRGB|GRID_FLAG_BGRGB)))
+ if (!extended && ((gc->fg & COLOUR_FLAG_RGB) ||
+ (gc->bg & COLOUR_FLAG_RGB)))
extended = 1;
if (extended) {
+ gl->flags |= GRID_LINE_EXTENDED;
+
if (~gce->flags & GRID_FLAG_EXTENDED) {
gl->extddata = xreallocarray(gl->extddata,
gl->extdsize + 1, sizeof *gl->extddata);
@@ -314,10 +334,14 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
return;
}
- gce->flags = gc->flags & ~GRID_FLAG_EXTENDED;
+ gce->flags = gc->flags;
gce->data.attr = gc->attr;
- gce->data.fg = gc->fg;
- gce->data.bg = gc->bg;
+ gce->data.fg = gc->fg & 0xff;
+ if (gc->fg & COLOUR_FLAG_256)
+ gce->flags |= GRID_FLAG_FG256;
+ gce->data.bg = gc->bg & 0xff;
+ if (gc->bg & COLOUR_FLAG_256)
+ gce->flags |= GRID_FLAG_BG256;
gce->data.data = gc->data.data[0];
}
@@ -446,18 +470,20 @@ size_t
grid_string_cells_fg(const struct grid_cell *gc, int *values)
{
size_t n;
+ u_char r, g, b;
n = 0;
- if (gc->flags & GRID_FLAG_FG256) {
+ if (gc->fg & COLOUR_FLAG_256) {
values[n++] = 38;
values[n++] = 5;
- values[n++] = gc->fg;
- } else if (gc->flags & GRID_FLAG_FGRGB) {
+ values[n++] = gc->fg & 0xff;
+ } else if (gc->fg & COLOUR_FLAG_RGB) {
values[n++] = 38;
values[n++] = 2;
- values[n++] = gc->fg_rgb.r;
- values[n++] = gc->fg_rgb.g;
- values[n++] = gc->fg_rgb.b;
+ colour_split_rgb(gc->fg, &r, &g, &b);
+ values[n++] = r;
+ values[n++] = g;
+ values[n++] = b;
} else {
switch (gc->fg) {
case 0:
@@ -493,18 +519,20 @@ size_t
grid_string_cells_bg(const struct grid_cell *gc, int *values)
{
size_t n;
+ u_char r, g, b;
n = 0;
- if (gc->flags & GRID_FLAG_BG256) {
+ if (gc->bg & COLOUR_FLAG_256) {
values[n++] = 48;
values[n++] = 5;
- values[n++] = gc->bg;
- } else if (gc->flags & GRID_FLAG_BGRGB) {
+ values[n++] = gc->bg & 0xff;
+ } else if (gc->bg & COLOUR_FLAG_RGB) {
values[n++] = 48;
values[n++] = 2;
- values[n++] = gc->bg_rgb.r;
- values[n++] = gc->bg_rgb.g;
- values[n++] = gc->bg_rgb.b;
+ colour_split_rgb(gc->bg, &r, &g, &b);
+ values[n++] = r;
+ values[n++] = g;
+ values[n++] = b;
} else {
switch (gc->bg) {
case 0:
@@ -525,7 +553,7 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values)
case 102:
case 103:
case 104:
- case 105:
+ case 105:
case 106:
case 107:
values[n++] = gc->bg - 10;
diff --git a/input.c b/input.c
index 18c8eb9a..289a25c8 100644
--- a/input.c
+++ b/input.c
@@ -1628,23 +1628,15 @@ input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
(*i)++;
c = input_get(ictx, *i, 0, -1);
if (c == -1) {
- if (fgbg == 38) {
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
+ if (fgbg == 38)
gc->fg = 8;
- } else if (fgbg == 48) {
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
+ else if (fgbg == 48)
gc->bg = 8;
- }
} else {
- if (fgbg == 38) {
- gc->flags |= GRID_FLAG_FG256;
- gc->flags &= ~GRID_FLAG_FGRGB;
- gc->fg = c;
- } else if (fgbg == 48) {
- gc->flags |= GRID_FLAG_BG256;
- gc->flags &= ~GRID_FLAG_BGRGB;
- gc->bg = c;
- }
+ if (fgbg == 38)
+ gc->fg = c | COLOUR_FLAG_256;
+ else if (fgbg == 48)
+ gc->bg = c | COLOUR_FLAG_256;
}
}
@@ -1668,19 +1660,10 @@ input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
if (b == -1 || b > 255)
return;
- if (fgbg == 38) {
- gc->flags &= ~GRID_FLAG_FG256;
- gc->flags |= GRID_FLAG_FGRGB;
- gc->fg_rgb.r = r;
- 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;
- }
+ if (fgbg == 38)
+ gc->fg = colour_join_rgb(r, g, b);
+ else if (fgbg == 48)
+ gc->bg = colour_join_rgb(r, g, b);
}
/* Handle CSI SGR. */
@@ -1761,11 +1744,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 35:
case 36:
case 37:
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = n - 30;
break;
case 39:
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = 8;
break;
case 40:
@@ -1776,11 +1757,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 45:
case 46:
case 47:
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = n - 40;
break;
case 49:
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = 8;
break;
case 90:
@@ -1791,7 +1770,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 95:
case 96:
case 97:
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
gc->fg = n;
break;
case 100:
@@ -1802,7 +1780,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 105:
case 106:
case 107:
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
gc->bg = n - 10;
break;
}
diff --git a/screen-redraw.c b/screen-redraw.c
index 694f6c27..4c402ff2 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -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);
if (w->active == wp)
- colour_set_bg(&gc, active_colour);
+ gc.bg = active_colour;
else
- colour_set_bg(&gc, colour);
+ gc.bg = colour;
tty_attributes(tty, &gc, wp);
for (ptr = buf; *ptr != '\0'; ptr++) {
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:
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
- colour_set_fg(&gc, active_colour);
+ gc.fg = active_colour;
else
- colour_set_fg(&gc, colour);
+ gc.fg = colour;
tty_attributes(tty, &gc, wp);
tty_puts(tty, buf);
diff --git a/screen-write.c b/screen-write.c
index 48af1383..3c4d2758 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -27,6 +27,7 @@ static void screen_write_initctx(struct screen_write_ctx *,
struct tty_ctx *);
static void screen_write_save_last(struct screen_write_ctx *,
struct tty_ctx *);
+static void screen_write_flush(struct screen_write_ctx *);
static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int);
@@ -34,25 +35,103 @@ static int screen_write_combine(struct screen_write_ctx *,
const struct utf8_data *);
static const struct grid_cell screen_write_pad_cell = {
- GRID_FLAG_PADDING, 0, { .fg = 8 }, { .bg = 8 }, { { 0 }, 0, 0, 0 }
+ GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
};
-/* Initialise writing with a window. */
+#define screen_dirty_bit(s, x, y) (((y) * screen_size_x(s)) + (x))
+#define screen_dirty_clear(s, sx, sy, ex, ey) \
+ do { \
+ if (s->dirty != NULL) { \
+ bit_nclear(s->dirty, \
+ screen_dirty_bit(s, sx, sy), \
+ screen_dirty_bit(s, ex, ey)); \
+ } \
+ } while (0)
+
+/* Initialize writing with a window. */
void
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
struct screen *s)
{
+ u_int size;
+ char tmp[16];
+ const char *cp = tmp;
+
ctx->wp = wp;
if (wp != NULL && s == NULL)
ctx->s = wp->screen;
else
ctx->s = s;
+
+ size = screen_size_x(ctx->s) * screen_size_y(ctx->s);
+ if (ctx->s->dirtysize != size) {
+ free(ctx->s->dirty);
+ ctx->s->dirty = NULL;
+ ctx->s->dirtysize = size;
+ }
+ ctx->dirty = 0;
+
+ ctx->cells = ctx->written = ctx->skipped = 0;
+
+ if (wp == NULL)
+ cp = "no pane";
+ else
+ snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
+ log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
+ screen_size_y(ctx->s), cp);
}
/* Finish writing. */
void
-screen_write_stop(__unused struct screen_write_ctx *ctx)
+screen_write_stop(struct screen_write_ctx *ctx)
+{
+ screen_write_flush(ctx);
+
+ log_debug("%s: %u of %u written (dirty %u, skipped %u)", __func__,
+ ctx->written, ctx->cells, ctx->cells - ctx->written, ctx->skipped);
+}
+
+/* Flush outstanding cell writes. */
+static void
+screen_write_flush(struct screen_write_ctx *ctx)
{
+ struct screen *s = ctx->s;
+ struct tty_ctx ttyctx;
+ u_int x, y, offset, cx, cy, dirty;
+ struct grid_cell gc;
+
+ if (ctx->dirty == 0)
+ return;
+ dirty = 0;
+
+ cx = s->cx;
+ cy = s->cy;
+
+ offset = 0;
+ for (y = 0; y < screen_size_y(s); y++) {
+ for (x = 0; x < screen_size_x(s); x++) {
+ offset++;
+ if (!bit_test(s->dirty, offset - 1))
+ continue;
+ bit_clear(s->dirty, offset - 1);
+
+ screen_write_cursormove(ctx, x, y);
+ grid_view_get_cell(s->grid, x, y, &gc);
+
+ screen_write_initctx(ctx, &ttyctx);
+ ttyctx.cell = &gc;
+ tty_write(tty_cmd_cell, &ttyctx);
+ ctx->written++;
+
+ if (++dirty == ctx->dirty)
+ break;
+ }
+ if (dirty == ctx->dirty)
+ break;
+ }
+
+ s->cx = cx;
+ s->cy = cy;
}
/* Reset screen state. */
@@ -382,7 +461,6 @@ screen_write_save_last(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
if (~gc.flags & GRID_FLAG_PADDING)
break;
}
- ttyctx->last_width = xx;
memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell);
}
@@ -517,9 +595,12 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
struct tty_ctx ttyctx;
struct grid_cell gc;
u_int xx, yy;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
+ screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
+
memcpy(&gc, &grid_default_cell, sizeof gc);
utf8_set(&gc.data, 'E');
@@ -532,7 +613,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
s->cy = 0;
s->rupper = 0;
-
s->rlower = screen_size_y(s) - 1;
tty_write(tty_cmd_alignmenttest, &ttyctx);
@@ -553,6 +633,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1)
@@ -577,6 +658,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
if (nx == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cx <= screen_size_x(s) - 1)
@@ -603,8 +685,11 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
screen_write_initctx(ctx, &ttyctx);
- if (s->cx <= screen_size_x(s) - 1)
+ if (s->cx <= screen_size_x(s) - 1) {
+ screen_dirty_clear(s, s->cx, s->cy, s->cx + nx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, nx, 1);
+ } else
+ return;
ttyctx.num = nx;
tty_write(tty_cmd_clearcharacter, &ttyctx);
@@ -626,6 +711,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
grid_view_insert_lines(s->grid, s->cy, ny);
@@ -640,6 +726,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower)
@@ -667,6 +754,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
grid_view_delete_lines(s->grid, s->cy, ny);
@@ -681,6 +769,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
if (ny == 0)
return;
+ screen_write_flush(ctx);
screen_write_initctx(ctx, &ttyctx);
if (s->cy < s->rupper || s->cy > s->rlower)
@@ -696,12 +785,19 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
void
screen_write_clearline(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
- struct tty_ctx ttyctx;
+ struct screen *s = ctx->s;
+ struct grid_line *gl;
+ struct tty_ctx ttyctx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
+ gl = &s->grid->linedata[s->grid->hsize + s->cy];
+ if (gl->cellsize != 0) {
+ screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
+ grid_view_clear(s->grid, 0, s->cy, sx, 1);
+ } else
+ return;
tty_write(tty_cmd_clearline, &ttyctx);
}
@@ -710,16 +806,19 @@ screen_write_clearline(struct screen_write_ctx *ctx)
void
screen_write_clearendofline(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
- struct tty_ctx ttyctx;
- u_int sx;
+ struct screen *s = ctx->s;
+ struct grid_line *gl;
+ struct tty_ctx ttyctx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
-
- if (s->cx <= sx - 1)
+ gl = &s->grid->linedata[s->grid->hsize + s->cy];
+ if (s->cx <= sx - 1 && s->cx < gl->cellsize) {
+ screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ } else
+ return;
tty_write(tty_cmd_clearendofline, &ttyctx);
}
@@ -730,16 +829,17 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
-
- if (s->cx > sx - 1)
+ if (s->cx > sx - 1) {
+ screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
- else
+ } else {
+ screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
+ }
tty_write(tty_cmd_clearstartofline, &ttyctx);
}
@@ -768,9 +868,10 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
screen_write_initctx(ctx, &ttyctx);
- if (s->cy == s->rupper)
+ if (s->cy == s->rupper) {
+ screen_write_flush(ctx);
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
- else if (s->cy > 0)
+ } else if (s->cy > 0)
s->cy--;
tty_write(tty_cmd_reverseindex, &ttyctx);
@@ -805,6 +906,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
struct screen *s = ctx->s;
struct grid_line *gl;
struct tty_ctx ttyctx;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
@@ -814,9 +916,11 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
else
gl->flags &= ~GRID_LINE_WRAPPED;
- if (s->cy == s->rlower)
+ if (s->cy == s->rlower) {
+ screen_dirty_clear(s, 0, s->rupper, sx - 1, s->rupper);
+ screen_write_flush(ctx);
grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
- else if (s->cy < screen_size_y(s) - 1)
+ } else if (s->cy < sy - 1)
s->cy++;
ttyctx.num = wrapped;
@@ -838,19 +942,20 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx, sy;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
- sy = screen_size_y(s);
-
/* Scroll into history if it is enabled and clearing entire screen. */
- if (s->cy == 0 && s->grid->flags & GRID_HISTORY)
+ if (s->cy == 0 && s->grid->flags & GRID_HISTORY) {
+ screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
grid_view_clear_history(s->grid);
- else {
- if (s->cx <= sx - 1)
+ } else {
+ if (s->cx <= sx - 1) {
+ screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
+ }
+ screen_dirty_clear(s, 0, s->cy + 1, sx - 1, sy - 1);
grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
}
@@ -863,18 +968,21 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx;
+ u_int sx = screen_size_x(s);
screen_write_initctx(ctx, &ttyctx);
- sx = screen_size_x(s);
-
- if (s->cy > 0)
+ if (s->cy > 0) {
+ screen_dirty_clear(s, 0, 0, sx - 1, s->cy);
grid_view_clear(s->grid, 0, 0, sx, s->cy);
- if (s->cx > sx - 1)
+ }
+ if (s->cx > sx - 1) {
+ screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
grid_view_clear(s->grid, 0, s->cy, sx, 1);
- else
+ } else {
+ screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
+ }
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
}
@@ -885,11 +993,12 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
- u_int sx = screen_size_x(s);
- u_int sy = screen_size_y(s);
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
screen_write_initctx(ctx, &ttyctx);
+ screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
+
/* Scroll into history if it is enabled. */
if (s->grid->flags & GRID_HISTORY)
grid_view_clear_history(s->grid);
@@ -918,8 +1027,13 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
struct grid *gd = s->grid;
struct tty_ctx ttyctx;
u_int width, xx, last;
+ u_int sx = screen_size_x(s), sy = screen_size_y(s);
+ struct grid_line *gl;
struct grid_cell tmp_gc, now_gc;
- int insert, skip, selected;
+ struct grid_cell_entry *gce;
+ int insert, skip, selected, wrapped = 0;
+
+ ctx->cells++;
/* Ignore padding. */
if (gc->flags & GRID_FLAG_PADDING)
@@ -930,10 +1044,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* If this is a wide character and there is no room on the screen, for
* the entire character, don't print it.
*/
- if (!(s->mode & MODE_WRAP)
- && (width > 1 && (width > screen_size_x(s) ||
- (s->cx != screen_size_x(s)
- && s->cx > screen_size_x(s) - width))))
+ if (!(s->mode & MODE_WRAP) && (width > 1 &&
+ (width > sx || (s->cx != sx && s->cx > sx - width))))
return;
/*
@@ -952,8 +1064,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
screen_write_initctx(ctx, &ttyctx);
/* If in insert mode, make space for the cells. */
- if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) {
- xx = screen_size_x(s) - s->cx - width;
+ if ((s->mode & MODE_INSERT) && s->cx <= sx - width) {
+ xx = sx - s->cx - width;
grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
insert = 1;
} else
@@ -961,20 +1073,26 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
skip = !insert;
/* Check this will fit on the current line and wrap if not. */
- if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
+ if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
+ screen_write_flush(ctx);
+ screen_write_save_last(ctx, &ttyctx);
screen_write_linefeed(ctx, 1);
s->cx = 0; /* carriage return */
skip = 0;
+ wrapped = 1;
}
/* Sanity check cursor position. */
- if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1)
+ if (s->cx > sx - width || s->cy > sy - 1)
return;
/* Handle overwriting of UTF-8 characters. */
- grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
- if (screen_write_overwrite(ctx, &now_gc, width))
- skip = 0;
+ gl = &s->grid->linedata[s->grid->hsize + s->cy];
+ if (gl->flags & GRID_LINE_EXTENDED) {
+ grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
+ if (screen_write_overwrite(ctx, &now_gc, width))
+ skip = 0;
+ }
/*
* If the new character is UTF-8 wide, fill in padding cells. Have
@@ -986,8 +1104,25 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
}
/* If no change, do not draw. */
- if (skip)
- skip = (memcmp(&now_gc, gc, sizeof now_gc) == 0);
+ if (skip) {
+ if (s->cx >= gl->cellsize)
+ skip = grid_cells_equal(gc, &grid_default_cell);
+ else {
+ gce = &gl->celldata[s->cx];
+ if (gce->flags & GRID_FLAG_EXTENDED)
+ skip = 0;
+ else if (gc->flags != (gce->flags & ~GRID_FLAG_EXTENDED))
+ skip = 0;
+ else if (gc->attr != gce->data.attr)
+ skip = 0;
+ else if (gc->fg != gce->data.fg)
+ skip = 0;
+ else if (gc->bg != gce->data.bg)
+ skip = 0;
+ else if (gc->data.width != 1 || gce->data.data != gc->data.data[0])
+ skip = 0;
+ }
+ }
/* Update the selection the flag and set the cell. */
selected = screen_check_selection(s, s->cx, s->cy);
@@ -1009,21 +1144,19 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* replace it.
*/
last = !(s->mode & MODE_WRAP);
- if (s->cx <= screen_size_x(s) - last - width)
+ if (s->cx <= sx - last - width)
s->cx += width;
else
- s->cx = screen_size_x(s) - last;
+ s->cx = sx - last;
/* Create space for character in insert mode. */
if (insert) {
+ if (!wrapped)
+ screen_write_flush(ctx);
ttyctx.num = width;
tty_write(tty_cmd_insertcharacter, &ttyctx);
}
- /* Save last cell if it will be needed. */
- if (!skip && ctx->wp != NULL && ttyctx.ocx > ctx->wp->sx - width)
- screen_write_save_last(ctx, &ttyctx);
-
/* Write to the screen. */
if (selected) {
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
@@ -1031,16 +1164,35 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
tmp_gc.flags = gc->flags;
- tmp_gc.flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_BGRGB);
- tmp_gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
- tmp_gc.flags |= s->sel.cell.flags &
- (GRID_FLAG_FG256|GRID_FLAG_BG256);
+ screen_write_flush(ctx);
ttyctx.cell = &tmp_gc;
tty_write(tty_cmd_cell, &ttyctx);
+ ctx->written++;
} else if (!skip) {
- ttyctx.cell = gc;
- tty_write(tty_cmd_cell, &ttyctx);
- }
+ if (wrapped) {
+ ttyctx.cell = gc;
+ tty_write(tty_cmd_cell, &ttyctx);
+ ctx->written++;
+ } else {
+ /*
+ * If wp is NULL, we are not updating the terminal and
+ * don't care about actually writing the cells
+ * (tty_write will just return). So don't even bother
+ * allocating the dirty array.
+ */
+ if (ctx->wp != NULL && s->dirty == NULL) {
+ log_debug("%s: allocating %u bits", __func__,
+ s->dirtysize);
+ s->dirty = bit_alloc(s->dirtysize);
+ }
+ if (s->dirty != NULL) {
+ bit_set(s->dirty, screen_dirty_bit(s,
+ ttyctx.ocx, ttyctx.ocy));
+ ctx->dirty++;
+ }
+ }
+ } else
+ ctx->skipped++;
}
/* Combine a UTF-8 zero-width character onto the previous. */
diff --git a/screen.c b/screen.c
index 4fa8e4c9..f5f39d37 100644
--- a/screen.c
+++ b/screen.c
@@ -38,6 +38,9 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
s->ccolour = xstrdup("");
s->tabs = NULL;
+ s->dirty = NULL;
+ s->dirtysize = 0;
+
screen_reinit(s);
}
@@ -64,6 +67,7 @@ screen_reinit(struct screen *s)
void
screen_free(struct screen *s)
{
+ free(s->dirty);
free(s->tabs);
free(s->title);
free(s->ccolour);
diff --git a/style.c b/style.c
index 151c2912..8af739e5 100644
--- a/style.c
+++ b/style.c
@@ -33,7 +33,8 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
char tmp[32];
int val;
size_t end;
- u_char fg, bg, attr, flags;
+ int fg, bg;
+ u_char attr, flags;
if (*in == '\0')
return (0);
@@ -56,38 +57,20 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
fg = defgc->fg;
bg = defgc->bg;
attr = defgc->attr;
- flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
- flags |=
- defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
+ flags = defgc->flags;
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
if ((val = colour_fromstring(tmp + 3)) == -1)
goto error;
if (*in == 'f' || *in == 'F') {
- if (val != 8) {
- if (val & 0x100) {
- flags |= GRID_FLAG_FG256;
- val &= ~0x100;
- } else
- flags &= ~GRID_FLAG_FG256;
+ if (val != 8)
fg = val;
- } else {
+ else
fg = defgc->fg;
- flags &= ~GRID_FLAG_FG256;
- flags |= defgc->flags & GRID_FLAG_FG256;
- }
} else if (*in == 'b' || *in == 'B') {
- if (val != 8) {
- if (val & 0x100) {
- flags |= GRID_FLAG_BG256;
- val &= ~0x100;
- } else
- flags &= ~GRID_FLAG_BG256;
+ if (val != 8)
bg = val;
- } else {
+ else
bg = defgc->bg;
- flags &= ~GRID_FLAG_BG256;
- flags |= defgc->flags & GRID_FLAG_BG256;
- }
} else
goto error;
} else if (strcasecmp(tmp, "none") == 0)
@@ -120,27 +103,19 @@ error:
const char *
style_tostring(struct grid_cell *gc)
{
- int c, off = 0, comma = 0;
+ int off = 0, comma = 0;
static char s[256];
*s = '\0';
- if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
- if (gc->flags & GRID_FLAG_FG256)
- c = gc->fg | 0x100;
- else
- c = gc->fg;
- off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
+ if (gc->fg != 8) {
+ off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(gc->fg));
comma = 1;
}
- if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
- if (gc->flags & GRID_FLAG_BG256)
- c = gc->bg | 0x100;
- else
- c = gc->bg;
+ if (gc->bg != 8) {
off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
- comma ? "," : "", colour_tostring(c));
+ comma ? "," : "", colour_tostring(gc->bg));
comma = 1;
}
@@ -177,9 +152,9 @@ style_update_new(struct options *oo, const char *name, const char *newname)
value = o->num;
if (strstr(name, "-bg") != NULL)
- colour_set_bg(gc, value);
+ gc->bg = value;
else if (strstr(name, "-fg") != NULL)
- colour_set_fg(gc, value);
+ gc->fg = value;
else if (strstr(name, "-attr") != NULL)
gc->attr = value;
}
@@ -189,23 +164,15 @@ void
style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
{
char newname[128];
- int c, size;
+ int size;
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);
- 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);
- options_set_number(oo, newname, c);
+ options_set_number(oo, newname, gc->fg);
xsnprintf(newname, sizeof newname, "%.*s-attr", s