Merge branch 'obsd-master'

Conflicts:
	Makefile
	grid-utf8.c
This commit is contained in:
Thomas Adam 2013-01-30 15:27:19 +00:00
commit a3f4eb7b24
14 changed files with 198 additions and 444 deletions

View File

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

View File

@ -58,12 +58,11 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
struct job *job; struct job *job;
struct grid *gd; struct grid *gd;
struct grid_line *gl; struct grid_line *gl;
u_int i, j, k; u_int i, j, k, lines;
size_t size;
char out[80]; char out[80];
char *tim; char *tim;
time_t t; time_t t;
u_int lines, ulines;
size_t size, usize;
tim = ctime(&start_time); tim = ctime(&start_time);
*strchr(tim, '\n') = '\0'; *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, "%s", "");
ctx->print(ctx, "Sessions: [%zu/%zu]", ctx->print(ctx, "Sessions: [%zu]", sizeof (struct grid_cell));
sizeof (struct grid_cell), sizeof (struct grid_utf8));
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
t = s->creation_time.tv_sec; t = s->creation_time.tv_sec;
tim = ctime(&t); tim = ctime(&t);
@ -115,26 +113,20 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
w->lastlayout); w->lastlayout);
j = 0; j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
lines = ulines = size = usize = 0; lines = size = 0;
gd = wp->base.grid; gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) { for (k = 0; k < gd->hsize + gd->sy; k++) {
gl = &gd->linedata[k]; gl = &gd->linedata[k];
if (gl->celldata != NULL) { if (gl->celldata == NULL)
lines++; continue;
size += gl->cellsize * lines++;
sizeof *gl->celldata; size += gl->cellsize *
} sizeof *gl->celldata;
if (gl->utf8data != NULL) {
ulines++;
usize += gl->utf8size *
sizeof *gl->utf8data;
}
} }
ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu " ctx->print(ctx,
"bytes; UTF-8 %u/%u, %zu bytes", j, "%6u: %s %lu %d %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines, wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size, ulines, gd->hsize + gd->sy, size);
gd->hsize + gd->sy, usize);
j++; j++;
} }
} }

6
cmd.c
View File

@ -377,14 +377,14 @@ cmd_session_better(struct session *s, struct session *best,
int prefer_unattached) int prefer_unattached)
{ {
if (best == NULL) if (best == NULL)
return 1; return (1);
if (prefer_unattached) { if (prefer_unattached) {
if (!(best->flags & SESSION_UNATTACHED) && if (!(best->flags & SESSION_UNATTACHED) &&
(s->flags & SESSION_UNATTACHED)) (s->flags & SESSION_UNATTACHED))
return 1; return (1);
else if ((best->flags & SESSION_UNATTACHED) && else if ((best->flags & SESSION_UNATTACHED) &&
!(s->flags & SESSION_UNATTACHED)) !(s->flags & SESSION_UNATTACHED))
return 0; return (0);
} }
return (timercmp(&s->activity_time, &best->activity_time, >)); return (timercmp(&s->activity_time, &best->activity_time, >));
} }

View File

@ -370,7 +370,6 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
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->utf8size * sizeof *gl->utf8data;
} }
size += gd->hsize * sizeof *gd->linedata; size += gd->hsize * sizeof *gd->linedata;

55
grid-cell.c Normal file
View File

@ -0,0 +1,55 @@
/* $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

@ -1,96 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2009 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"
/*
* 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);
}

View File

@ -52,28 +52,6 @@ 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);
} }
/* 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. */ /* Clear into history. */
void void
grid_view_clear_history(struct grid *gd) grid_view_clear_history(struct grid *gd)
@ -87,7 +65,7 @@ grid_view_clear_history(struct grid *gd)
last = 0; last = 0;
for (yy = 0; yy < gd->sy; yy++) { for (yy = 0; yy < gd->sy; yy++) {
gl = &gd->linedata[grid_view_y(gd, yy)]; gl = &gd->linedata[grid_view_y(gd, yy)];
if (gl->cellsize != 0 || gl->utf8size != 0) if (gl->cellsize != 0)
last = yy + 1; last = yy + 1;
} }
if (last == 0) if (last == 0)

103
grid.c
View File

