Merge branch 'obsd-master'

Conflicts:
	Makefile
This commit is contained in:
Thomas Adam 2015-11-13 10:42:45 +00:00
commit 3df4959f51
12 changed files with 297 additions and 282 deletions

View File

@ -136,7 +136,6 @@ dist_tmux_SOURCES = \
control-notify.c \ control-notify.c \
environ.c \ environ.c \
format.c \ format.c \
grid-cell.c \
grid-view.c \ grid-view.c \
grid.c \ grid.c \
input-keys.c \ input-keys.c \

View File

@ -432,6 +432,7 @@ format_cb_history_bytes(struct format_tree *ft, struct format_entry *fe)
for (i = 0; i < gd->hsize; i++) { for (i = 0; i < gd->hsize; i++) {
gl = &gd->linedata[i]; gl = &gd->linedata[i];
size += gl->cellsize * sizeof *gl->celldata; size += gl->cellsize * sizeof *gl->celldata;
size += gl->extdsize * sizeof *gl->extddata;
} }
size += gd->hsize * sizeof *gd->linedata; size += gd->hsize * sizeof *gd->linedata;

View File

@ -1,55 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#include <string.h>
#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;
}

View File

@ -30,24 +30,17 @@
#define grid_view_x(gd, x) (x) #define grid_view_x(gd, x) (x)
#define grid_view_y(gd, y) ((gd)->hsize + (y)) #define grid_view_y(gd, y) ((gd)->hsize + (y))
/* Get cell for reading. */ /* Get cel. */
const struct grid_cell * void
grid_view_peek_cell(struct grid *gd, u_int px, u_int py) grid_view_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
{ {
return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py))); grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
}
/* Get cell for writing. */
struct grid_cell *
grid_view_get_cell(struct grid *gd, u_int px, u_int py)
{
return (grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
} }
/* Set cell. */ /* Set cell. */
void void
grid_view_set_cell( grid_view_set_cell(struct grid *gd, u_int px, u_int py,
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc) const struct grid_cell *gc)
{ {
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);
} }

169
grid.c
View File

