Have the save/restore colors escape codes also save restore the ANSI color table

This commit is contained in:
Kovid Goyal 2020-12-21 19:38:03 +05:30
parent c3c5a5446f
commit e97f1a4310
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 77 additions and 33 deletions

View File

@ -180,23 +180,24 @@ rectangular region of the screen from (3, 4) to (10, 11), you use::
<ESC>[2*x<ESC>[4;3;11;10;44$r<ESC>[*x
Saving and restoring the default foreground/background/selection/cursor colors
Saving and restoring colors
---------------------------------------------------------------------------------
It is often useful for a full screen application with its own color themes
to set the default foreground, background, selection and cursor colors. This
allows for various performance optimizations when drawing the screen. The
problem is that if the user previously used the escape codes to change these
colors herself, then running the full screen application will lose her
changes even after it exits. To avoid this, kitty introduces a new pair of
*OSC* escape codes to push and pop the current color values from a stack::
It is often useful for a full screen application with its own color themes to
set the default foreground, background, selection and cursor colors and the
ANSI color table. This allows for various performance optimizations when
drawing the screen. The problem is that if the user previously used the escape
codes to change these colors herself, then running the full screen application
will lose her changes even after it exits. To avoid this, kitty introduces a
new pair of *OSC* escape codes to push and pop the current color values from a
stack::
<ESC>]30001<ESC>\ # push onto stack
<ESC>]30101<ESC>\ # pop from stack
These escape codes save/restore the so called *dynamic colors*, default
These escape codes save/restore the colors, default
background, default foreground, selection background, selection foreground and
cursor color.
cursor color and the 256 colors of the ANSI color table.
Pasting to clipboard

View File

@ -318,19 +318,56 @@ copy_color_table_to_buffer(ColorProfile *self, color_type *buf, int offset, size
self->dirty = false;
}
void
colorprofile_push_dynamic_colors(ColorProfile *self) {
if (self->dynamic_color_stack_idx >= arraysz(self->dynamic_color_stack)) {
memmove(self->dynamic_color_stack, self->dynamic_color_stack + 1, sizeof(self->dynamic_color_stack) - sizeof(self->dynamic_color_stack[0]));
self->dynamic_color_stack_idx = arraysz(self->dynamic_color_stack) - 1;
}
self->dynamic_color_stack[self->dynamic_color_stack_idx++] = self->overridden;
static void
push_onto_color_stack_at(ColorProfile *self, unsigned int i) {
self->color_stack[i].dynamic_colors = self->overridden;
self->color_stack[i].valid = true;
memcpy(self->color_stack[i].color_table, self->color_table, sizeof(self->color_stack->color_table));
}
void
colorprofile_pop_dynamic_colors(ColorProfile *self) {
if (!self->dynamic_color_stack_idx) return;
self->overridden = self->dynamic_color_stack[--(self->dynamic_color_stack_idx)];
static void
copy_from_color_stack_at(ColorProfile *self, unsigned int i) {
self->overridden = self->color_stack[i].dynamic_colors;
memcpy(self->color_table, self->color_stack[i].color_table, sizeof(self->color_table));
}
bool
colorprofile_push_colors(ColorProfile *self, unsigned int idx) {
if (idx == 0) {
for (unsigned i = 0; i < arraysz(self->color_stack); i++) {
if (!self->color_stack[i].valid) {
push_onto_color_stack_at(self, i);
return true;
}
}
memmove(self->color_stack, self->color_stack + 1, sizeof(self->color_stack) - sizeof(self->color_stack[0]));
push_onto_color_stack_at(self, arraysz(self->color_stack) - 1);
return true;
}
if (idx < arraysz(self->color_stack)) {
push_onto_color_stack_at(self, idx);
return true;
}
return false;
}
bool
colorprofile_pop_colors(ColorProfile *self, unsigned int idx) {
if (idx == 0) {
for (unsigned i = arraysz(self->color_stack) - 1; i-- > 0; ) {
if (self->color_stack[i].valid) {
copy_from_color_stack_at(self, i);
self->color_stack[i].valid = false;
return true;
}
}
return false;
}
if (idx < arraysz(self->color_stack)) {
copy_from_color_stack_at(self, idx);
return true;
}
return false;
}
static PyObject*

View File

@ -237,14 +237,20 @@ typedef struct {
color_type default_fg, default_bg, cursor_color, cursor_text_color, cursor_text_uses_bg, highlight_fg, highlight_bg;
} DynamicColor;
typedef struct {
DynamicColor dynamic_colors;
uint32_t color_table[256];
bool valid;
} ColorStackEntry;
typedef struct {
PyObject_HEAD
bool dirty;
uint32_t color_table[256];
uint32_t orig_color_table[256];
DynamicColor dynamic_color_stack[10];
size_t dynamic_color_stack_idx;
ColorStackEntry color_stack[16];
DynamicColor configured, overridden;
color_type mark_foregrounds[MARK_MASK+1], mark_backgrounds[MARK_MASK+1];
} ColorProfile;
@ -304,8 +310,8 @@ bool set_iutf8(int, bool);
color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval);
float cursor_text_as_bg(ColorProfile *self);
void copy_color_table_to_buffer(ColorProfile *self, color_type *address, int offset, size_t stride);
void colorprofile_push_dynamic_colors(ColorProfile*);
void colorprofile_pop_dynamic_colors(ColorProfile*);
bool colorprofile_push_colors(ColorProfile*, unsigned int);
bool colorprofile_pop_colors(ColorProfile*, unsigned int);
void set_mouse_cursor(MouseShape);
void enter_event(void);

View File

@ -414,11 +414,11 @@ dispatch_osc(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
END_DISPATCH
case 30001:
REPORT_COMMAND(screen_push_dynamic_colors);
screen_push_dynamic_colors(screen);
screen_push_colors(screen, 0);
break;
case 30101:
REPORT_COMMAND(screen_pop_dynamic_colors);
screen_pop_dynamic_colors(screen);
screen_pop_colors(screen, 0);
break;
default:
REPORT_ERROR("Unknown OSC code: %u", code);

View File

@ -1594,13 +1594,13 @@ screen_handle_cmd(Screen *self, PyObject *cmd) {
}
void
screen_push_dynamic_colors(Screen *self) {
colorprofile_push_dynamic_colors(self->color_profile);
screen_push_colors(Screen *self, unsigned int idx) {
colorprofile_push_colors(self->color_profile, idx);
}
void
screen_pop_dynamic_colors(Screen *self) {
colorprofile_pop_dynamic_colors(self->color_profile);
screen_pop_colors(Screen *self, unsigned int idx) {
colorprofile_pop_colors(self->color_profile, idx);
}
void

View File

@ -179,8 +179,8 @@ void screen_erase_characters(Screen *self, unsigned int count);
void screen_set_margins(Screen *self, unsigned int top, unsigned int bottom);
void screen_change_charset(Screen *, uint32_t to);
void screen_handle_cmd(Screen *, PyObject *cmd);
void screen_push_dynamic_colors(Screen *);
void screen_pop_dynamic_colors(Screen *);
void screen_push_colors(Screen *, unsigned int);
void screen_pop_colors(Screen *, unsigned int);
void screen_handle_print(Screen *, PyObject *cmd);
void screen_designate_charset(Screen *, uint32_t which, uint32_t as);
void screen_use_latin1(Screen *, bool);