Skip to content

Commit

Permalink
ui: improve color palette reset
Browse files Browse the repository at this point in the history
Do not restore color palette for :! commands (i.e. in ui_terminal_save).
By far the most common use of this is to invoke vis-menu(1)
(e.g. indirectly through `:open .` or for word completion).
Restoring the palette in this case also affects the file content still
being visible above the menu thus causing weird display artifacts.

Use the OSC 104 escape sequence to reset color palette. This should
respect custom color profiles.
  • Loading branch information
martanne committed Jan 7, 2017
1 parent 6d2d23a commit c71760a
Showing 1 changed file with 9 additions and 46 deletions.
55 changes: 9 additions & 46 deletions ui-curses.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +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;

typedef struct {
attr_t attr;
Expand Down Expand Up @@ -134,48 +135,17 @@ static void get_6cube_rgb(unsigned int n, int *r, int *g, int *b)
}
}

/* Reset color to xterm-style defaults via init_color and 6x6 cube */
static void reset_color_by_6cube(unsigned int n)
{
/* n should be in [16, 256) */
if (n >= MAX_COLOR_CLOBBER)
return;

int r = 0, g = 0, b = 0;
get_6cube_rgb(n, &r, &g, &b);
init_color(n, (r * 1000) / 0xff, (g * 1000) / 0xff,
(b * 1000) / 0xff);
}

/* Reset every overwritten color to the standard-ish color cube */
/* Reset color palette to default values using OSC 104 */
static void undo_palette(void)
{
for (short i = 0; i < MAX_COLOR_CLOBBER; ++i) {
if (!clobbering_colors[i])
break;
reset_color_by_6cube(i + 16);
}
}

/* Re-overwrite the contents of clobbering_colors */
static void redo_palette(void)
{
for (short i = 0; i < MAX_COLOR_CLOBBER; ++i) {
if (!clobbering_colors[i])
break;
uint32_t c = clobbering_colors[i] - 1;
unsigned char r = (c >> 16) % 0x100;
unsigned char g = (c >> 8) % 0x100;
unsigned char b = c % 0x100;
init_color(16 + i, (r * 1000) / 0xff, (g * 1000) / 0xff,
(b * 1000) / 0xff);
}
fputs("\033]104;\a", stderr);
fflush(stderr);
}

/* 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)
{
if (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) {
if (clobbering_colors[i] == hexrep)
Expand Down Expand Up @@ -860,6 +830,8 @@ static TermKey *ui_termkey_get(Ui *ui) {
}

static void ui_suspend(Ui *ui) {
if (change_colors)
undo_palette();
endwin();
raise(SIGSTOP);
}
Expand Down Expand Up @@ -888,8 +860,6 @@ static bool ui_getkey(Ui *ui, TermKeyKey *key) {
}

static void ui_terminal_save(Ui *ui) {
if (can_change_color() && COLORS >= 256)
undo_palette();
UiCurses *uic = (UiCurses*)ui;
curs_set(1);
reset_shell_mode();
Expand All @@ -902,8 +872,6 @@ static void ui_terminal_restore(Ui *ui) {
reset_prog_mode();
wclear(stdscr);
curs_set(0);
if (can_change_color() && COLORS >= 256)
redo_palette();
}

static int ui_colors(Ui *ui) {
Expand Down Expand Up @@ -945,6 +913,7 @@ 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 @@ -991,14 +960,8 @@ void ui_curses_free(Ui *ui) {
return;
while (uic->windows)
ui_window_free((UiWin*)uic->windows);

/* we must manually reset color palette, and flicker is undesirable */
if (can_change_color() && COLORS >= 256) {
clear();
refresh();
if (change_colors)
undo_palette();
}

endwin();
if (uic->termkey)
termkey_destroy(uic->termkey);
Expand Down

0 comments on commit c71760a

Please sign in to comment.