@ -36,15 +36,17 @@
*/ */
/* Default grid cell data. */ /* Default grid cell data. */
const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " }; const struct grid_cell grid_default_cell = {
0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
#define grid_put_cell(gd, px, py, gc) do { \ };
memcpy(&gd->linedata[py].celldata[px], \ const struct grid_cell_entry grid_default_entry = {
gc, sizeof gd->linedata[py].celldata[px]); \ 0, { .data = { 0, 8, 8, ' ' } }
} while (0) };
int grid_check_y(struct grid *, u_int); 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); void grid_reflow_join(struct grid *, u_int *, struct grid_line *, u_int);
void grid_reflow_split(struct grid *, u_int *, struct grid_line *, u_int, void grid_reflow_split(struct grid *, u_int *, struct grid_line *, u_int,
u_int); u_int);
@ -54,6 +56,13 @@ size_t grid_string_cells_bg(const struct grid_cell *, int *);
void grid_string_cells_code(const struct grid_cell *, void grid_string_cells_code(const struct grid_cell *,
const struct grid_cell *, char *, size_t, int); const struct grid_cell *, char *, size_t, int);
/* Copy default into a cell. */
static void
grid_clear_cell(struct grid *gd, u_int px, u_int py)
{
gd->linedata[py].celldata[px] = grid_default_entry;
}
/* Check grid y position. */ /* Check grid y position. */
int int
grid_check_y(struct grid *gd, u_int py) grid_check_y(struct grid *gd, u_int py)
@ -95,6 +104,7 @@ grid_destroy(struct grid *gd)
for (yy = 0; yy < gd->hsize + gd->sy; yy++) { for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
gl = &gd->linedata[yy]; gl = &gd->linedata[yy];
free(gl->celldata); free(gl->celldata);
free(gl->extddata);
} }
free(gd->linedata); free(gd->linedata);
@ -107,7 +117,7 @@ int
grid_compare(struct grid *ga, struct grid *gb) grid_compare(struct grid *ga, struct grid *gb)
{ {
struct grid_line *gla, *glb; struct grid_line *gla, *glb;
struct grid_cell *gca, *gcb; struct grid_cell gca, gcb;
u_int xx, yy; u_int xx, yy;
if (ga->sx != gb->sx || ga->sy != gb->sy) if (ga->sx != gb->sx || ga->sy != gb->sy)
@ -118,10 +128,10 @@ grid_compare(struct grid *ga, struct grid *gb)
glb = &gb->linedata[yy]; glb = &gb->linedata[yy];
if (gla->cellsize != glb->cellsize) if (gla->cellsize != glb->cellsize)
return (1); return (1);
for (xx = 0; xx < ga->sx; xx++) { for (xx = 0; xx < gla->cellsize; xx++) {
gca = &gla->celldata[xx]; grid_get_cell(ga, xx, yy, &gca);
gcb = &glb->celldata[xx]; grid_get_cell(gb, xx, yy, &gcb);
if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0) if (memcmp(&gca, &gcb, sizeof (struct grid_cell)) != 0)
return (1); return (1);
} }
} }
@ -224,7 +234,7 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx)
gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata); gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata);
for (xx = gl->cellsize; xx < sx; xx++) for (xx = gl->cellsize; xx < sx; xx++)
grid_put_cell(gd, xx, py, &grid_default_cell); grid_clear_cell(gd, xx, py);
gl->cellsize = sx; gl->cellsize = sx;
} }
@ -238,37 +248,72 @@ grid_peek_line(struct grid *gd, u_int py)
} }
/* Get cell for reading. */ /* Get cell for reading. */
const struct grid_cell * void
grid_peek_cell(struct grid *gd, u_int px, u_int py) grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
{ {
if (grid_check_y(gd, py) != 0) struct grid_line *gl;
return (&grid_default_cell); struct grid_cell_entry *gce;
if (px >= gd->linedata[py].cellsize) if (grid_check_y(gd, py) != 0 || px >= gd->linedata[py].cellsize) {
return (&grid_default_cell); memcpy(gc, &grid_default_cell, sizeof *gc);
return (&gd->linedata[py].celldata[px]); return;
} }
/* Get cell at relative position (for writing). */ gl = &gd->linedata[py];
struct grid_cell * gce = &gl->celldata[px];
grid_get_cell(struct grid *gd, u_int px, u_int py)
{
if (grid_check_y(gd, py) != 0)
return (NULL);
grid_expand_line(gd, py, px + 1); if (gce->flags & GRID_FLAG_EXTENDED) {
return (&gd->linedata[py].celldata[px]); if (gce->offset >= gl->extdsize)
memcpy(gc, &grid_default_cell, sizeof *gc);
else
memcpy(gc, &gl->extddata[gce->offset], sizeof *gc);
return;
}
gc->flags = gce->flags & ~GRID_FLAG_EXTENDED;
gc->attr = gce->data.attr;
gc->fg = gce->data.fg;
gc->bg = gce->data.bg;
utf8_set(&gc->data, gce->data.data);
} }
/* Set cell at relative position. */ /* Set cell at relative position. */
void void
grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc) grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{ {
struct grid_line *gl;
struct grid_cell_entry *gce;
struct grid_cell *gcp;
if (grid_check_y(gd, py) != 0) if (grid_check_y(gd, py) != 0)
return; return;
grid_expand_line(gd, py, px + 1); grid_expand_line(gd, py, px + 1);
grid_put_cell(gd, px, py, gc);
gl = &gd->linedata[py];
gce = &gl->celldata[px];
if ((gce->flags & GRID_FLAG_EXTENDED) || gc->data.size != 1 ||
gc->data.width != 1) {
if (~gce->flags & GRID_FLAG_EXTENDED) {
gl->extddata = xreallocarray(gl->extddata,
gl->extdsize + 1, sizeof *gl->extddata);
gce->offset = gl->extdsize++;
gce->flags = gc->flags | GRID_FLAG_EXTENDED;
}
if (gce->offset >= gl->extdsize)
fatalx("offset too big");
gcp = &gl->extddata[gce->offset];
memcpy(gcp, gc, sizeof *gcp);
return;
}
gce->flags = gc->flags & ~GRID_FLAG_EXTENDED;
gce->data.attr = gc->attr;
gce->data.fg = gc->fg;
gce->data.bg = gc->bg;
gce->data.data = gc->data.data[0];
} }
/* Clear area. */ /* Clear area. */
@ -300,7 +345,7 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
for (xx = px; xx < px + nx; xx++) { for (xx = px; xx < px + nx; xx++) {
if (xx >= gd->linedata[yy].cellsize) if (xx >= gd->linedata[yy].cellsize)
break; break;
grid_put_cell(gd, xx, yy, &grid_default_cell); grid_clear_cell(gd, xx, yy);
} }
} }
} }
@ -324,6 +369,10 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny)
gl = &gd->linedata[yy]; gl = &gd->linedata[yy];
free(gl->celldata); free(gl->celldata);
memset(gl, 0, sizeof *gl); memset(gl, 0, sizeof *gl);
free(gl->extddata);
gl->extddata = NULL;
gl->extdsize = 0;
} }
} }
@ -386,7 +435,7 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
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;
grid_put_cell(gd, xx, py, &grid_default_cell); grid_clear_cell(gd, xx, py);
} }
} }
@ -568,9 +617,8 @@ char *
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
struct grid_cell **lastgc, int with_codes, int escape_c0, int trim) struct grid_cell **lastgc, int with_codes, int escape_c0, int trim)
{ {
const struct grid_cell *gc; struct grid_cell gc;
static struct grid_cell lastgc1; static struct grid_cell lastgc1;
struct utf8_data ud;
const char *data; const char *data;
char *buf, code[128]; char *buf, code[128];
size_t len, off, size, codelen; size_t len, off, size, codelen;
@ -590,21 +638,20 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
for (xx = px; xx < px + nx; xx++) { for (xx = px; xx < px + nx; xx++) {
if (gl == NULL || xx >= gl->cellsize) if (gl == NULL || xx >= gl->cellsize)
break; break;
gc = &gl->celldata[xx]; grid_get_cell(gd, xx, py, &gc);
if (gc->flags & GRID_FLAG_PADDING) if (gc.flags & GRID_FLAG_PADDING)
continue; continue;
grid_cell_get(gc, &ud);
if (with_codes) { if (with_codes) {
grid_string_cells_code(*lastgc, gc, code, sizeof code, grid_string_cells_code(*lastgc, &gc, code, sizeof code,
escape_c0); escape_c0);
codelen = strlen(code); codelen = strlen(code);
memcpy(*lastgc, gc, sizeof *gc); memcpy(*lastgc, &gc, sizeof **lastgc);
} else } else
codelen = 0; codelen = 0;
data = ud.data; data = gc.data.data;
size = ud.size; size = gc.data.size;
if (escape_c0 && size == 1 && *data == '\\') { if (escape_c0 && size == 1 && *data == '\\') {
data = "\\\\"; data = "\\\\";
size = 2; size = 2;
@ -663,11 +710,44 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
} else } else
dstl->celldata = NULL; dstl->celldata = NULL;
if (srcl->extdsize != 0) {
dstl->extdsize = srcl->extdsize;
dstl->extddata = xreallocarray(NULL, dstl->extdsize,
sizeof *dstl->extddata);
memcpy(dstl->extddata, srcl->extddata, dstl->extdsize *
sizeof *dstl->extddata);
}
sy++; sy++;
dy++; dy++;
} }
} }
/* Copy a section of a line. */
void
grid_reflow_copy(struct grid_line *dst_gl, u_int to, struct grid_line *src_gl,
u_int from, u_int to_copy)
{
struct grid_cell_entry *gce;
u_int i, was;
memcpy(&dst_gl->celldata[to], &src_gl->celldata[from],
to_copy * sizeof *dst_gl->celldata);
for (i = to; i < to + to_copy; i++) {
gce = &dst_gl->celldata[i];
if (~gce->flags & GRID_FLAG_EXTENDED)
continue;
was = gce->offset;
dst_gl->extddata = xreallocarray(dst_gl->extddata,
dst_gl->extdsize + 1, sizeof *dst_gl->extddata);
gce->offset = dst_gl->extdsize++;
memcpy(&dst_gl->extddata[gce->offset], &src_gl->extddata[was],
sizeof *dst_gl->extddata);
}
}
/* Join line data. */ /* Join line data. */
void void
grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl, grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
@ -692,8 +772,7 @@ grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
dst_gl->cellsize = nx; dst_gl->cellsize = nx;
/* Append as much as possible. */ /* Append as much as possible. */
memcpy(&dst_gl->celldata[ox], &src_gl->celldata[0], grid_reflow_copy(dst_gl, ox, src_gl, 0, to_copy);
to_copy * sizeof src_gl->celldata[0]);
/* If there is any left in the source, split it. */ /* If there is any left in the source, split it. */
if (src_gl->cellsize > to_copy) { if (src_gl->cellsize > to_copy) {
@ -732,8 +811,7 @@ grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
dst_gl->flags |= GRID_LINE_WRAPPED; dst_gl->flags |= GRID_LINE_WRAPPED;
/* Copy the data. */ /* Copy the data. */
memcpy(&dst_gl->celldata[0], &src_gl->celldata[offset], grid_reflow_copy(dst_gl, 0, src_gl, offset, to_copy);
to_copy * sizeof dst_gl->celldata[0]);
/* Move offset and reduce old line size. */ /* Move offset and reduce old line size. */
offset += to_copy; offset += to_copy;
@ -763,6 +841,7 @@ grid_reflow_move(struct grid *dst, u_int *py, struct grid_line *src_gl)
/* Clear old line. */ /* Clear old line. */
src_gl->celldata = NULL; src_gl->celldata = NULL;
src_gl->extddata = NULL;
} }
/* /*
@ -792,7 +871,7 @@ grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
/* Previous was wrapped. Try to join. */ /* Previous was wrapped. Try to join. */
grid_reflow_join(dst, &py, src_gl, new_x); grid_reflow_join(dst, &py, src_gl, new_x);
} }
previous_wrapped = src_gl->flags & GRID_LINE_WRAPPED; previous_wrapped = (src_gl->flags & GRID_LINE_WRAPPED);
} }
grid_destroy(src); grid_destroy(src);

