mirror of
https://github.com/tmux/tmux.git
synced 2024-11-16 09:28:51 +00:00
Initial UTF-8 support.
This commit is contained in:
parent
1e145a639b
commit
19a2c87f04
7
CHANGES
7
CHANGES
@ -1,3 +1,8 @@
|
|||||||
|
09 September 2008
|
||||||
|
|
||||||
|
* Initial UTF-8 support. A bit ugly and with a limit of 4096 UTF-8
|
||||||
|
characters per window.
|
||||||
|
|
||||||
08 September 2008
|
08 September 2008
|
||||||
|
|
||||||
* 256 colour support. tmux attempts to autodetect the terminal by looking
|
* 256 colour support. tmux attempts to autodetect the terminal by looking
|
||||||
@ -655,4 +660,4 @@
|
|||||||
(including mutt, emacs). No status bar yet and no key remapping or other
|
(including mutt, emacs). No status bar yet and no key remapping or other
|
||||||
customisation.
|
customisation.
|
||||||
|
|
||||||
$Id: CHANGES,v 1.158 2008-09-08 17:40:50 nicm Exp $
|
$Id: CHANGES,v 1.159 2008-09-09 22:16:36 nicm Exp $
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $Id: GNUmakefile,v 1.38 2008-08-28 17:45:24 nicm Exp $
|
# $Id: GNUmakefile,v 1.39 2008-09-09 22:16:36 nicm Exp $
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
|||||||
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
|
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
|
||||||
cmd-respawn-window.c \
|
cmd-respawn-window.c \
|
||||||
window-scroll.c window-more.c window-copy.c options.c paste.c \
|
window-scroll.c window-more.c window-copy.c options.c paste.c \
|
||||||
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c
|
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c utf8.c
|
||||||
|
|
||||||
CC?= gcc
|
CC?= gcc
|
||||||
INCDIRS+= -I. -I-
|
INCDIRS+= -I. -I-
|
||||||
|
4
Makefile
4
Makefile
@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile,v 1.72 2008-08-07 05:15:21 nicm Exp $
|
# $Id: Makefile,v 1.73 2008-09-09 22:16:36 nicm Exp $
|
||||||
|
|
||||||
.SUFFIXES: .c .o .y .h
|
.SUFFIXES: .c .o .y .h
|
||||||
.PHONY: clean update-index.html upload-index.html
|
.PHONY: clean update-index.html upload-index.html
|
||||||
@ -35,7 +35,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
|||||||
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
|
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
|
||||||
cmd-respawn-window.c \
|
cmd-respawn-window.c \
|
||||||
window-scroll.c window-more.c window-copy.c options.c paste.c \
|
window-scroll.c window-more.c window-copy.c options.c paste.c \
|
||||||
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c
|
tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c utf8.c
|
||||||
|
|
||||||
CC?= cc
|
CC?= cc
|
||||||
INCDIRS+= -I. -I- -I/usr/local/include
|
INCDIRS+= -I. -I- -I/usr/local/include
|
||||||
|
40
TODO
40
TODO
@ -41,6 +41,46 @@
|
|||||||
|
|
||||||
-- For 0.5 --------------------------------------------------------------------
|
-- For 0.5 --------------------------------------------------------------------
|
||||||
|
|
||||||
|
- FINISH UTF8: fix copy and paste
|
||||||
|
- SPLIT u_short attr into attr,flags?
|
||||||
|
- maybe rethink backend data structure?
|
||||||
|
- utf8 can be 1-4 bytes
|
||||||
|
- most common is 1 bytes
|
||||||
|
- there can be double-width characters which take n bytes but 2 columns on screen
|
||||||
|
- they are not only drawn as two characters, they also require two backspaces to remove
|
||||||
|
- three operations:
|
||||||
|
- simultaneously update screen and ttys
|
||||||
|
- redraw screen or section of screen to ttys
|
||||||
|
- write to ttys without updating screen
|
||||||
|
|
||||||
|
---
|
||||||
|
split off grid manip:
|
||||||
|
16-bit characters
|
||||||
|
8-bit flags
|
||||||
|
8-bit attributes
|
||||||
|
8-bit fg colour
|
||||||
|
8-bit bg colour
|
||||||
|
|
||||||
|
struct grid_data {
|
||||||
|
struct grid_cell **cells;
|
||||||
|
u_int sx;
|
||||||
|
u_int sy;
|
||||||
|
};
|
||||||
|
struct grid_cell {
|
||||||
|
u_short data;
|
||||||
|
u_char attr;
|
||||||
|
u_char flags;
|
||||||
|
u_char fg;
|
||||||
|
u_char bg;
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
Would it be better to just expand char to 16-bits and use it as an index only
|
||||||
|
for >2-byte characters? or - better - don't support entire UTF range? only the BMP?
|
||||||
|
this would get rid of UTF table and limits, but still leave double-width character annoyances
|
||||||
|
also would double memory usage
|
||||||
|
----
|
||||||
|
|
||||||
21:09 < merdely> NicM: if I run 'tmux attach -t main' and there is no tmux session named main, start a new one.
|
21:09 < merdely> NicM: if I run 'tmux attach -t main' and there is no tmux session named main, start a new one.
|
||||||
- commands: save-buffer -b number filename
|
- commands: save-buffer -b number filename
|
||||||
load-buffer -b number filename
|
load-buffer -b number filename
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: buffer-poll.c,v 1.9 2008-08-28 17:45:25 nicm Exp $ */
|
/* $Id: buffer-poll.c,v 1.10 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -40,9 +40,11 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
|
|||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
|
#if 0
|
||||||
log_debug("buffer_poll (%ld): fd=%d, revents=%d; out=%zu in=%zu",
|
log_debug("buffer_poll (%ld): fd=%d, revents=%d; out=%zu in=%zu",
|
||||||
(long) getpid(),
|
(long) getpid(),
|
||||||
pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in));
|
pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in));
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef BROKEN_POLL
|
#ifndef BROKEN_POLL
|
||||||
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
||||||
@ -51,7 +53,9 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
|
|||||||
if (pfd->revents & POLLIN) {
|
if (pfd->revents & POLLIN) {
|
||||||
buffer_ensure(in, BUFSIZ);
|
buffer_ensure(in, BUFSIZ);
|
||||||
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
|
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
|
||||||
|
#if 0
|
||||||
log_debug("buffer_poll: fd=%d, read=%zd", pfd->fd, n);
|
log_debug("buffer_poll: fd=%d, read=%zd", pfd->fd, n);
|
||||||
|
#endif
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
@ -62,7 +66,9 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
|
|||||||
}
|
}
|
||||||
if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) {
|
if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) {
|
||||||
n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out));
|
n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out));
|
||||||
|
#if 0
|
||||||
log_debug("buffer_poll: fd=%d, write=%zd", pfd->fd, n);
|
log_debug("buffer_poll: fd=%d, write=%zd", pfd->fd, n);
|
||||||
|
#endif
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno != EINTR && errno != EAGAIN)
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
6
client.c
6
client.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: client.c,v 1.34 2008-07-01 19:47:02 nicm Exp $ */
|
/* $Id: client.c,v 1.35 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -34,7 +34,8 @@
|
|||||||
void client_handle_winch(struct client_ctx *);
|
void client_handle_winch(struct client_ctx *);
|
||||||
|
|
||||||
int
|
int
|
||||||
client_init(const char *path, struct client_ctx *cctx, int start_server)
|
client_init(
|
||||||
|
const char *path, struct client_ctx *cctx, int start_server, int flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
@ -94,6 +95,7 @@ retry:
|
|||||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
||||||
fatal("ioctl(TIOCGWINSZ)");
|
fatal("ioctl(TIOCGWINSZ)");
|
||||||
data.version = PROTOCOL_VERSION;
|
data.version = PROTOCOL_VERSION;
|
||||||
|
data.flags = flags;
|
||||||
data.sx = ws.ws_col;
|
data.sx = ws.ws_col;
|
||||||
data.sy = ws.ws_row;
|
data.sy = ws.ws_row;
|
||||||
*data.tty = '\0';
|
*data.tty = '\0';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-windows.c,v 1.22 2008-09-08 17:40:50 nicm Exp $ */
|
/* $Id: cmd-list-windows.c,v 1.23 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -72,10 +72,12 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
else
|
else
|
||||||
name = "";
|
name = "";
|
||||||
ctx->print(ctx,
|
ctx->print(ctx,
|
||||||
"%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]",
|
"%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes] "
|
||||||
|
"[UTF8 table %u/%u]",
|
||||||
wl->idx, w->name, w->base.title, name,
|
wl->idx, w->name, w->base.title, name,
|
||||||
screen_size_x(&w->base), screen_size_y(&w->base),
|
screen_size_x(&w->base), screen_size_y(&w->base),
|
||||||
w->base.hsize, w->base.hlimit, size);
|
w->base.hsize, w->base.hlimit, size,
|
||||||
|
ARRAY_LENGTH(&w->base.utf8_table.array), UTF8_LIMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL)
|
if (ctx->cmdclient != NULL)
|
||||||
|
51
input.c
51
input.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: input.c,v 1.57 2008-09-09 17:35:04 nicm Exp $ */
|
/* $Id: input.c,v 1.58 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -56,6 +56,7 @@ void input_state_sequence_next(u_char, struct input_ctx *);
|
|||||||
void input_state_sequence_intermediate(u_char, struct input_ctx *);
|
void input_state_sequence_intermediate(u_char, struct input_ctx *);
|
||||||
void input_state_string_next(u_char, struct input_ctx *);
|
void input_state_string_next(u_char, struct input_ctx *);
|
||||||
void input_state_string_escape(u_char, struct input_ctx *);
|
void input_state_string_escape(u_char, struct input_ctx *);
|
||||||
|
void input_state_utf8(u_char, struct input_ctx *);
|
||||||
|
|
||||||
void input_handle_character(u_char, struct input_ctx *);
|
void input_handle_character(u_char, struct input_ctx *);
|
||||||
void input_handle_c0_control(u_char, struct input_ctx *);
|
void input_handle_c0_control(u_char, struct input_ctx *);
|
||||||
@ -247,6 +248,7 @@ input_state_first(u_char ch, struct input_ctx *ictx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (INPUT_C1CONTROL(ch)) {
|
if (INPUT_C1CONTROL(ch)) {
|
||||||
ch -= 0x40;
|
ch -= 0x40;
|
||||||
if (ch == '[')
|
if (ch == '[')
|
||||||
@ -257,6 +259,10 @@ input_state_first(u_char ch, struct input_ctx *ictx)
|
|||||||
input_handle_c1_control(ch, ictx);
|
input_handle_c1_control(ch, ictx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (INPUT_DELETE(ch))
|
||||||
|
return;
|
||||||
|
|
||||||
input_handle_character(ch, ictx);
|
input_handle_character(ch, ictx);
|
||||||
}
|
}
|
||||||
@ -481,11 +487,54 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx)
|
|||||||
input_state_string_next(ch, ictx);
|
input_state_string_next(ch, ictx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
input_state_utf8(u_char ch, struct input_ctx *ictx)
|
||||||
|
{
|
||||||
|
log_debug2("-- un %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
|
|
||||||
|
ictx->utf8_buf.data[ictx->utf8_off++] = ch;
|
||||||
|
if (--ictx->utf8_len != 0)
|
||||||
|
return;
|
||||||
|
input_state(ictx, input_state_first);
|
||||||
|
|
||||||
|
screen_write_put_utf8(&ictx->ctx, &ictx->utf8_buf);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
input_handle_character(u_char ch, struct input_ctx *ictx)
|
input_handle_character(u_char ch, struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
|
|
||||||
|
if (ch > 0x7f) {
|
||||||
|
/*
|
||||||
|
* UTF8 sequence.
|
||||||
|
*
|
||||||
|
* 11000010-11011111 C2-DF start of 2-byte sequence
|
||||||
|
* 11100000-11101111 E0-EF start of 3-byte sequence
|
||||||
|
* 11110000-11110100 F0-F4 start of 4-byte sequence
|
||||||
|
*/
|
||||||
|
memset(&ictx->utf8_buf.data, 0xff, sizeof &ictx->utf8_buf.data);
|
||||||
|
ictx->utf8_buf.data[0] = ch;
|
||||||
|
ictx->utf8_off = 1;
|
||||||
|
|
||||||
|
if (ch >= 0xc2 && ch <= 0xdf) {
|
||||||
|
log_debug2(":: u2");
|
||||||
|
input_state(ictx, input_state_utf8);
|
||||||
|
ictx->utf8_len = 1;
|
||||||
|
}
|
||||||
|
if (ch >= 0xe0 && ch <= 0xef) {
|
||||||
|
log_debug2(":: u3");
|
||||||
|
input_state(ictx, input_state_utf8);
|
||||||
|
ictx->utf8_len = 2;
|
||||||
|
}
|
||||||
|
if (ch >= 0xf0 && ch <= 0xf4) {
|
||||||
|
log_debug2(":: u4");
|
||||||
|
input_state(ictx, input_state_utf8);
|
||||||
|
ictx->utf8_len = 3;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
screen_write_put_character(&ictx->ctx, ch);
|
screen_write_put_character(&ictx->ctx, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen-display.c,v 1.20 2008-09-08 22:03:54 nicm Exp $ */
|
/* $Id: screen-display.c,v 1.21 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -22,6 +22,15 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/* Get a cell. */
|
||||||
|
void
|
||||||
|
screen_display_get_cell(struct screen *s,
|
||||||
|
u_int px, u_int py, u_char *data, u_short *attr, u_char *fg, u_char *bg)
|
||||||
|
{
|
||||||
|
screen_get_cell(
|
||||||
|
s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set a cell. */
|
/* Set a cell. */
|
||||||
void
|
void
|
||||||
screen_display_set_cell(struct screen *s,
|
screen_display_set_cell(struct screen *s,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen-write.c,v 1.12 2008-09-08 22:03:54 nicm Exp $ */
|
/* $Id: screen-write.c,v 1.13 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -99,6 +99,7 @@ void
|
|||||||
screen_write_put_character(struct screen_write_ctx *ctx, u_char ch)
|
screen_write_put_character(struct screen_write_ctx *ctx, u_char ch)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
|
u_short attr;
|
||||||
|
|
||||||
if (s->cx == screen_size_x(s)) {
|
if (s->cx == screen_size_x(s)) {
|
||||||
s->cx = 0;
|
s->cx = 0;
|
||||||
@ -109,14 +110,87 @@ screen_write_put_character(struct screen_write_ctx *ctx, u_char ch)
|
|||||||
SCREEN_DEBUG(s);
|
SCREEN_DEBUG(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
attr = s->attr & ~(ATTR_UTF8|ATTR_PAD);
|
||||||
|
|
||||||
screen_display_set_cell(s, s->cx, s->cy, ch, s->attr, s->fg, s->bg);
|
screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
|
||||||
s->cx++;
|
s->cx++;
|
||||||
|
|
||||||
if (ctx->write != NULL)
|
if (ctx->write != NULL)
|
||||||
ctx->write(ctx->data, TTY_CHARACTER, ch);
|
ctx->write(ctx->data, TTY_CHARACTER, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Put a UTF8 character. */
|
||||||
|
void
|
||||||
|
screen_write_put_utf8(struct screen_write_ctx *ctx, struct utf8_data *udat)
|
||||||
|
{
|
||||||
|
struct screen *s = ctx->s;
|
||||||
|
u_char ch, ch2, fg, bg;
|
||||||
|
u_short attr, attr2;
|
||||||
|
int idx, wide;
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
wide = 0;
|
||||||
|
if (udat->data[2] == 0xff)
|
||||||
|
n = ((udat->data[0] & 0x1f)<<6) + (udat->data[1] & 0x3f);
|
||||||
|
else if (udat->data[3] == 0xff) {
|
||||||
|
n = ((udat->data[0] & 0x0f)<<12) +
|
||||||
|
((udat->data[1] & 0x3f)<<6) + (udat->data[2] & 0x3f);
|
||||||
|
} else
|
||||||
|
n = 0;
|
||||||
|
if ((n >= 0x1100 && n <= 0x115f) || n == 0x2329 || n == 0x232a ||
|
||||||
|
(n >= 0x2e80 && n <= 0xa4cf && n != 0x303f) ||
|
||||||
|
(n >= 0xac00 && n <= 0xd7a3) || (n >= 0xf900 && n <= 0xfaff) ||
|
||||||
|
(n >= 0xfe10 && n <= 0xfe19) || (n >= 0xfe30 && n <= 0xfe6f) ||
|
||||||
|
(n >= 0xff00 && n <= 0xff60) || (n >= 0xffe0 && n <= 0xffe6) ||
|
||||||
|
(n >= 0x20000 && n <= 0x2fffd) || (n >= 0x30000 && n <= 0x3fffd))
|
||||||
|
wide = 1;
|
||||||
|
|
||||||
|
if (s->cx >= screen_size_x(s) - wide) {
|
||||||
|
s->cx = 0;
|
||||||
|
if (ctx->write != NULL)
|
||||||
|
ctx->write(ctx->data, TTY_CHARACTER, '\r');
|
||||||
|
screen_write_cursor_down_scroll(ctx);
|
||||||
|
} else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) {
|
||||||
|
SCREEN_DEBUG(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
attr = s->attr & ~(ATTR_UTF8|ATTR_PAD);
|
||||||
|
|
||||||
|
if ((idx = utf8_add(&s->utf8_table, udat)) == -1)
|
||||||
|
ch = '_';
|
||||||
|
else {
|
||||||
|
utf8_pack(idx, &ch, &attr);
|
||||||
|
attr |= ATTR_UTF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove padding before and after, if any. */
|
||||||
|
screen_display_get_cell(s, s->cx, s->cy, &ch2, &attr2, &fg, &bg);
|
||||||
|
if (s->cx > 0 && (attr2 & ATTR_PAD))
|
||||||
|
screen_display_set_cell(s, s->cx - 1, s->cy, ' ', 0, 8, 8);
|
||||||
|
if (s->cx < screen_last_x(s) && (attr2 & ATTR_UTF8)) {
|
||||||
|
screen_display_get_cell(
|
||||||
|
s, s->cx + 1, s->cy, &ch2, &attr2, &fg, &bg);
|
||||||
|
if (s->cx > 0 && (attr2 & ATTR_PAD)) {
|
||||||
|
screen_display_set_cell(
|
||||||
|
s, s->cx + 1, s->cy, ' ', 0, 8, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_display_set_cell(s, s->cx, s->cy, ch, attr, s->fg, s->bg);
|
||||||
|
s->cx++;
|
||||||
|
|
||||||
|
if (wide) {
|
||||||
|
screen_display_set_cell(s, s->cx, s->cy, ' ', ATTR_PAD, 8, 8);
|
||||||
|
s->cx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->write != NULL) {
|
||||||
|
ctx->write(ctx->data, TTY_ATTRIBUTES, attr, s->fg, s->bg);
|
||||||
|
ctx->write(ctx->data, TTY_CHARACTER, ch);
|
||||||
|
ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->fg, s->bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Put a string right-justified. */
|
/* Put a string right-justified. */
|
||||||
size_t printflike2
|
size_t printflike2
|
||||||
screen_write_put_string_rjust(
|
screen_write_put_string_rjust(
|
||||||
|
5
screen.c
5
screen.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen.c,v 1.68 2008-09-08 22:03:54 nicm Exp $ */
|
/* $Id: screen.c,v 1.69 2008-09-09 22:16:36 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -155,6 +155,8 @@ screen_create(struct screen *s, u_int dx, u_int dy, u_int hlimit)
|
|||||||
s->grid_size = xmalloc(dy * (sizeof *s->grid_size));
|
s->grid_size = xmalloc(dy * (sizeof *s->grid_size));
|
||||||
screen_make_lines(s, 0, dy);
|
screen_make_lines(s, 0, dy);
|
||||||
|
|
||||||
|
utf8_init(&s->utf8_table, UTF8_LIMIT);
|
||||||
|
|
||||||
screen_clear_selection(s);
|
screen_clear_selection(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +350,7 @@ screen_set_cell(struct screen *s,
|
|||||||
void
|
void
|
||||||
screen_destroy(struct screen *s)
|
screen_destroy(struct screen *s)
|
||||||
{
|
{
|
||||||
|
utf8_free(&s->utf8_table);
|
||||||
xfree(s->title);
|
xfree(s->title);
|
||||||
screen_free_lines(s, 0, s->dy + s->hsize);
|
screen_free_lines(s, 0, s->dy + s->hsize);
|
||||||
xfree(s->grid_data);
|
xfree(s->grid_data);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-msg.c,v 1.49 2008-07-01 19:47:02 nicm Exp $ */
|
/* $Id: server-msg.c,v 1.50 2008-09-09 22:16:37 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -187,6 +187,8 @@ server_msg_fn_identify(struct hdr *hdr, struct client *c)
|
|||||||
|
|
||||||
data.tty[(sizeof data.tty) - 1] = '\0';
|
data.tty[(sizeof data.tty) - 1] = '\0';
|
||||||
tty_init(&c->tty, data.tty, xstrdup(term));
|
tty_init(&c->tty, data.tty, xstrdup(term));
|
||||||
|
if (data.flags & IDENTIFY_UTF8)
|
||||||
|
c->tty.flags |= TTY_UTF8;
|
||||||
xfree(term);
|
xfree(term);
|
||||||
|
|
||||||
c->flags |= CLIENT_TERMINAL;
|
c->flags |= CLIENT_TERMINAL;
|
||||||
|
13
tmux.c
13
tmux.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.c,v 1.74 2008-08-28 17:45:27 nicm Exp $ */
|
/* $Id: tmux.c,v 1.75 2008-09-09 22:16:37 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -175,10 +175,11 @@ main(int argc, char **argv)
|
|||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
char *path, *cause, *home;
|
char *path, *cause, *home;
|
||||||
char rpath[MAXPATHLEN];
|
char rpath[MAXPATHLEN];
|
||||||
int n, opt;
|
int n, opt, flags;
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
path = NULL;
|
path = NULL;
|
||||||
while ((opt = getopt(argc, argv, "f:qS:Vv")) != EOF) {
|
while ((opt = getopt(argc, argv, "f:qS:uVv")) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'f':
|
case 'f':
|
||||||
cfg_file = xstrdup(optarg);
|
cfg_file = xstrdup(optarg);
|
||||||
@ -189,6 +190,9 @@ main(int argc, char **argv)
|
|||||||
case 'q':
|
case 'q':
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'u':
|
||||||
|
flags |= IDENTIFY_UTF8;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
debug_level++;
|
debug_level++;
|
||||||
break;
|
break;
|
||||||
@ -286,7 +290,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
memset(&cctx, 0, sizeof cctx);
|
memset(&cctx, 0, sizeof cctx);
|
||||||
client_fill_session(&data);
|
client_fill_session(&data);
|
||||||
if (client_init(rpath, &cctx, cmd->entry->flags & CMD_STARTSERVER) != 0)
|
if (client_init(
|
||||||
|
rpath, &cctx, cmd->entry->flags & CMD_STARTSERVER, flags) != 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
b = buffer_create(BUFSIZ);
|
b = buffer_create(BUFSIZ);
|
||||||
cmd_send(cmd, b);
|
cmd_send(cmd, b);
|
||||||
|
50
tmux.h
50
tmux.h
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.h,v 1.185 2008-09-08 22:18:03 nicm Exp $ */
|
/* $Id: tmux.h,v 1.186 2008-09-09 22:16:37 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -19,7 +19,7 @@
|
|||||||
#ifndef TMUX_H
|
#ifndef TMUX_H
|
||||||
#define TMUX_H
|
#define TMUX_H
|
||||||
|
|
||||||
#define PROTOCOL_VERSION -1
|
#define PROTOCOL_VERSION -2
|
||||||
|
|
||||||
/* Shut up gcc warnings about empty if bodies. */
|
/* Shut up gcc warnings about empty if bodies. */
|
||||||
#define RB_AUGMENT(x) do {} while (0)
|
#define RB_AUGMENT(x) do {} while (0)
|
||||||
@ -375,6 +375,9 @@ struct msg_identify_data {
|
|||||||
char tty[TTY_NAME_MAX];
|
char tty[TTY_NAME_MAX];
|
||||||
int version;
|
int version;
|
||||||
|
|
||||||
|
#define IDENTIFY_UTF8 0x1
|
||||||
|
int flags;
|
||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
|
|
||||||
@ -386,6 +389,17 @@ struct msg_resize_data {
|
|||||||
u_int sy;
|
u_int sy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* UTF8 data. */
|
||||||
|
struct utf8_data {
|
||||||
|
u_char data[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct utf8_table {
|
||||||
|
u_int limit;
|
||||||
|
ARRAY_DECL(, struct utf8_data) array;
|
||||||
|
};
|
||||||
|
#define UTF8_LIMIT ((1<<11) - 1)
|
||||||
|
|
||||||
/* Attributes. */
|
/* Attributes. */
|
||||||
#define ATTR_BRIGHT 0x1
|
#define ATTR_BRIGHT 0x1
|
||||||
#define ATTR_DIM 0x2
|
#define ATTR_DIM 0x2
|
||||||
@ -395,9 +409,18 @@ struct msg_resize_data {
|
|||||||
#define ATTR_HIDDEN 0x20
|
#define ATTR_HIDDEN 0x20
|
||||||
#define ATTR_ITALICS 0x40
|
#define ATTR_ITALICS 0x40
|
||||||
#define ATTR_CHARSET 0x80 /* alternative character set */
|
#define ATTR_CHARSET 0x80 /* alternative character set */
|
||||||
|
|
||||||
#define ATTR_FG256 0x100
|
#define ATTR_FG256 0x100
|
||||||
#define ATTR_BG256 0x200
|
#define ATTR_BG256 0x200
|
||||||
|
|
||||||
|
#define ATTR_UTF8 0x400
|
||||||
|
#define ATTR_PAD 0x800
|
||||||
|
|
||||||
|
#define ATTR_UTF8b8 0x8000
|
||||||
|
#define ATTR_UTF8b9 0x4000
|
||||||
|
#define ATTR_UTF8b10 0x2000
|
||||||
|
#define ATTR_UTF8b11 0x1000
|
||||||
|
|
||||||
/* Modes. */
|
/* Modes. */
|
||||||
#define MODE_CURSOR 0x1
|
#define MODE_CURSOR 0x1
|
||||||
#define MODE_INSERT 0x2
|
#define MODE_INSERT 0x2
|
||||||
@ -442,6 +465,8 @@ struct screen {
|
|||||||
u_char fg;
|
u_char fg;
|
||||||
u_char bg;
|
u_char bg;
|
||||||
|
|
||||||
|
struct utf8_table utf8_table;
|
||||||
|
|
||||||
u_int saved_cx;
|
u_int saved_cx;
|
||||||
u_int saved_cy;
|
u_int saved_cy;
|
||||||
u_short saved_attr;
|
u_short saved_attr;
|
||||||
@ -541,6 +566,10 @@ struct input_ctx {
|
|||||||
#define STRING_NAME 1
|
#define STRING_NAME 1
|
||||||
#define STRING_IGNORE 2
|
#define STRING_IGNORE 2
|
||||||
|
|
||||||
|
struct utf8_data utf8_buf;
|
||||||
|
u_int utf8_len;
|
||||||
|
u_int utf8_off;
|
||||||
|
|
||||||
void *(*state)(u_char, struct input_ctx *);
|
void *(*state)(u_char, struct input_ctx *);
|
||||||
|
|
||||||
u_char private;
|
u_char private;
|
||||||
@ -692,6 +721,8 @@ struct tty {
|
|||||||
struct buffer *in;
|
struct buffer *in;
|
||||||
struct buffer *out;
|
struct buffer *out;
|
||||||
|
|
||||||
|
int log_fd;
|
||||||
|
|
||||||
struct termios tio;
|
struct termios tio;
|
||||||
|
|
||||||
u_short attr;
|
u_short attr;
|
||||||
@ -703,6 +734,7 @@ struct tty {
|
|||||||
#define TTY_NOCURSOR 0x1
|
#define TTY_NOCURSOR 0x1
|
||||||
#define TTY_FREEZE 0x2
|
#define TTY_FREEZE 0x2
|
||||||
#define TTY_ESCAPE 0x4
|
#define TTY_ESCAPE 0x4
|
||||||
|
#define TTY_UTF8 0x8
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct timeval key_timer;
|
struct timeval key_timer;
|
||||||
@ -1066,7 +1098,7 @@ void cmd_buffer_free(struct cmd *);
|
|||||||
void cmd_buffer_print(struct cmd *, char *, size_t);
|
void cmd_buffer_print(struct cmd *, char *, size_t);
|
||||||
|
|
||||||
/* client.c */
|
/* client.c */
|
||||||
int client_init(const char *, struct client_ctx *, int);
|
int client_init(const char *, struct client_ctx *, int, int);
|
||||||
int client_flush(struct client_ctx *);
|
int client_flush(struct client_ctx *);
|
||||||
int client_main(struct client_ctx *);
|
int client_main(struct client_ctx *);
|
||||||
|
|
||||||
@ -1140,6 +1172,8 @@ void input_parse(struct window *);
|
|||||||
void input_key(struct window *, int);
|
void input_key(struct window *, int);
|
||||||
|
|
||||||
/* screen-display.c */
|
/* screen-display.c */
|
||||||
|
void screen_display_get_cell(struct screen *,
|
||||||
|
u_int, u_int, u_char *, u_short *, u_char *, u_char *);
|
||||||
void screen_display_set_cell(
|
void screen_display_set_cell(
|
||||||
struct screen *, u_int, u_int, u_char, u_short, u_char, u_char);
|
struct screen *, u_int, u_int, u_char, u_short, u_char, u_char);
|
||||||
void screen_display_make_lines(struct screen *, u_int, u_int);
|
void screen_display_make_lines(struct screen *, u_int, u_int);
|
||||||
@ -1168,6 +1202,7 @@ void screen_write_start(struct screen_write_ctx *,
|
|||||||
void screen_write_stop(struct screen_write_ctx *);
|
void screen_write_stop(struct screen_write_ctx *);
|
||||||
void screen_write_set_title(struct screen_write_ctx *, char *);
|
void screen_write_set_title(struct screen_write_ctx *, char *);
|
||||||
void screen_write_put_character(struct screen_write_ctx *, u_char);
|
void screen_write_put_character(struct screen_write_ctx *, u_char);
|
||||||
|
void screen_write_put_utf8(struct screen_write_ctx *, struct utf8_data *);
|
||||||
size_t printflike2 screen_write_put_string_rjust(
|
size_t printflike2 screen_write_put_string_rjust(
|
||||||
struct screen_write_ctx *, const char *, ...);
|
struct screen_write_ctx *, const char *, ...);
|
||||||
void printflike2 screen_write_put_string(
|
void printflike2 screen_write_put_string(
|
||||||
@ -1290,6 +1325,15 @@ int session_previous(struct session *);
|
|||||||
int session_select(struct session *, int);
|
int session_select(struct session *, int);
|
||||||
int session_last(struct session *);
|
int session_last(struct session *);
|
||||||
|
|
||||||
|
/* utf8.c */
|
||||||
|
void utf8_pack(int, u_char *, u_short *);
|
||||||
|
int utf8_unpack(u_char, u_short);
|
||||||
|
void utf8_init(struct utf8_table *, int);
|
||||||
|
void utf8_free(struct utf8_table *);
|
||||||
|
struct utf8_data *utf8_lookup(struct utf8_table *, int);
|
||||||
|
int utf8_search(struct utf8_table *, struct utf8_data *);
|
||||||
|
int utf8_add(struct utf8_table *, struct utf8_data *);
|
||||||
|
|
||||||
/* buffer.c */
|
/* buffer.c */
|
||||||
struct buffer *buffer_create(size_t);
|
struct buffer *buffer_create(size_t);
|
||||||
void buffer_destroy(struct buffer *);
|
void buffer_destroy(struct buffer *);
|
||||||
|
51
tty.c
51
tty.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty.c,v 1.40 2008-09-08 22:03:56 nicm Exp $ */
|
/* $Id: tty.c,v 1.41 2008-09-09 22:16:37 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -54,6 +54,7 @@ tty_init(struct tty *tty, char *path, char *term)
|
|||||||
tty->termname = xstrdup("unknown");
|
tty->termname = xstrdup("unknown");
|
||||||
else
|
else
|
||||||
tty->termname = xstrdup(term);
|
tty->termname = xstrdup(term);
|
||||||
|
tty->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -73,18 +74,23 @@ tty_open(struct tty *tty, char **cause)
|
|||||||
if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl");
|
fatal("fcntl");
|
||||||
|
|
||||||
|
if (debug_level > 3) {
|
||||||
|
tty->log_fd = open("tmux.out", O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||||
|
} else
|
||||||
|
tty->log_fd = -1;
|
||||||
|
|
||||||
if ((tty->term = tty_find_term(tty->termname, tty->fd, cause)) == NULL)
|
if ((tty->term = tty_find_term(tty->termname, tty->fd, cause)) == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
tty->in = buffer_create(BUFSIZ);
|
tty->in = buffer_create(BUFSIZ);
|
||||||
tty->out = buffer_create(BUFSIZ);
|
tty->out = buffer_create(BUFSIZ);
|
||||||
|
|
||||||
|
tty->flags &= TTY_UTF8;
|
||||||
|
|
||||||
tty->attr = 0;
|
tty->attr = 0;
|
||||||
tty->fg = 8;
|
tty->fg = 8;
|
||||||
tty->bg = 8;
|
tty->bg = 8;
|
||||||
|
|
||||||
tty->flags = 0;
|
|
||||||
|
|
||||||
if (tcgetattr(tty->fd, &tty->tio) != 0)
|
if (tcgetattr(tty->fd, &tty->tio) != 0)
|
||||||
fatal("tcgetattr failed");
|
fatal("tcgetattr failed");
|
||||||
memcpy(&tio, &tty->tio, sizeof tio);
|
memcpy(&tio, &tty->tio, sizeof tio);
|
||||||
@ -140,6 +146,11 @@ tty_close(struct tty *tty)
|
|||||||
if (tty->fd == -1)
|
if (tty->fd == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (tty->log_fd != -1) {
|
||||||
|
close(tty->log_fd);
|
||||||
|
tty->log_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip any writing if the fd is invalid. Things like ssh -t can
|
* Skip any writing if the fd is invalid. Things like ssh -t can
|
||||||
* easily leave us with a dead tty.
|
* easily leave us with a dead tty.
|
||||||
@ -384,6 +395,9 @@ tty_puts(struct tty *tty, const char *s)
|
|||||||
|
|
||||||
t = tty_strip(s);
|
t = tty_strip(s);
|
||||||
buffer_write(tty->out, t, strlen(t));
|
buffer_write(tty->out, t, strlen(t));
|
||||||
|
|
||||||
|
if (tty->log_fd != -1)
|
||||||
|
write(tty->log_fd, t, strlen(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -392,6 +406,9 @@ tty_putc(struct tty *tty, char ch)
|
|||||||
if (tty->attr & ATTR_CHARSET)
|
if (tty->attr & ATTR_CHARSET)
|
||||||
ch = tty_get_acs(tty, ch);
|
ch = tty_get_acs(tty, ch);
|
||||||
buffer_write8(tty->out, ch);
|
buffer_write8(tty->out, ch);
|
||||||
|
|
||||||
|
if (tty->log_fd != -1)
|
||||||
|
write(tty->log_fd, &ch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -410,6 +427,7 @@ tty_set_title(struct tty *tty, const char *title)
|
|||||||
void
|
void
|
||||||
tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
|
tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
|
||||||
{
|
{
|
||||||
|
struct utf8_data *udat;
|
||||||
char ch;
|
char ch;
|
||||||
u_int i, ua, ub, uc;
|
u_int i, ua, ub, uc;
|
||||||
|
|
||||||
@ -423,6 +441,33 @@ tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap)
|
|||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case TTY_CHARACTER:
|
case TTY_CHARACTER:
|
||||||
ch = va_arg(ap, int);
|
ch = va_arg(ap, int);
|
||||||
|
|
||||||
|
if (tty->attr & ATTR_PAD)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((tty->attr & ATTR_UTF8) && (tty->flags & TTY_UTF8)) {
|
||||||
|
udat = utf8_lookup(
|
||||||
|
&s->utf8_table, utf8_unpack(ch, tty->attr));
|
||||||
|
if (udat == NULL)
|
||||||
|
ch = '_';
|
||||||
|
else {
|
||||||
|
if (udat->data[0] == 0xff)
|
||||||
|
break;
|
||||||
|
tty_putc(tty, udat->data[0]);
|
||||||
|
if (udat->data[1] == 0xff)
|
||||||
|
break;
|
||||||
|
tty_putc(tty, udat->data[1]);
|
||||||
|
if (udat->data[2] == 0xff)
|
||||||
|
break;
|
||||||
|
tty_putc(tty, udat->data[2]);
|
||||||
|
if (udat->data[3] == 0xff)
|
||||||
|
break;
|
||||||
|
tty_putc(tty, udat->data[3]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (tty->attr & ATTR_UTF8)
|
||||||
|
ch = '_';
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '\n': /* LF */
|
case '\n': /* LF */
|
||||||
tty_putc(tty, '\n');
|
tty_putc(tty, '\n');
|
||||||
|
114
utf8.c
Normal file
114
utf8.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* $Id: utf8.c,v 1.1 2008-09-09 22:16:37 nicm Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 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"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UTF8 data structures. Just crappy array + linear search for now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Pack UTF8 index into attr, data. */
|
||||||
|
void
|
||||||
|
utf8_pack(int idx, u_char *data, u_short *attr)
|
||||||
|
{
|
||||||
|
*data = idx & 0xff;
|
||||||
|
|
||||||
|
*attr &= ~(ATTR_UTF8b8|ATTR_UTF8b9);
|
||||||
|
if (idx & 0x100)
|
||||||
|
*attr |= ATTR_UTF8b8;
|
||||||
|
if (idx & 0x200)
|
||||||
|
*attr |= ATTR_UTF8b9;
|
||||||
|
if (idx & 0x400)
|
||||||
|
*attr |= ATTR_UTF8b10;
|
||||||
|
if (idx & 0x800)
|
||||||
|
*attr |= ATTR_UTF8b11;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unpack UTF8 index from attr, data. */
|
||||||
|
int
|
||||||
|
utf8_unpack(u_char data, u_short attr)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = data;
|
||||||
|
if (attr & ATTR_UTF8b8)
|
||||||
|
idx |= 0x100;
|
||||||
|
if (attr & ATTR_UTF8b9)
|
||||||
|
idx |= 0x200;
|
||||||
|
if (attr & ATTR_UTF8b10)
|
||||||
|
idx |= 0x400;
|
||||||
|
if (attr & ATTR_UTF8b11)
|
||||||
|
idx |= 0x800;
|
||||||
|
|
||||||
|
return (idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
utf8_init(struct utf8_table *utab, int limit)
|
||||||
|
{
|
||||||
|
utab->limit = limit;
|
||||||
|
ARRAY_INIT(&utab->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
utf8_free(struct utf8_table *utab)
|
||||||
|
{
|
||||||
|
ARRAY_FREE(&utab->array);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct utf8_data *
|
||||||
|
utf8_lookup(struct utf8_table *utab, int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= (int) ARRAY_LENGTH(&utab->array))
|
||||||
|
return (NULL);
|
||||||
|
return (&ARRAY_ITEM(&utab->array, idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
utf8_search(struct utf8_table *utab, struct utf8_data *udat)
|
||||||
|
{
|
||||||
|
u_int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < ARRAY_LENGTH(&utab->array); idx++) {
|
||||||
|
if (memcmp(udat->data,
|
||||||
|
ARRAY_ITEM(&utab->array, idx).data, sizeof udat->data) == 0)
|
||||||
|
return (idx);
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
utf8_add(struct utf8_table *utab, struct utf8_data *udat)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (ARRAY_LENGTH(&utab->array) == utab->limit)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if ((idx = utf8_search(utab, udat)) != -1)
|
||||||
|
return (idx);
|
||||||
|
|
||||||
|
ARRAY_EXPAND(&utab->array, 1);
|
||||||
|
memcpy(
|
||||||
|
&ARRAY_LAST(&utab->array), udat, sizeof ARRAY_LAST(&utab->array));
|
||||||
|
return (ARRAY_LENGTH(&utab->array) - 1);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user