Step 2 of the Grand Plan To Make UTF-8 Better.

Split grid into two arrays, one containing grid attributes/flags/colours (keeps
the name grid_cell for now) and a separate with the character data (called
text). The text is stored as a u_short but is treated as a uint64_t elsewhere;
eventually the grid will have two arrays.

I'm not happy with the naming so that might change.

Still need to decide where to go from here. I'm not sure whether to combine
the peek/set functions together, and also whether to continue to treat the
text as a uint64_t (and convert to/from Unicode) or make it a char array
(of size one when UTF-8 disabled, eight when enabled) and keep everything
as UTF-8.

Also since UTF-8 will eventually become an attribute of the grid itself it
might be nice to move all the padding crap into grid.c.
This commit is contained in:
Nicholas Marriott 2009-03-28 16:30:05 +00:00
parent 5872633aef
commit 6c0728fe07
10 changed files with 167 additions and 89 deletions

View File

@ -1,4 +1,4 @@
/* $Id: cmd-find-window.c,v 1.3 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-find-window.c,v 1.4 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -163,19 +163,19 @@ cmd_find_window_callback(void *data, int idx)
char * char *
cmd_find_window_search(struct window_pane *wp, const char *searchstr) cmd_find_window_search(struct window_pane *wp, const char *searchstr)
{ {
char *buf, *s; char *buf, *s;
size_t off; size_t off;
const struct grid_cell *gc; uint64_t text;
u_int i, j, k; u_int i, j, k;
u_char data[4]; u_char data[4];
buf = xmalloc(1); buf = xmalloc(1);
for (j = 0; j < screen_size_y(&wp->base); j++) { for (j = 0; j < screen_size_y(&wp->base); j++) {
off = 0; off = 0;
for (i = 0; i < screen_size_x(&wp->base); i++) { for (i = 0; i < screen_size_x(&wp->base); i++) {
gc = grid_view_peek_cell(wp->base.grid, i, j); text = grid_view_peek_text(wp->base.grid, i, j);
utf8_split(gc->data, data); utf8_split(text, data);
buf = xrealloc(buf, 1, off + 4); buf = xrealloc(buf, 1, off + 4);
for (k = 0; k < sizeof data; k++) { for (k = 0; k < sizeof data; k++) {

View File

@ -1,4 +1,4 @@
/* $Id: cmd-list-windows.c,v 1.31 2009-03-28 15:43:41 nicm Exp $ */ /* $Id: cmd-list-windows.c,v 1.32 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -66,8 +66,10 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
gd = wp->base.grid; gd = wp->base.grid;
size = 0; size = 0;
for (i = 0; i < gd->hsize; i++) for (i = 0; i < gd->hsize; i++) {
size += gd->size[i] * sizeof **gd->data; size += gd->size[i] * sizeof **gd->data;
size += gd->size[i] * sizeof (u_short);
}
size += gd->hsize * (sizeof *gd->data); size += gd->hsize * (sizeof *gd->data);
size += gd->hsize * (sizeof *gd->size); size += gd->hsize * (sizeof *gd->size);

View File

@ -1,4 +1,4 @@
/* $Id: grid-view.c,v 1.7 2009-03-28 15:43:41 nicm Exp $ */ /* $Id: grid-view.c,v 1.8 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -37,6 +37,13 @@ grid_view_peek_cell(struct grid *gd, u_int px, u_int py)
return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py))); return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
} }
/* Get cell text. */
uint64_t
grid_view_peek_text(struct grid *gd, u_int px, u_int py)
{
return (grid_peek_text(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
}
/* Get cell for writing. */ /* Get cell for writing. */
struct grid_cell * struct grid_cell *
grid_view_get_cell(struct grid *gd, u_int px, u_int py) grid_view_get_cell(struct grid *gd, u_int px, u_int py)
@ -52,6 +59,13 @@ grid_view_set_cell(
grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc); grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
} }
/* Set text. */
void
grid_view_set_text(struct grid *gd, u_int px, u_int py, uint64_t text)
{
grid_set_text(gd, grid_view_x(gd, px), grid_view_y(gd, py), text);
}
/* Clear area. */ /* Clear area. */
void void
grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)

