Sync OpenBSD patchset 547:

Cleanup by moving various (mostly horrible) little bits handling UTF-8 grid
data into functions in a new file, grid-utf8.c, and use sizeof intead of
UTF8_DATA.

Also nuke trailing whitespace from tmux.1, reminded by jmc.
This commit is contained in:
Tiago Cunha 2009-11-19 22:23:27 +00:00
parent acc331c787
commit a0b2b8e875
7 changed files with 162 additions and 75 deletions

96
grid-utf8.c Normal file
View File

@ -0,0 +1,96 @@
/* $Id: grid-utf8.c,v 1.1 2009-11-19 22:23:27 tcunha Exp $ */
/*
* 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);
}

18
grid.c
View File

@ -1,4 +1,4 @@
/* $Id: grid.c,v 1.34 2009-10-15 01:55:12 tcunha Exp $ */ /* $Id: grid.c,v 1.35 2009-11-19 22:23:27 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -502,8 +502,8 @@ 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; const struct grid_utf8 *gu;
char *buf; char *buf;
size_t len, off; size_t len, off, size;
u_int xx, i; 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);
@ -517,17 +517,15 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
continue; continue;
if (gc->flags & GRID_FLAG_UTF8) { if (gc->flags & GRID_FLAG_UTF8) {
while (len < off + UTF8_SIZE + 1) { gu = grid_peek_utf8(gd, xx, py);
size = grid_utf8_size(gu);
while (len < off + size + 1) {
buf = xrealloc(buf, 2, len); buf = xrealloc(buf, 2, len);
len *= 2; len *= 2;
} }
gu = grid_peek_utf8(gd, xx, py); off += grid_utf8_copy(gu, buf + off, len - off);
for (i = 0; i < UTF8_SIZE; i++) {
if (gu->data[i] == 0xff)
break;
buf[off++] = gu->data[i];
}
} else { } else {
while (len < off + 2) { while (len < off + 2) {
buf = xrealloc(buf, 2, len); buf = xrealloc(buf, 2, len);

View File

@ -1,4 +1,4 @@
/* $Id: screen-write.c,v 1.85 2009-11-18 01:25:35 tcunha Exp $ */ /* $Id: screen-write.c,v 1.86 2009-11-19 22:23:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -354,7 +354,7 @@ screen_write_copy(struct screen_write_ctx *ctx,
const struct grid_cell *gc; const struct grid_cell *gc;
const struct grid_utf8 *gu; const struct grid_utf8 *gu;
struct utf8_data utf8data; struct utf8_data utf8data;
u_int xx, yy, cx, cy, ax, bx, i; u_int xx, yy, cx, cy, ax, bx;
cx = s->cx; cx = s->cx;
cy = s->cy; cy = s->cy;
@ -381,18 +381,15 @@ 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) { if (!(gc->flags & GRID_FLAG_UTF8)) {
gu = &gl->utf8data[xx]; screen_write_cell(ctx, gc, NULL);
memcpy(utf8data.data, continue;
gu->data, sizeof utf8data.data);
utf8data.width = gu->width;
utf8data.size = 0;
for (i = 0; i < UTF8_SIZE; i++) {
if (gu->data[i] == 0xff)
break;
utf8data.size++;
}
} }
/* 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); screen_write_cell(ctx, gc, &utf8data);
} }
if (px + nx == gd->sx && px + nx > gl->cellsize) if (px + nx == gd->sx && px + nx > gl->cellsize)
@ -1037,13 +1034,7 @@ screen_write_cell(struct screen_write_ctx *ctx,
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) { if (gc->flags & GRID_FLAG_UTF8) {
/* Construct UTF-8 and write it. */ /* Construct UTF-8 and write it. */
gu.width = utf8data->width; grid_utf8_set(&gu, utf8data);
memset(gu.data, 0xff, sizeof gu.data);
if (utf8data->size == 0)
fatalx("UTF-8 data empty");
if (utf8data->size > sizeof gu.data)
fatalx("UTF-8 data overflow");
memcpy(gu.data, utf8data->data, utf8data->size);
grid_view_set_utf8(gd, s->cx, s->cy, &gu); grid_view_set_utf8(gd, s->cx, s->cy, &gu);
} }
@ -1080,7 +1071,7 @@ screen_write_combine(
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 grid_utf8 *gu, tmp_gu;
u_int i, old_size; u_int i;
/* Can't combine if at 0. */ /* Can't combine if at 0. */
if (s->cx == 0) if (s->cx == 0)
@ -1093,35 +1084,30 @@ screen_write_combine(
/* Retrieve the previous cell and convert to UTF-8 if not already. */ /* Retrieve the previous cell and convert to UTF-8 if not already. */
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)) { if (!(gc->flags & GRID_FLAG_UTF8)) {
memset(&tmp_gu.data, 0xff, sizeof tmp_gu.data); tmp_gu.data[0] = gc->data;
*tmp_gu.data = gc->data; tmp_gu.data[1] = 0xff;
tmp_gu.width = 1; tmp_gu.width = 1;
grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu); grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu);
gc->flags |= GRID_FLAG_UTF8; gc->flags |= GRID_FLAG_UTF8;
} }
/* Get the previous cell's UTF-8 data and its size. */ /* Append the current cell. */
gu = grid_view_get_utf8(gd, s->cx - 1, s->cy); gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
for (old_size = 0; old_size < UTF8_SIZE; old_size++) { if (grid_utf8_append(gu, utf8data) != 0) {
if (gu->data[old_size] == 0xff) /* Failed: scrap this character and replace with underscores. */
break; 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;
}
} }
/* If there isn't space, scrap this character. */
if (old_size + utf8data->size > UTF8_SIZE) {
for (i = 0; i < gu->width && i != UTF8_SIZE; i++)
gu->data[i] = '_';
if (i != UTF8_SIZE)
gu->data[i] = 0xff;
gu->width = i;
return (0);
}
/* Otherwise save the character. */
memcpy(gu->data + old_size, utf8data->data, utf8data->size);
if (old_size + utf8data->size != UTF8_SIZE)
gu->data[old_size + utf8data->size] = 0xff;
return (0); return (0);
} }