@ -36,8 +36,8 @@
*/ */
/* 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, (1 << 4) | 1, " " };
const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, '_' }; const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, (1 << 4) | 1, "_" };
#define grid_put_cell(gd, px, py, gc) do { \ #define grid_put_cell(gd, px, py, gc) do { \
memcpy(&gd->linedata[py].celldata[px], \ memcpy(&gd->linedata[py].celldata[px], \
@ -100,7 +100,6 @@ 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->utf8data);
} }
free(gd->linedata); free(gd->linedata);
@ -114,7 +113,6 @@ 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;
struct grid_utf8 *gua, *gub;
u_int xx, yy; u_int xx, yy;
if (ga->sx != gb->sx || ga->sy != ga->sy) 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]; gcb = &glb->celldata[xx];
if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0) if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0)
return (1); 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; 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. */ /* Get cell for reading. */
const struct grid_cell * const struct grid_cell *
grid_peek_cell(struct grid *gd, u_int px, u_int py) 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); 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. */ /* Clear area. */
void void
grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny) 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++) { for (yy = py; yy < py + ny; yy++) {
gl = &gd->linedata[yy]; gl = &gd->linedata[yy];
free(gl->celldata); free(gl->celldata);
free(gl->utf8data);
memset(gl, 0, sizeof *gl); 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( memmove(
&gl->celldata[dx], &gl->celldata[px], nx * sizeof *gl->celldata); &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. */ /* 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)
@ -457,9 +392,9 @@ 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)
{ {
const struct grid_cell *gc; const struct grid_cell *gc;
const struct grid_utf8 *gu; struct utf8_data ud;
char *buf; char *buf;
size_t len, off, size; size_t len, off;
u_int xx; u_int xx;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); 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); gc = grid_peek_cell(gd, xx, py);
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
continue; continue;
grid_cell_get(gc, &ud);
if (gc->flags & GRID_FLAG_UTF8) { while (len < off + ud.size + 1) {
gu = grid_peek_utf8(gd, xx, py); buf = xrealloc(buf, 2, len);
len *= 2;
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;
} }
memcpy(buf + off, ud.data, ud.size);
off += ud.size;
} }
while (off > 0 && buf[off - 1] == ' ') while (off > 0 && buf[off - 1] == ' ')
@ -530,12 +455,6 @@ grid_duplicate_lines(
memcpy(dstl->celldata, srcl->celldata, memcpy(dstl->celldata, srcl->celldata,
srcl->cellsize * sizeof *dstl->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++; sy++;
dy++; dy++;

View File

@ -879,8 +879,8 @@ input_clear(struct input_ctx *ictx)
int int
input_print(struct input_ctx *ictx) input_print(struct input_ctx *ictx)
{ {
ictx->cell.data = ictx->ch; grid_cell_one(&ictx->cell, ictx->ch);
screen_write_cell(&ictx->ctx, &ictx->cell, NULL); screen_write_cell(&ictx->ctx, &ictx->cell);
return (0); return (0);
} }
@ -1657,9 +1657,8 @@ input_utf8_close(struct input_ctx *ictx)
utf8_append(&ictx->utf8data, ictx->ch); utf8_append(&ictx->utf8data, ictx->ch);
ictx->cell.flags |= GRID_FLAG_UTF8; grid_cell_set(&ictx->cell, &ictx->utf8data);
screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data); screen_write_cell(&ictx->ctx, &ictx->cell);
ictx->cell.flags &= ~GRID_FLAG_UTF8;
return (0); return (0);
} }

View File

@ -67,11 +67,10 @@ screen_write_reset(struct screen_write_ctx *ctx)
/* Write character. */ /* Write character. */
void 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; grid_cell_one(gc, ch);
screen_write_cell(ctx, gc, NULL); screen_write_cell(ctx, gc);
} }
/* Calculate string length, with embedded formatting. */ /* Calculate string length, with embedded formatting. */
@ -203,9 +202,8 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
} }
size += utf8data.width; size += utf8data.width;
gc->flags |= GRID_FLAG_UTF8; grid_cell_set(gc, &utf8data);
screen_write_cell(ctx, gc, &utf8data); screen_write_cell(ctx, gc);
gc->flags &= ~GRID_FLAG_UTF8;
} else { } else {
if (maxlen > 0 && size + 1 > (size_t) maxlen) if (maxlen > 0 && size + 1 > (size_t) maxlen)
break; break;
@ -277,9 +275,8 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
} }
size += utf8data.width; size += utf8data.width;
lgc.flags |= GRID_FLAG_UTF8; grid_cell_set(&lgc, &utf8data);
screen_write_cell(ctx, &lgc, &utf8data); screen_write_cell(ctx, &lgc);
lgc.flags &= ~GRID_FLAG_UTF8;
} else { } else {
if (maxlen > 0 && size + 1 > (size_t) maxlen) if (maxlen > 0 && size + 1 > (size_t) maxlen)
break; break;
@ -385,8 +382,7 @@ screen_write_copy(struct screen_write_ctx *ctx,
struct grid *gd = src->grid; struct grid *gd = src->grid;
struct grid_line *gl; struct grid_line *gl;
const struct grid_cell *gc; const struct grid_cell *gc;
const struct grid_utf8 *gu; struct utf8_data ud;
struct utf8_data utf8data;
u_int xx, yy, cx, cy, ax, bx; u_int xx, yy, cx, cy, ax, bx;
cx = s->cx; cx = s->cx;
@ -414,16 +410,8 @@ screen_write_copy(struct screen_write_ctx *ctx,
gc = &grid_default_cell; gc = &grid_default_cell;
else else
gc = &gl->celldata[xx]; gc = &gl->celldata[xx];
if (!(gc->flags & GRID_FLAG_UTF8)) { grid_cell_get(gc, &ud);
screen_write_cell(ctx, gc, NULL); screen_write_cell(ctx, gc);
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);
} }
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);
@ -442,7 +430,6 @@ screen_write_initctx(
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; const struct grid_cell *gc;
const struct grid_utf8 *gu;
u_int xx; u_int xx;
ttyctx->wp = ctx->wp; ttyctx->wp = ctx->wp;
@ -465,10 +452,6 @@ screen_write_initctx(
} }
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);
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. */ /* Cursor up by ny. */
@ -584,7 +567,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);
gc.data = 'E'; grid_cell_one(&gc, '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++)
@ -1066,26 +1049,20 @@ screen_write_clearhistory(struct screen_write_ctx *ctx)
/* Write cell data. */ /* Write cell data. */
void void
screen_write_cell(struct screen_write_ctx *ctx, screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
const struct grid_cell *gc, const struct utf8_data *utf8data)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
struct grid_utf8 gu;
u_int width, xx; u_int width, xx;
struct grid_cell tmp_gc, *tmp_gcp; struct grid_cell tmp_gc, *tmp_gcp;
struct utf8_data ud;
int insert = 0; int insert = 0;
/* Ignore padding. */ /* Ignore padding. */
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
return; return;
width = grid_cell_width(gc);
/* Find character width. */
if (gc->flags & GRID_FLAG_UTF8)
width = utf8data->width;
else
width = 1;
/* /*
* 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
@ -1102,7 +1079,8 @@ screen_write_cell(struct screen_write_ctx *ctx,
* there is space. * there is space.
*/ */
if (width == 0) { 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); screen_write_initctx(ctx, &ttyctx, 0);
tty_write(tty_cmd_utf8character, &ttyctx); tty_write(tty_cmd_utf8character, &ttyctx);
} }
@ -1145,11 +1123,6 @@ screen_write_cell(struct screen_write_ctx *ctx,
/* 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);
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. */ /* Move the cursor. */
s->cx += width; s->cx += width;
@ -1159,12 +1132,11 @@ screen_write_cell(struct screen_write_ctx *ctx,
ttyctx.num = width; ttyctx.num = width;
tty_write(tty_cmd_insertcharacter, &ttyctx); tty_write(tty_cmd_insertcharacter, &ttyctx);
} }
ttyctx.utf8 = &gu;
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);
tmp_gc.data = gc->data; grid_cell_get(gc, &ud);
tmp_gc.flags = gc->flags & grid_cell_set(&tmp_gc, &ud);
~(GRID_FLAG_FG256|GRID_FLAG_BG256); tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
tmp_gc.flags |= s->sel.cell.flags & tmp_gc.flags |= s->sel.cell.flags &
(GRID_FLAG_FG256|GRID_FLAG_BG256); (GRID_FLAG_FG256|GRID_FLAG_BG256);
ttyctx.cell = &tmp_gc; 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. */ /* Combine a UTF-8 zero-width character onto the previous. */
int int
screen_write_combine( screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
struct screen_write_ctx *ctx, const struct utf8_data *utf8data)
{ {
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 grid_utf8 *gu, tmp_gu; struct utf8_data ud1;
u_int i;
/* Can't combine if at 0. */ /* Can't combine if at 0. */
if (s->cx == 0) if (s->cx == 0)
return (-1); return (-1);
/* Empty utf8data is out. */ /* Empty data is out. */
if (utf8data->size == 0) if (ud->size == 0)
fatalx("UTF-8 data empty"); 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); gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
if (!(gc->flags & GRID_FLAG_UTF8)) { grid_cell_get(gc, &ud1);
tmp_gu.data[0] = gc->data;
tmp_gu.data[1] = 0xff;
tmp_gu.width = 1;
grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu); /* Check there is enough space. */
gc->flags |= GRID_FLAG_UTF8; if (ud1.size + ud->size > sizeof ud1.data)
} return (-1);
/* Append the current cell. */ /* Append the data and set the cell. */
gu = grid_view_get_utf8(gd, s->cx - 1, s->cy); memcpy(ud1.data + ud1.size, ud->data, ud->size);
if (grid_utf8_append(gu, utf8data) != 0) { ud1.size += ud->size;
/* Failed: scrap this character and replace with underscores. */ grid_cell_set(gc, &ud1);
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;
}
}
return (0); return (0);
} }