62
grid.c
View File

@ -1,4 +1,4 @@
/* $Id: grid.c,v 1.10 2009-03-28 15:43:41 nicm Exp $ */ /* $Id: grid.c,v 1.11 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -35,11 +35,14 @@
*/ */
/* Default grid cell data. */ /* Default grid cell data. */
const struct grid_cell grid_default_cell = { ' ', 0, 0, 8, 8 }; const struct grid_cell grid_default_cell = { 0, 0, 8, 8 };
#define grid_put_cell(gd, px, py, gc) do { \ #define grid_put_cell(gd, px, py, gc) do { \
memcpy(&gd->data[py][px], gc, sizeof gd->data[py][px]); \ memcpy(&gd->data[py][px], gc, sizeof gd->data[py][px]); \
} while (0) } while (0)
#define grid_put_text(gd, px, py, xtext) do { \
gd->text[py][px] = xtext; \
} while (0)
int grid_check_x(struct grid *, u_int); int grid_check_x(struct grid *, u_int);
int grid_check_y(struct grid *, u_int); int grid_check_y(struct grid *, u_int);
@ -97,6 +100,7 @@ grid_create(u_int sx, u_int sy, u_int hlimit)
gd->size = xcalloc(gd->sy, sizeof *gd->size); gd->size = xcalloc(gd->sy, sizeof *gd->size);
gd->data = xcalloc(gd->sy, sizeof *gd->data); gd->data = xcalloc(gd->sy, sizeof *gd->data);
gd->text = xcalloc(gd->sy, sizeof *gd->text);
return (gd); return (gd);
} }
@ -108,10 +112,14 @@ grid_destroy(struct grid *gd)
u_int yy; u_int yy;
for (yy = 0; yy < gd->hsize + gd->sy; yy++) { for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
if (gd->text[yy] != NULL)
xfree(gd->text[yy]);
if (gd->data[yy] != NULL) if (gd->data[yy] != NULL)
xfree(gd->data[yy]); xfree(gd->data[yy]);
} }
if (gd->text != NULL)
xfree(gd->text);
if (gd->data != NULL) if (gd->data != NULL)
xfree(gd->data); xfree(gd->data);
if (gd->size != NULL) if (gd->size != NULL)
@ -164,8 +172,10 @@ grid_scroll_line(struct grid *gd)
yy = gd->hsize + gd->sy; yy = gd->hsize + gd->sy;
gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size); gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size);
gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data); gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data);
gd->text = xrealloc(gd->text, yy + 1, sizeof *gd->text);
gd->data[yy] = NULL; gd->data[yy] = NULL;
gd->text[yy] = NULL;
gd->size[yy] = 0; gd->size[yy] = 0;
gd->hsize++; gd->hsize++;
@ -179,6 +189,7 @@ grid_reduce_line(struct grid *gd, u_int py, u_int sx)
return; return;
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data); gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
gd->text[py] = xrealloc(gd->text[py], sx, sizeof **gd->text);
gd->size[py] = sx; gd->size[py] = sx;
} }
@ -192,8 +203,11 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx)
return; return;
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data); gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
for (xx = gd->size[py]; xx < sx; xx++) gd->text[py] = xrealloc(gd->text[py], sx, sizeof **gd->text);
for (xx = gd->size[py]; xx < sx; xx++) {
grid_put_cell(gd, xx, py, &grid_default_cell); grid_put_cell(gd, xx, py, &grid_default_cell);
grid_put_text(gd, xx, py, ' ');
}
gd->size[py] = sx; gd->size[py] = sx;
} }
@ -211,6 +225,20 @@ grid_peek_cell(struct grid *gd, u_int px, u_int py)
return (&gd->data[py][px]); return (&gd->data[py][px]);
} }
/* Get text for reading. */
uint64_t
grid_peek_text(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (' ');
if (grid_check_y(gd, py) != 0)
return (' ');
if (px >= gd->size[py])
return (' ');
return (gd->text[py][px]);
}
/* Get cell at relative position (for writing). */ /* Get cell at relative position (for writing). */
struct grid_cell * struct grid_cell *
grid_get_cell(struct grid *gd, u_int px, u_int py) grid_get_cell(struct grid *gd, u_int px, u_int py)
@ -238,6 +266,19 @@ grid_set_cell(
grid_put_cell(gd, px, py, gc); grid_put_cell(gd, px, py, gc);
} }
/* Set text at relative position. */
void
grid_set_text(struct grid *gd, u_int px, u_int py, uint64_t text)
{
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
grid_expand_line(gd, py, px + 1);
grid_put_text(gd, px, py, text);
}
/* /*
* Clear area. Note this is different from a fill as it just omits unallocated * Clear area. Note this is different from a fill as it just omits unallocated
* cells. * cells.
@ -321,9 +362,11 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny)
return; return;
for (yy = py; yy < py + ny; yy++) { for (yy = py; yy < py + ny; yy++) {
if (gd->data[yy] != NULL) { if (gd->data[yy] != NULL || gd->text[yy] != NULL) {
xfree(gd->data[yy]); xfree(gd->data[yy]);
gd->data[yy] = NULL; xfree(gd->text[yy]);
gd->data[yy] = NULL;
gd->text[yy] = NULL;
gd->size[yy] = 0; gd->size[yy] = 0;
} }
} }
@ -364,7 +407,8 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
grid_clear_lines(gd, yy, 1); grid_clear_lines(gd, yy, 1);
} }
memmove(&gd->data[dy], &gd->data[py], ny * (sizeof *gd->data)); memmove(&gd->data[dy], &gd->data[py], ny * (sizeof *gd->data));
memmove(&gd->text[dy], &gd->text[py], ny * (sizeof *gd->text));
memmove(&gd->size[dy], &gd->size[py], ny * (sizeof *gd->size)); memmove(&gd->size[dy], &gd->size[py], ny * (sizeof *gd->size));
/* Wipe any lines that have been moved (without freeing them). */ /* Wipe any lines that have been moved (without freeing them). */
@ -372,6 +416,7 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
if (yy >= dy && yy < dy + ny) if (yy >= dy && yy < dy + ny)
continue; continue;
gd->data[yy] = NULL; gd->data[yy] = NULL;
gd->text[yy] = NULL;
gd->size[yy] = 0; gd->size[yy] = 0;
} }
} }
@ -424,13 +469,14 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
grid_expand_line(gd, py, px + nx); grid_expand_line(gd, py, px + nx);
grid_expand_line(gd, py, dx + nx); grid_expand_line(gd, py, dx + nx);
memmove(&gd->data[py][dx], &gd->data[py][px], nx * (sizeof **gd->data)); memmove(&gd->data[py][dx], &gd->data[py][px], nx * (sizeof **gd->data));
memmove(&gd->text[py][dx], &gd->text[py][px], nx * (sizeof **gd->text));
/* Wipe any cells that have been moved. */ /* Wipe any cells that have been moved. */
for (xx = px; xx < px + nx; xx++) { for (xx = px; xx < px + nx; xx++) {
if (xx >= dx && xx < dx + nx) if (xx >= dx && xx < dx + nx)
continue; continue;
memcpy( grid_put_cell(gd, xx, py, &grid_default_cell);
&gd->data[py][xx], &grid_default_cell, sizeof **gd->data); grid_put_text(gd, xx, py, ' ' );
} }
} }

