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.
pull/1/head
Nicholas Marriott 2009-11-18 17:02:17 +00:00
parent 8db145da1e
commit a78cc98c8b
8 changed files with 157 additions and 70 deletions

View File

@ -30,7 +30,7 @@ SRCS= attributes.c cfg.c client.c clock.c \
cmd-set-environment.c cmd-show-environment.c cmd-choose-client.c \
cmd-up-pane.c cmd-display-message.c cmd-display-panes.c \
cmd-pipe-pane.c cmd.c \
colour.c environ.c grid-view.c grid.c input-keys.c \
colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \
imsg.c imsg-buffer.c input.c key-bindings.c key-string.c \
layout-set.c layout.c log.c job.c \
mode-key.c names.c options-cmd.c options.c paste.c procname.c \

96
grid-utf8.c Normal file
View File

@ -0,0 +1,96 @@
/* $OpenBSD$ */
/*
* 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);
}

16
grid.c
View File

@ -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_utf8 *gu;
char *buf;
size_t len, off;
u_int xx, i;
size_t len, off, size;
u_int xx;
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;
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);
len *= 2;
}
gu = grid_peek_utf8(gd, xx, py);
for (i = 0; i < UTF8_SIZE; i++) {
if (gu->data[i] == 0xff)
break;
buf[off++] = gu->data[i];
}
off += grid_utf8_copy(gu, buf + off, len - off);
} else {
while (len < off + 2) {
buf = xrealloc(buf, 2, len);

View File

@ -354,7 +354,7 @@ screen_write_copy(struct screen_write_ctx *ctx,
const struct grid_cell *gc;
const struct grid_utf8 *gu;
struct utf8_data utf8data;
u_int xx, yy, cx, cy, ax, bx, i;
u_int xx, yy, cx, cy, ax, bx;
cx = s->cx;
cy = s->cy;
@ -381,18 +381,15 @@ screen_write_copy(struct screen_write_ctx *ctx,
gc = &grid_default_cell;
else
gc = &gl->celldata[xx];
if (gc->flags & GRID_FLAG_UTF8) {
gu = &gl->utf8data[xx];
memcpy(utf8data.data,
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++;
}
if (!(gc->flags & GRID_FLAG_UTF8)) {
screen_write_cell(ctx, gc, NULL);
continue;
}
/* Reinject the UTF-8 sequence. */
gu = &gl->utf8data[xx];
utf8data.size = grid_utf8_copy(
gu, utf8data.data, sizeof utf8data.data);
utf8data.width = gu->width;
screen_write_cell(ctx, gc, &utf8data);
}
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);
if (gc->flags & GRID_FLAG_UTF8) {
/* Construct UTF-8 and write it. */
gu.width = utf8data->width;
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_utf8_set(&gu, utf8data);
grid_view_set_utf8(gd, s->cx, s->cy, &gu);
}
@ -1080,7 +1071,7 @@ screen_write_combine(
struct grid *gd = s->grid;
struct grid_cell *gc;
struct grid_utf8 *gu, tmp_gu;
u_int i, old_size;
u_int i;
/* Can't combine if at 0. */
if (s->cx == 0)
@ -1093,35 +1084,30 @@ screen_write_combine(
/* Retrieve the previous cell and convert to UTF-8 if not already. */
gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
if (!(gc->flags & GRID_FLAG_UTF8)) {
memset(&tmp_gu.data, 0xff, sizeof tmp_gu.data);
*tmp_gu.data = gc->data;
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);
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);
for (old_size = 0; old_size < UTF8_SIZE; old_size++) {
if (gu->data[old_size] == 0xff)
break;
if (grid_utf8_append(gu, utf8data) != 0) {
/* Failed: scrap this character and replace with underscores. */
if (gu->width == 1) {
gc->data = '_';
gc->flags &= ~GRID_FLAG_UTF8;
} else {
for (i = 0; i < gu->width && i != sizeof gu->data; i++)
gu->data[i] = '_';
if (i != sizeof gu->data)
gu->data[i] = 0xff;
gu->width = i;
}
}
/* 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);
}

2
tmux.1
View File

@ -454,7 +454,7 @@ with
.D1 (alias: Ic rename )
Rename the session to
.Ar new-name .
.It Xo Ic show-messages
.It Xo Ic show-messages
.Op Fl t Ar target-client
.Xc
.D1 (alias: Ic showmsgs )

16
tmux.h
View File

@ -74,6 +74,12 @@ extern char **environ;
#define PRINT_LENGTH 512 /* printed error/message size */
#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. */
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
#define fatalx(msg) log_fatalx("%s: %s", __func__, msg);
@ -525,13 +531,12 @@ struct mode_key_table {
#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
* reinject stored UTF-8 data back into screen_write_cell after combining (ugh
* XXX XXX).
*/
#define UTF8_SIZE 9
struct utf8_data {
u_char data[UTF8_SIZE];
@ -1675,6 +1680,13 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int);
void grid_duplicate_lines(
struct grid *, u_int, struct grid *, u_int, u_int);
/* grid-utf8.c */
size_t grid_utf8_size(const struct grid_utf8 *);
size_t grid_utf8_copy(const struct grid_utf8 *, char *, size_t);
void grid_utf8_set(struct grid_utf8 *, const struct utf8_data *);
int grid_utf8_append(struct grid_utf8 *, const struct utf8_data *);
int grid_utf8_compare(const struct grid_utf8 *, const struct grid_utf8 *);
/* grid-view.c */
const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int);
struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int);

14
tty.c
View File

@ -365,16 +365,12 @@ tty_putc(struct tty *tty, u_char ch)
void
tty_pututf8(struct tty *tty, const struct grid_utf8 *gu)
{
u_int i;
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_t size;
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;
}

View File

@ -486,6 +486,7 @@ window_copy_search_compare(
{
const struct grid_cell *gc, *sgc;
const struct grid_utf8 *gu, *sgu;
size_t size;
gc = grid_peek_cell(gd, px, py);
sgc = grid_peek_cell(sgd, spx, 0);
@ -496,7 +497,7 @@ window_copy_search_compare(
if (gc->flags & GRID_FLAG_UTF8) {
gu = grid_peek_utf8(gd, px, py);
sgu = grid_peek_utf8(sgd, spx, 0);
if (memcmp(gu->data, sgu->data, UTF8_SIZE) == 0)
if (grid_utf8_compare(gu, sgu))
return (1);
} else {
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_utf8 *gu;
struct grid_line *gl;
u_int i, j, xx, wrapped = 0;
u_int i, xx, wrapped = 0;
size_t size;
if (sx > ex)
return;
@ -928,12 +930,9 @@ window_copy_copy_line(struct window_pane *wp,
(*buf)[(*off)++] = gc->data;
} else {
gu = grid_peek_utf8(gd, i, sy);
*buf = xrealloc(*buf, 1, (*off) + UTF8_SIZE);
for (j = 0; j < UTF8_SIZE; j++) {
if (gu->data[j] == 0xff)
break;
(*buf)[(*off)++] = gu->data[j];
}
size = grid_utf8_size(gu);
*buf = xrealloc(*buf, 1, (*off) + size);
*off += grid_utf8_copy(gu, *buf + *off, size);
}
}
}