View File

@ -1006,7 +1006,7 @@ input_print(struct input_ctx *ictx)
else else
ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
grid_cell_one(&ictx->cell.cell, ictx->ch); utf8_set(&ictx->cell.cell.data, ictx->ch);
screen_write_cell(&ictx->ctx, &ictx->cell.cell); screen_write_cell(&ictx->ctx, &ictx->cell.cell);
ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
@ -1945,7 +1945,7 @@ input_utf8_close(struct input_ctx *ictx)
utf8_append(&ictx->utf8data, ictx->ch); utf8_append(&ictx->utf8data, ictx->ch);
grid_cell_set(&ictx->cell.cell, &ictx->utf8data); utf8_copy(&ictx->cell.cell.data, &ictx->utf8data);
screen_write_cell(&ictx->ctx, &ictx->cell.cell); screen_write_cell(&ictx->ctx, &ictx->cell.cell);
return (0); return (0);

View File

@ -67,7 +67,7 @@ void
screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc, screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
u_char ch) u_char ch)
{ {
grid_cell_one(gc, ch); utf8_set(&gc->data, ch);
screen_write_cell(ctx, gc); screen_write_cell(ctx, gc);
} }
@ -126,7 +126,7 @@ screen_write_strlen(const char *fmt, ...)
ptr++; ptr++;
left = strlen(ptr); left = strlen(ptr);
if (left < ud.size - 1) if (left < (size_t)ud.size - 1)
break; break;
while (utf8_append(&ud, *ptr)) while (utf8_append(&ud, *ptr))
ptr++; ptr++;
@ -185,7 +185,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
ptr++; ptr++;
left = strlen(ptr); left = strlen(ptr);
if (left < ud.size - 1) if (left < (size_t)ud.size - 1)
break; break;
while (utf8_append(&ud, *ptr)) while (utf8_append(&ud, *ptr))
ptr++; ptr++;
@ -201,7 +201,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
} }
size += ud.width; size += ud.width;
grid_cell_set(gc, &ud); utf8_copy(&gc->data, &ud);
screen_write_cell(ctx, gc); screen_write_cell(ctx, gc);
} else { } else {
if (maxlen > 0 && size + 1 > (size_t) maxlen) if (maxlen > 0 && size + 1 > (size_t) maxlen)
@ -258,7 +258,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
ptr++; ptr++;
left = strlen(ptr); left = strlen(ptr);
if (left < ud.size - 1) if (left < (size_t)ud.size - 1)
break; break;
while (utf8_append(&ud, *ptr)) while (utf8_append(&ud, *ptr))
ptr++; ptr++;
@ -274,7 +274,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
} }
size += ud.width; size += ud.width;
grid_cell_set(&lgc, &ud); utf8_copy(&lgc.data, &ud);
screen_write_cell(ctx, &lgc); screen_write_cell(ctx, &lgc);
} else { } else {
if (maxlen > 0 && size + 1 > (size_t) maxlen) 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 screen *s = ctx->s;
struct grid *gd = src->grid; struct grid *gd = src->grid;
struct grid_line *gl; struct grid_line *gl;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
u_int xx, yy, cx, cy, ax, bx; u_int xx, yy, cx, cy, ax, bx;
cx = s->cx; cx = s->cx;
@ -324,12 +323,8 @@ screen_write_copy(struct screen_write_ctx *ctx,
bx = px + nx; bx = px + nx;
for (xx = ax; xx < bx; xx++) { for (xx = ax; xx < bx; xx++) {
if (xx >= gl->cellsize) grid_get_cell(gd, xx, yy, &gc);
gc = &grid_default_cell; screen_write_cell(ctx, &gc);
else
gc = &gl->celldata[xx];
grid_cell_get(gc, &ud);
screen_write_cell(ctx, gc);
} }
if (px + nx == gd->sx && px + nx > gl->cellsize) if (px + nx == gd->sx && px + nx > gl->cellsize)
screen_write_clearendofline(ctx); screen_write_clearendofline(ctx);
@ -342,12 +337,12 @@ screen_write_copy(struct screen_write_ctx *ctx,
/* Set up context for TTY command. */ /* Set up context for TTY command. */
void void
screen_write_initctx( screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, int save_last) int save_last)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
const struct grid_cell *gc; struct grid_cell gc;
u_int xx; u_int xx;
ttyctx->wp = ctx->wp; ttyctx->wp = ctx->wp;
@ -362,14 +357,14 @@ screen_write_initctx(
return; return;
/* Save the last cell on the screen. */ /* 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++) { for (xx = 1; xx <= screen_size_x(s); xx++) {
gc = grid_view_peek_cell(gd, screen_size_x(s) - xx, s->cy); grid_view_get_cell(gd, screen_size_x(s) - xx, s->cy, &gc);
if (!(gc->flags & GRID_FLAG_PADDING)) if (~gc.flags & GRID_FLAG_PADDING)
break; break;
} }
ttyctx->last_width = xx; 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. */ /* Set a mode. */
@ -507,7 +502,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0);
memcpy(&gc, &grid_default_cell, sizeof gc); 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 (yy = 0; yy < screen_size_y(s); yy++) {
for (xx = 0; xx < screen_size_x(s); xx++) 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 grid *gd = s->grid;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int width, xx, last; u_int width, xx, last;
struct grid_cell tmp_gc, *tmp_gcp; struct grid_cell tmp_gc;
struct utf8_data ud;
int insert; int insert;
/* Ignore padding. */ /* Ignore padding. */
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
return; 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 * 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. * there is space.
*/ */
if (width == 0) { if (width == 0) {
grid_cell_get(gc, &ud); if (screen_write_combine(ctx, &gc->data) == 0) {
if (screen_write_combine(ctx, &ud) == 0) {
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0);
tty_write(tty_cmd_utf8character, &ttyctx); 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 * If the new character is UTF-8 wide, fill in padding cells. Have
* already ensured there is enough room. * already ensured there is enough room.
*/ */
for (xx = s->cx + 1; xx < s->cx + width; xx++) { memcpy(&tmp_gc, &grid_default_cell, sizeof tmp_gc);
tmp_gcp = grid_view_get_cell(gd, xx, s->cy); tmp_gc.flags |= GRID_FLAG_PADDING;
if (tmp_gcp != NULL) tmp_gc.data.width = 0;
tmp_gcp->flags |= GRID_FLAG_PADDING; for (xx = s->cx + 1; xx < s->cx + width; xx++)
} grid_view_set_cell(gd, xx, s->cy, &tmp_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);
@ -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)) { if (screen_check_selection(s, s->cx - width, s->cy)) {
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc); memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
grid_cell_get(gc, &ud); utf8_copy(&tmp_gc.data, &gc->data);
grid_cell_set(&tmp_gc, &ud);
tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET; tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET; tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256); 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 screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud1;
/* Can't combine if at 0. */ /* Can't combine if at 0. */
if (s->cx == 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"); fatalx("UTF-8 data empty");
/* Retrieve the previous cell. */ /* Retrieve the previous cell. */
gc = grid_view_get_cell(gd, s->cx - 1, s->cy); grid_view_get_cell(gd, s->cx - 1, s->cy, &gc);
grid_cell_get(gc, &ud1);
/* Check there is enough space. */ /* 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); return (-1);
/* Append the data and set the cell. */ /* Append the data. */
memcpy(ud1.data + ud1.size, ud->data, ud->size); memcpy(gc.data.data + gc.data.size, ud->data, ud->size);
ud1.size += ud->size; gc.data.size += ud->size;
grid_cell_set(gc, &ud1);
/* Set the new cell. */
grid_view_set_cell(gd, s->cx - 1, s->cy, &gc);
return (0); return (0);
} }
@ -1052,11 +1044,11 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
const struct grid_cell *gc; struct grid_cell gc;
u_int xx; u_int xx;
gc = grid_view_peek_cell(gd, s->cx, s->cy); grid_view_get_cell(gd, s->cx, s->cy, &gc);
if (gc->flags & GRID_FLAG_PADDING) { if (gc.flags & GRID_FLAG_PADDING) {
/* /*
* A padding cell, so clear any following and leading padding * A padding cell, so clear any following and leading padding
* cells back to the character. Don't overwrite the current * 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; xx = s->cx + 1;
while (--xx > 0) { while (--xx > 0) {
gc = grid_view_peek_cell(gd, xx, s->cy); grid_view_get_cell(gd, xx, s->cy, &gc);
if (!(gc->flags & GRID_FLAG_PADDING)) if (~gc.flags & GRID_FLAG_PADDING)
break; break;
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); 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; xx = s->cx + width - 1;
while (++xx < screen_size_x(s)) { while (++xx < screen_size_x(s)) {
gc = grid_view_peek_cell(gd, xx, s->cy); grid_view_get_cell(gd, xx, s->cy, &gc);
if (!(gc->flags & GRID_FLAG_PADDING)) if (~gc.flags & GRID_FLAG_PADDING)
break; break;
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell); grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
} }

View File

@ -746,7 +746,7 @@ status_prompt_redraw(struct client *c)
struct session *s = c->session; struct session *s = c->session;
struct screen old_status; struct screen old_status;
size_t i, size, left, len, off; size_t i, size, left, len, off;
struct grid_cell gc, *gcp; struct grid_cell gc;
if (c->tty.sx == 0 || c->tty.sy == 0) if (c->tty.sx == 0 || c->tty.sy == 0)
return (0); return (0);
@ -789,8 +789,9 @@ status_prompt_redraw(struct client *c)
/* Apply fake cursor. */ /* Apply fake cursor. */
off = len + c->prompt_index - off; off = len + c->prompt_index - off;
gcp = grid_view_get_cell(c->status.grid, off, 0); grid_view_get_cell(c->status.grid, off, 0, &gc);
gcp->attr ^= GRID_ATTR_REVERSE; gc.attr ^= GRID_ATTR_REVERSE;
grid_view_set_cell(c->status.grid, off, 0, &gc);
if (grid_compare(c->status.grid, old_status.grid) == 0) { if (grid_compare(c->status.grid, old_status.grid) == 0) {
screen_free(&old_status); screen_free(&old_status);

72
tmux.h
View File

@ -624,11 +624,11 @@ struct mode_key_table {
struct utf8_data { struct utf8_data {
u_char data[UTF8_SIZE]; u_char data[UTF8_SIZE];
size_t have; u_char have;
size_t size; u_char size;
u_int width; u_char width;
}; } __packed;
/* Grid attributes. */ /* Grid attributes. */
#define GRID_ATTR_BRIGHT 0x1 #define GRID_ATTR_BRIGHT 0x1
@ -644,41 +644,56 @@ struct utf8_data {
#define GRID_FLAG_FG256 0x1 #define GRID_FLAG_FG256 0x1
#define GRID_FLAG_BG256 0x2 #define GRID_FLAG_BG256 0x2
#define GRID_FLAG_PADDING 0x4 #define GRID_FLAG_PADDING 0x4
#define GRID_FLAG_EXTENDED 0x8
/* Grid line flags. */ /* Grid line flags. */
#define GRID_LINE_WRAPPED 0x1 #define GRID_LINE_WRAPPED 0x1
/* Grid cell data. */ /* Grid cell data. */
struct grid_cell { struct grid_cell {
u_char attr; u_char flags;
u_char flags; u_char attr;
u_char fg; u_char fg;
u_char bg; u_char bg;
struct utf8_data data;
u_char xstate; /* top 4 bits width, bottom 4 bits size */ };
u_char xdata[UTF8_SIZE]; struct grid_cell_entry {
u_char flags;
union {
u_int offset;
struct {
u_char attr;
u_char fg;
u_char bg;
u_char data;
} data;
};
} __packed; } __packed;
/* Grid line. */ /* Grid line. */
struct grid_line { struct grid_line {
u_int cellsize; u_int cellsize;
struct grid_cell *celldata; struct grid_cell_entry *celldata;
int flags; u_int extdsize;
struct grid_cell *extddata;
int flags;
} __packed; } __packed;
/* Entire grid of cells. */ /* Entire grid of cells. */
struct grid { struct grid {
int flags; int flags;
#define GRID_HISTORY 0x1 /* scroll lines into history */ #define GRID_HISTORY 0x1 /* scroll lines into history */
u_int sx; u_int sx;
u_int sy; u_int sy;
u_int hsize; u_int hsize;
u_int hlimit; u_int hlimit;
struct grid_line *linedata; struct grid_line *linedata;
}; };
/* Option data structures. */ /* Option data structures. */
@ -1857,9 +1872,8 @@ void grid_scroll_history(struct grid *);
void grid_scroll_history_region(struct grid *, u_int, u_int); void grid_scroll_history_region(struct grid *, u_int, u_int);
void grid_clear_history(struct grid *); void grid_clear_history(struct grid *);
void grid_expand_line(struct grid *, u_int, u_int); void grid_expand_line(struct grid *, u_int, u_int);
const struct grid_cell *grid_peek_cell(struct grid *, u_int, u_int);
const struct grid_line *grid_peek_line(struct grid *, u_int); const struct grid_line *grid_peek_line(struct grid *, u_int);
struct grid_cell *grid_get_cell(struct grid *, u_int, u_int); void grid_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *); void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
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_clear_lines(struct grid *, u_int, u_int); void grid_clear_lines(struct grid *, u_int, u_int);
@ -1871,17 +1885,10 @@ void grid_duplicate_lines(
struct grid *, u_int, struct grid *, u_int, u_int); struct grid *, u_int, struct grid *, u_int, u_int);
u_int grid_reflow(struct grid *, struct grid *, u_int); u_int grid_reflow(struct grid *, struct grid *, u_int);
/* 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 */ /* grid-view.c */
const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int); void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int); void grid_view_set_cell(struct grid *, u_int, u_int,
void grid_view_set_cell( const struct grid_cell *);
struct grid *, u_int, u_int, const struct grid_cell *);
void grid_view_clear_history(struct grid *); void grid_view_clear_history(struct grid *);
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_scroll_region_up(struct grid *, u_int, u_int); void grid_view_scroll_region_up(struct grid *, u_int, u_int);
@ -2186,6 +2193,7 @@ void session_renumber_windows(struct session *);
/* utf8.c */ /* utf8.c */
u_int utf8_width(u_int); u_int utf8_width(u_int);
void utf8_set(struct utf8_data *, u_char); void utf8_set(struct utf8_data *, u_char);
void utf8_copy(struct utf8_data *, const struct utf8_data *);
int utf8_open(struct utf8_data *, u_char); int utf8_open(struct utf8_data *, u_char);
int utf8_append(struct utf8_data *, u_char); int utf8_append(struct utf8_data *, u_char);
u_int utf8_combine(const struct utf8_data *); u_int utf8_combine(const struct utf8_data *);

37
tty.c
View File

@ -656,10 +656,8 @@ void
tty_draw_line(struct tty *tty, const struct window_pane *wp, tty_draw_line(struct tty *tty, const struct window_pane *wp,
struct screen *s, u_int py, u_int ox, u_int oy) struct screen *s, u_int py, u_int ox, u_int oy)
{ {
const struct grid_cell *gc; struct grid_cell gc;
struct grid_line *gl; struct grid_line *gl;
struct grid_cell tmpgc;
struct utf8_data ud;
u_int i, sx; u_int i, sx;
int flags; int flags;
@ -686,18 +684,13 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
tty_cursor(tty, ox, oy + py); tty_cursor(tty, ox, oy + py);
for (i = 0; i < sx; i++) { for (i = 0; i < sx; i++) {
gc = grid_view_peek_cell(s->grid, i, py); grid_view_get_cell(s->grid, i, py, &gc);
if (screen_check_selection(s, i, py)) { if (screen_check_selection(s, i, py)) {
memcpy(&tmpgc, &s->sel.cell, sizeof tmpgc); gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
grid_cell_get(gc, &ud); gc.flags |= s->sel.cell.flags &
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); (GRID_FLAG_FG256|GRID_FLAG_BG256);
tty_cell(tty, &tmpgc, wp); }
} else tty_cell(tty, &gc, wp);
tty_cell(tty, gc, wp);
} }
if (sx < tty->sx) { if (sx < tty->sx) {
@ -1078,7 +1071,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower); tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
/* Is the cursor in the very last position? */ /* Is the cursor in the very last position? */
width = grid_cell_width(ctx->cell); width = ctx->cell->data.width;
if (ctx->ocx > wp->sx - width) { if (ctx->ocx > wp->sx - width) {
if (ctx->xoff != 0 || wp->sx != tty->sx) { if (ctx->xoff != 0 || wp->sx != tty->sx) {
/* /*
@ -1095,7 +1088,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
* move as far left as possible and redraw the last * move as far left as possible and redraw the last
* cell to move into the last position. * cell to move into the last position.
*/ */
cx = screen_size_x(s) - grid_cell_width(&ctx->last_cell); cx = screen_size_x(s) - ctx->last_cell.data.width;
tty_cursor_pane(tty, ctx, cx, ctx->ocy); tty_cursor_pane(tty, ctx, cx, ctx->ocy);
tty_cell(tty, &ctx->last_cell, wp); tty_cell(tty, &ctx->last_cell, wp);
} }
@ -1155,8 +1148,7 @@ void
tty_cell(struct tty *tty, const struct grid_cell *gc, tty_cell(struct tty *tty, const struct grid_cell *gc,
const struct window_pane *wp) const struct window_pane *wp)
{ {
struct utf8_data ud; u_int i;
u_int i;
/* Skip last character if terminal is stupid. */ /* Skip last character if terminal is stupid. */
if (tty->term->flags & TERM_EARLYWRAP && if (tty->term->flags & TERM_EARLYWRAP &&
@ -1171,23 +1163,22 @@ tty_cell(struct tty *tty, const struct grid_cell *gc,
tty_attributes(tty, gc, wp); tty_attributes(tty, gc, wp);
/* Get the cell and if ASCII write with putc to do ACS translation. */ /* Get the cell and if ASCII write with putc to do ACS translation. */
grid_cell_get(gc, &ud); if (gc->data.size == 1) {
if (ud.size == 1) { if (*gc->data.data < 0x20 || *gc->data.data == 0x7f)
if (*ud.data < 0x20 || *ud.data == 0x7f)
return; return;
tty_putc(tty, *ud.data); tty_putc(tty, *gc->data.data);
return; return;
} }
/* If not UTF-8, write _. */ /* If not UTF-8, write _. */
if (!(tty->flags & TTY_UTF8)) { if (!(tty->flags & TTY_UTF8)) {
for (i = 0; i < ud.width; i++) for (i = 0; i < gc->data.width; i++)
tty_putc(tty, '_'); tty_putc(tty, '_');
return; return;
} }
/* Write the data. */ /* Write the data. */
tty_putn(tty, ud.data, ud.size, ud.width); tty_putn(tty, gc->data.data, gc->data.size, gc->data.width);
} }
void void

17
utf8.c
View File

@ -351,10 +351,27 @@ static void utf8_build(void);
void void
utf8_set(struct utf8_data *ud, u_char ch) utf8_set(struct utf8_data *ud, u_char ch)
{ {
u_int i;
*ud->data = ch; *ud->data = ch;
ud->size = 1; ud->size = 1;
ud->width = 1; ud->width = 1;
for (i = ud->size; i < sizeof ud->data; i++)
ud->data[i] = '\0';
}
/* Copy UTF-8 character. */
void
utf8_copy(struct utf8_data *to, const struct utf8_data *from)
{
u_int i;
memcpy(to, from, sizeof *to);
for (i = to->size; i < sizeof to->data; i++)
to->data[i] = '\0';
} }
/* /*

View File

@ -942,21 +942,21 @@ int
window_copy_search_compare(struct grid *gd, u_int px, u_int py, window_copy_search_compare(struct grid *gd, u_int px, u_int py,
struct grid *sgd, u_int spx, int cis) struct grid *sgd, u_int spx, int cis)
{ {
const struct grid_cell *gc, *sgc; struct grid_cell gc, sgc;
struct utf8_data ud, sud; const struct utf8_data *ud, *sud;
gc = grid_peek_cell(gd, px, py); grid_get_cell(gd, px, py, &gc);
grid_cell_get(gc, &ud); ud = &gc.data;
sgc = grid_peek_cell(sgd, spx, 0); grid_get_cell(sgd, spx, 0, &sgc);
grid_cell_get(sgc, &sud); sud = &sgc.data;
if (ud.size != sud.size || ud.width != sud.width) if (ud->size != sud->size || ud->width != sud->width)
return (0); return (0);
if (cis && ud.size == 1) if (cis && ud->size == 1)
return (tolower(ud.data[0]) == sud.data[0]); return (tolower(ud->data[0]) == sud->data[0]);
return (memcmp(ud.data, sud.data, ud.size) == 0); return (memcmp(ud->data, sud->data, ud->size) == 0);
} }
int int
@ -1541,12 +1541,12 @@ window_copy_append_selection(struct window_pane *wp, const char *bufname)
} }
void void
window_copy_copy_line(struct window_pane *wp, window_copy_copy_line(struct window_pane *wp, char **buf, size_t *off, u_int sy,
char **buf, size_t *off, u_int sy, u_int sx, u_int ex) u_int sx, u_int ex)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct grid *gd = data->backing->grid; struct grid *gd = data->backing->grid;
const struct grid_cell *gc; struct grid_cell gc;
struct grid_line *gl; struct grid_line *gl;
struct utf8_data ud; struct utf8_data ud;
u_int i, xx, wrapped = 0; u_int i, xx, wrapped = 0;
@ -1575,11 +1575,11 @@ window_copy_copy_line(struct window_pane *wp,
if (sx < ex) { if (sx < ex) {
for (i = sx; i < ex; i++) { for (i = sx; i < ex; i++) {
gc = grid_peek_cell(gd, i, sy); grid_get_cell(gd, i, sy, &gc);
if (gc->flags & GRID_FLAG_PADDING) if (gc.flags & GRID_FLAG_PADDING)
continue; continue;
grid_cell_get(gc, &ud); utf8_copy(&ud, &gc.data);
if (ud.size == 1 && (gc->attr & GRID_ATTR_CHARSET)) { if (ud.size == 1 && (gc.attr & GRID_ATTR_CHARSET)) {
s = tty_acs_get(NULL, ud.data[0]); s = tty_acs_get(NULL, ud.data[0]);
if (s != NULL && strlen(s) <= sizeof ud.data) { if (s != NULL && strlen(s) <= sizeof ud.data) {
ud.size = strlen(s); ud.size = strlen(s);
@ -1618,16 +1618,17 @@ int
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set) 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; struct window_copy_mode_data *data = wp->modedata;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud; const struct utf8_data *ud;
gc = grid_peek_cell(data->backing->grid, px, py); grid_get_cell(data->backing->grid, px, py, &gc);
grid_cell_get(gc, &ud);
if (ud.size != 1 || gc->flags & GRID_FLAG_PADDING) ud = &gc.data;
if (ud->size != 1 || (gc.flags & GRID_FLAG_PADDING))
return (0); return (0);
if (*ud.data == 0x00 || *ud.data == 0x7f) if (*ud->data == 0x00 || *ud->data == 0x7f)
return (0); return (0);
return (strchr(set, *ud.data) != NULL); return (strchr(set, *ud->data) != NULL);
} }
u_int u_int
@ -1635,8 +1636,7 @@ window_copy_find_length(struct window_pane *wp, u_int py)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *s = data->backing; struct screen *s = data->backing;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
u_int px; u_int px;
/* /*
@ -1649,9 +1649,8 @@ window_copy_find_length(struct window_pane *wp, u_int py)
if (px > screen_size_x(s)) if (px > screen_size_x(s))
px = screen_size_x(s); px = screen_size_x(s);
while (px > 0) { while (px > 0) {
gc = grid_peek_cell(s->grid, px - 1, py); grid_get_cell(s->grid, px - 1, py, &gc);
grid_cell_get(gc, &ud); if (gc.data.size != 1 || *gc.data.data != ' ')
if (ud.size != 1 || *ud.data != ' ')
break; break;
px--; px--;
} }
@ -1685,17 +1684,15 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
u_int px, py, xx; u_int px, py, xx;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
px = 0; px = 0;
py = screen_hsize(data->backing) + data->cy - data->oy; py = screen_hsize(data->backing) + data->cy - data->oy;
xx = window_copy_find_length(wp, py); xx = window_copy_find_length(wp, py);
while (px < xx) { while (px < xx) {
gc = grid_peek_cell(data->backing->grid, px, py); grid_get_cell(data->backing->grid, px, py, &gc);
grid_cell_get(gc, &ud); if (gc.data.size != 1 || *gc.data.data != ' ')
if (ud.size != 1 || *ud.data != ' ')
break; break;
px++; px++;
} }
@ -1909,8 +1906,7 @@ window_copy_cursor_jump(struct window_pane *wp)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
u_int px, py, xx; u_int px, py, xx;
px = data->cx + 1; px = data->cx + 1;
@ -1918,10 +1914,9 @@ window_copy_cursor_jump(struct window_pane *wp)
xx = window_copy_find_length(wp, py); xx = window_copy_find_length(wp, py);
while (px < xx) { while (px < xx) {
gc = grid_peek_cell(back_s->grid, px, py); grid_get_cell(back_s->grid, px, py, &gc);
grid_cell_get(gc, &ud); if (!(gc.flags & GRID_FLAG_PADDING) &&
if (!(gc->flags & GRID_FLAG_PADDING) && gc.data.size == 1 && *gc.data.data == data->jumpchar) {
ud.size == 1 && *ud.data == data->jumpchar) {
window_copy_update_cursor(wp, px, data->cy); window_copy_update_cursor(wp, px, data->cy);
if (window_copy_update_selection(wp, 1)) if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1); window_copy_redraw_lines(wp, data->cy, 1);
@ -1936,8 +1931,7 @@ window_copy_cursor_jump_back(struct window_pane *wp)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
u_int px, py; u_int px, py;
px = data->cx; px = data->cx;
@ -1947,10 +1941,9 @@ window_copy_cursor_jump_back(struct window_pane *wp)
px--; px--;
for (;;) { for (;;) {
gc = grid_peek_cell(back_s->grid, px, py); grid_get_cell(back_s->grid, px, py, &gc);
grid_cell_get(gc, &ud); if (!(gc.flags & GRID_FLAG_PADDING) &&
if (!(gc->flags & GRID_FLAG_PADDING) && gc.data.size == 1 && *gc.data.data == data->jumpchar) {
ud.size == 1 && *ud.data == data->jumpchar) {
window_copy_update_cursor(wp, px, data->cy); window_copy_update_cursor(wp, px, data->cy);
if (window_copy_update_selection(wp, 1)) if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1); window_copy_redraw_lines(wp, data->cy, 1);
@ -1967,8 +1960,7 @@ window_copy_cursor_jump_to(struct window_pane *wp, int jump_again)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
u_int px, py, xx; u_int px, py, xx;
px = data->cx + 1 + jump_again; px = data->cx + 1 + jump_again;
@ -1976,10 +1968,9 @@ window_copy_cursor_jump_to(struct window_pane *wp, int jump_again)
xx = window_copy_find_length(wp, py); xx = window_copy_find_length(wp, py);
while (px < xx) { while (px < xx) {
gc = grid_peek_cell(back_s->grid, px, py); grid_get_cell(back_s->grid, px, py, &gc);
grid_cell_get(gc, &ud); if (!(gc.flags & GRID_FLAG_PADDING) &&
if (!(gc->flags & GRID_FLAG_PADDING) && gc.data.size == 1 && *gc.data.data == data->jumpchar) {
ud.size == 1 && *ud.data == data->jumpchar) {
window_copy_update_cursor(wp, px - 1, data->cy); window_copy_update_cursor(wp, px - 1, data->cy);
if (window_copy_update_selection(wp, 1)) if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1); window_copy_redraw_lines(wp, data->cy, 1);
@ -1994,8 +1985,7 @@ window_copy_cursor_jump_to_back(struct window_pane *wp, int jump_again)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; struct grid_cell gc;
struct utf8_data ud;
u_int px, py; u_int px, py;
px = data->cx; px = data->cx;
@ -2008,10 +1998,9 @@ window_copy_cursor_jump_to_back(struct window_pane *wp, int jump_again)
px--; px--;
for (;;) { for (;;) {
gc = grid_peek_cell(back_s->grid, px, py); grid_get_cell(back_s->grid, px, py, &gc);
grid_cell_get(gc, &ud); if (!(gc.flags & GRID_FLAG_PADDING) &&
if (!(gc->flags & GRID_FLAG_PADDING) && gc.data.size == 1 && *gc.data.data == data->jumpchar) {
ud.size == 1 && *ud.data == data->jumpchar) {
window_copy_update_cursor(wp, px + 1, data->cy); window_copy_update_cursor(wp, px + 1, data->cy);
if (window_copy_update_selection(wp, 1)) if (window_copy_update_selection(wp, 1))
window_copy_redraw_lines(wp, data->cy, 1); window_copy_redraw_lines(wp, data->cy, 1);