From fdbfc7e3498e1cdd04e8df58aa1a937ee4d79caa Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 18 Jan 2013 02:16:21 +0000 Subject: [PATCH] Rather than having two grids for each pane, one for ASCII and one for UTF-8, collapse the two together. Simplifies the code at the expense of more memory (which can probably be reduced again later). --- Makefile | 2 +- cmd-server-info.c | 32 ++++++-------- format.c | 1 - grid-cell.c | 55 +++++++++++++++++++++++ grid-utf8.c | 96 ----------------------------------------- grid-view.c | 24 +---------- grid.c | 103 +++++-------------------------------------- input.c | 9 ++-- screen-write.c | 108 ++++++++++++++-------------------------------- tmux.h | 49 ++++++--------------- tty.c | 68 +++++++++++------------------ window-copy.c | 83 ++++++++++++++++------------------- 12 files changed, 192 insertions(+), 438 deletions(-) create mode 100644 grid-cell.c delete mode 100644 grid-utf8.c diff --git a/Makefile b/Makefile index 7333f0f1..cebcac8e 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,7 @@ SRCS= arguments.c \ control-notify.c \ environ.c \ format.c \ - grid-utf8.c \ + grid-cell.c \ grid-view.c \ grid.c \ input-keys.c \ diff --git a/cmd-server-info.c b/cmd-server-info.c index 0d09626a..f434f942 100644 --- a/cmd-server-info.c +++ b/cmd-server-info.c @@ -59,12 +59,11 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) struct job *job; struct grid *gd; struct grid_line *gl; - u_int i, j, k; + u_int i, j, k, lines; + size_t size; char out[80]; char *tim; time_t t; - u_int lines, ulines; - size_t size, usize; tim = ctime(&start_time); *strchr(tim, '\n') = '\0'; @@ -97,8 +96,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) } ctx->print(ctx, "%s", ""); - ctx->print(ctx, "Sessions: [%zu/%zu]", - sizeof (struct grid_cell), sizeof (struct grid_utf8)); + ctx->print(ctx, "Sessions: [%zu]", sizeof (struct grid_cell)); RB_FOREACH(s, sessions, &sessions) { t = s->creation_time.tv_sec; tim = ctime(&t); @@ -115,26 +113,20 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) w->lastlayout); j = 0; TAILQ_FOREACH(wp, &w->panes, entry) { - lines = ulines = size = usize = 0; + lines = size = 0; gd = wp->base.grid; for (k = 0; k < gd->hsize + gd->sy; k++) { gl = &gd->linedata[k]; - if (gl->celldata != NULL) { - lines++; - size += gl->cellsize * - sizeof *gl->celldata; - } - if (gl->utf8data != NULL) { - ulines++; - usize += gl->utf8size * - sizeof *gl->utf8data; - } + if (gl->celldata == NULL) + continue; + lines++; + size += gl->cellsize * + sizeof *gl->celldata; } - ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu " - "bytes; UTF-8 %u/%u, %zu bytes", j, + ctx->print(ctx, + "%6u: %s %lu %d %u/%u, %zu bytes", j, wp->tty, (u_long) wp->pid, wp->fd, lines, - gd->hsize + gd->sy, size, ulines, - gd->hsize + gd->sy, usize); + gd->hsize + gd->sy, size); j++; } } diff --git a/format.c b/format.c index 0eeb622d..72c65c28 100644 --- a/format.c +++ b/format.c @@ -370,7 +370,6 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp) for (i = 0; i < gd->hsize; i++) { gl = &gd->linedata[i]; size += gl->cellsize * sizeof *gl->celldata; - size += gl->utf8size * sizeof *gl->utf8data; } size += gd->hsize * sizeof *gd->linedata; diff --git a/grid-cell.c b/grid-cell.c new file mode 100644 index 00000000..09643a9c --- /dev/null +++ b/grid-cell.c @@ -0,0 +1,55 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2012 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "tmux.h" + +/* Get cell width. */ +u_int +grid_cell_width(const struct grid_cell *gc) +{ + return (gc->xstate >> 4); +} + +/* Get cell data. */ +void +grid_cell_get(const struct grid_cell *gc, struct utf8_data *ud) +{ + ud->size = gc->xstate & 0xf; + ud->width = gc->xstate >> 4; + memcpy(ud->data, gc->xdata, ud->size); +} + +/* Set cell data. */ +void +grid_cell_set(struct grid_cell *gc, const struct utf8_data *ud) +{ + memcpy(gc->xdata, ud->data, ud->size); + gc->xstate = (ud->width << 4) | ud->size; +} + +/* Set a single character as cell data. */ +void +grid_cell_one(struct grid_cell *gc, u_char ch) +{ + *gc->xdata = ch; + gc->xstate = (1 << 4) | 1; +} diff --git a/grid-utf8.c b/grid-utf8.c deleted file mode 100644 index 0c829711..00000000 --- a/grid-utf8.c +++ /dev/null @@ -1,96 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2009 Nicholas Marriott - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include - -#include "tmux.h" - -/* - * Grid UTF-8 utility functions. - */ - -/* Calculate UTF-8 grid cell size. Data is terminated by 0xff. */ -size_t -grid_utf8_size(const struct grid_utf8 *gu) -{ - size_t size; - - for (size = 0; size < sizeof gu->data; size++) { - if (gu->data[size] == 0xff) - break; - } - return (size); -} - -/* Copy UTF-8 out into a buffer. */ -size_t -grid_utf8_copy(const struct grid_utf8 *gu, char *buf, size_t len) -{ - size_t size; - - size = grid_utf8_size(gu); - if (size > len) - fatalx("UTF-8 copy overflow"); - memcpy(buf, gu->data, size); - return (size); -} - -/* Set UTF-8 grid data from input UTF-8. */ -void -grid_utf8_set(struct grid_utf8 *gu, const struct utf8_data *utf8data) -{ - if (utf8data->size == 0) - fatalx("UTF-8 data empty"); - if (utf8data->size > sizeof gu->data) - fatalx("UTF-8 data too long"); - memcpy(gu->data, utf8data->data, utf8data->size); - if (utf8data->size != sizeof gu->data) - gu->data[utf8data->size] = 0xff; - gu->width = utf8data->width; -} - -/* Append UTF-8 character onto the cell data (for combined characters). */ -int -grid_utf8_append(struct grid_utf8 *gu, const struct utf8_data *utf8data) -{ - size_t old_size; - - old_size = grid_utf8_size(gu); - if (old_size + utf8data->size > sizeof gu->data) - return (-1); - memcpy(gu->data + old_size, utf8data->data, utf8data->size); - if (old_size + utf8data->size != sizeof gu->data) - gu->data[old_size + utf8data->size] = 0xff; - return (0); -} - -/* Compare two UTF-8 cells. */ -int -grid_utf8_compare(const struct grid_utf8 *gu1, const struct grid_utf8 *gu2) -{ - size_t size; - - size = grid_utf8_size(gu1); - if (size != grid_utf8_size(gu2)) - return (0); - if (memcmp(gu1->data, gu2->data, size) != 0) - return (0); - return (1); -} diff --git a/grid-view.c b/grid-view.c index e36144f0..bde624cc 100644 --- a/grid-view.c +++ b/grid-view.c @@ -52,28 +52,6 @@ grid_view_set_cell( grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc); } -/* Get UTF-8 for reading. */ -const struct grid_utf8 * -grid_view_peek_utf8(struct grid *gd, u_int px, u_int py) -{ - return (grid_peek_utf8(gd, grid_view_x(gd, px), grid_view_y(gd, py))); -} - -/* Get UTF-8 for writing. */ -struct grid_utf8 * -grid_view_get_utf8(struct grid *gd, u_int px, u_int py) -{ - return (grid_get_utf8(gd, grid_view_x(gd, px), grid_view_y(gd, py))); -} - -/* Set UTF-8. */ -void -grid_view_set_utf8( - struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gu) -{ - grid_set_utf8(gd, grid_view_x(gd, px), grid_view_y(gd, py), gu); -} - /* Clear into history. */ void grid_view_clear_history(struct grid *gd) @@ -87,7 +65,7 @@ grid_view_clear_history(struct grid *gd) last = 0; for (yy = 0; yy < gd->sy; yy++) { gl = &gd->linedata[grid_view_y(gd, yy)]; - if (gl->cellsize != 0 || gl->utf8size != 0) + if (gl->cellsize != 0) last = yy + 1; } if (last == 0) diff --git a/grid.c b/grid.c index 91ec7856..da769122 100644 --- a/grid.c +++ b/grid.c @@ -36,8 +36,8 @@ */ /* Default grid cell data. */ -const struct grid_cell grid_default_cell = { 0, 0, 8, 8, ' ' }; -const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, '_' }; +const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " }; +const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, (1 << 4) | 1, "_" }; #define grid_put_cell(gd, px, py, gc) do { \ memcpy(&gd->linedata[py].celldata[px], \ @@ -100,7 +100,6 @@ grid_destroy(struct grid *gd) for (yy = 0; yy < gd->hsize + gd->sy; yy++) { gl = &gd->linedata[yy]; free(gl->celldata); - free(gl->utf8data); } free(gd->linedata); @@ -114,7 +113,6 @@ grid_compare(struct grid *ga, struct grid *gb) { struct grid_line *gla, *glb; struct grid_cell *gca, *gcb; - struct grid_utf8 *gua, *gub; u_int xx, yy; if (ga->sx != gb->sx || ga->sy != ga->sy) @@ -130,12 +128,6 @@ grid_compare(struct grid *ga, struct grid *gb) gcb = &glb->celldata[xx]; if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0) return (1); - if (!(gca->flags & GRID_FLAG_UTF8)) - continue; - gua = &gla->utf8data[xx]; - gub = &glb->utf8data[xx]; - if (memcmp(gua, gub, sizeof (struct grid_utf8)) != 0) - return (1); } } @@ -233,20 +225,6 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx) gl->cellsize = sx; } -/* Expand line to fit to cell for UTF-8. */ -void -grid_expand_line_utf8(struct grid *gd, u_int py, u_int sx) -{ - struct grid_line *gl; - - gl = &gd->linedata[py]; - if (sx <= gl->utf8size) - return; - - gl->utf8data = xrealloc(gl->utf8data, sx, sizeof *gl->utf8data); - gl->utf8size = sx; -} - /* Get cell for reading. */ const struct grid_cell * grid_peek_cell(struct grid *gd, u_int px, u_int py) @@ -282,41 +260,6 @@ grid_set_cell( grid_put_cell(gd, px, py, gc); } -/* Get UTF-8 for reading. */ -const struct grid_utf8 * -grid_peek_utf8(struct grid *gd, u_int px, u_int py) -{ - if (grid_check_y(gd, py) != 0) - return (NULL); - - if (px >= gd->linedata[py].utf8size) - return (NULL); - return (&gd->linedata[py].utf8data[px]); -} - -/* Get utf8 at relative position (for writing). */ -struct grid_utf8 * -grid_get_utf8(struct grid *gd, u_int px, u_int py) -{ - if (grid_check_y(gd, py) != 0) - return (NULL); - - grid_expand_line_utf8(gd, py, px + 1); - return (&gd->linedata[py].utf8data[px]); -} - -/* Set utf8 at relative position. */ -void -grid_set_utf8( - struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gc) -{ - if (grid_check_y(gd, py) != 0) - return; - - grid_expand_line_utf8(gd, py, px + 1); - grid_put_utf8(gd, px, py, gc); -} - /* Clear area. */ void grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) @@ -373,7 +316,6 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny) for (yy = py; yy < py + ny; yy++) { gl = &gd->linedata[yy]; free(gl->celldata); - free(gl->utf8data); memset(gl, 0, sizeof *gl); } } @@ -437,13 +379,6 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx) memmove( &gl->celldata[dx], &gl->celldata[px], nx * sizeof *gl->celldata); - if (gl->utf8data != NULL) { - grid_expand_line_utf8(gd, py, px + nx); - grid_expand_line_utf8(gd, py, dx + nx); - memmove(&gl->utf8data[dx], - &gl->utf8data[px], nx * sizeof *gl->utf8data); - } - /* Wipe any cells that have been moved. */ for (xx = px; xx < px + nx; xx++) { if (xx >= dx && xx < dx + nx) @@ -457,9 +392,9 @@ char * grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) { const struct grid_cell *gc; - const struct grid_utf8 *gu; + struct utf8_data ud; char *buf; - size_t len, off, size; + size_t len, off; u_int xx; GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); @@ -472,25 +407,15 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) gc = grid_peek_cell(gd, xx, py); if (gc->flags & GRID_FLAG_PADDING) continue; + grid_cell_get(gc, &ud); - if (gc->flags & GRID_FLAG_UTF8) { - gu = grid_peek_utf8(gd, xx, py); - - size = grid_utf8_size(gu); - while (len < off + size + 1) { - buf = xrealloc(buf, 2, len); - len *= 2; - } - - off += grid_utf8_copy(gu, buf + off, len - off); - } else { - while (len < off + 2) { - buf = xrealloc(buf, 2, len); - len *= 2; - } - - buf[off++] = gc->data; + while (len < off + ud.size + 1) { + buf = xrealloc(buf, 2, len); + len *= 2; } + + memcpy(buf + off, ud.data, ud.size); + off += ud.size; } while (off > 0 && buf[off - 1] == ' ') @@ -530,12 +455,6 @@ grid_duplicate_lines( memcpy(dstl->celldata, srcl->celldata, srcl->cellsize * sizeof *dstl->celldata); } - if (srcl->utf8size != 0) { - dstl->utf8data = xcalloc( - srcl->utf8size, sizeof *dstl->utf8data); - memcpy(dstl->utf8data, srcl->utf8data, - srcl->utf8size * sizeof *dstl->utf8data); - } sy++; dy++; diff --git a/input.c b/input.c index e04ddc4f..20917fa1 100644 --- a/input.c +++ b/input.c @@ -879,8 +879,8 @@ input_clear(struct input_ctx *ictx) int input_print(struct input_ctx *ictx) { - ictx->cell.data = ictx->ch; - screen_write_cell(&ictx->ctx, &ictx->cell, NULL); + grid_cell_one(&ictx->cell, ictx->ch); + screen_write_cell(&ictx->ctx, &ictx->cell); return (0); } @@ -1657,9 +1657,8 @@ input_utf8_close(struct input_ctx *ictx) utf8_append(&ictx->utf8data, ictx->ch); - ictx->cell.flags |= GRID_FLAG_UTF8; - screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data); - ictx->cell.flags &= ~GRID_FLAG_UTF8; + grid_cell_set(&ictx->cell, &ictx->utf8data); + screen_write_cell(&ictx->ctx, &ictx->cell); return (0); } diff --git a/screen-write.c b/screen-write.c index 4d147b5b..e68e498d 100644 --- a/screen-write.c +++ b/screen-write.c @@ -67,11 +67,10 @@ screen_write_reset(struct screen_write_ctx *ctx) /* Write character. */ void -screen_write_putc( - struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch) +screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch) { - gc->data = ch; - screen_write_cell(ctx, gc, NULL); + grid_cell_one(gc, ch); + screen_write_cell(ctx, gc); } /* Calculate string length, with embedded formatting. */ @@ -203,9 +202,8 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen, } size += utf8data.width; - gc->flags |= GRID_FLAG_UTF8; - screen_write_cell(ctx, gc, &utf8data); - gc->flags &= ~GRID_FLAG_UTF8; + grid_cell_set(gc, &utf8data); + screen_write_cell(ctx, gc); } else { if (maxlen > 0 && size + 1 > (size_t) maxlen) break; @@ -277,9 +275,8 @@ screen_write_cnputs(struct screen_write_ctx *ctx, } size += utf8data.width; - lgc.flags |= GRID_FLAG_UTF8; - screen_write_cell(ctx, &lgc, &utf8data); - lgc.flags &= ~GRID_FLAG_UTF8; + grid_cell_set(&lgc, &utf8data); + screen_write_cell(ctx, &lgc); } else { if (maxlen > 0 && size + 1 > (size_t) maxlen) break; @@ -385,8 +382,7 @@ screen_write_copy(struct screen_write_ctx *ctx, struct grid *gd = src->grid; struct grid_line *gl; const struct grid_cell *gc; - const struct grid_utf8 *gu; - struct utf8_data utf8data; + struct utf8_data ud; u_int xx, yy, cx, cy, ax, bx; cx = s->cx; @@ -414,16 +410,8 @@ screen_write_copy(struct screen_write_ctx *ctx, gc = &grid_default_cell; else gc = &gl->celldata[xx]; - if (!(gc->flags & GRID_FLAG_UTF8)) { - screen_write_cell(ctx, gc, NULL); - continue; - } - /* Reinject the UTF-8 sequence. */ - gu = &gl->utf8data[xx]; - utf8data.size = grid_utf8_copy( - gu, utf8data.data, sizeof utf8data.data); - utf8data.width = gu->width; - screen_write_cell(ctx, gc, &utf8data); + grid_cell_get(gc, &ud); + screen_write_cell(ctx, gc); } if (px + nx == gd->sx && px + nx > gl->cellsize) screen_write_clearendofline(ctx); @@ -442,7 +430,6 @@ screen_write_initctx( struct screen *s = ctx->s; struct grid *gd = s->grid; const struct grid_cell *gc; - const struct grid_utf8 *gu; u_int xx; ttyctx->wp = ctx->wp; @@ -465,10 +452,6 @@ screen_write_initctx( } ttyctx->last_width = xx; memcpy(&ttyctx->last_cell, gc, sizeof ttyctx->last_cell); - if (gc->flags & GRID_FLAG_UTF8) { - gu = grid_view_peek_utf8(gd, screen_size_x(s) - xx, s->cy); - memcpy(&ttyctx->last_utf8, gu, sizeof ttyctx->last_utf8); - } } /* Cursor up by ny. */ @@ -584,7 +567,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx) screen_write_initctx(ctx, &ttyctx, 0); memcpy(&gc, &grid_default_cell, sizeof gc); - gc.data = 'E'; + grid_cell_one(&gc, 'E'); for (yy = 0; yy < screen_size_y(s); yy++) { for (xx = 0; xx < screen_size_x(s); xx++) @@ -1066,26 +1049,20 @@ screen_write_clearhistory(struct screen_write_ctx *ctx) /* Write cell data. */ void -screen_write_cell(struct screen_write_ctx *ctx, - const struct grid_cell *gc, const struct utf8_data *utf8data) +screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) { struct screen *s = ctx->s; struct grid *gd = s->grid; struct tty_ctx ttyctx; - struct grid_utf8 gu; u_int width, xx; struct grid_cell tmp_gc, *tmp_gcp; + struct utf8_data ud; int insert = 0; /* Ignore padding. */ if (gc->flags & GRID_FLAG_PADDING) return; - - /* Find character width. */ - if (gc->flags & GRID_FLAG_UTF8) - width = utf8data->width; - else - width = 1; + width = grid_cell_width(gc); /* * If this is a wide character and there is no room on the screen, for @@ -1102,7 +1079,8 @@ screen_write_cell(struct screen_write_ctx *ctx, * there is space. */ if (width == 0) { - if (screen_write_combine(ctx, utf8data) == 0) { + grid_cell_get(gc, &ud); + if (screen_write_combine(ctx, &ud) == 0) { screen_write_initctx(ctx, &ttyctx, 0); tty_write(tty_cmd_utf8character, &ttyctx); } @@ -1145,11 +1123,6 @@ screen_write_cell(struct screen_write_ctx *ctx, /* Set the cell. */ grid_view_set_cell(gd, s->cx, s->cy, gc); - if (gc->flags & GRID_FLAG_UTF8) { - /* Construct UTF-8 and write it. */ - grid_utf8_set(&gu, utf8data); - grid_view_set_utf8(gd, s->cx, s->cy, &gu); - } /* Move the cursor. */ s->cx += width; @@ -1159,12 +1132,11 @@ screen_write_cell(struct screen_write_ctx *ctx, ttyctx.num = width; tty_write(tty_cmd_insertcharacter, &ttyctx); } - ttyctx.utf8 = &gu; if (screen_check_selection(s, s->cx - width, s->cy)) { memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); - tmp_gc.data = gc->data; - tmp_gc.flags = gc->flags & - ~(GRID_FLAG_FG256|GRID_FLAG_BG256); + grid_cell_get(gc, &ud); + grid_cell_set(&tmp_gc, &ud); + tmp_gc.flags = 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; @@ -1177,49 +1149,33 @@ screen_write_cell(struct screen_write_ctx *ctx, /* Combine a UTF-8 zero-width character onto the previous. */ int -screen_write_combine( - struct screen_write_ctx *ctx, const struct utf8_data *utf8data) +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 grid_utf8 *gu, tmp_gu; - u_int i; + struct utf8_data ud1; /* Can't combine if at 0. */ if (s->cx == 0) return (-1); - /* Empty utf8data is out. */ - if (utf8data->size == 0) + /* Empty data is out. */ + if (ud->size == 0) fatalx("UTF-8 data empty"); - /* Retrieve the previous cell and convert to UTF-8 if not already. */ + /* Retrieve the previous cell. */ gc = grid_view_get_cell(gd, s->cx - 1, s->cy); - if (!(gc->flags & GRID_FLAG_UTF8)) { - tmp_gu.data[0] = gc->data; - tmp_gu.data[1] = 0xff; - tmp_gu.width = 1; + grid_cell_get(gc, &ud1); - grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu); - gc->flags |= GRID_FLAG_UTF8; - } + /* Check there is enough space. */ + if (ud1.size + ud->size > sizeof ud1.data) + return (-1); - /* Append the current cell. */ - gu = grid_view_get_utf8(gd, s->cx - 1, s->cy); - if (grid_utf8_append(gu, utf8data) != 0) { - /* Failed: scrap this character and replace with underscores. */ - if (gu->width == 1) { - gc->data = '_'; - gc->flags &= ~GRID_FLAG_UTF8; - } else { - for (i = 0; i < gu->width && i != sizeof gu->data; i++) - gu->data[i] = '_'; - if (i != sizeof gu->data) - gu->data[i] = 0xff; - gu->width = i; - } - } + /* 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); return (0); } diff --git a/tmux.h b/tmux.h index 9c062d65..9149f6b5 100644 --- a/tmux.h +++ b/tmux.h @@ -669,13 +669,7 @@ struct mode_key_table { #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY) -/* - * A single UTF-8 character. - * - * The data member in this must be UTF8_SIZE to allow screen_write_copy to - * reinject stored UTF-8 data back into screen_write_cell after combining (ugh - * XXX XXX). - */ +/* A single UTF-8 character. */ struct utf8_data { u_char data[UTF8_SIZE]; @@ -709,7 +703,6 @@ struct utf8_data { #define GRID_FLAG_FG256 0x1 #define GRID_FLAG_BG256 0x2 #define GRID_FLAG_PADDING 0x4 -#define GRID_FLAG_UTF8 0x8 /* Grid line flags. */ #define GRID_LINE_WRAPPED 0x1 @@ -720,13 +713,9 @@ struct grid_cell { u_char flags; u_char fg; u_char bg; - u_char data; -} __packed; -/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */ -struct grid_utf8 { - u_char width; - u_char data[UTF8_SIZE]; + u_char xstate; /* top 4 bits width, bottom 4 bits size */ + u_char xdata[UTF8_SIZE]; } __packed; /* Grid line. */ @@ -734,9 +723,6 @@ struct grid_line { u_int cellsize; struct grid_cell *celldata; - u_int utf8size; - struct grid_utf8 *utf8data; - int flags; } __packed; @@ -1233,7 +1219,6 @@ struct tty_ctx { struct window_pane *wp; const struct grid_cell *cell; - const struct grid_utf8 *utf8; u_int num; void *ptr; @@ -1254,7 +1239,6 @@ struct tty_ctx { /* Saved last cell on line. */ struct grid_cell last_cell; - struct grid_utf8 last_utf8; u_int last_width; }; @@ -1623,10 +1607,11 @@ void tty_putcode(struct tty *, enum tty_code_code); void tty_putcode1(struct tty *, enum tty_code_code, int); void tty_putcode2(struct tty *, enum tty_code_code, int, int); void tty_putcode_ptr1(struct tty *, enum tty_code_code, const void *); -void tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *, const void *); +void tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *, + const void *); void tty_puts(struct tty *, const char *); void tty_putc(struct tty *, u_char); -void tty_pututf8(struct tty *, const struct grid_utf8 *); +void tty_putn(struct tty *, const void *, size_t, u_int); void tty_init(struct tty *, struct client *, int, char *); int tty_resize(struct tty *); int tty_set_size(struct tty *, u_int, u_int); @@ -1969,13 +1954,9 @@ void grid_collect_history(struct grid *); void grid_scroll_history(struct grid *); void grid_scroll_history_region(struct grid *, u_int, u_int); void grid_expand_line(struct grid *, u_int, u_int); -void grid_expand_line_utf8(struct grid *, u_int, u_int); const struct grid_cell *grid_peek_cell(struct grid *, u_int, u_int); struct grid_cell *grid_get_cell(struct grid *, u_int, u_int); void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *); -const struct grid_utf8 *grid_peek_utf8(struct grid *, u_int, u_int); -struct grid_utf8 *grid_get_utf8(struct grid *, u_int, u_int); -void grid_set_utf8(struct grid *, u_int, u_int, const struct grid_utf8 *); void grid_clear(struct grid *, u_int, u_int, u_int, u_int); void grid_clear_lines(struct grid *, u_int, u_int); void grid_move_lines(struct grid *, u_int, u_int, u_int); @@ -1984,22 +1965,17 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int); void grid_duplicate_lines( struct grid *, u_int, struct grid *, u_int, u_int); -/* grid-utf8.c */ -size_t grid_utf8_size(const struct grid_utf8 *); -size_t grid_utf8_copy(const struct grid_utf8 *, char *, size_t); -void grid_utf8_set(struct grid_utf8 *, const struct utf8_data *); -int grid_utf8_append(struct grid_utf8 *, const struct utf8_data *); -int grid_utf8_compare(const struct grid_utf8 *, const struct grid_utf8 *); +/* grid-cell.c */ +u_int grid_cell_width(const struct grid_cell *); +void grid_cell_get(const struct grid_cell *, struct utf8_data *); +void grid_cell_set(struct grid_cell *, const struct utf8_data *); +void grid_cell_one(struct grid_cell *, u_char); /* grid-view.c */ const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int); struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int); void grid_view_set_cell( struct grid *, u_int, u_int, const struct grid_cell *); -const struct grid_utf8 *grid_view_peek_utf8(struct grid *, u_int, u_int); -struct grid_utf8 *grid_view_get_utf8(struct grid *, u_int, u_int); -void grid_view_set_utf8( - struct grid *, u_int, u_int, const struct grid_utf8 *); void grid_view_clear_history(struct grid *); void grid_view_clear(struct grid *, u_int, u_int, u_int, u_int); void grid_view_scroll_region_up(struct grid *, u_int, u_int); @@ -2064,8 +2040,7 @@ void screen_write_clearendofscreen(struct screen_write_ctx *); void screen_write_clearstartofscreen(struct screen_write_ctx *); void screen_write_clearscreen(struct screen_write_ctx *); void screen_write_clearhistory(struct screen_write_ctx *); -void screen_write_cell(struct screen_write_ctx *, - const struct grid_cell *, const struct utf8_data *); +void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); void screen_write_bracketpaste(struct screen_write_ctx *, int); diff --git a/tty.c b/tty.c index a650c836..79cac5bb 100644 --- a/tty.c +++ b/tty.c @@ -48,8 +48,7 @@ void tty_redraw_region(struct tty *, const struct tty_ctx *); void tty_emulate_repeat( struct tty *, enum tty_code_code, enum tty_code_code, u_int); void tty_repeat_space(struct tty *, u_int); -void tty_cell(struct tty *, - const struct grid_cell *, const struct grid_utf8 *); +void tty_cell(struct tty *, const struct grid_cell *); #define tty_use_acs(tty) \ (tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) @@ -416,15 +415,12 @@ tty_putc(struct tty *tty, u_char ch) } void -tty_pututf8(struct tty *tty, const struct grid_utf8 *gu) +tty_putn(struct tty *tty, const void *buf, size_t len, u_int width) { - size_t size; - - size = grid_utf8_size(gu); - bufferevent_write(tty->event, gu->data, size); + bufferevent_write(tty->event, buf, len); if (tty->log_fd != -1) - write(tty->log_fd, gu->data, size); - tty->cx += gu->width; + write(tty->log_fd, buf, len); + tty->cx += width; } void @@ -582,7 +578,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy) const struct grid_cell *gc; struct grid_line *gl; struct grid_cell tmpgc; - const struct grid_utf8 *gu; + struct utf8_data ud; u_int i, sx; tty_update_mode(tty, tty->mode & ~MODE_CURSOR, s); @@ -607,21 +603,17 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy) for (i = 0; i < sx; i++) { gc = grid_view_peek_cell(s->grid, i, py); - - gu = NULL; - if (gc->flags & GRID_FLAG_UTF8) - gu = grid_view_peek_utf8(s->grid, i, py); - if (screen_check_selection(s, i, py)) { memcpy(&tmpgc, &s->sel.cell, sizeof tmpgc); - tmpgc.data = gc->data; + grid_cell_get(gc, &ud); + grid_cell_set(&tmpgc, &ud); tmpgc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmpgc.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256); - tty_cell(tty, &tmpgc, gu); + tty_cell(tty, &tmpgc); } else - tty_cell(tty, gc, gu); + tty_cell(tty, gc); } if (sx >= tty->sx) { @@ -984,17 +976,11 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) struct screen *s = wp->screen; u_int cx; u_int width; - const struct grid_cell *gc = ctx->cell; - const struct grid_utf8 *gu = ctx->utf8; - - if (gc->flags & GRID_FLAG_UTF8) - width = gu->width; - else - width = 1; tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); /* Is the cursor in the very last position? */ + width = grid_cell_width(ctx->cell); if (ctx->ocx > wp->sx - width) { if (ctx->xoff != 0 || wp->sx != tty->sx) { /* @@ -1011,17 +997,14 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) * move as far left as possible and redraw the last * cell to move into the last position. */ - if (ctx->last_cell.flags & GRID_FLAG_UTF8) - cx = screen_size_x(s) - ctx->last_utf8.width; - else - cx = screen_size_x(s) - 1; + cx = screen_size_x(s) - grid_cell_width(&ctx->last_cell); tty_cursor_pane(tty, ctx, cx, ctx->ocy); - tty_cell(tty, &ctx->last_cell, &ctx->last_utf8); + tty_cell(tty, &ctx->last_cell); } } else tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - tty_cell(tty, ctx->cell, ctx->utf8); + tty_cell(tty, ctx->cell); } void @@ -1071,10 +1054,10 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) } void -tty_cell( - struct tty *tty, const struct grid_cell *gc, const struct grid_utf8 *gu) +tty_cell(struct tty *tty, const struct grid_cell *gc) { - u_int i; + struct utf8_data ud; + u_int i; /* Skip last character if terminal is stupid. */ if (tty->term->flags & TERM_EARLYWRAP && @@ -1088,23 +1071,24 @@ tty_cell( /* Set the attributes. */ tty_attributes(tty, gc); - /* If not UTF-8, write directly. */ - if (!(gc->flags & GRID_FLAG_UTF8)) { - if (gc->data < 0x20 || gc->data == 0x7f) + /* Get the cell and if ASCII write with putc to do ACS translation. */ + grid_cell_get(gc, &ud); + if (ud.size == 1) { + if (*ud.data < 0x20 || *ud.data == 0x7f) return; - tty_putc(tty, gc->data); + tty_putc(tty, *ud.data); return; } - /* If the terminal doesn't support UTF-8, write underscores. */ + /* If not UTF-8, write _. */ if (!(tty->flags & TTY_UTF8)) { - for (i = 0; i < gu->width; i++) + for (i = 0; i < ud.width; i++) tty_putc(tty, '_'); return; } - /* Otherwise, write UTF-8. */ - tty_pututf8(tty, gu); + /* Write the data. */ + tty_putn(tty, ud.data, ud.size, ud.width); } void diff --git a/window-copy.c b/window-copy.c index 097c056a..79d0c6ed 100644 --- a/window-copy.c +++ b/window-copy.c @@ -908,24 +908,16 @@ window_copy_search_compare( struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx) { const struct grid_cell *gc, *sgc; - const struct grid_utf8 *gu, *sgu; + struct utf8_data ud, sud; gc = grid_peek_cell(gd, px, py); + grid_cell_get(gc, &ud); sgc = grid_peek_cell(sgd, spx, 0); + grid_cell_get(sgc, &sud); - if ((gc->flags & GRID_FLAG_UTF8) != (sgc->flags & GRID_FLAG_UTF8)) + if (ud.size != sud.size || ud.width != sud.width) return (0); - - if (gc->flags & GRID_FLAG_UTF8) { - gu = grid_peek_utf8(gd, px, py); - sgu = grid_peek_utf8(sgd, spx, 0); - if (grid_utf8_compare(gu, sgu)) - return (1); - } else { - if (gc->data == sgc->data) - return (1); - } - return (0); + return (memcmp(ud.data, sud.data, ud.size) == 0); } int @@ -1395,10 +1387,9 @@ window_copy_copy_line(struct window_pane *wp, struct window_copy_mode_data *data = wp->modedata; struct grid *gd = data->backing->grid; const struct grid_cell *gc; - const struct grid_utf8 *gu; struct grid_line *gl; + struct utf8_data ud; u_int i, xx, wrapped = 0; - size_t size; if (sx > ex) return; @@ -1426,15 +1417,11 @@ window_copy_copy_line(struct window_pane *wp, gc = grid_peek_cell(gd, i, sy); if (gc->flags & GRID_FLAG_PADDING) continue; - if (!(gc->flags & GRID_FLAG_UTF8)) { - *buf = xrealloc(*buf, 1, (*off) + 1); - (*buf)[(*off)++] = gc->data; - } else { - gu = grid_peek_utf8(gd, i, sy); - size = grid_utf8_size(gu); - *buf = xrealloc(*buf, 1, (*off) + size); - *off += grid_utf8_copy(gu, *buf + *off, size); - } + grid_cell_get(gc, &ud); + + *buf = xrealloc(*buf, 1, (*off) + ud.size); + memcpy(*buf + *off, ud.data, ud.size); + *off += ud.size; } } @@ -1464,13 +1451,15 @@ window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set) { struct window_copy_mode_data *data = wp->modedata; const struct grid_cell *gc; + struct utf8_data ud; gc = grid_peek_cell(data->backing->grid, px, py); - if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) + grid_cell_get(gc, &ud); + if (ud.size != 1 || gc->flags & GRID_FLAG_PADDING) return (0); - if (gc->data == 0x00 || gc->data == 0x7f) + if (*ud.data == 0x00 || *ud.data == 0x7f) return (0); - return (strchr(set, gc->data) != NULL); + return (strchr(set, *ud.data) != NULL); } u_int @@ -1479,6 +1468,7 @@ window_copy_find_length(struct window_pane *wp, u_int py) struct window_copy_mode_data *data = wp->modedata; struct screen *s = data->backing; const struct grid_cell *gc; + struct utf8_data ud; u_int px; /* @@ -1492,9 +1482,8 @@ window_copy_find_length(struct window_pane *wp, u_int py) px = screen_size_x(s); while (px > 0) { gc = grid_peek_cell(s->grid, px - 1, py); - if (gc->flags & GRID_FLAG_UTF8) - break; - if (gc->data != ' ') + grid_cell_get(gc, &ud); + if (ud.size != 1 || *ud.data != ' ') break; px--; } @@ -1527,6 +1516,7 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp) struct window_copy_mode_data *data = wp->modedata; u_int px, py, xx; const struct grid_cell *gc; + struct utf8_data ud; px = 0; py = screen_hsize(data->backing) + data->cy - data->oy; @@ -1534,9 +1524,8 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp) while (px < xx) { gc = grid_peek_cell(data->backing->grid, px, py); - if (gc->flags & GRID_FLAG_UTF8) - break; - if (gc->data != ' ') + grid_cell_get(gc, &ud); + if (ud.size != 1 || *ud.data != ' ') break; px++; } @@ -1696,6 +1685,7 @@ window_copy_cursor_jump(struct window_pane *wp) struct window_copy_mode_data *data = wp->modedata; struct screen *back_s = data->backing; const struct grid_cell *gc; + struct utf8_data ud; u_int px, py, xx; px = data->cx + 1; @@ -1704,9 +1694,9 @@ window_copy_cursor_jump(struct window_pane *wp) while (px < xx) { gc = grid_peek_cell(back_s->grid, px, py); - if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 - && gc->data == data->jumpchar) { - + grid_cell_get(gc, &ud); + if (!(gc->flags & GRID_FLAG_PADDING) && + ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px, data->cy); if (window_copy_update_selection(wp)) window_copy_redraw_lines(wp, data->cy, 1); @@ -1722,6 +1712,7 @@ window_copy_cursor_jump_back(struct window_pane *wp) struct window_copy_mode_data *data = wp->modedata; struct screen *back_s = data->backing; const struct grid_cell *gc; + struct utf8_data ud; u_int px, py; px = data->cx; @@ -1732,9 +1723,9 @@ window_copy_cursor_jump_back(struct window_pane *wp) for (;;) { gc = grid_peek_cell(back_s->grid, px, py); - if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 - && gc->data == data->jumpchar) { - + grid_cell_get(gc, &ud); + if (!(gc->flags & GRID_FLAG_PADDING) && + ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px, data->cy); if (window_copy_update_selection(wp)) window_copy_redraw_lines(wp, data->cy, 1); @@ -1752,6 +1743,7 @@ window_copy_cursor_jump_to(struct window_pane *wp) struct window_copy_mode_data *data = wp->modedata; struct screen *back_s = data->backing; const struct grid_cell *gc; + struct utf8_data ud; u_int px, py, xx; px = data->cx + 1; @@ -1760,9 +1752,9 @@ window_copy_cursor_jump_to(struct window_pane *wp) while (px < xx) { gc = grid_peek_cell(back_s->grid, px, py); - if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 - && gc->data == data->jumpchar) { - + grid_cell_get(gc, &ud); + if (!(gc->flags & GRID_FLAG_PADDING) && + ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px - 1, data->cy); if (window_copy_update_selection(wp)) window_copy_redraw_lines(wp, data->cy, 1); @@ -1778,6 +1770,7 @@ window_copy_cursor_jump_to_back(struct window_pane *wp) struct window_copy_mode_data *data = wp->modedata; struct screen *back_s = data->backing; const struct grid_cell *gc; + struct utf8_data ud; u_int px, py; px = data->cx; @@ -1788,9 +1781,9 @@ window_copy_cursor_jump_to_back(struct window_pane *wp) for (;;) { gc = grid_peek_cell(back_s->grid, px, py); - if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 - && gc->data == data->jumpchar) { - + grid_cell_get(gc, &ud); + if (!(gc->flags & GRID_FLAG_PADDING) && + ud.size == 1 && *ud.data == data->jumpchar) { window_copy_update_cursor(wp, px + 1, data->cy); if (window_copy_update_selection(wp)) window_copy_redraw_lines(wp, data->cy, 1);