10
input.c
View File

@ -1,4 +1,4 @@
/* $Id: input.c,v 1.74 2009-01-18 21:46:30 nicm Exp $ */ /* $Id: input.c,v 1.75 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -541,9 +541,9 @@ input_state_utf8(u_char ch, struct input_ctx *ictx)
if (value > 0xffff) /* non-BMP not supported */ if (value > 0xffff) /* non-BMP not supported */
value = '_'; value = '_';
ictx->cell.data = value; ictx->text = value;
ictx->cell.flags |= GRID_FLAG_UTF8; ictx->cell.flags |= GRID_FLAG_UTF8;
screen_write_cell(&ictx->ctx, &ictx->cell); screen_write_cell(&ictx->ctx, &ictx->cell, ictx->text);
ictx->cell.flags &= ~GRID_FLAG_UTF8; ictx->cell.flags &= ~GRID_FLAG_UTF8;
} }
@ -585,8 +585,8 @@ input_handle_character(u_char ch, struct input_ctx *ictx)
} }
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch); log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
ictx->cell.data = ch; ictx->text = ch;
screen_write_cell(&ictx->ctx, &ictx->cell); screen_write_cell(&ictx->ctx, &ictx->cell, ictx->text);
} }
void void

View File

@ -1,4 +1,4 @@
/* $Id: screen-write.c,v 1.38 2009-03-28 15:43:41 nicm Exp $ */ /* $Id: screen-write.c,v 1.39 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -47,8 +47,7 @@ void
screen_write_putc( screen_write_putc(
struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch) struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch)
{ {
gc->data = ch; screen_write_cell(ctx, gc, ch);
screen_write_cell(ctx, gc);
} }
/* Write string. */ /* Write string. */
@ -77,17 +76,21 @@ screen_write_copy(struct screen_write_ctx *ctx,
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = src->grid; struct grid *gd = src->grid;
const struct grid_cell *gc; const struct grid_cell *gc;
uint64_t text;
u_int xx, yy, cx, cy; u_int xx, yy, cx, cy;
cx = s->cx; cx = s->cx;
cy = s->cy; cy = s->cy;
for (yy = py; yy < py + ny; yy++) { for (yy = py; yy < py + ny; yy++) {
for (xx = px; xx < px + nx; xx++) { for (xx = px; xx < px + nx; xx++) {
if (xx >= gd->sx || yy >= gd->hsize + gd->sy) if (xx >= gd->sx || yy >= gd->hsize + gd->sy) {
gc = &grid_default_cell; gc = &grid_default_cell;
else text = ' ';
} else {
gc = grid_peek_cell(gd, xx, yy); gc = grid_peek_cell(gd, xx, yy);
screen_write_cell(ctx, gc); text = grid_peek_text(gd, xx, yy);
}
screen_write_cell(ctx, gc, text);
} }
cy++; cy++;
screen_write_cursormove(ctx, cx, cy); screen_write_cursormove(ctx, cx, cy);
@ -513,17 +516,19 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
/* Write cell data. */ /* Write cell data. */
void void
screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) screen_write_cell(
struct screen_write_ctx *ctx, const struct grid_cell *gc, uint64_t text)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
u_int width, xx; u_int width, xx;
const struct grid_cell *hc; const struct grid_cell *hc;
uint64_t htext;
struct grid_cell *ic, tc; struct grid_cell *ic, tc;
/* Find character width. */ /* Find character width. */
if (gc->flags & GRID_FLAG_UTF8) if (gc->flags & GRID_FLAG_UTF8)
width = utf8_width(gc->data); width = utf8_width(text);
else else
width = 1; width = 1;
@ -534,8 +539,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
/* If the character is wider than the screen, don't print it. */ /* If the character is wider than the screen, don't print it. */
if (width > screen_size_x(s)) { if (width > screen_size_x(s)) {
memcpy(&tc, gc, sizeof tc); memcpy(&tc, gc, sizeof tc);
tc.data = '_'; text = '_';
width = 1; width = 1;
gc = &tc; gc = &tc;
} }
@ -560,6 +564,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* which covered by the same character. * which covered by the same character.
*/ */
hc = grid_view_peek_cell(gd, s->cx, s->cy); hc = grid_view_peek_cell(gd, s->cx, s->cy);
htext = grid_view_peek_text(gd, s->cx, s->cy);
if (hc->flags & GRID_FLAG_PADDING) { if (hc->flags & GRID_FLAG_PADDING) {
/* /*
* A padding cell, so clear any following and leading padding * A padding cell, so clear any following and leading padding
@ -585,7 +590,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
break; break;
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
} }
} else if (hc->flags & GRID_FLAG_UTF8 && utf8_width(hc->data) > 1) { } else if (hc->flags & GRID_FLAG_UTF8 && utf8_width(htext) > 1) {
/* /*
* An UTF-8 wide cell; overwrite following padding cells only. * An UTF-8 wide cell; overwrite following padding cells only.
*/ */
@ -610,16 +615,15 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
/* Set the cell. */ /* Set the cell. */
grid_view_set_cell(gd, s->cx, s->cy, gc); grid_view_set_cell(gd, s->cx, s->cy, gc);
grid_view_set_text(gd, s->cx, s->cy, text);
/* Move the cursor. */ /* Move the cursor. */
screen_write_save(ctx); screen_write_save(ctx);
s->cx += width; s->cx += width;
/* Draw to the screen if necessary. */ /* Draw to the screen if necessary. */
if (screen_check_selection(s, s->cx - width, s->cy)) { if (screen_check_selection(s, s->cx - width, s->cy))
memcpy(&tc, &s->sel.cell, sizeof tc); tty_write_cmd(ctx->wp, TTY_CELL, &s->sel.cell, text);
tc.data = gc->data; else
tty_write_cmd(ctx->wp, TTY_CELL, &tc); tty_write_cmd(ctx->wp, TTY_CELL, gc, text);
} else
tty_write_cmd(ctx->wp, TTY_CELL, gc);
} }

View File

@ -1,4 +1,4 @@
/* $Id: screen.c,v 1.79 2009-03-28 15:43:41 nicm Exp $ */ /* $Id: screen.c,v 1.80 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -89,6 +89,7 @@ screen_resize_x(struct screen *s, u_int sx)
{ {
struct grid *gd = s->grid; struct grid *gd = s->grid;
const struct grid_cell *gc; const struct grid_cell *gc;
uint64_t text;
u_int xx, yy; u_int xx, yy;
if (sx == 0) if (sx == 0)
@ -106,14 +107,15 @@ screen_resize_x(struct screen *s, u_int sx)
* If the character after the last is wide or padding, remove * If the character after the last is wide or padding, remove
* it and any leading padding. * it and any leading padding.
*/ */
gc = &grid_default_cell; text = ' ';
for (xx = sx; xx > 0; xx--) { for (xx = sx; xx > 0; xx--) {
gc = grid_peek_cell(gd, xx - 1, yy); gc = grid_peek_cell(gd, xx - 1, yy);
text = grid_peek_text(gd, xx - 1, yy);
if (!(gc->flags & GRID_FLAG_PADDING)) if (!(gc->flags & GRID_FLAG_PADDING))
break; break;
grid_set_cell(gd, xx - 1, yy, &grid_default_cell); grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
} }
if (xx > 0 && xx != sx && utf8_width(gc->data) != 1) if (xx > 0 && xx != sx && utf8_width(text) != 1)
grid_set_cell(gd, xx - 1, yy, &grid_default_cell); grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
/* Reduce the line size. */ /* Reduce the line size. */
@ -165,6 +167,7 @@ screen_resize_y(struct screen *s, u_int sy)
/* Resize line arrays. */ /* Resize line arrays. */
gd->size = xrealloc(gd->size, gd->hsize + sy, sizeof *gd->size); gd->size = xrealloc(gd->size, gd->hsize + sy, sizeof *gd->size);
gd->data = xrealloc(gd->data, gd->hsize + sy, sizeof *gd->data); gd->data = xrealloc(gd->data, gd->hsize + sy, sizeof *gd->data);
gd->text = xrealloc(gd->text, gd->hsize + sy, sizeof *gd->text);
/* Size increasing. */ /* Size increasing. */
if (sy > screen_size_y(s)) { if (sy > screen_size_y(s)) {
@ -172,6 +175,7 @@ screen_resize_y(struct screen *s, u_int sy)
for (yy = gd->hsize + oy; yy < gd->hsize + sy; yy++) { for (yy = gd->hsize + oy; yy < gd->hsize + sy; yy++) {
gd->size[yy] = 0; gd->size[yy] = 0;
gd->data[yy] = NULL; gd->data[yy] = NULL;
gd->text[yy] = NULL;
} }
} }

29
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.287 2009-03-28 15:43:41 nicm Exp $ */ /* $Id: tmux.h,v 1.288 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -482,16 +482,15 @@ struct mode_key_data {
#define GRID_FLAG_PADDING 0x4 #define GRID_FLAG_PADDING 0x4
#define GRID_FLAG_UTF8 0x8 #define GRID_FLAG_UTF8 0x8
/* Grid cell. */ /* Grid cell attributes. */
struct grid_cell { struct grid_cell {
u_short data;
u_char attr; u_char attr;
u_char flags; u_char flags;
u_char fg; u_char fg;
u_char bg; u_char bg;
} __packed; } __packed;
/* Grid data. */ /* Entire grid of cells. */
struct grid { struct grid {
u_int sx; u_int sx;
u_int sy; u_int sy;
@ -499,8 +498,10 @@ struct grid {
u_int hsize; u_int hsize;
u_int hlimit; u_int hlimit;
u_int *size; u_int *size; /* row size */
struct grid_cell **data; struct grid_cell **data;
uint16_t **text;
}; };
/* Option data structures. */ /* Option data structures. */
@ -589,7 +590,8 @@ struct input_ctx {
size_t len; size_t len;
size_t off; size_t off;
struct grid_cell cell; /* current cell data */ struct grid_cell cell;
uint64_t text;
struct grid_cell saved_cell; struct grid_cell saved_cell;
u_int saved_cx; u_int saved_cx;
@ -1054,7 +1056,7 @@ long long options_get_number(struct options *, const char *);
void tty_reset(struct tty *); void tty_reset(struct tty *);
void tty_region(struct tty *, u_int, u_int, u_int); void tty_region(struct tty *, u_int, u_int, u_int);
void tty_cursor(struct tty *, u_int, u_int, u_int); void tty_cursor(struct tty *, u_int, u_int, u_int);
void tty_cell(struct tty *, const struct grid_cell *); void tty_cell(struct tty *, const struct grid_cell *, uint64_t);
void tty_putcode(struct tty *, enum tty_code_code); void tty_putcode(struct tty *, enum tty_code_code);
void tty_putcode1(struct tty *, enum tty_code_code, int); void tty_putcode1(struct tty *, enum tty_code_code, int);
void tty_putcode2(struct tty *, enum tty_code_code, int, int); void tty_putcode2(struct tty *, enum tty_code_code, int, int);
@ -1373,8 +1375,9 @@ void grid_expand_line(struct grid *, u_int, u_int);
void grid_scroll_line(struct grid *); void grid_scroll_line(struct grid *);
const struct grid_cell *grid_peek_cell(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); struct grid_cell *grid_get_cell(struct grid *, u_int, u_int);
void grid_set_cell( void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
struct grid *, u_int, u_int, const struct grid_cell *); uint64_t grid_peek_text(struct grid *, u_int, u_int);
void grid_set_text(struct grid *, u_int, u_int, uint64_t);
void grid_clear(struct grid *, u_int, u_int, u_int, u_int); void grid_clear(struct grid *, u_int, u_int, u_int, u_int);
void grid_fill(struct grid *, void grid_fill(struct grid *,
const struct grid_cell *, u_int, u_int, u_int, u_int); const struct grid_cell *, u_int, u_int, u_int, u_int);
@ -1387,9 +1390,12 @@ void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int);
/* grid-view.c */ /* grid-view.c */
const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int); const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int);
uint64_t grid_view_peek_text(struct grid *, u_int, u_int);
struct grid_cell *grid_view_get_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( void grid_view_set_cell(
struct grid *, u_int, u_int, const struct grid_cell *); struct grid *, u_int, u_int, const struct grid_cell *);
uint64_t grid_view_peek_text(struct grid *, u_int, u_int);
void grid_view_set_text(struct grid *, u_int, u_int, uint64_t);
void grid_view_clear(struct grid *, u_int, u_int, u_int, u_int); void grid_view_clear(struct grid *, u_int, u_int, u_int, u_int);
void grid_view_fill(struct grid *, void grid_view_fill(struct grid *,
const struct grid_cell *, u_int, u_int, u_int, u_int); const struct grid_cell *, u_int, u_int, u_int, u_int);
@ -1438,7 +1444,8 @@ void screen_write_kkeypadmode(struct screen_write_ctx *, int);
void screen_write_clearendofscreen(struct screen_write_ctx *); void screen_write_clearendofscreen(struct screen_write_ctx *);
void screen_write_clearstartofscreen(struct screen_write_ctx *); void screen_write_clearstartofscreen(struct screen_write_ctx *);
void screen_write_clearscreen(struct screen_write_ctx *); void screen_write_clearscreen(struct screen_write_ctx *);
void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_cell(
struct screen_write_ctx *, const struct grid_cell *, uint64_t);
/* screen-redraw.c */ /* screen-redraw.c */
void screen_redraw_screen(struct client *, struct screen *); void screen_redraw_screen(struct client *, struct screen *);

41
tty.c
View File

@ -1,4 +1,4 @@
/* $Id: tty.c,v 1.83 2009-03-28 10:15:01 nicm Exp $ */ /* $Id: tty.c,v 1.84 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -381,8 +381,8 @@ tty_emulate_repeat(
void void
tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int oy) tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int oy)
{ {
const struct grid_cell *gc; const struct grid_cell *gc;
struct grid_cell tc; uint64_t text;
u_int i, sx; u_int i, sx;
sx = screen_size_x(s); sx = screen_size_x(s);
@ -393,15 +393,13 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int oy)
for (i = 0; i < sx; i++) { for (i = 0; i < sx; i++) {
gc = grid_view_peek_cell(s->grid, i, py); gc = grid_view_peek_cell(s->grid, i, py);
text = grid_view_peek_text(s->grid, i, py);
if (screen_check_selection(s, i, py)) {
memcpy(&tc, &s->sel.cell, sizeof tc);
tc.data = gc->data;
gc = &tc;
}
tty_cursor(tty, i, py, oy); tty_cursor(tty, i, py, oy);
tty_cell(tty, gc); if (screen_check_selection(s, i, py))
tty_cell(tty, &s->sel.cell, text);
else
tty_cell(tty, gc, text);
} }
if (sx >= tty->sx) if (sx >= tty->sx)
@ -739,16 +737,18 @@ tty_cmd_cell(struct tty *tty, struct window_pane *wp, va_list ap)
{ {
struct screen *s = wp->screen; struct screen *s = wp->screen;
struct grid_cell *gc; struct grid_cell *gc;
uint64_t text;
gc = va_arg(ap, struct grid_cell *); gc = va_arg(ap, struct grid_cell *);
text = va_arg(ap, uint64_t);
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff); tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
tty_cell(tty, gc); tty_cell(tty, gc, text);
} }
void void
tty_cell(struct tty *tty, const struct grid_cell *gc) tty_cell(struct tty *tty, const struct grid_cell *gc, uint64_t text)
{ {
u_int i, width; u_int i, width;
u_char out[4]; u_char out[4];
@ -767,22 +767,22 @@ tty_cell(struct tty *tty, const struct grid_cell *gc)
/* If not UTF-8, write directly. */ /* If not UTF-8, write directly. */
if (!(gc->flags & GRID_FLAG_UTF8)) { if (!(gc->flags & GRID_FLAG_UTF8)) {
if (gc->data > 0xff || gc->data < 0x20 || gc->data == 0x7f) if (text > 0xff || text < 0x20 || text == 0x7f)
return; return;
tty_putc(tty, gc->data); tty_putc(tty, text);
return; return;
} }
/* If the terminal doesn't support UTF-8, write underscores. */ /* If the terminal doesn't support UTF-8, write underscores. */
if (!(tty->flags & TTY_UTF8)) { if (!(tty->flags & TTY_UTF8)) {
width = utf8_width(gc->data); width = utf8_width(text);
while (width-- > 0) while (width-- > 0)
tty_putc(tty, '_'); tty_putc(tty, '_');
return; return;
} }
/* Otherwise, unpack UTF-8 and write it. */ /* Otherwise, unpack UTF-8 and write it. */
utf8_split(gc->data, out); utf8_split(text, out);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (out[i] == 0xff) if (out[i] == 0xff)
break; break;
@ -793,16 +793,15 @@ tty_cell(struct tty *tty, const struct grid_cell *gc)
void void
tty_reset(struct tty *tty) tty_reset(struct tty *tty)
{ {
struct grid_cell *tc = &tty->cell; struct grid_cell *gc = &tty->cell;
tc->data = grid_default_cell.data; if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
if (memcmp(tc, &grid_default_cell, sizeof *tc) == 0)
return; return;
if (tty_term_has(tty->term, TTYC_RMACS) && tc->attr & GRID_ATTR_CHARSET) if (tty_term_has(tty->term, TTYC_RMACS) && gc->attr & GRID_ATTR_CHARSET)
tty_putcode(tty, TTYC_RMACS); tty_putcode(tty, TTYC_RMACS);
tty_putcode(tty, TTYC_SGR0); tty_putcode(tty, TTYC_SGR0);
memcpy(tc, &grid_default_cell, sizeof *tc); memcpy(gc, &grid_default_cell, sizeof *gc);
} }
void void

View File

@ -1,4 +1,4 @@
/* $Id: window-copy.c,v 1.50 2009-02-13 21:39:45 nicm Exp $ */ /* $Id: window-copy.c,v 1.51 2009-03-28 16:30:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -465,9 +465,9 @@ void
window_copy_copy_line( window_copy_copy_line(
struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex) struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
{ {
const struct grid_cell *gc; u_int i, j, xx;
u_int i, j, xx; uint64_t text;
u_char data[4]; u_char data[4];
if (sx > ex) if (sx > ex)
return; return;
@ -480,8 +480,8 @@ window_copy_copy_line(
if (sx < ex) { if (sx < ex) {
for (i = sx; i < ex; i++) { for (i = sx; i < ex; i++) {
gc = grid_peek_cell(wp->base.grid, i, sy); text = grid_peek_text(wp->base.grid, i, sy);
utf8_split(gc->data, data); utf8_split(text, data);
*buf = xrealloc(*buf, 1, (*off) + 4); *buf = xrealloc(*buf, 1, (*off) + 4);
for (j = 0; j < sizeof data; j++) { for (j = 0; j < sizeof data; j++) {
@ -501,26 +501,28 @@ int
window_copy_is_space(struct window_pane *wp, u_int px, u_int py) window_copy_is_space(struct window_pane *wp, u_int px, u_int py)
{ {
const struct grid_cell *gc; const struct grid_cell *gc;
const char *spaces = " -_@"; uint64_t text;
const char *spaces = " -_@";
gc = grid_peek_cell(wp->base.grid, px, py); gc = grid_peek_cell(wp->base.grid, px, py);
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
return (0); return (0);
if (gc->data == 0x00 || gc->data > 0xff) text = grid_peek_text(wp->base.grid, px, py);
if (text == 0x00 || text == 0x7f || text > 0xff)
return (0); return (0);
return (strchr(spaces, gc->data) != NULL); return (strchr(spaces, text) != NULL);
} }
u_int u_int
window_copy_find_length(struct window_pane *wp, u_int py) window_copy_find_length(struct window_pane *wp, u_int py)
{ {
const struct grid_cell *gc; uint64_t text;
u_int px; u_int px;
px = wp->base.grid->size[py]; px = wp->base.grid->size[py];
while (px > 0) { while (px > 0) {
gc = grid_peek_cell(wp->base.grid, px - 1, py); text = grid_peek_text(wp->base.grid, px - 1, py);
if (gc->data != 0x20) if (text != 0x20)
break; break;
px--; px--;
} }