Skip to content

Commit

Permalink
vis: add workaround for broken color handling in Terminal.app
Browse files Browse the repository at this point in the history
Terminal.app sets $TERM=xterm-256color and ships a corresponding
terminfo description advocating that it is capable of color changes
to the 256 color palette when in fact it can not.

We introduce a new boolean option "change-256colors" which is
true by default but can be used to disable color changes. It is
automatically set if Terminal.app is detected using $TERM_PROGRAM.

This should fix display artifacts as described in martanne#456.
  • Loading branch information
martanne committed Jan 31, 2017
1 parent eca2fbb commit 963c238
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 9 deletions.
3 changes: 3 additions & 0 deletions lua/vis-std.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ vis.events.subscribe(vis.events.INIT, function()
vis.lexers = require('lexer')
end

if os.getenv("TERM_PROGRAM") == "Apple_Terminal" then
vis:command("set change-256colors false");
end
vis:command("set theme ".. (vis.ui.colors <= 16 and "default-16" or "default-256"))
end)

Expand Down
7 changes: 7 additions & 0 deletions sam.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ enum {
OPTION_COLOR_COLUMN,
OPTION_HORIZON,
OPTION_SAVE_METHOD,
OPTION_CHANGE_256COLORS,
};

static const OptionDef options[] = {
Expand Down Expand Up @@ -385,6 +386,12 @@ static const OptionDef options[] = {
OPTION_TYPE_STRING, OPTION_FLAG_WINDOW,
"Save method to use for current file 'auto', 'atomic' or 'inplace'",
},
[OPTION_CHANGE_256COLORS] = {
{ "change-256colors" },
OPTION_TYPE_BOOL, OPTION_FLAG_NONE,
"Change 256 color palette to support 24bit colors",
},

};

bool sam_init(Vis *vis) {
Expand Down
19 changes: 10 additions & 9 deletions ui-curses.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
#define MAX_COLOR_CLOBBER 240
static short color_clobber_idx = 0;
static uint32_t clobbering_colors[MAX_COLOR_CLOBBER];
static bool change_colors;
static int change_colors = -1;

typedef struct {
attr_t attr;
Expand Down Expand Up @@ -143,8 +143,10 @@ static void undo_palette(void)
}

/* Work out the nearest color from the 256 color set, or perhaps exactly. */
static int color_find_rgb(unsigned char r, unsigned char g, unsigned char b)
static int color_find_rgb(UiCurses *ui, unsigned char r, unsigned char g, unsigned char b)
{
if (change_colors == -1)
change_colors = ui->vis->change_colors && can_change_color() && COLORS >= 256;
if (change_colors) {
uint32_t hexrep = ((r << 16) | (g << 8) | b) + 1;
for (short i = 0; i < MAX_COLOR_CLOBBER; ++i) {
Expand Down Expand Up @@ -217,7 +219,7 @@ static int color_find_rgb(unsigned char r, unsigned char g, unsigned char b)
}

/* Convert color from string. */
static int color_fromstring(const char *s)
static int color_fromstring(UiCurses *ui, const char *s)
{
if (!s)
return -1;
Expand All @@ -230,7 +232,7 @@ static int color_fromstring(const char *s)
int n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
if (n != 3)
return -1;
return color_find_rgb(r, g, b);
return color_find_rgb(ui, r, g, b);
} else if ('0' <= *s && *s <= '9') {
int col = atoi(s);
return (col <= 0 || col > 255) ? -1 : col;
Expand Down Expand Up @@ -349,9 +351,9 @@ static bool ui_window_syntax_style(UiWin *w, int id, const char *style) {
} else if (!strcasecmp(option, "notblink")) {
cell_style.attr &= ~A_BLINK;
} else if (!strcasecmp(option, "fore")) {
cell_style.fg = color_fromstring(p);
cell_style.fg = color_fromstring(win->ui, p);
} else if (!strcasecmp(option, "back")) {
cell_style.bg = color_fromstring(p);
cell_style.bg = color_fromstring(win->ui, p);
}
option = next;
}
Expand Down Expand Up @@ -830,7 +832,7 @@ static TermKey *ui_termkey_get(Ui *ui) {
}

static void ui_suspend(Ui *ui) {
if (change_colors)
if (change_colors == 1)
undo_palette();
endwin();
kill(0, SIGSTOP);
Expand Down Expand Up @@ -913,7 +915,6 @@ static bool ui_init(Ui *ui, Vis *vis) {
keypad(stdscr, TRUE);
meta(stdscr, TRUE);
curs_set(0);
change_colors = can_change_color() && COLORS >= 256;

ui_resize(ui);
return true;
Expand Down Expand Up @@ -960,7 +961,7 @@ void ui_curses_free(Ui *ui) {
return;
while (uic->windows)
ui_window_free((UiWin*)uic->windows);
if (change_colors)
if (change_colors == 1)
undo_palette();
endwin();
if (uic->termkey)
Expand Down
3 changes: 3 additions & 0 deletions vis-cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ static bool cmd_set(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor
return false;
}
break;
case OPTION_CHANGE_256COLORS:
vis->change_colors = toggle ? !vis->change_colors : arg.b;
break;
default:
return false;
}
Expand Down
1 change: 1 addition & 0 deletions vis-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ struct Vis {
int tabwidth; /* how many spaces should be used to display a tab */
bool expandtab; /* whether typed tabs should be converted to spaces */
bool autoindent; /* whether indentation should be copied from previous line on newline */
bool change_colors; /* whether to adjust 256 color palette for true colors */
char *shell; /* shell used to launch external commands */
Map *cmds; /* ":"-commands, used for unique prefix queries */
Map *usercmds; /* user registered ":"-commands */
Expand Down
1 change: 1 addition & 0 deletions vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ Vis *vis_new(Ui *ui, VisEvent *event) {
vis->ui = ui;
vis->tabwidth = 8;
vis->expandtab = false;
vis->change_colors = true;
vis->registers[VIS_REG_BLACKHOLE].type = REGISTER_BLACKHOLE;
vis->registers[VIS_REG_CLIPBOARD].type = REGISTER_CLIPBOARD;
array_init(&vis->motions);
Expand Down

0 comments on commit 963c238

Please sign in to comment.