From 193e2ec06375dad38cdba4815cb32cf24f3e39d4 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 22 Dec 2024 09:57:29 +0000 Subject: [PATCH] Rework identification of OSC sequences. I didn't like the previous patch setting a flag claiming that two kinds of thing were APC which aren't in fact APC. So I've made a little enum to distinguish them in the code. There's an outside chance we might want to handle some case of these in future, in which case this makes it easier, but more likely it's just making me feel less wrong about it. But I've also folded the two existing flags osc_is_apc and osc_w into that single enum field, which I think is an improvement. --- terminal/terminal.c | 42 ++++++++++++++++++++++-------------------- terminal/terminal.h | 11 +++++++++-- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index ad309436..0c52fc6e 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -3185,22 +3185,18 @@ static void toggle_mode(Terminal *term, int mode, int query, bool state) } /* - * Process an OSC sequence: set window title or icon name. + * Process an OSC or similar sequence, with a whole embedded string, + * like setting the window title or icon name. */ 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) { + switch (term->osc_type) { + case OSCLIKE_OSC_W: while (term->osc_strlen--) term->wordness[(unsigned char)term->osc_string[term->osc_strlen]] = term->esc_args[0]; - } else { + break; + case OSCLIKE_OSC: term->osc_string[term->osc_strlen] = '\0'; switch (term->esc_args[0]) { case 0: @@ -3242,6 +3238,11 @@ static void do_osc(Terminal *term) } break; } + break; + default: + /* APC, SOS and PM are recognised as control sequences but + * ignored. PuTTY implements no support for any of them. */ + break; } } @@ -4122,7 +4123,7 @@ 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_type = OSCLIKE_OSC; term->osc_strlen = 0; term->esc_args[0] = 0; term->esc_nargs = 1; @@ -4130,15 +4131,16 @@ static void term_out(Terminal *term, bool called_from_term_data) case 'X': /* SOS: Start of String */ case '^': /* PM: privacy message */ case '_': /* APC: application program command */ - /* SOS, PM, and APC sequences are just a string, terminated by - * ST or (I've observed in practice for APC) ^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. */ + /* SOS, PM, and APC sequences are just a string, terminated + * by ST or (I've observed in practice for APC) ^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_type = (c == 'X' ? OSCLIKE_SOS : + c == '^' ? OSCLIKE_PM : OSCLIKE_APC); term->osc_strlen = 0; term->esc_args[0] = 0; term->esc_nargs = 1; @@ -5247,7 +5249,7 @@ static void term_out(Terminal *term, bool called_from_term_data) } break; case SEEN_OSC: - term->osc_w = false; + term->osc_type = OSCLIKE_OSC; switch (c) { case 'P': /* Linux palette sequence */ term->termstate = SEEN_OSC_P; @@ -5260,7 +5262,7 @@ static void term_out(Terminal *term, bool called_from_term_data) break; case 'W': /* word-set */ term->termstate = SEEN_OSC_W; - term->osc_w = true; + term->osc_type = OSCLIKE_OSC_W; break; case '0': case '1': diff --git a/terminal/terminal.h b/terminal/terminal.h index e5bb16ae..0e7ab771 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -73,6 +73,14 @@ struct term_utf8_decode { struct term_userpass_state; +typedef enum { + OSCLIKE_OSC, + OSCLIKE_OSC_W, + OSCLIKE_APC, + OSCLIKE_SOS, + OSCLIKE_PM, +} OscType; + struct terminal_tag { int compatibility_level; @@ -183,10 +191,9 @@ struct terminal_tag { #define ANSI_QUE(x) ANSI(x,1) #define OSC_STR_MAX 2048 - bool osc_is_apc; + OscType osc_type; int osc_strlen; char osc_string[OSC_STR_MAX + 1]; - bool osc_w; char id_string[1024];