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 <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 It is often useful for a full screen application with its own color themes to
to set the default foreground, background, selection and cursor colors. This set the default foreground, background, selection and cursor colors and the
allows for various performance optimizations when drawing the screen. The ANSI color table. This allows for various performance optimizations when
problem is that if the user previously used the escape codes to change these drawing the screen. The problem is that if the user previously used the escape
colors herself, then running the full screen application will lose her codes to change these colors herself, then running the full screen application
changes even after it exits. To avoid this, kitty introduces a new pair of will lose her changes even after it exits. To avoid this, kitty introduces a
*OSC* escape codes to push and pop the current color values from a stack:: new pair of *OSC* escape codes to push and pop the current color values from a
stack::
<ESC>]30001<ESC>\ # push onto stack <ESC>]30001<ESC>\ # push onto stack
<ESC>]30101<ESC>\ # pop from 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 background, default foreground, selection background, selection foreground and
cursor color. cursor color and the 256 colors of the ANSI color table.
Pasting to clipboard 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; self->dirty = false;
} }
void static void
colorprofile_push_dynamic_colors(ColorProfile *self) { push_onto_color_stack_at(ColorProfile *self, unsigned int i) {
if (self->dynamic_color_stack_idx >= arraysz(self->dynamic_color_stack)) { self->color_stack[i].dynamic_colors = self->overridden;
memmove(self->dynamic_color_stack, self->dynamic_color_stack + 1, sizeof(self->dynamic_color_stack) - sizeof(self->dynamic_color_stack[0])); self->color_stack[i].valid = true;
self->dynamic_color_stack_idx = arraysz(self->dynamic_color_stack) - 1; memcpy(self->color_stack[i].color_table, self->color_table, sizeof(self->color_stack->color_table));
}
self->dynamic_color_stack[self->dynamic_color_stack_idx++] = self->overridden;
} }
void static void
colorprofile_pop_dynamic_colors(ColorProfile *self) { copy_from_color_stack_at(ColorProfile *self, unsigned int i) {
if (!self->dynamic_color_stack_idx) return; self->overridden = self->color_stack[i].dynamic_colors;
self->overridden = self->dynamic_color_stack[--(self->dynamic_color_stack_idx)]; 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* 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; color_type default_fg, default_bg, cursor_color, cursor_text_color, cursor_text_uses_bg, highlight_fg, highlight_bg;
} DynamicColor; } DynamicColor;
typedef struct {
DynamicColor dynamic_colors;
uint32_t color_table[256];
bool valid;
} ColorStackEntry;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
bool dirty; bool dirty;
uint32_t color_table[256]; uint32_t color_table[256];
uint32_t orig_color_table[256]; uint32_t orig_color_table[256];
DynamicColor dynamic_color_stack[10]; ColorStackEntry color_stack[16];
size_t dynamic_color_stack_idx;
DynamicColor configured, overridden; DynamicColor configured, overridden;
color_type mark_foregrounds[MARK_MASK+1], mark_backgrounds[MARK_MASK+1]; color_type mark_foregrounds[MARK_MASK+1], mark_backgrounds[MARK_MASK+1];
} ColorProfile; } ColorProfile;
@ -304,8 +310,8 @@ bool set_iutf8(int, bool);
color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval); color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval);
float cursor_text_as_bg(ColorProfile *self); float cursor_text_as_bg(ColorProfile *self);
void copy_color_table_to_buffer(ColorProfile *self, color_type *address, int offset, size_t stride); void copy_color_table_to_buffer(ColorProfile *self, color_type *address, int offset, size_t stride);
void colorprofile_push_dynamic_colors(ColorProfile*); bool colorprofile_push_colors(ColorProfile*, unsigned int);
void colorprofile_pop_dynamic_colors(ColorProfile*); bool colorprofile_pop_colors(ColorProfile*, unsigned int);
void set_mouse_cursor(MouseShape); void set_mouse_cursor(MouseShape);
void enter_event(void); void enter_event(void);

View File

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

View File

@ -1594,13 +1594,13 @@ screen_handle_cmd(Screen *self, PyObject *cmd) {
} }
void void
screen_push_dynamic_colors(Screen *self) { screen_push_colors(Screen *self, unsigned int idx) {
colorprofile_push_dynamic_colors(self->color_profile); colorprofile_push_colors(self->color_profile, idx);
} }
void void
screen_pop_dynamic_colors(Screen *self) { screen_pop_colors(Screen *self, unsigned int idx) {
colorprofile_pop_dynamic_colors(self->color_profile); colorprofile_pop_colors(self->color_profile, idx);
} }
void 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_set_margins(Screen *self, unsigned int top, unsigned int bottom);
void screen_change_charset(Screen *, uint32_t to); void screen_change_charset(Screen *, uint32_t to);
void screen_handle_cmd(Screen *, PyObject *cmd); void screen_handle_cmd(Screen *, PyObject *cmd);
void screen_push_dynamic_colors(Screen *); void screen_push_colors(Screen *, unsigned int);
void screen_pop_dynamic_colors(Screen *); void screen_pop_colors(Screen *, unsigned int);
void screen_handle_print(Screen *, PyObject *cmd); void screen_handle_print(Screen *, PyObject *cmd);
void screen_designate_charset(Screen *, uint32_t which, uint32_t as); void screen_designate_charset(Screen *, uint32_t which, uint32_t as);
void screen_use_latin1(Screen *, bool); void screen_use_latin1(Screen *, bool);