mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-07 16:54:01 +01:00
Use UTF-8 line drawing characters on UTF-8 terminals. Fixes some stupid
terminals (I'm looking at you, putty) which disable the vt100 ACS mode switching sequences in UTF-8 mode. Also on terminals without ACS at all, use ASCII equivalents where obvious.
This commit is contained in:
parent
3696cce4ae
commit
cb564bb427
2
Makefile
2
Makefile
@ -35,7 +35,7 @@ SRCS= attributes.c cfg.c client.c clock.c \
|
||||
mode-key.c names.c options.c paste.c procname.c \
|
||||
resize.c screen-redraw.c screen-write.c screen.c session.c status.c \
|
||||
signal.c server-fn.c server.c server-client.c server-window.c \
|
||||
tmux.c tty-keys.c tty-term.c tty.c utf8.c \
|
||||
tmux.c tty-acs.c tty-keys.c tty-term.c tty.c utf8.c \
|
||||
window-choose.c window-clock.c window-copy.c window.c \
|
||||
xterm-keys.c xmalloc.c
|
||||
|
||||
|
@ -41,6 +41,8 @@ void screen_redraw_draw_number(struct client *, struct window_pane *);
|
||||
#define CELL_JOIN 11
|
||||
#define CELL_OUTSIDE 12
|
||||
|
||||
#define CELL_BORDERS " xqlkmjwvtun~"
|
||||
|
||||
/* Check if cell is on the border of a particular pane. */
|
||||
int
|
||||
screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
|
||||
@ -173,8 +175,6 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
||||
struct grid_cell active_gc, other_gc;
|
||||
u_int i, j, type;
|
||||
int status, fg, bg;
|
||||
const u_char *base, *ptr;
|
||||
u_char ch, border[20];
|
||||
|
||||
/* Get status line, er, status. */
|
||||
if (c->message_string != NULL || c->prompt_string != NULL)
|
||||
@ -193,6 +193,7 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
||||
memcpy(&other_gc, &grid_default_cell, sizeof other_gc);
|
||||
memcpy(&active_gc, &grid_default_cell, sizeof active_gc);
|
||||
active_gc.data = other_gc.data = 'x'; /* not space */
|
||||
active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET;
|
||||
fg = options_get_number(&c->session->options, "pane-border-fg");
|
||||
colour_set_fg(&other_gc, fg);
|
||||
bg = options_get_number(&c->session->options, "pane-border-bg");
|
||||
@ -203,16 +204,6 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
||||
colour_set_bg(&active_gc, bg);
|
||||
|
||||
/* Draw background and borders. */
|
||||
strlcpy(border, " |-....--||+.", sizeof border);
|
||||
if (tty_term_has(tty->term, TTYC_ACSC)) {
|
||||
base = " xqlkmjwvtun~";
|
||||
for (ptr = base; *ptr != '\0'; ptr++) {
|
||||
if ((ch = tty_get_acs(tty, *ptr)) != '\0')
|
||||
border[ptr - base] = ch;
|
||||
}
|
||||
other_gc.attr |= GRID_ATTR_CHARSET;
|
||||
active_gc.attr |= GRID_ATTR_CHARSET;
|
||||
}
|
||||
for (j = 0; j < tty->sy - status; j++) {
|
||||
if (status_only && j != tty->sy - 1)
|
||||
continue;
|
||||
@ -225,7 +216,7 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
||||
else
|
||||
tty_attributes(tty, &other_gc);
|
||||
tty_cursor(tty, i, j);
|
||||
tty_putc(tty, border[type]);
|
||||
tty_putc(tty, CELL_BORDERS[type]);
|
||||
}
|
||||
}
|
||||
|
||||
|
8
tmux.h
8
tmux.h
@ -972,6 +972,8 @@ struct tty_term {
|
||||
char *name;
|
||||
u_int references;
|
||||
|
||||
char acs[UCHAR_MAX + 1][2];
|
||||
|
||||
struct tty_code codes[NTTYCODE];
|
||||
|
||||
#define TERM_256COLOURS 0x1
|
||||
@ -1009,8 +1011,6 @@ struct tty {
|
||||
|
||||
struct grid_cell cell;
|
||||
|
||||
u_char acs[UCHAR_MAX + 1];
|
||||
|
||||
#define TTY_NOCURSOR 0x1
|
||||
#define TTY_FREEZE 0x2
|
||||
#define TTY_ESCAPE 0x4
|
||||
@ -1372,7 +1372,6 @@ void environ_push(struct environ *);
|
||||
|
||||
/* tty.c */
|
||||
void tty_raw(struct tty *, const char *);
|
||||
u_char tty_get_acs(struct tty *, u_char);
|
||||
void tty_attributes(struct tty *, const struct grid_cell *);
|
||||
void tty_reset(struct tty *);
|
||||
void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, u_int);
|
||||
@ -1426,6 +1425,9 @@ const char *tty_term_string2(
|
||||
int tty_term_number(struct tty_term *, enum tty_code_code);
|
||||
int tty_term_flag(struct tty_term *, enum tty_code_code);
|
||||
|
||||
/* tty-acs.c */
|
||||
const char *tty_acs_get(struct tty *, u_char);
|
||||
|
||||
/* tty-keys.c */
|
||||
void tty_keys_init(struct tty *);
|
||||
void tty_keys_free(struct tty *);
|
||||
|
97
tty-acs.c
Normal file
97
tty-acs.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 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 <stdlib.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
int tty_acs_cmp(const void *, const void *);
|
||||
|
||||
/* Table mapping ACS entries to UTF-8. */
|
||||
struct tty_acs_entry {
|
||||
u_char key;
|
||||
const char *string;
|
||||
};
|
||||
const struct tty_acs_entry tty_acs_table[] = {
|
||||
{ '+', "\342\206\222" },
|
||||
{ ',', "\342\206\220" },
|
||||
{ '-', "\342\206\221" },
|
||||
{ '.', "\342\206\223" },
|
||||
{ '0', "\342\226\256" },
|
||||
{ '`', "\342\227\206" },
|
||||
{ 'a', "\342\226\222" },
|
||||
{ 'f', "\302\260" },
|
||||
{ 'g', "\302\261" },
|
||||
{ 'h', "\342\226\222" },
|
||||
{ 'i', "\342\230\203" },
|
||||
{ 'j', "\342\224\230" },
|
||||
{ 'k', "\342\224\220" },
|
||||
{ 'l', "\342\224\214" },
|
||||
{ 'm', "\342\224\224" },
|
||||
{ 'n', "\342\224\274" },
|
||||
{ 'o', "\342\216\272" },
|
||||
{ 'p', "\342\216\273" },
|
||||
{ 'q', "\342\224\200" },
|
||||
{ 'r', "\342\216\274" },
|
||||
{ 's', "\342\216\275" },
|
||||
{ 't', "\342\224\234" },
|
||||
{ 'u', "\342\224\244" },
|
||||
{ 'v', "\342\224\264" },
|
||||
{ 'w', "\342\224\254" },
|
||||
{ 'x', "\342\224\202" },
|
||||
{ 'y', "\342\211\244" },
|
||||
{ 'z', "\342\211\245" },
|
||||
{ '{', "\317\200" },
|
||||
{ '|', "\342\211\240" },
|
||||
{ '}', "\302\243" },
|
||||
{ '~', "\302\267" }
|
||||
};
|
||||
|
||||
int
|
||||
tty_acs_cmp(const void *key, const void *value)
|
||||
{
|
||||
const struct tty_acs_entry *entry = value;
|
||||
u_char ch;
|
||||
|
||||
ch = *(u_char *) key;
|
||||
return (ch - entry->key);
|
||||
}
|
||||
|
||||
/* Retrieve ACS to output as a string. */
|
||||
const char *
|
||||
tty_acs_get(struct tty *tty, u_char ch)
|
||||
{
|
||||
struct tty_acs_entry *entry;
|
||||
|
||||
/* If not a UTF-8 terminal, use the ACS set. */
|
||||
if (!(tty->flags & TTY_UTF8)) {
|
||||
if (tty->term->acs[ch][0] == '\0')
|
||||
return (NULL);
|
||||
return (&tty->term->acs[ch][0]);
|
||||
}
|
||||
|
||||
/* Otherwise look up the UTF-8 translation. */
|
||||
entry = bsearch(&ch,
|
||||
tty_acs_table, nitems(tty_acs_table), sizeof tty_acs_table[0],
|
||||
tty_acs_cmp);
|
||||
if (entry == NULL)
|
||||
return (NULL);
|
||||
return (entry->string);
|
||||
}
|
12
tty-term.c
12
tty-term.c
@ -302,6 +302,7 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
||||
u_int i;
|
||||
int n, error;
|
||||
char *s;
|
||||
const char *acs;
|
||||
|
||||
SLIST_FOREACH(term, &tty_terms, entry) {
|
||||
if (strcmp(term->name, name) == 0) {
|
||||
@ -315,7 +316,7 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
||||
term->name = xstrdup(name);
|
||||
term->references = 1;
|
||||
term->flags = 0;
|
||||
memset(&term->codes, 0, sizeof term->codes);
|
||||
memset(term->codes, 0, sizeof term->codes);
|
||||
SLIST_INSERT_HEAD(&tty_terms, term, entry);
|
||||
|
||||
/* Set up curses terminal. */
|
||||
@ -411,6 +412,15 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
||||
if (!tty_term_flag(term, TTYC_XENL))
|
||||
term->flags |= TERM_EARLYWRAP;
|
||||
|
||||
/* Generate ACS table. If none is present, use nearest ASCII. */
|
||||
memset(term->acs, 0, sizeof term->acs);
|
||||
if (tty_term_has(term, TTYC_ACSC))
|
||||
acs = tty_term_string(term, TTYC_ACSC);
|
||||
else
|
||||
acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~.";
|
||||
for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
|
||||
term->acs[(u_char) acs[0]][0] = acs[1];
|
||||
|
||||
return (term);
|
||||
|
||||
error:
|
||||
|
55
tty.c
55
tty.c
@ -31,8 +31,6 @@
|
||||
void tty_read_callback(struct bufferevent *, void *);
|
||||
void tty_error_callback(struct bufferevent *, short, void *);
|
||||
|
||||
void tty_fill_acs(struct tty *);
|
||||
|
||||
int tty_try_256(struct tty *, u_char, const char *);
|
||||
int tty_try_88(struct tty *, u_char, const char *);
|
||||
|
||||
@ -48,6 +46,9 @@ void tty_emulate_repeat(
|
||||
void tty_cell(struct tty *,
|
||||
const struct grid_cell *, const struct grid_utf8 *);
|
||||
|
||||
#define tty_use_acs(tty) \
|
||||
(tty_term_has(tty, TTYC_ACSC) && !((tty)->flags & TTY_UTF8))
|
||||
|
||||
void
|
||||
tty_init(struct tty *tty, int fd, char *term)
|
||||
{
|
||||
@ -143,8 +144,6 @@ tty_open(struct tty *tty, const char *overrides, char **cause)
|
||||
|
||||
tty_keys_init(tty);
|
||||
|
||||
tty_fill_acs(tty);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -201,7 +200,8 @@ tty_start_tty(struct tty *tty)
|
||||
memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
|
||||
|
||||
tty_putcode(tty, TTYC_RMKX);
|
||||
tty_putcode(tty, TTYC_ENACS);
|
||||
if (tty_use_acs(tty))
|
||||
tty_putcode(tty, TTYC_ENACS);
|
||||
tty_putcode(tty, TTYC_CLEAR);
|
||||
|
||||
tty_putcode(tty, TTYC_CNORM);
|
||||
@ -242,7 +242,8 @@ tty_stop_tty(struct tty *tty)
|
||||
return;
|
||||
|
||||
tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
|
||||
if (tty_use_acs(tty))
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
|
||||
@ -257,30 +258,6 @@ tty_stop_tty(struct tty *tty)
|
||||
fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
void
|
||||
tty_fill_acs(struct tty *tty)
|
||||
{
|
||||
const char *ptr;
|
||||
|
||||
memset(tty->acs, 0, sizeof tty->acs);
|
||||
if (!tty_term_has(tty->term, TTYC_ACSC))
|
||||
return;
|
||||
|
||||
ptr = tty_term_string(tty->term, TTYC_ACSC);
|
||||
if (strlen(ptr) % 2 != 0)
|
||||
return;
|
||||
for (; *ptr != '\0'; ptr += 2)
|
||||
tty->acs[(u_char) ptr[0]] = ptr[1];
|
||||
}
|
||||
|
||||
u_char
|
||||
tty_get_acs(struct tty *tty, u_char ch)
|
||||
{
|
||||
if (tty->acs[ch] != '\0')
|
||||
return (tty->acs[ch]);
|
||||
return (ch);
|
||||
}
|
||||
|
||||
void
|
||||
tty_close(struct tty *tty)
|
||||
{
|
||||
@ -360,11 +337,17 @@ tty_puts(struct tty *tty, const char *s)
|
||||
void
|
||||
tty_putc(struct tty *tty, u_char ch)
|
||||
{
|
||||
u_int sx;
|
||||
const char *acs;
|
||||
u_int sx;
|
||||
|
||||
if (tty->cell.attr & GRID_ATTR_CHARSET)
|
||||
ch = tty_get_acs(tty, ch);
|
||||
bufferevent_write(tty->event, &ch, 1);
|
||||
if (tty->cell.attr & GRID_ATTR_CHARSET) {
|
||||
acs = tty_acs_get(tty, ch);
|
||||
if (acs != NULL)
|
||||
bufferevent_write(tty->event, acs, strlen(acs));
|
||||
else
|
||||
bufferevent_write(tty->event, &ch, 1);
|
||||
} else
|
||||
bufferevent_write(tty->event, &ch, 1);
|
||||
|
||||
if (ch >= 0x20 && ch != 0x7f) {
|
||||
sx = tty->sx;
|
||||
@ -997,7 +980,7 @@ tty_reset(struct tty *tty)
|
||||
if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
|
||||
return;
|
||||
|
||||
if (tty_term_has(tty->term, TTYC_RMACS) && gc->attr & GRID_ATTR_CHARSET)
|
||||
if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty))
|
||||
tty_putcode(tty, TTYC_RMACS);
|
||||
tty_putcode(tty, TTYC_SGR0);
|
||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||
@ -1234,7 +1217,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc)
|
||||
}
|
||||
if (changed & GRID_ATTR_HIDDEN)
|
||||
tty_putcode(tty, TTYC_INVIS);
|
||||
if (changed & GRID_ATTR_CHARSET)
|
||||
if ((changed & GRID_ATTR_CHARSET) && tty_use_acs(tty))
|
||||
tty_putcode(tty, TTYC_SMACS);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user