summaryrefslogtreecommitdiffstats
path: root/screen-write.c
diff options
context:
space:
mode:
authornicm <nicm>2015-11-13 08:09:28 +0000
committernicm <nicm>2015-11-13 08:09:28 +0000
commitc5689a5a4031a43769b8b721cafa6d1eab6abc44 (patch)
tree8eb234cb05f7934a41365dc0674794ccb34561c5 /screen-write.c
parente71a9154126c7ee853b9a657678de40d475279eb (diff)
Long overdue change to the way we store cells in the grid: now, instead
of storing a full grid_cell with UTF-8 data and everything, store a new type grid_cell_entry. This can either be the cell itself (for ASCII cells), or an offset into an extended array (per line) for UTF-8 data. This avoid a large (8 byte) overhead on non-UTF-8 cells (by far the majority for most users) without the complexity of the shadow array we had before. Grid memory without any UTF-8 is about half. The disadvantage that cells can no longer be modified in place and need to be copied out of the grid and back but it turned out to be lot less complicated than I expected.
Diffstat (limited to 'screen-write.c')
-rw-r--r--screen-write.c92
1 files changed, 42 insertions, 50 deletions
diff --git a/screen-write.c b/screen-write.c
index 4bf3ec72..14b8a41a 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -67,7 +67,7 @@ void
screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
u_char ch)
{
- grid_cell_one(gc, ch);
+ utf8_set(&gc->data, ch);
screen_write_cell(ctx, gc);
}
@@ -126,7 +126,7 @@ screen_write_strlen(const char *fmt, ...)
ptr++;
left = strlen(ptr);
- if (left < ud.size - 1)
+ if (left < (size_t)ud.size - 1)
break;
while (utf8_append(&ud, *ptr))
ptr++;
@@ -185,7 +185,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
ptr++;
left = strlen(ptr);
- if (left < ud.size - 1)
+ if (left < (size_t)ud.size - 1)
break;
while (utf8_append(&ud, *ptr))
ptr++;
@@ -201,7 +201,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
}
size += ud.width;
- grid_cell_set(gc, &ud);
+ utf8_copy(&gc->data, &ud);
screen_write_cell(ctx, gc);
} else {
if (maxlen > 0 && size + 1 > (size_t) maxlen)
@@ -258,7 +258,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
ptr++;
left = strlen(ptr);
- if (left < ud.size - 1)
+ if (left < (size_t)ud.size - 1)
break;
while (utf8_append(&ud, *ptr))
ptr++;
@@ -274,7 +274,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
}
size += ud.width;
- grid_cell_set(&lgc, &ud);
+ utf8_copy(&lgc.data, &ud);
screen_write_cell(ctx, &lgc);
} else {
if (maxlen > 0 && size + 1 > (size_t) maxlen)
@@ -299,8 +299,7 @@ screen_write_copy(struct screen_write_ctx *ctx,
struct screen *s = ctx->s;
struct grid *gd = src->grid;
struct grid_line *gl;
- const struct grid_cell *gc;
- struct utf8_data ud;
+ struct grid_cell gc;
u_int xx, yy, cx, cy, ax, bx;
cx = s->cx;
@@ -324,12 +323,8 @@ screen_write_copy(struct screen_write_ctx *ctx,
bx = px + nx;
for (xx = ax; xx < bx; xx++) {
- if (xx >= gl->cellsize)
- gc = &grid_default_cell;
- else
- gc = &gl->celldata[xx];
- grid_cell_get(gc, &ud);
- screen_write_cell(ctx, gc);
+ grid_get_cell(gd, xx, yy, &gc);
+ screen_write_cell(ctx, &gc);
}
if (px + nx == gd->sx && px + nx > gl->cellsize)
screen_write_clearendofline(ctx);
@@ -342,12 +337,12 @@ screen_write_copy(struct screen_write_ctx *ctx,
/* Set up context for TTY command. */
void
-screen_write_initctx(
- struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, int save_last)
+screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
+ int save_last)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
- const struct grid_cell *gc;
+ struct grid_cell gc;
u_int xx;
ttyctx->wp = ctx->wp;
@@ -362,14 +357,14 @@ screen_write_initctx(
return;
/* Save the last cell on the screen. */
- gc = &grid_default_cell;
+ memcpy(&gc, &grid_default_cell, sizeof gc);
for (xx = 1; xx <= screen_size_x(s); xx++) {
- gc = grid_view_peek_cell(gd, screen_size_x(s) - xx, s->cy);
- if (!(gc->flags & GRID_FLAG_PADDING))
+ grid_view_get_cell(gd, screen_size_x(s) - xx, s->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
break;
}
ttyctx->last_width = xx;
- memcpy(&ttyctx->last_cell, gc, sizeof ttyctx->last_cell);
+ memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell);
}
/* Set a mode. */
@@ -507,7 +502,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
screen_write_initctx(ctx, &ttyctx, 0);
memcpy(&gc, &grid_default_cell, sizeof gc);
- grid_cell_one(&gc, 'E');
+ utf8_set(&gc.data, 'E');
for (yy = 0; yy < screen_size_y(s); yy++) {
for (xx = 0; xx < screen_size_x(s); xx++)
@@ -904,14 +899,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;
- struct grid_cell tmp_gc, *tmp_gcp;
- struct utf8_data ud;
+ struct grid_cell tmp_gc;
int insert;
/* Ignore padding. */
if (gc->flags & GRID_FLAG_PADDING)
return;
- width = grid_cell_width(gc);
+ width = gc->data.width;
/*
* If this is a wide character and there is no room on the screen, for
@@ -928,8 +922,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* there is space.
*/
if (width == 0) {
- grid_cell_get(gc, &ud);
- if (screen_write_combine(ctx, &ud) == 0) {
+ if (screen_write_combine(ctx, &gc->data) == 0) {
screen_write_initctx(ctx, &ttyctx, 0);
tty_write(tty_cmd_utf8character, &ttyctx);
}
@@ -964,11 +957,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* If the new character is UTF-8 wide, fill in padding cells. Have
* already ensured there is enough room.
*/
- for (xx = s->cx + 1; xx < s->cx + width; xx++) {
- tmp_gcp = grid_view_get_cell(gd, xx, s->cy);
- if (tmp_gcp != NULL)
- tmp_gcp->flags |= GRID_FLAG_PADDING;
- }
+ memcpy(&tmp_gc, &grid_default_cell, sizeof tmp_gc);
+ tmp_gc.flags |= GRID_FLAG_PADDING;
+ tmp_gc.data.width = 0;
+ for (xx = s->cx + 1; xx < s->cx + width; xx++)
+ grid_view_set_cell(gd, xx, s->cy, &tmp_gc);
/* Set the cell. */
grid_view_set_cell(gd, s->cx, s->cy, gc);
@@ -990,8 +983,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
}
if (screen_check_selection(s, s->cx - width, s->cy)) {
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
- grid_cell_get(gc, &ud);
- grid_cell_set(&tmp_gc, &ud);
+ utf8_copy(&tmp_gc.data, &gc->data);
tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
@@ -1011,8 +1003,7 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
- struct grid_cell *gc;
- struct utf8_data ud1;
+ struct grid_cell gc;
/* Can't combine if at 0. */
if (s->cx == 0)
@@ -1023,17 +1014,18 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
fatalx("UTF-8 data empty");
/* Retrieve the previous cell. */
- gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
- grid_cell_get(gc, &ud1);
+ grid_view_get_cell(gd, s->cx - 1, s->cy, &gc);
/* Check there is enough space. */
- if (ud1.size + ud->size > sizeof ud1.data)
+ if (gc.data.size + ud->size > sizeof gc.data.data)
return (-1);
- /* Append the data and set the cell. */
- memcpy(ud1.data + ud1.size, ud->data, ud->size);
- ud1.size += ud->size;
- grid_cell_set(gc, &ud1);
+ /* Append the data. */
+ memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
+ gc.data.size += ud->size;
+
+ /* Set the new cell. */
+ grid_view_set_cell(gd, s->cx - 1, s->cy, &gc);
return (0);
}
@@ -1052,11 +1044,11 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
- const struct grid_cell *gc;
+ struct grid_cell gc;
u_int xx;
- gc = grid_view_peek_cell(gd, s->cx, s->cy);
- if (gc->flags & GRID_FLAG_PADDING) {
+ grid_view_get_cell(gd, s->cx, s->cy, &gc);
+ if (gc.flags & GRID_FLAG_PADDING) {
/*
* A padding cell, so clear any following and leading padding
* cells back to the character. Don't overwrite the current
@@ -1064,8 +1056,8 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
*/
xx = s->cx + 1;
while (--xx > 0) {
- gc = grid_view_peek_cell(gd, xx, s->cy);
- if (!(gc->flags & GRID_FLAG_PADDING))
+ grid_view_get_cell(gd, xx, s->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
break;
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
}
@@ -1080,8 +1072,8 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
*/
xx = s->cx + width - 1;
while (++xx < screen_size_x(s)) {
- gc = grid_view_peek_cell(gd, xx, s->cy);
- if (!(gc->flags & GRID_FLAG_PADDING))
+ grid_view_get_cell(gd, xx, s->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
break;
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
}