From 578807cc46a197b771929b31ddea7d49d384ef48 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Mon, 27 Oct 2025 16:22:37 +0000 Subject: [PATCH] Add OSC 110/111/112 Support This change add support for resetting the terminal bg/fg/cursor colors via OSC 110/111/112. These OSC command are widely used among other terminals and are part of the XTerm control sequences. Some terminals that implement this include but not limited to: xterm, vte, konsole, foot, ghostty, alacritty, iterm2, apple terminal, st, and many other. Signed-off-by: Ayman Bagabas --- src/command.C | 36 ++++++++++++++--------- src/init.C | 5 +++- src/main.C | 23 +++++++++++++++ src/rxvt.h | 81 ++++++++++++++++++++++++++++----------------------- 4 files changed, 94 insertions(+), 51 deletions(-) diff --git a/src/command.C b/src/command.C index 891ffab4..42cf7cbc 100644 --- a/src/command.C +++ b/src/command.C @@ -3315,22 +3315,22 @@ void rxvt_term::process_osc_seq () { int arg; + string_term st; + char *s; - unicode_t ch = cmd_getc (); - for (arg = 0; isdigit (ch); ch = cmd_getc ()) - arg = arg * 10 + (ch - '0'); + s = get_to_st (st); + if (!s) + return; - if (ch == ';') - { - string_term st; - char *s = get_to_st (st); + char *ch = s; + for (arg = 0; isdigit (ch[0]); ch++) + arg = arg * 10 + (*ch - '0'); - if (s) - { - process_xterm_seq (arg, s, st); - free (s); - } - } + if (*ch == ';') + ch++; + + process_xterm_seq (arg, ch, st); + free (s); } static unsigned int @@ -3479,6 +3479,13 @@ rxvt_term::process_xterm_seq (int op, char *str, string_term &st) if (HOOK_INVOKE ((this, HOOK_OSC_SEQ, DT_INT, op, DT_STR, str, DT_END))) return; + // These operations take no parameters and expect empty string. + if (strlen (str) == 0 && + op != XTerm_RestoreColor00 && + op != XTerm_RestoreColor01 && + op != XTerm_RestoreColor_cursor) + return; + switch (op) { case XTerm_name: @@ -3549,14 +3556,17 @@ rxvt_term::process_xterm_seq (int op, char *str, string_term &st) break; case Rxvt_restoreFG: case XTerm_Color00: + case XTerm_RestoreColor00: process_color_seq (op, Color_fg, str, st); break; case Rxvt_restoreBG: case XTerm_Color01: + case XTerm_RestoreColor01: process_color_seq (op, Color_bg, str, st); break; #ifndef NO_CURSORCOLOR case XTerm_Color_cursor: + case XTerm_RestoreColor_cursor: process_color_seq (op, Color_cursor, str, st); break; #endif diff --git a/src/init.C b/src/init.C index 907cdabe..80d5e506 100644 --- a/src/init.C +++ b/src/init.C @@ -765,10 +765,13 @@ rxvt_term::init_resources (int argc, const char *const *argv) } #endif - for (i = 0; i < NRS_COLORS; i++) + for (i = 0; i < NRS_COLORS; i++) { if (!rs[Rs_color + i]) rs[Rs_color + i] = def_colorName[i]; + def_colors[i] = rs[Rs_color + i]; + } + #ifndef XTERM_REVERSE_VIDEO /* this is how we implement reverseVideo */ if (option (Opt_reverseVideo)) diff --git a/src/main.C b/src/main.C index 10e5065b..69213784 100644 --- a/src/main.C +++ b/src/main.C @@ -944,6 +944,8 @@ rxvt_term::set_window_color (int idx, const char *color) { #ifdef XTERM_COLOR_CHANGE if (color == NULL || *color == '\0') + color = get_def_color (idx); + if (!color) return; color = strdup (color); @@ -1045,6 +1047,27 @@ rxvt_term::set_color (rxvt_color &color, const char *name) return false; } +const char * +rxvt_term::get_def_color(int idx) +{ + const char *color; + + color = def_colors[idx]; + if (!color) { + // If cursor colors are not defined, use fg/bg respectively. + switch (idx) { + case Color_cursor: + color = def_colors[Color_fg]; + break; + case Color_cursor2: + color = def_colors[Color_bg]; + break; + } + } + + return color; +} + void rxvt_term::alias_color (int dst, int src) { diff --git a/src/rxvt.h b/src/rxvt.h index 37aba23a..8cda9a46 100644 --- a/src/rxvt.h +++ b/src/rxvt.h @@ -412,54 +412,58 @@ struct string_term * colour extensions by Christian W. Zuckschwerdt */ enum { - XTerm_name = 0, - XTerm_iconName = 1, - XTerm_title = 2, - XTerm_property = 3, // change X property - XTerm_Color = 4, // change colors - XTerm_Color00 = 10, // change fg color - XTerm_Color01 = 11, // change bg color - XTerm_Color_cursor = 12, // change actual 'Cursor' color - XTerm_Color_pointer_fg = 13, // change actual 'Pointer' fg color - XTerm_Color_pointer_bg = 14, // change actual 'Pointer' bg color - XTerm_Color05 = 15, // not implemented (tektronix fg) - XTerm_Color06 = 16, // not implemented (tektronix bg) - XTerm_Color_HC = 17, // change actual 'Highlight' bg color - XTerm_Color_HTC = 19, // change actual 'Highlight' fg color - XTerm_logfile = 46, // not implemented - XTerm_font = 50, - - XTerm_konsole30 = 30, // reserved for konsole - XTerm_konsole31 = 31, // reserved for konsole - XTerm_emacs51 = 51, // reserved for emacs shell + XTerm_name = 0, + XTerm_iconName = 1, + XTerm_title = 2, + XTerm_property = 3, // change X property + XTerm_Color = 4, // change colors + XTerm_Color00 = 10, // change fg color + XTerm_Color01 = 11, // change bg color + XTerm_Color_cursor = 12, // change actual 'Cursor' color + XTerm_Color_pointer_fg = 13, // change actual 'Pointer' fg color + XTerm_Color_pointer_bg = 14, // change actual 'Pointer' bg color + XTerm_Color05 = 15, // not implemented (tektronix fg) + XTerm_Color06 = 16, // not implemented (tektronix bg) + XTerm_Color_HC = 17, // change actual 'Highlight' bg color + XTerm_Color_HTC = 19, // change actual 'Highlight' fg color + XTerm_logfile = 46, // not implemented + XTerm_font = 50, + + XTerm_konsole30 = 30, // reserved for konsole + XTerm_konsole31 = 31, // reserved for konsole + XTerm_emacs51 = 51, // reserved for emacs shell /* * rxvt extensions of XTerm OSCs: ESC ] Ps;Pt (ST|BEL) */ // deprecated - Rxvt_restoreFG = 39, - Rxvt_restoreBG = 49, + Rxvt_restoreFG = 39, + Rxvt_restoreBG = 49, - Rxvt_dumpscreen = 55, // dump scrollback and all of screen + Rxvt_dumpscreen = 55, // dump scrollback and all of screen + // + XTerm_RestoreColor00 = 110, // restore fg color + XTerm_RestoreColor01 = 111, // restore bg color + XTerm_RestoreColor_cursor = 112, // restore cursor color - URxvt_locale = 701, // change locale - URxvt_version = 702, // request version + URxvt_locale = 701, // change locale + URxvt_version = 702, // request version - URxvt_Color_IT = 704, // change actual 'Italic' colour - URxvt_Color_BD = 706, // change actual 'Bold' color - URxvt_Color_UL = 707, // change actual 'Underline' color - URxvt_Color_border = 708, + URxvt_Color_IT = 704, // change actual 'Italic' colour + URxvt_Color_BD = 706, // change actual 'Bold' color + URxvt_Color_UL = 707, // change actual 'Underline' color + URxvt_Color_border = 708, - URxvt_font = 710, - URxvt_boldFont = 711, - URxvt_italicFont = 712, - URxvt_boldItalicFont = 713, + URxvt_font = 710, + URxvt_boldFont = 711, + URxvt_italicFont = 712, + URxvt_boldItalicFont = 713, - URxvt_view_up = 720, - URxvt_view_down = 721, + URxvt_view_up = 720, + URxvt_view_down = 721, - URxvt_cellinfo = 776, // returns font cell width, height etc. - URxvt_perl = 777, // for use by perl extensions, starts with "extension-name;" + URxvt_cellinfo = 776, // returns font cell width, height etc. + URxvt_perl = 777, // for use by perl extensions, starts with "extension-name;" }; /* Words starting with `Color_' are colours. Others are counts */ @@ -1228,6 +1232,8 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen #endif const char *rs[NUM_RESOURCES]; + const char *def_colors[NRS_COLORS]; + /* command input buffering */ char *cmdbuf_ptr, *cmdbuf_endp; char cmdbuf_base[CBUFSIZ]; @@ -1417,6 +1423,7 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen void set_window_color (int idx, const char *color); char *get_colorfgbg (); bool set_color (rxvt_color &color, const char *name); + const char *get_def_color(int idx); void alias_color (int dst, int src); void set_widthheight (unsigned int newwidth, unsigned int newheight); void get_window_origin (int &x, int &y);