mirror of
https://github.com/tmux/tmux.git
synced 2024-12-12 17:38:48 +00:00
Better UTF-8 support, including combined characters. Unicode data is now stored
as UTF-8 in a separate array, the code does a lookup into this every time it gets to a UTF-8 cell. Zero width characters are just appended onto the UTF-8 data for the previous cell. This also means that almost no bytes extra are wasted non-Unicode data (yay). Still some oddities, such as copy mode skips over wide characters in a strange way, and the code could do with some tidying.
This commit is contained in:
parent
34dd72f008
commit
cf7b384c43
10
CHANGES
10
CHANGES
@ -1,5 +1,13 @@
|
||||
28 March 2009
|
||||
|
||||
* Better UTF-8 support, including combined characters. Unicode data is now
|
||||
stored as UTF-8 in a separate array, the code does a lookup into this every
|
||||
time it gets to a UTF-8 cell. Zero width characters are just appended onto
|
||||
the UTF-8 data for the previous cell. This also means that almost no bytes
|
||||
extra are wasted non-Unicode data (yay).
|
||||
|
||||
Still some oddities, such as copy mode skips over wide characters in a
|
||||
strange way, and the code could do with some tidying.
|
||||
* Key repeating is now a property of the key binding not of the command.
|
||||
Repeat is turned on when the key is bound with the -r flag to bind-key.
|
||||
next/previous-window no longer repeat by default as it turned out to annoy
|
||||
@ -1152,7 +1160,7 @@
|
||||
(including mutt, emacs). No status bar yet and no key remapping or other
|
||||
customisation.
|
||||
|
||||
$Id: CHANGES,v 1.262 2009-03-28 14:08:09 nicm Exp $
|
||||
$Id: CHANGES,v 1.263 2009-03-28 20:17:29 nicm Exp $
|
||||
|
||||
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
|
||||
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms
|
||||
|
6
TODO
6
TODO
@ -69,11 +69,6 @@
|
||||
errors better
|
||||
- would be nice if tmux could be the shell (tmux attach, but hard link to tmux
|
||||
binary as "tmuxsh" or wrapper script?) -- problems with tty dev permissions
|
||||
- UTF-8 combining characters don't work. store in one cell - pointer to table
|
||||
of chains. bit of a hack and would mean max of 65536 per screen. OR maybe
|
||||
utf8 should work differently; could store as multiple cells, 1 of width >0
|
||||
and n of width 0, then translate cursor indexes on-the-fly would need to
|
||||
adjust all cursor movement and also handle different width lines properly.
|
||||
- support other mouse modes (highlight etc) and use it in copy mode
|
||||
- set-remain-on-exit is a bit of a hack, some way to do it generically?
|
||||
- set-option should be set-session-option and should be overall global options
|
||||
@ -92,6 +87,7 @@
|
||||
- refer to windows by name etc (duplicates? fnmatch?)
|
||||
- a confirm-before command which asks "Are you sure? (y/n)" before executing
|
||||
command, eg bind-key "&" confirm-before "kill-window"
|
||||
- c&p is funny w/ UTF-8
|
||||
|
||||
- document repeat behaviour and -r on bind-key
|
||||
- document status-keys
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-find-window.c,v 1.4 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: cmd-find-window.c,v 1.5 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -163,25 +163,29 @@ cmd_find_window_callback(void *data, int idx)
|
||||
char *
|
||||
cmd_find_window_search(struct window_pane *wp, const char *searchstr)
|
||||
{
|
||||
char *buf, *s;
|
||||
size_t off;
|
||||
uint64_t text;
|
||||
u_int i, j, k;
|
||||
u_char data[4];
|
||||
const struct grid_cell *gc;
|
||||
const struct grid_utf8 *gu;
|
||||
char *buf, *s;
|
||||
size_t off;
|
||||
u_int i, j, k;
|
||||
|
||||
buf = xmalloc(1);
|
||||
|
||||
for (j = 0; j < screen_size_y(&wp->base); j++) {
|
||||
off = 0;
|
||||
for (i = 0; i < screen_size_x(&wp->base); i++) {
|
||||
text = grid_view_peek_text(wp->base.grid, i, j);
|
||||
utf8_split(text, data);
|
||||
|
||||
buf = xrealloc(buf, 1, off + 4);
|
||||
for (k = 0; k < sizeof data; k++) {
|
||||
if (data[k] == 0xff)
|
||||
break;
|
||||
buf[off++] = data[k];
|
||||
gc = grid_view_peek_cell(wp->base.grid, i, j);
|
||||
if (gc->flags & GRID_FLAG_UTF8) {
|
||||
gu = grid_view_peek_utf8(wp->base.grid, i, j);
|
||||
buf = xrealloc(buf, 1, off + 8);
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (gu->data[k] == 0xff)
|
||||
break;
|
||||
buf[off++] = gu->data[k];
|
||||
}
|
||||
} else {
|
||||
buf = xrealloc(buf, 1, off + 1);
|
||||
buf[off++] = gc->data;
|
||||
}
|
||||
}
|
||||
while (off > 0 && buf[off - 1] == ' ')
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list-windows.c,v 1.32 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: cmd-list-windows.c,v 1.33 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -68,7 +68,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
size = 0;
|
||||
for (i = 0; i < gd->hsize; i++) {
|
||||
size += gd->size[i] * sizeof **gd->data;
|
||||
size += gd->size[i] * sizeof (u_short);
|
||||
size += gd->usize[i] * sizeof **gd->udata;
|
||||
}
|
||||
size += gd->hsize * (sizeof *gd->data);
|
||||
size += gd->hsize * (sizeof *gd->size);
|
||||
|
32
grid-view.c
32
grid-view.c
@ -1,4 +1,4 @@
|
||||
/* $Id: grid-view.c,v 1.10 2009-03-28 16:57:03 nicm Exp $ */
|
||||
/* $Id: grid-view.c,v 1.11 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -37,13 +37,6 @@ grid_view_peek_cell(struct grid *gd, u_int px, u_int py)
|
||||
return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
|
||||
}
|
||||
|
||||
/* Get cell text. */
|
||||
uint64_t
|
||||
grid_view_peek_text(struct grid *gd, u_int px, u_int py)
|
||||
{
|
||||
return (grid_peek_text(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
|
||||
}
|
||||
|
||||
/* Get cell for writing. */
|
||||
struct grid_cell *
|
||||
grid_view_get_cell(struct grid *gd, u_int px, u_int py)
|
||||
@ -59,11 +52,26 @@ grid_view_set_cell(
|
||||
grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
|
||||
}
|
||||
|
||||
/* Set text. */
|
||||
void
|
||||
grid_view_set_text(struct grid *gd, u_int px, u_int py, uint64_t text)
|
||||
/* Get UTF-8 for reading. */
|
||||
const struct grid_utf8 *
|
||||
grid_view_peek_utf8(struct grid *gd, u_int px, u_int py)
|
||||
{
|
||||
grid_set_text(gd, grid_view_x(gd, px), grid_view_y(gd, py), text);
|
||||
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 area. */
|
||||
|
146
grid.c
146
grid.c
@ -1,4 +1,4 @@
|
||||
/* $Id: grid.c,v 1.13 2009-03-28 16:57:03 nicm Exp $ */
|
||||
/* $Id: grid.c,v 1.14 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -35,13 +35,13 @@
|
||||
*/
|
||||
|
||||
/* Default grid cell data. */
|
||||
const struct grid_cell grid_default_cell = { 0, 0, 8, 8 };
|
||||
const struct grid_cell grid_default_cell = { 0, 0, 8, 8, ' ' };
|
||||
|
||||
#define grid_put_cell(gd, px, py, gc) do { \
|
||||
memcpy(&gd->data[py][px], gc, sizeof gd->data[py][px]); \
|
||||
} while (0)
|
||||
#define grid_put_text(gd, px, py, xtext) do { \
|
||||
gd->text[py][px] = xtext; \
|
||||
#define grid_put_utf8(gd, px, py, gc) do { \
|
||||
memcpy(&gd->udata[py][px], gc, sizeof gd->udata[py][px]); \
|
||||
} while (0)
|
||||
|
||||
int grid_check_x(struct grid *, u_int);
|
||||
@ -100,7 +100,9 @@ grid_create(u_int sx, u_int sy, u_int hlimit)
|
||||
|
||||
gd->size = xcalloc(gd->sy, sizeof *gd->size);
|
||||
gd->data = xcalloc(gd->sy, sizeof *gd->data);
|
||||
gd->text = xcalloc(gd->sy, sizeof *gd->text);
|
||||
|
||||
gd->usize = xcalloc(gd->sy, sizeof *gd->usize);
|
||||
gd->udata = xcalloc(gd->sy, sizeof *gd->udata);
|
||||
|
||||
return (gd);
|
||||
}
|
||||
@ -112,18 +114,22 @@ grid_destroy(struct grid *gd)
|
||||
u_int yy;
|
||||
|
||||
for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
|
||||
if (gd->text[yy] != NULL)
|
||||
xfree(gd->text[yy]);
|
||||
if (gd->udata[yy] != NULL)
|
||||
xfree(gd->udata[yy]);
|
||||
if (gd->data[yy] != NULL)
|
||||
xfree(gd->data[yy]);
|
||||
}
|
||||
|
||||
if (gd->text != NULL)
|
||||
xfree(gd->text);
|
||||
if (gd->udata != NULL)
|
||||
xfree(gd->udata);
|
||||
if (gd->usize != NULL)
|
||||
xfree(gd->usize);
|
||||
|
||||
if (gd->data != NULL)
|
||||
xfree(gd->data);
|
||||
if (gd->size != NULL)
|
||||
xfree(gd->size);
|
||||
|
||||
xfree(gd);
|
||||
}
|
||||
|
||||
@ -145,6 +151,7 @@ grid_compare(struct grid *ga, struct grid *gb)
|
||||
gcb = &gb->data[yy][xx];
|
||||
if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0)
|
||||
return (1);
|
||||
/* XXX */
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,13 +177,16 @@ grid_scroll_line(struct grid *gd)
|
||||
}
|
||||
|
||||
yy = gd->hsize + gd->sy;
|
||||
gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size);
|
||||
gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data);
|
||||
gd->text = xrealloc(gd->text, yy + 1, sizeof *gd->text);
|
||||
|
||||
gd->data[yy] = NULL;
|
||||
gd->text[yy] = NULL;
|
||||
gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size);
|
||||
gd->size[yy] = 0;
|
||||
gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data);
|
||||
gd->data[yy] = NULL;
|
||||
|
||||
gd->usize = xrealloc(gd->usize, yy + 1, sizeof *gd->usize);
|
||||
gd->usize[yy] = 0;
|
||||
gd->udata = xrealloc(gd->udata, yy + 1, sizeof *gd->udata);
|
||||
gd->udata[yy] = NULL;
|
||||
|
||||
gd->hsize++;
|
||||
}
|
||||
@ -185,12 +195,14 @@ grid_scroll_line(struct grid *gd)
|
||||
void
|
||||
grid_reduce_line(struct grid *gd, u_int py, u_int sx)
|
||||
{
|
||||
if (sx >= gd->size[py])
|
||||
return;
|
||||
|
||||
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
|
||||
gd->text[py] = xrealloc(gd->text[py], sx, sizeof **gd->text);
|
||||
gd->size[py] = sx;
|
||||
if (sx < gd->size[py]) {
|
||||
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
|
||||
gd->size[py] = sx;
|
||||
}
|
||||
if (sx < gd->usize[py]) {
|
||||
gd->udata[py] = xrealloc(gd->udata[py], sx, sizeof **gd->udata);
|
||||
gd->usize[py] = sx;
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand line to fit to cell. */
|
||||
@ -203,14 +215,22 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx)
|
||||
return;
|
||||
|
||||
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
|
||||
gd->text[py] = xrealloc(gd->text[py], sx, sizeof **gd->text);
|
||||
for (xx = gd->size[py]; xx < sx; xx++) {
|
||||
for (xx = gd->size[py]; xx < sx; xx++)
|
||||
grid_put_cell(gd, xx, py, &grid_default_cell);
|
||||
grid_put_text(gd, xx, py, ' ');
|
||||
}
|
||||
gd->size[py] = sx;
|
||||
}
|
||||
|
||||
/* Expand line to fit to cell for UTF-8. */
|
||||
void
|
||||
grid_expand_line_utf8(struct grid *gd, u_int py, u_int sx)
|
||||
{
|
||||
if (sx <= gd->usize[py])
|
||||
return;
|
||||
|
||||
gd->udata[py] = xrealloc(gd->udata[py], sx, sizeof **gd->udata);
|
||||
gd->usize[py] = sx;
|
||||
}
|
||||
|
||||
/* Get cell for reading. */
|
||||
const struct grid_cell *
|
||||
grid_peek_cell(struct grid *gd, u_int px, u_int py)
|
||||
@ -225,20 +245,6 @@ grid_peek_cell(struct grid *gd, u_int px, u_int py)
|
||||
return (&gd->data[py][px]);
|
||||
}
|
||||
|
||||
/* Get text for reading. */
|
||||
uint64_t
|
||||
grid_peek_text(struct grid *gd, u_int px, u_int py)
|
||||
{
|
||||
if (grid_check_x(gd, px) != 0)
|
||||
return (' ');
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
return (' ');
|
||||
|
||||
if (px >= gd->size[py])
|
||||
return (' ');
|
||||
return (gd->text[py][px]);
|
||||
}
|
||||
|
||||
/* Get cell at relative position (for writing). */
|
||||
struct grid_cell *
|
||||
grid_get_cell(struct grid *gd, u_int px, u_int py)
|
||||
@ -266,17 +272,45 @@ grid_set_cell(
|
||||
grid_put_cell(gd, px, py, gc);
|
||||
}
|
||||
|
||||
/* Set text at relative position. */
|
||||
/* Get UTF-8 for reading. */
|
||||
const struct grid_utf8 *
|
||||
grid_peek_utf8(struct grid *gd, u_int px, u_int py)
|
||||
{
|
||||
if (grid_check_x(gd, px) != 0)
|
||||
return (NULL);
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
return (NULL);
|
||||
|
||||
if (px >= gd->usize[py])
|
||||
return (NULL);
|
||||
return (&gd->udata[py][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_x(gd, px) != 0)
|
||||
return (NULL);
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
return (NULL);
|
||||
|
||||
grid_expand_line_utf8(gd, py, px + 1);
|
||||
return (&gd->udata[py][px]);
|
||||
}
|
||||
|
||||
/* Set utf8 at relative position. */
|
||||
void
|
||||
grid_set_text(struct grid *gd, u_int px, u_int py, uint64_t text)
|
||||
grid_set_utf8(
|
||||
struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gc)
|
||||
{
|
||||
if (grid_check_x(gd, px) != 0)
|
||||
return;
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
return;
|
||||
|
||||
grid_expand_line(gd, py, px + 1);
|
||||
grid_put_text(gd, px, py, text);
|
||||
grid_expand_line_utf8(gd, py, px + 1);
|
||||
grid_put_utf8(gd, px, py, gc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -312,7 +346,6 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
|
||||
if (xx >= gd->size[yy])
|
||||
break;
|
||||
grid_put_cell(gd, xx, yy, &grid_default_cell);
|
||||
grid_put_text(gd, xx, yy, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -334,13 +367,16 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny)
|
||||
return;
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
if (gd->data[yy] != NULL || gd->text[yy] != NULL) {
|
||||
if (gd->data[yy] != NULL) {
|
||||
xfree(gd->data[yy]);
|
||||
xfree(gd->text[yy]);
|
||||
gd->data[yy] = NULL;
|
||||
gd->text[yy] = NULL;
|
||||
gd->size[yy] = 0;
|
||||
}
|
||||
if (gd->udata[yy] != NULL) {
|
||||
xfree(gd->udata[yy]);
|
||||
gd->udata[yy] = NULL;
|
||||
gd->usize[yy] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,16 +408,19 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
|
||||
}
|
||||
|
||||
memmove(&gd->data[dy], &gd->data[py], ny * (sizeof *gd->data));
|
||||
memmove(&gd->text[dy], &gd->text[py], ny * (sizeof *gd->text));
|
||||
memmove(&gd->size[dy], &gd->size[py], ny * (sizeof *gd->size));
|
||||
|
||||
memmove(&gd->udata[dy], &gd->udata[py], ny * (sizeof *gd->udata));
|
||||
memmove(&gd->usize[dy], &gd->usize[py], ny * (sizeof *gd->usize));
|
||||
|
||||
/* Wipe any lines that have been moved (without freeing them). */
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
if (yy >= dy && yy < dy + ny)
|
||||
continue;
|
||||
gd->data[yy] = NULL;
|
||||
gd->text[yy] = NULL;
|
||||
gd->size[yy] = 0;
|
||||
gd->udata[yy] = NULL;
|
||||
gd->usize[yy] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,7 +446,6 @@ grid_clear_cells(struct grid *gd, u_int px, u_int py, u_int nx)
|
||||
if (xx >= gd->size[py])
|
||||
break;
|
||||
grid_put_cell(gd, xx, py, &grid_default_cell);
|
||||
grid_put_text(gd, xx, py, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,14 +472,20 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
|
||||
grid_expand_line(gd, py, px + nx);
|
||||
grid_expand_line(gd, py, dx + nx);
|
||||
memmove(&gd->data[py][dx], &gd->data[py][px], nx * (sizeof **gd->data));
|
||||
memmove(&gd->text[py][dx], &gd->text[py][px], nx * (sizeof **gd->text));
|
||||
|
||||
if (gd->udata[py] != NULL) {
|
||||
grid_expand_line_utf8(gd, py, px + nx);
|
||||
grid_expand_line_utf8(gd, py, dx + nx);
|
||||
memmove(&gd->udata[py][dx],
|
||||
&gd->udata[py][px], nx * (sizeof **gd->udata));
|
||||
}
|
||||
|
||||
/* Wipe any cells that have been moved. */
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= dx && xx < dx + nx)
|
||||
continue;
|
||||
grid_put_cell(gd, xx, py, &grid_default_cell);
|
||||
grid_put_text(gd, xx, py, ' ' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
19
input.c
19
input.c
@ -1,4 +1,4 @@
|
||||
/* $Id: input.c,v 1.75 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: input.c,v 1.76 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -528,8 +528,6 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx)
|
||||
void
|
||||
input_state_utf8(u_char ch, struct input_ctx *ictx)
|
||||
{
|
||||
u_int value;
|
||||
|
||||
log_debug2("-- un %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
|
||||
ictx->utf8_buf[ictx->utf8_off++] = ch;
|
||||
@ -537,14 +535,9 @@ input_state_utf8(u_char ch, struct input_ctx *ictx)
|
||||
return;
|
||||
input_state(ictx, input_state_first);
|
||||
|
||||
value = utf8_combine(ictx->utf8_buf);
|
||||
if (value > 0xffff) /* non-BMP not supported */
|
||||
value = '_';
|
||||
|
||||
ictx->text = value;
|
||||
ictx->cell.flags |= GRID_FLAG_UTF8;
|
||||
screen_write_cell(&ictx->ctx, &ictx->cell, ictx->text);
|
||||
ictx->cell.flags &= ~GRID_FLAG_UTF8;
|
||||
ictx->cell.flags |= GRID_FLAG_UTF8;
|
||||
screen_write_cell(&ictx->ctx, &ictx->cell, ictx->utf8_buf);
|
||||
ictx->cell.flags &= ~GRID_FLAG_UTF8;
|
||||
}
|
||||
|
||||
void
|
||||
@ -585,8 +578,8 @@ input_handle_character(u_char ch, struct input_ctx *ictx)
|
||||
}
|
||||
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||
|
||||
ictx->text = ch;
|
||||
screen_write_cell(&ictx->ctx, &ictx->cell, ictx->text);
|
||||
ictx->cell.data = ch;
|
||||
screen_write_cell(&ictx->ctx, &ictx->cell, ictx->utf8_buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
170
screen-write.c
170
screen-write.c
@ -1,4 +1,4 @@
|
||||
/* $Id: screen-write.c,v 1.39 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: screen-write.c,v 1.40 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -23,6 +23,7 @@
|
||||
#include "tmux.h"
|
||||
|
||||
void screen_write_save(struct screen_write_ctx *);
|
||||
void screen_write_overwrite(struct screen_write_ctx *);
|
||||
|
||||
/* Initialise writing with a window. */
|
||||
void
|
||||
@ -47,7 +48,8 @@ void
|
||||
screen_write_putc(
|
||||
struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch)
|
||||
{
|
||||
screen_write_cell(ctx, gc, ch);
|
||||
gc->data = ch;
|
||||
screen_write_cell(ctx, gc, NULL);
|
||||
}
|
||||
|
||||
/* Write string. */
|
||||
@ -76,21 +78,26 @@ screen_write_copy(struct screen_write_ctx *ctx,
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = src->grid;
|
||||
const struct grid_cell *gc;
|
||||
uint64_t text;
|
||||
struct grid_utf8 *gu;
|
||||
u_char *udata;
|
||||
u_int xx, yy, cx, cy;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= gd->sx || yy >= gd->hsize + gd->sy) {
|
||||
if (xx >= gd->sx || yy >= gd->hsize + gd->sy)
|
||||
gc = &grid_default_cell;
|
||||
text = ' ';
|
||||
} else {
|
||||
else
|
||||
gc = grid_peek_cell(gd, xx, yy);
|
||||
text = grid_peek_text(gd, xx, yy);
|
||||
|
||||
udata = NULL;
|
||||
if (gc->flags & GRID_FLAG_UTF8) {
|
||||
gu = grid_get_utf8(gd, xx, yy);
|
||||
udata = gu->data;
|
||||
}
|
||||
screen_write_cell(ctx, gc, text);
|
||||
|
||||
screen_write_cell(ctx, gc, udata);
|
||||
}
|
||||
cy++;
|
||||
screen_write_cursormove(ctx, cx, cy);
|
||||
@ -517,31 +524,55 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
|
||||
/* Write cell data. */
|
||||
void
|
||||
screen_write_cell(
|
||||
struct screen_write_ctx *ctx, const struct grid_cell *gc, uint64_t text)
|
||||
struct screen_write_ctx *ctx, const struct grid_cell *gc, u_char *udata)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
u_int width, xx;
|
||||
const struct grid_cell *hc;
|
||||
uint64_t htext;
|
||||
struct grid_cell *ic, tc;
|
||||
struct grid_utf8 gu, *tmp_gu;
|
||||
u_int width, uvalue, xx, i;
|
||||
struct grid_cell tmp_gc, *tmp_gc2;
|
||||
size_t size;
|
||||
|
||||
/* Find character width. */
|
||||
if (gc->flags & GRID_FLAG_UTF8)
|
||||
width = utf8_width(text);
|
||||
else
|
||||
if (gc->flags & GRID_FLAG_UTF8) {
|
||||
uvalue = utf8_combine(udata);
|
||||
width = utf8_width(uvalue);
|
||||
|
||||
gu.width = width;
|
||||
memcpy(&gu.data, udata, sizeof gu.data);
|
||||
} else
|
||||
width = 1;
|
||||
|
||||
/* Discard zero-width characters. */
|
||||
if (width == 0)
|
||||
/* If the width is zero, combine onto the previous character. */
|
||||
if (width == 0) {
|
||||
if (s->cx == 0)
|
||||
return;
|
||||
gc = grid_view_peek_cell(gd, s->cx - 1, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_UTF8))
|
||||
return;
|
||||
tmp_gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (tmp_gu->data[i] == 0xff)
|
||||
break;
|
||||
}
|
||||
memcpy(tmp_gu->data + i, udata, 8 - i);
|
||||
|
||||
/* Assume the previous character has just been input. */
|
||||
for (size = 0; size < 8; size++) {
|
||||
if (udata[size] == 0xff)
|
||||
break;
|
||||
}
|
||||
tty_write_cmd(ctx->wp, TTY_RAW, udata, size);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the character is wider than the screen, don't print it. */
|
||||
if (width > screen_size_x(s)) {
|
||||
memcpy(&tc, gc, sizeof tc);
|
||||
text = '_';
|
||||
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
||||
tmp_gc.data = '_';
|
||||
width = 1;
|
||||
gc = &tc;
|
||||
gc = &tmp_gc;
|
||||
}
|
||||
|
||||
/* Check this will fit on the current line; scroll if not. */
|
||||
@ -554,18 +585,57 @@ screen_write_cell(
|
||||
if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
|
||||
return;
|
||||
|
||||
/* Handle overwriting of UTF-8 characters. */
|
||||
screen_write_overwrite(ctx);
|
||||
|
||||
/*
|
||||
* UTF-8 wide characters are a bit of an annoyance. They take up more
|
||||
* than one cell on the screen, so following cells must not be drawn by
|
||||
* marking them as padding.
|
||||
*
|
||||
* So far, so good. The problem is, when overwriting a padding cell, or
|
||||
* a UTF-8 character, it is necessary to also overwrite any other cells
|
||||
* which covered by the same character.
|
||||
* If the new character is UTF-8 wide, fill in padding cells. Have
|
||||
* already ensured there is enough room.
|
||||
*/
|
||||
hc = grid_view_peek_cell(gd, s->cx, s->cy);
|
||||
htext = grid_view_peek_text(gd, s->cx, s->cy);
|
||||
if (hc->flags & GRID_FLAG_PADDING) {
|
||||
for (xx = s->cx + 1; xx < s->cx + width; xx++) {
|
||||
tmp_gc2 = grid_view_get_cell(gd, xx, s->cy);
|
||||
if (tmp_gc2 != NULL)
|
||||
tmp_gc2->flags |= GRID_FLAG_PADDING;
|
||||
}
|
||||
|
||||
/* Set the cell. */
|
||||
grid_view_set_cell(gd, s->cx, s->cy, gc);
|
||||
if (gc->flags & GRID_FLAG_UTF8)
|
||||
grid_view_set_utf8(gd, s->cx, s->cy, &gu);
|
||||
|
||||
/* Move the cursor. */
|
||||
screen_write_save(ctx);
|
||||
s->cx += width;
|
||||
|
||||
/* Draw to the screen if necessary. */
|
||||
if (screen_check_selection(s, s->cx - width, s->cy))
|
||||
tty_write_cmd(ctx->wp, TTY_CELL, &s->sel.cell, &gu);
|
||||
else
|
||||
tty_write_cmd(ctx->wp, TTY_CELL, gc, &gu);
|
||||
}
|
||||
|
||||
/*
|
||||
* UTF-8 wide characters are a bit of an annoyance. They take up more than one
|
||||
* cell on the screen, so following cells must not be drawn by marking them as
|
||||
* padding.
|
||||
*
|
||||
* So far, so good. The problem is, when overwriting a padding cell, or a UTF-8
|
||||
* character, it is necessary to also overwrite any other cells which covered
|
||||
* by the same character.
|
||||
*/
|
||||
void
|
||||
screen_write_overwrite(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
const struct grid_cell *gc;
|
||||
const struct grid_utf8 *gu;
|
||||
u_int xx;
|
||||
|
||||
gc = grid_view_peek_cell(gd, s->cx, s->cy);
|
||||
gu = grid_view_peek_utf8(gd, s->cx, s->cy);
|
||||
|
||||
if (gc->flags & GRID_FLAG_PADDING) {
|
||||
/*
|
||||
* A padding cell, so clear any following and leading padding
|
||||
* cells back to the character. Don't overwrite the current
|
||||
@ -573,8 +643,8 @@ screen_write_cell(
|
||||
*/
|
||||
xx = s->cx + 1;
|
||||
while (--xx > 0) {
|
||||
hc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(hc->flags & GRID_FLAG_PADDING))
|
||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
@ -585,45 +655,21 @@ screen_write_cell(
|
||||
/* Overwrite following padding cells. */
|
||||
xx = s->cx;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
hc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(hc->flags & GRID_FLAG_PADDING))
|
||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
} else if (hc->flags & GRID_FLAG_UTF8 && utf8_width(htext) > 1) {
|
||||
} else if (gc->flags & GRID_FLAG_UTF8 && gu->width > 1) {
|
||||
/*
|
||||
* An UTF-8 wide cell; overwrite following padding cells only.
|
||||
*/
|
||||
xx = s->cx;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
hc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(hc->flags & GRID_FLAG_PADDING))
|
||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the new character is UTF-8 wide, fill in padding cells. Have
|
||||
* already ensured there is enough room.
|
||||
*/
|
||||
for (xx = s->cx + 1; xx < s->cx + width; xx++) {
|
||||
ic = grid_view_get_cell(gd, xx, s->cy);
|
||||
if (ic != NULL)
|
||||
ic->flags |= GRID_FLAG_PADDING;
|
||||
}
|
||||
|
||||
/* Set the cell. */
|
||||
grid_view_set_cell(gd, s->cx, s->cy, gc);
|
||||
grid_view_set_text(gd, s->cx, s->cy, text);
|
||||
|
||||
/* Move the cursor. */
|
||||
screen_write_save(ctx);
|
||||
s->cx += width;
|
||||
|
||||
/* Draw to the screen if necessary. */
|
||||
if (screen_check_selection(s, s->cx - width, s->cy))
|
||||
tty_write_cmd(ctx->wp, TTY_CELL, &s->sel.cell, text);
|
||||
else
|
||||
tty_write_cmd(ctx->wp, TTY_CELL, gc, text);
|
||||
}
|
||||
|
22
screen.c
22
screen.c
@ -1,4 +1,4 @@
|
||||
/* $Id: screen.c,v 1.80 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: screen.c,v 1.81 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -89,7 +89,7 @@ screen_resize_x(struct screen *s, u_int sx)
|
||||
{
|
||||
struct grid *gd = s->grid;
|
||||
const struct grid_cell *gc;
|
||||
uint64_t text;
|
||||
const struct grid_utf8 *gu;
|
||||
u_int xx, yy;
|
||||
|
||||
if (sx == 0)
|
||||
@ -107,16 +107,20 @@ screen_resize_x(struct screen *s, u_int sx)
|
||||
* If the character after the last is wide or padding, remove
|
||||
* it and any leading padding.
|
||||
*/
|
||||
text = ' ';
|
||||
gc = &grid_default_cell;
|
||||
for (xx = sx; xx > 0; xx--) {
|
||||
gc = grid_peek_cell(gd, xx - 1, yy);
|
||||
text = grid_peek_text(gd, xx - 1, yy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
|
||||
}
|
||||
if (xx > 0 && xx != sx && utf8_width(text) != 1)
|
||||
grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
|
||||
if (xx > 0 && xx != sx && gc->flags & GRID_FLAG_UTF8) {
|
||||
gu = grid_peek_utf8(gd, xx - 1, yy);
|
||||
if (gu->width > 1) {
|
||||
grid_set_cell(
|
||||
gd, xx - 1, yy, &grid_default_cell);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduce the line size. */
|
||||
grid_reduce_line(gd, yy, sx);
|
||||
@ -167,7 +171,8 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
/* Resize line arrays. */
|
||||
gd->size = xrealloc(gd->size, gd->hsize + sy, sizeof *gd->size);
|
||||
gd->data = xrealloc(gd->data, gd->hsize + sy, sizeof *gd->data);
|
||||
gd->text = xrealloc(gd->text, gd->hsize + sy, sizeof *gd->text);
|
||||
gd->usize = xrealloc(gd->usize, gd->hsize + sy, sizeof *gd->usize);
|
||||
gd->udata = xrealloc(gd->udata, gd->hsize + sy, sizeof *gd->udata);
|
||||
|
||||
/* Size increasing. */
|
||||
if (sy > screen_size_y(s)) {
|
||||
@ -175,7 +180,8 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
for (yy = gd->hsize + oy; yy < gd->hsize + sy; yy++) {
|
||||
gd->size[yy] = 0;
|
||||
gd->data[yy] = NULL;
|
||||
gd->text[yy] = NULL;
|
||||
gd->usize[yy] = 0;
|
||||
gd->udata[yy] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
41
tmux.h
41
tmux.h
@ -1,4 +1,4 @@
|
||||
/* $Id: tmux.h,v 1.290 2009-03-28 16:57:03 nicm Exp $ */
|
||||
/* $Id: tmux.h,v 1.291 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -346,7 +346,7 @@ struct tty_term_code_entry {
|
||||
|
||||
/* Output commands. */
|
||||
enum tty_cmd {
|
||||
TTY_CELL,
|
||||
TTY_CELL,
|
||||
TTY_CLEARENDOFLINE,
|
||||
TTY_CLEARENDOFSCREEN,
|
||||
TTY_CLEARLINE,
|
||||
@ -358,6 +358,7 @@ enum tty_cmd {
|
||||
TTY_INSERTCHARACTER,
|
||||
TTY_INSERTLINE,
|
||||
TTY_LINEFEED,
|
||||
TTY_RAW,
|
||||
TTY_REVERSEINDEX,
|
||||
};
|
||||
|
||||
@ -482,12 +483,19 @@ struct mode_key_data {
|
||||
#define GRID_FLAG_PADDING 0x4
|
||||
#define GRID_FLAG_UTF8 0x8
|
||||
|
||||
/* Grid cell attributes. */
|
||||
/* Grid cell data. */
|
||||
struct grid_cell {
|
||||
u_char attr;
|
||||
u_char flags;
|
||||
u_char fg;
|
||||
u_char bg;
|
||||
u_char data;
|
||||
} __packed;
|
||||
|
||||
/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */
|
||||
struct grid_utf8 {
|
||||
u_char width;
|
||||
u_char data[8];
|
||||
} __packed;
|
||||
|
||||
/* Entire grid of cells. */
|
||||
@ -498,10 +506,11 @@ struct grid {
|
||||
u_int hsize;
|
||||
u_int hlimit;
|
||||
|
||||
u_int *size; /* row size */
|
||||
|
||||
u_int *size;
|
||||
struct grid_cell **data;
|
||||
uint16_t **text;
|
||||
|
||||
u_int *usize;
|
||||
struct grid_utf8 **udata;
|
||||
};
|
||||
|
||||
/* Option data structures. */
|
||||
@ -591,7 +600,7 @@ struct input_ctx {
|
||||
size_t off;
|
||||
|
||||
struct grid_cell cell;
|
||||
uint64_t text;
|
||||
|
||||
|
||||
struct grid_cell saved_cell;
|
||||
u_int saved_cx;
|
||||
@ -1056,7 +1065,8 @@ long long options_get_number(struct options *, const char *);
|
||||
void tty_reset(struct tty *);
|
||||
void tty_region(struct tty *, u_int, u_int, u_int);
|
||||
void tty_cursor(struct tty *, u_int, u_int, u_int);
|
||||
void tty_cell(struct tty *, const struct grid_cell *, uint64_t);
|
||||
void tty_cell(struct tty *,
|
||||
const struct grid_cell *, const struct grid_utf8 *);
|
||||
void tty_putcode(struct tty *, enum tty_code_code);
|
||||
void tty_putcode1(struct tty *, enum tty_code_code, int);
|
||||
void tty_putcode2(struct tty *, enum tty_code_code, int, int);
|
||||
@ -1372,12 +1382,14 @@ void grid_destroy(struct grid *);
|
||||
int grid_compare(struct grid *, struct grid *);
|
||||
void grid_reduce_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);
|
||||
void grid_scroll_line(struct grid *);
|
||||
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);
|
||||
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
|
||||
uint64_t grid_peek_text(struct grid *, u_int, u_int);
|
||||
void grid_set_text(struct grid *, u_int, u_int, uint64_t);
|
||||
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_lines(struct grid *, u_int, u_int);
|
||||
void grid_move_lines(struct grid *, u_int, u_int, u_int);
|
||||
@ -1386,12 +1398,13 @@ void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int);
|
||||
|
||||
/* grid-view.c */
|
||||
const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int);
|
||||
uint64_t grid_view_peek_text(struct grid *, u_int, u_int);
|
||||
struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int);
|
||||
void grid_view_set_cell(
|
||||
struct grid *, u_int, u_int, const struct grid_cell *);
|
||||
uint64_t grid_view_peek_text(struct grid *, u_int, u_int);
|
||||
void grid_view_set_text(struct grid *, u_int, u_int, uint64_t);
|
||||
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(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_down(struct grid *, u_int, u_int);
|
||||
@ -1439,7 +1452,7 @@ void screen_write_clearendofscreen(struct screen_write_ctx *);
|
||||
void screen_write_clearstartofscreen(struct screen_write_ctx *);
|
||||
void screen_write_clearscreen(struct screen_write_ctx *);
|
||||
void screen_write_cell(
|
||||
struct screen_write_ctx *, const struct grid_cell *, uint64_t);
|
||||
struct screen_write_ctx *, const struct grid_cell *, u_char *);
|
||||
|
||||
/* screen-redraw.c */
|
||||
void screen_redraw_screen(struct client *, struct screen *);
|
||||
|
60
tty.c
60
tty.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tty.c,v 1.84 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: tty.c,v 1.85 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -54,6 +54,7 @@ void tty_cmd_deleteline(struct tty *, struct window_pane *, va_list);
|
||||
void tty_cmd_insertcharacter(struct tty *, struct window_pane *, va_list);
|
||||
void tty_cmd_insertline(struct tty *, struct window_pane *, va_list);
|
||||
void tty_cmd_linefeed(struct tty *, struct window_pane *, va_list);
|
||||
void tty_cmd_raw(struct tty *, struct window_pane *, va_list);
|
||||
void tty_cmd_reverseindex(struct tty *, struct window_pane *, va_list);
|
||||
|
||||
void (*tty_cmds[])(struct tty *, struct window_pane *, va_list) = {
|
||||
@ -69,6 +70,7 @@ void (*tty_cmds[])(struct tty *, struct window_pane *, va_list) = {
|
||||
tty_cmd_insertcharacter,
|
||||
tty_cmd_insertline,
|
||||
tty_cmd_linefeed,
|
||||
tty_cmd_raw,
|
||||
tty_cmd_reverseindex,
|
||||
};
|
||||
|
||||
@ -382,7 +384,8 @@ void
|
||||
tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int oy)
|
||||
{
|
||||
const struct grid_cell *gc;
|
||||
uint64_t text;
|
||||
struct grid_cell tmp_gc;
|
||||
const struct grid_utf8 *gu;
|
||||
u_int i, sx;
|
||||
|
||||
sx = screen_size_x(s);
|
||||
@ -393,13 +396,17 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int oy)
|
||||
|
||||
for (i = 0; i < sx; i++) {
|
||||
gc = grid_view_peek_cell(s->grid, i, py);
|
||||
text = grid_view_peek_text(s->grid, i, py);
|
||||
|
||||
gu = NULL;
|
||||
if (gc->flags & GRID_FLAG_UTF8)
|
||||
gu = grid_view_peek_utf8(s->grid, i, py);
|
||||
|
||||
tty_cursor(tty, i, py, oy);
|
||||
if (screen_check_selection(s, i, py))
|
||||
tty_cell(tty, &s->sel.cell, text);
|
||||
else
|
||||
tty_cell(tty, gc, text);
|
||||
if (screen_check_selection(s, i, py)) {
|
||||
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
|
||||
tty_cell(tty, &tmp_gc, gu);
|
||||
} else
|
||||
tty_cell(tty, gc, gu);
|
||||
}
|
||||
|
||||
if (sx >= tty->sx)
|
||||
@ -737,21 +744,34 @@ tty_cmd_cell(struct tty *tty, struct window_pane *wp, va_list ap)
|
||||
{
|
||||
struct screen *s = wp->screen;
|
||||
struct grid_cell *gc;
|
||||
uint64_t text;
|
||||
struct grid_utf8 *gu;
|
||||
|
||||
gc = va_arg(ap, struct grid_cell *);
|
||||
text = va_arg(ap, uint64_t);
|
||||
gu = va_arg(ap, struct grid_utf8 *);
|
||||
|
||||
tty_cursor(tty, s->old_cx, s->old_cy, wp->yoff);
|
||||
|
||||
tty_cell(tty, gc, text);
|
||||
tty_cell(tty, gc, gu);
|
||||
}
|
||||
|
||||
void
|
||||
tty_cell(struct tty *tty, const struct grid_cell *gc, uint64_t text)
|
||||
tty_cmd_raw(struct tty *tty, unused struct window_pane *wp, va_list ap)
|
||||
{
|
||||
u_int i, width;
|
||||
u_char out[4];
|
||||
u_char *buf;
|
||||
size_t i, len;
|
||||
|
||||
buf = va_arg(ap, u_char *);
|
||||
len = va_arg(ap, size_t);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
tty_putc(tty, buf[i]);
|
||||
}
|
||||
|
||||
void
|
||||
tty_cell(
|
||||
struct tty *tty, const struct grid_cell *gc, const struct grid_utf8 *gu)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
/* Skip last character if terminal is stupid. */
|
||||
if (tty->term->flags & TERM_EARLYWRAP &&
|
||||
@ -767,26 +787,24 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, uint64_t text)
|
||||
|
||||
/* If not UTF-8, write directly. */
|
||||
if (!(gc->flags & GRID_FLAG_UTF8)) {
|
||||
if (text > 0xff || text < 0x20 || text == 0x7f)
|
||||
if (gc->data < 0x20 || gc->data == 0x7f)
|
||||
return;
|
||||
tty_putc(tty, text);
|
||||
tty_putc(tty, gc->data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the terminal doesn't support UTF-8, write underscores. */
|
||||
if (!(tty->flags & TTY_UTF8)) {
|
||||
width = utf8_width(text);
|
||||
while (width-- > 0)
|
||||
for (i = 0; i < gu->width; i++)
|
||||
tty_putc(tty, '_');
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, unpack UTF-8 and write it. */
|
||||
utf8_split(text, out);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (out[i] == 0xff)
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (gu->data[i] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, out[i]);
|
||||
tty_putc(tty, gu->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: window-copy.c,v 1.51 2009-03-28 16:30:05 nicm Exp $ */
|
||||
/* $Id: window-copy.c,v 1.52 2009-03-28 20:17:29 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -462,12 +462,12 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_copy_line(
|
||||
struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
|
||||
window_copy_copy_line(struct window_pane *wp,
|
||||
char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
|
||||
{
|
||||
u_int i, j, xx;
|
||||
uint64_t text;
|
||||
u_char data[4];
|
||||
const struct grid_cell *gc;
|
||||
const struct grid_utf8 *gu;
|
||||
u_int i, j, xx;
|
||||
|
||||
if (sx > ex)
|
||||
return;
|
||||
@ -480,14 +480,18 @@ window_copy_copy_line(
|
||||
|
||||
if (sx < ex) {
|
||||
for (i = sx; i < ex; i++) {
|
||||
text = grid_peek_text(wp->base.grid, i, sy);
|
||||
utf8_split(text, data);
|
||||
|
||||
*buf = xrealloc(*buf, 1, (*off) + 4);
|
||||
for (j = 0; j < sizeof data; j++) {
|
||||
if (data[j] == 0xff)
|
||||
break;
|
||||
(*buf)[(*off)++] = data[j];
|
||||
gc = grid_peek_cell(wp->base.grid, i, sy);
|
||||
if (gc->flags & GRID_FLAG_UTF8) {
|
||||
*buf = xrealloc(*buf, 1, (*off) + 1);
|
||||
(*buf)[(*off)++] = gc->data;
|
||||
} else {
|
||||
gu = grid_peek_utf8(wp->base.grid, i, sy);
|
||||
*buf = xrealloc(*buf, 1, (*off) + 8);
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (gu->data[i] == 0xff)
|
||||
break;
|
||||
(*buf)[(*off)++] = gc->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -501,28 +505,26 @@ int
|
||||
window_copy_is_space(struct window_pane *wp, u_int px, u_int py)
|
||||
{
|
||||
const struct grid_cell *gc;
|
||||
uint64_t text;
|
||||
const char *spaces = " -_@";
|
||||
|
||||
gc = grid_peek_cell(wp->base.grid, px, py);
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8))
|
||||
return (0);
|
||||
text = grid_peek_text(wp->base.grid, px, py);
|
||||
if (text == 0x00 || text == 0x7f || text > 0xff)
|
||||
if (gc->data == 0x00 || gc->data == 0x7f)
|
||||
return (0);
|
||||
return (strchr(spaces, text) != NULL);
|
||||
return (strchr(spaces, gc->data) != NULL);
|
||||
}
|
||||
|
||||
u_int
|
||||
window_copy_find_length(struct window_pane *wp, u_int py)
|
||||
{
|
||||
uint64_t text;
|
||||
u_int px;
|
||||
const struct grid_cell *gc;
|
||||
u_int px;
|
||||
|
||||
px = wp->base.grid->size[py];
|
||||
while (px > 0) {
|
||||
text = grid_peek_text(wp->base.grid, px - 1, py);
|
||||
if (text != 0x20)
|
||||
gc = grid_peek_cell(wp->base.grid, px - 1, py);
|
||||
if (!(gc->flags & GRID_FLAG_UTF8) && gc->data != ' ')
|
||||
break;
|
||||
px--;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user