View File

@ -333,12 +333,12 @@ server_client_assume_paste(struct session *s)
u_int t; u_int t;
if ((t = options_get_number(&s->options, "assume-paste-time")) == 0) if ((t = options_get_number(&s->options, "assume-paste-time")) == 0)
return 0; return (0);
timersub(&s->activity_time, &s->last_activity_time, &tv); timersub(&s->activity_time, &s->last_activity_time, &tv);
if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) if (tv.tv_sec == 0 && tv.tv_usec < t * 1000)
return 1; return (1);
return 0; return (0);
} }
/* Handle data key input from client. */ /* Handle data key input from client. */

49
tmux.h
View File

@ -665,13 +665,7 @@ struct mode_key_table {
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY) #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
/* /* A single UTF-8 character. */
* 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).
*/
struct utf8_data { struct utf8_data {
u_char data[UTF8_SIZE]; u_char data[UTF8_SIZE];
@ -705,7 +699,6 @@ 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_UTF8 0x8
/* Grid line flags. */ /* Grid line flags. */
#define GRID_LINE_WRAPPED 0x1 #define GRID_LINE_WRAPPED 0x1
@ -716,13 +709,9 @@ struct grid_cell {
u_char flags; u_char flags;
u_char fg; u_char fg;
u_char bg; u_char bg;
u_char data;
} __packed;
/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */ u_char xstate; /* top 4 bits width, bottom 4 bits size */
struct grid_utf8 { u_char xdata[UTF8_SIZE];
u_char width;
u_char data[UTF8_SIZE];
} __packed; } __packed;
/* Grid line. */ /* Grid line. */
@ -730,9 +719,6 @@ struct grid_line {
u_int cellsize; u_int cellsize;
struct grid_cell *celldata; struct grid_cell *celldata;
u_int utf8size;
struct grid_utf8 *utf8data;
int flags; int flags;
} __packed; } __packed;
@ -1229,7 +1215,6 @@ struct tty_ctx {
struct window_pane *wp; struct window_pane *wp;
const struct grid_cell *cell; const struct grid_cell *cell;
const struct grid_utf8 *utf8;
u_int num; u_int num;
void *ptr; void *ptr;
@ -1250,7 +1235,6 @@ struct tty_ctx {
/* Saved last cell on line. */ /* Saved last cell on line. */
struct grid_cell last_cell; struct grid_cell last_cell;
struct grid_utf8 last_utf8;
u_int last_width; u_int last_width;
}; };
@ -1619,10 +1603,11 @@ 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);
void tty_putcode_ptr1(struct tty *, enum tty_code_code, const void *); 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_puts(struct tty *, const char *);
void tty_putc(struct tty *, u_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 *); void tty_init(struct tty *, struct client *, int, char *);
int tty_resize(struct tty *); int tty_resize(struct tty *);
int tty_set_size(struct tty *, u_int, u_int); int tty_set_size(struct tty *, u_int, u_int);
@ -1965,13 +1950,9 @@ void grid_collect_history(struct grid *);
void grid_scroll_history(struct grid *); 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_expand_line(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); 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(struct grid *, u_int, u_int, const struct grid_cell *); 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(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);
void grid_move_lines(struct grid *, u_int, u_int, u_int); void grid_move_lines(struct grid *, u_int, u_int, u_int);
@ -1980,22 +1961,17 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int);
void grid_duplicate_lines( void grid_duplicate_lines(
struct grid *, u_int, struct grid *, u_int, u_int); struct grid *, u_int, struct grid *, u_int, u_int);
/* grid-utf8.c */ /* grid-cell.c */
size_t grid_utf8_size(const struct grid_utf8 *); u_int grid_cell_width(const struct grid_cell *);
size_t grid_utf8_copy(const struct grid_utf8 *, char *, size_t); void grid_cell_get(const struct grid_cell *, struct utf8_data *);
void grid_utf8_set(struct grid_utf8 *, const struct utf8_data *); void grid_cell_set(struct grid_cell *, const struct utf8_data *);
int grid_utf8_append(struct grid_utf8 *, const struct utf8_data *); void grid_cell_one(struct grid_cell *, u_char);
int grid_utf8_compare(const struct grid_utf8 *, const struct grid_utf8 *);
/* 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);
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 *);
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_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);
@ -2060,8 +2036,7 @@ 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_clearhistory(struct screen_write_ctx *); void screen_write_clearhistory(struct screen_write_ctx *);
void screen_write_cell(struct screen_write_ctx *, void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *);
const struct grid_cell *, const struct utf8_data *);
void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); 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_rawstring(struct screen_write_ctx *, u_char *, u_int);
void screen_write_bracketpaste(struct screen_write_ctx *, int); void screen_write_bracketpaste(struct screen_write_ctx *, int);

68
tty.c
View File

@ -48,8 +48,7 @@ void tty_redraw_region(struct tty *, const struct tty_ctx *);
void tty_emulate_repeat( void tty_emulate_repeat(
struct tty *, enum tty_code_code, enum tty_code_code, u_int); struct tty *, enum tty_code_code, enum tty_code_code, u_int);
void tty_repeat_space(struct tty *, u_int); void tty_repeat_space(struct tty *, u_int);
void tty_cell(struct tty *, void tty_cell(struct tty *, const struct grid_cell *);
const struct grid_cell *, const struct grid_utf8 *);
#define tty_use_acs(tty) \ #define tty_use_acs(tty) \
(tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) (tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8))
@ -416,15 +415,12 @@ tty_putc(struct tty *tty, u_char ch)
} }
void 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; bufferevent_write(tty->event, buf, len);
size = grid_utf8_size(gu);
bufferevent_write(tty->event, gu->data, size);
if (tty->log_fd != -1) if (tty->log_fd != -1)
write(tty->log_fd, gu->data, size); write(tty->log_fd, buf, len);
tty->cx += gu->width; tty->cx += width;
} }
void 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; const struct grid_cell *gc;
struct grid_line *gl; struct grid_line *gl;
struct grid_cell tmpgc; struct grid_cell tmpgc;
const struct grid_utf8 *gu; struct utf8_data ud;
u_int i, sx; u_int i, sx;
tty_update_mode(tty, tty->mode & ~MODE_CURSOR, s); 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++) { for (i = 0; i < sx; i++) {
gc = grid_view_peek_cell(s->grid, i, py); 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)) { if (screen_check_selection(s, i, py)) {
memcpy(&tmpgc, &s->sel.cell, sizeof tmpgc); 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 & tmpgc.flags = gc->flags &
~(GRID_FLAG_FG256|GRID_FLAG_BG256); ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
tmpgc.flags |= s->sel.cell.flags & tmpgc.flags |= s->sel.cell.flags &
(GRID_FLAG_FG256|GRID_FLAG_BG256); (GRID_FLAG_FG256|GRID_FLAG_BG256);
tty_cell(tty, &tmpgc, gu); tty_cell(tty, &tmpgc);
} else } else
tty_cell(tty, gc, gu); tty_cell(tty, gc);
} }
if (sx >= tty->sx) { if (sx >= tty->sx) {
@ -984,17 +976,11 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
struct screen *s = wp->screen; struct screen *s = wp->screen;
u_int cx; u_int cx;
u_int width; 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); 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);
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) {
/* /*
@ -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 * move as far left as possible and redraw the last
* cell to move into the last position. * cell to move into the last position.
*/ */
if (ctx->last_cell.flags & GRID_FLAG_UTF8) cx = screen_size_x(s) - grid_cell_width(&ctx->last_cell);
cx = screen_size_x(s) - ctx->last_utf8.width;
else
cx = screen_size_x(s) - 1;
tty_cursor_pane(tty, ctx, cx, ctx->ocy); tty_cursor_pane(tty, ctx, cx, ctx->ocy);
tty_cell(tty, &ctx->last_cell, &ctx->last_utf8); tty_cell(tty, &ctx->last_cell);
} }
} else } else
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
tty_cell(tty, ctx->cell, ctx->utf8); tty_cell(tty, ctx->cell);
} }
void void
@ -1071,10 +1054,10 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
} }
void void
tty_cell( tty_cell(struct tty *tty, const struct grid_cell *gc)
struct tty *tty, const struct grid_cell *gc, const struct grid_utf8 *gu)
{ {
u_int i; struct utf8_data ud;
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 &&
@ -1088,23 +1071,24 @@ tty_cell(
/* Set the attributes. */ /* Set the attributes. */
tty_attributes(tty, gc); tty_attributes(tty, gc);
/* If not UTF-8, write directly. */ /* Get the cell and if ASCII write with putc to do ACS translation. */
if (!(gc->flags & GRID_FLAG_UTF8)) { grid_cell_get(gc, &ud);
if (gc->data < 0x20 || gc->data == 0x7f) if (ud.size == 1) {
if (*ud.data < 0x20 || *ud.data == 0x7f)
return; return;
tty_putc(tty, gc->data); tty_putc(tty, *ud.data);
return; return;
} }
/* If the terminal doesn't support UTF-8, write underscores. */ /* If not UTF-8, write _. */
if (!(tty->flags & TTY_UTF8)) { if (!(tty->flags & TTY_UTF8)) {
for (i = 0; i < gu->width; i++) for (i = 0; i < ud.width; i++)
tty_putc(tty, '_'); tty_putc(tty, '_');
return; return;
} }
/* Otherwise, write UTF-8. */ /* Write the data. */
tty_pututf8(tty, gu); tty_putn(tty, ud.data, ud.size, ud.width);
} }
void void

View File

@ -908,24 +908,16 @@ window_copy_search_compare(
struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx) struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx)
{ {
const struct grid_cell *gc, *sgc; const struct grid_cell *gc, *sgc;
const struct grid_utf8 *gu, *sgu; struct utf8_data ud, sud;
gc = grid_peek_cell(gd, px, py); gc = grid_peek_cell(gd, px, py);
grid_cell_get(gc, &ud);
sgc = grid_peek_cell(sgd, spx, 0); 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); return (0);
return (memcmp(ud.data, sud.data, ud.size) == 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);
} }
int int
@ -1395,10 +1387,9 @@ window_copy_copy_line(struct window_pane *wp,
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; const struct grid_cell *gc;
const struct grid_utf8 *gu;
struct grid_line *gl; struct grid_line *gl;
struct utf8_data ud;
u_int i, xx, wrapped = 0; u_int i, xx, wrapped = 0;
size_t size;
if (sx > ex) if (sx > ex)
return; return;
@ -1426,15 +1417,11 @@ window_copy_copy_line(struct window_pane *wp,
gc = grid_peek_cell(gd, i, sy); gc = grid_peek_cell(gd, i, sy);
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
continue; continue;
if (!(gc->flags & GRID_FLAG_UTF8)) { grid_cell_get(gc, &ud);
*buf = xrealloc(*buf, 1, (*off) + 1);
(*buf)[(*off)++] = gc->data; *buf = xrealloc(*buf, 1, (*off) + ud.size);
} else { memcpy(*buf + *off, ud.data, ud.size);
gu = grid_peek_utf8(gd, i, sy); *off += ud.size;
size = grid_utf8_size(gu);
*buf = xrealloc(*buf, 1, (*off) + size);
*off += grid_utf8_copy(gu, *buf + *off, 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; struct window_copy_mode_data *data = wp->modedata;
const struct grid_cell *gc; const struct grid_cell *gc;
struct utf8_data ud;
gc = grid_peek_cell(data->backing->grid, px, py); 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); return (0);
if (gc->data == 0x00 || gc->data == 0x7f) if (*ud.data == 0x00 || *ud.data == 0x7f)
return (0); return (0);
return (strchr(set, gc->data) != NULL); return (strchr(set, *ud.data) != NULL);
} }
u_int 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 window_copy_mode_data *data = wp->modedata;
struct screen *s = data->backing; struct screen *s = data->backing;
const struct grid_cell *gc; const struct grid_cell *gc;
struct utf8_data ud;
u_int px; u_int px;
/* /*
@ -1492,9 +1482,8 @@ window_copy_find_length(struct window_pane *wp, u_int py)
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); gc = grid_peek_cell(s->grid, px - 1, py);
if (gc->flags & GRID_FLAG_UTF8) grid_cell_get(gc, &ud);
break; if (ud.size != 1 || *ud.data != ' ')
if (gc->data != ' ')
break; break;
px--; px--;
} }
@ -1527,6 +1516,7 @@ 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; const 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;
@ -1534,9 +1524,8 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
while (px < xx) { while (px < xx) {
gc = grid_peek_cell(data->backing->grid, px, py); gc = grid_peek_cell(data->backing->grid, px, py);
if (gc->flags & GRID_FLAG_UTF8) grid_cell_get(gc, &ud);
break; if (ud.size != 1 || *ud.data != ' ')
if (gc->data != ' ')
break; break;
px++; px++;
} }
@ -1696,6 +1685,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; const 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;
@ -1704,9 +1694,9 @@ window_copy_cursor_jump(struct window_pane *wp)
while (px < xx) { while (px < xx) {
gc = grid_peek_cell(back_s->grid, px, py); gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 grid_cell_get(gc, &ud);
&& gc->data == data->jumpchar) { if (!(gc->flags & GRID_FLAG_PADDING) &&
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)) if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1); 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 window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; const struct grid_cell *gc;
struct utf8_data ud;
u_int px, py; u_int px, py;
px = data->cx; px = data->cx;
@ -1732,9 +1723,9 @@ window_copy_cursor_jump_back(struct window_pane *wp)
for (;;) { for (;;) {
gc = grid_peek_cell(back_s->grid, px, py); gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 grid_cell_get(gc, &ud);
&& gc->data == data->jumpchar) { if (!(gc->flags & GRID_FLAG_PADDING) &&
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)) if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1); 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 window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; const 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;
@ -1760,9 +1752,9 @@ window_copy_cursor_jump_to(struct window_pane *wp)
while (px < xx) { while (px < xx) {
gc = grid_peek_cell(back_s->grid, px, py); gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 grid_cell_get(gc, &ud);
&& gc->data == data->jumpchar) { if (!(gc->flags & GRID_FLAG_PADDING) &&
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)) if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1); 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 window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing; struct screen *back_s = data->backing;
const struct grid_cell *gc; const struct grid_cell *gc;
struct utf8_data ud;
u_int px, py; u_int px, py;
px = data->cx; px = data->cx;
@ -1788,9 +1781,9 @@ window_copy_cursor_jump_to_back(struct window_pane *wp)
for (;;) { for (;;) {
gc = grid_peek_cell(back_s->grid, px, py); gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0 grid_cell_get(gc, &ud);
&& gc->data == data->jumpchar) { if (!(gc->flags & GRID_FLAG_PADDING) &&
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)) if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1); window_copy_redraw_lines(wp, data->cy, 1);