diff --git a/Makefile b/Makefile index b70804f1..70f073da 100644 --- a/Makefile +++ b/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 diff --git a/screen-redraw.c b/screen-redraw.c index bd3010cb..2024e675 100644 --- a/screen-redraw.c +++ b/screen-redraw.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]); } } diff --git a/tmux.h b/tmux.h index 34274b50..257c0816 100644 --- a/tmux.h +++ b/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 *); diff --git a/tty-acs.c b/tty-acs.c new file mode 100644 index 00000000..297c51ac --- /dev/null +++ b/tty-acs.c @@ -0,0 +1,97 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2010 Nicholas Marriott + * + * 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 + +#include + +#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); +} diff --git a/tty-term.c b/tty-term.c index 18858501..1566253d 100644 --- a/tty-term.c +++ b/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~."; + for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2) + term->acs[(u_char) acs[0]][0] = acs[1]; + return (term); error: diff --git a/tty.c b/tty.c index bf0a48b0..642b9766 100644 --- a/tty.c +++ b/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); }