diff --git a/terminal/terminal.c b/terminal/terminal.c index 3cdfc0d4..90c2880d 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -3206,6 +3206,13 @@ static void toggle_mode(Terminal *term, int mode, int query, bool state) */ static void do_osc(Terminal *term) { + if (term->osc_is_apc) { + /* This OSC was really an APC, and we don't support that + * sequence at all. We only recognise it in order to ignore it + * and filter it out of input. */ + return; + } + if (term->osc_w) { while (term->osc_strlen--) term->wordness[(unsigned char)term->osc_string[term->osc_strlen]] = @@ -4134,6 +4141,21 @@ static void term_out(Terminal *term, bool called_from_term_data) /* Compatibility is nasty here, xterm, linux, decterm yuk! */ compatibility(OTHER); term->termstate = SEEN_OSC; + term->osc_is_apc = false; + term->osc_strlen = 0; + term->esc_args[0] = 0; + term->esc_nargs = 1; + break; + case '_': /* APC: application program command */ + /* APC sequences are just a string, terminated by + * ST or (I've observed in practice) ^G. That is, + * they have the same termination convention as + * OSC. So we handle them by going straight into + * OSC_STRING state and setting a flag indicating + * that it's not really an OSC. */ + compatibility(OTHER); + term->termstate = SEEN_OSC; + term->osc_is_apc = true; term->osc_strlen = 0; term->esc_args[0] = 0; term->esc_nargs = 1; diff --git a/terminal/terminal.h b/terminal/terminal.h index d00133b9..e0361313 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -183,6 +183,7 @@ struct terminal_tag { #define ANSI_QUE(x) ANSI(x,1) #define OSC_STR_MAX 2048 + bool osc_is_apc; int osc_strlen; char osc_string[OSC_STR_MAX + 1]; bool osc_w;