4
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.202 2009-11-19 22:20:04 tcunha Exp $ .\" $Id: tmux.1,v 1.203 2009-11-19 22:23:27 tcunha Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -454,7 +454,7 @@ with
.D1 (alias: Ic rename ) .D1 (alias: Ic rename )
Rename the session to Rename the session to
.Ar new-name . .Ar new-name .
.It Xo Ic show-messages .It Xo Ic show-messages
.Op Fl t Ar target-client .Op Fl t Ar target-client
.Xc .Xc
.D1 (alias: Ic showmsgs ) .D1 (alias: Ic showmsgs )

18
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.518 2009-11-19 22:20:04 tcunha Exp $ */ /* $Id: tmux.h,v 1.519 2009-11-19 22:23:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -73,6 +73,12 @@ extern char **environ;
#define PRINT_LENGTH 512 /* printed error/message size */ #define PRINT_LENGTH 512 /* printed error/message size */
#define ENVIRON_LENGTH 1024 /* environment variable length */ #define ENVIRON_LENGTH 1024 /* environment variable length */
/*
* UTF-8 data size. This must be big enough to hold combined characters as well
* as single.
*/
#define UTF8_SIZE 9
/* Fatal errors. */ /* Fatal errors. */
#define fatal(msg) log_fatal("%s: %s", __func__, msg); #define fatal(msg) log_fatal("%s: %s", __func__, msg);
#define fatalx(msg) log_fatalx("%s: %s", __func__, msg); #define fatalx(msg) log_fatalx("%s: %s", __func__, msg);
@ -524,13 +530,12 @@ struct mode_key_table {
#define MODE_MOUSE 0x10 #define MODE_MOUSE 0x10
/* /*
* 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 * 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 * reinject stored UTF-8 data back into screen_write_cell after combining (ugh
* XXX XXX). * XXX XXX).
*/ */
#define UTF8_SIZE 9
struct utf8_data { struct utf8_data {
u_char data[UTF8_SIZE]; u_char data[UTF8_SIZE];
@ -1674,6 +1679,13 @@ 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 */
size_t grid_utf8_size(const struct grid_utf8 *);
size_t grid_utf8_copy(const struct grid_utf8 *, char *, size_t);
void grid_utf8_set(struct grid_utf8 *, const struct utf8_data *);
int grid_utf8_append(struct grid_utf8 *, const struct utf8_data *);
int grid_utf8_compare(const struct grid_utf8 *, const struct grid_utf8 *);
/* grid-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);

16
tty.c
View File

@ -1,4 +1,4 @@
/* $Id: tty.c,v 1.174 2009-11-13 16:57:21 tcunha Exp $ */ /* $Id: tty.c,v 1.175 2009-11-19 22:23:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -370,16 +370,12 @@ tty_putc(struct tty *tty, u_char ch)
void void
tty_pututf8(struct tty *tty, const struct grid_utf8 *gu) tty_pututf8(struct tty *tty, const struct grid_utf8 *gu)
{ {
u_int i; size_t size;
for (i = 0; i < UTF8_SIZE; i++) {
if (gu->data[i] == 0xff)
break;
bufferevent_write(tty->event, &gu->data[i], 1);
if (tty->log_fd != -1)
write(tty->log_fd, &gu->data[i], 1);
}
size = grid_utf8_size(gu);
bufferevent_write(tty->event, gu->data, size);
if (tty->log_fd != -1)
write(tty->log_fd, gu->data, size);
tty->cx += gu->width; tty->cx += gu->width;
} }

View File

@ -1,4 +1,4 @@
/* $Id: window-copy.c,v 1.90 2009-10-23 17:17:20 tcunha Exp $ */ /* $Id: window-copy.c,v 1.91 2009-11-19 22:23:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -486,6 +486,7 @@ window_copy_search_compare(
{ {
const struct grid_cell *gc, *sgc; const struct grid_cell *gc, *sgc;
const struct grid_utf8 *gu, *sgu; const struct grid_utf8 *gu, *sgu;
size_t size;
gc = grid_peek_cell(gd, px, py); gc = grid_peek_cell(gd, px, py);
sgc = grid_peek_cell(sgd, spx, 0); sgc = grid_peek_cell(sgd, spx, 0);
@ -496,7 +497,7 @@ window_copy_search_compare(
if (gc->flags & GRID_FLAG_UTF8) { if (gc->flags & GRID_FLAG_UTF8) {
gu = grid_peek_utf8(gd, px, py); gu = grid_peek_utf8(gd, px, py);
sgu = grid_peek_utf8(sgd, spx, 0); sgu = grid_peek_utf8(sgd, spx, 0);
if (memcmp(gu->data, sgu->data, UTF8_SIZE) == 0) if (grid_utf8_compare(gu, sgu))
return (1); return (1);
} else { } else {
if (gc->data == sgc->data) if (gc->data == sgc->data)
@ -895,7 +896,8 @@ window_copy_copy_line(struct window_pane *wp,
const struct grid_cell *gc; const struct grid_cell *gc;
const struct grid_utf8 *gu; const struct grid_utf8 *gu;
struct grid_line *gl; struct grid_line *gl;
u_int i, j, xx, wrapped = 0; u_int i, xx, wrapped = 0;
size_t size;
if (sx > ex) if (sx > ex)
return; return;
@ -928,12 +930,9 @@ window_copy_copy_line(struct window_pane *wp,
(*buf)[(*off)++] = gc->data; (*buf)[(*off)++] = gc->data;
} else { } else {
gu = grid_peek_utf8(gd, i, sy); gu = grid_peek_utf8(gd, i, sy);
*buf = xrealloc(*buf, 1, (*off) + UTF8_SIZE); size = grid_utf8_size(gu);
for (j = 0; j < UTF8_SIZE; j++) { *buf = xrealloc(*buf, 1, (*off) + size);
if (gu->data[j] == 0xff) *off += grid_utf8_copy(gu, *buf + *off, size);
break;
(*buf)[(*off)++] = gu->data[j];
}
} }
} }
} }