1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

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.
This commit is contained in:
Simon Tatham 2024-12-22 09:57:29 +00:00
parent b6b95f23e5
commit 193e2ec063
2 changed files with 31 additions and 22 deletions

View File

@ -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) static void do_osc(Terminal *term)
{ {
if (term->osc_is_apc) { switch (term->osc_type) {
/* This OSC was really an APC, and we don't support that case OSCLIKE_OSC_W:
* 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--) while (term->osc_strlen--)
term->wordness[(unsigned char)term->osc_string[term->osc_strlen]] = term->wordness[(unsigned char)term->osc_string[term->osc_strlen]] =
term->esc_args[0]; term->esc_args[0];
} else { break;
case OSCLIKE_OSC:
term->osc_string[term->osc_strlen] = '\0'; term->osc_string[term->osc_strlen] = '\0';
switch (term->esc_args[0]) { switch (term->esc_args[0]) {
case 0: case 0:
@ -3242,6 +3238,11 @@ static void do_osc(Terminal *term)
} }
break; 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 is nasty here, xterm, linux, decterm yuk! */
compatibility(OTHER); compatibility(OTHER);
term->termstate = SEEN_OSC; term->termstate = SEEN_OSC;
term->osc_is_apc = false; term->osc_type = OSCLIKE_OSC;
term->osc_strlen = 0; term->osc_strlen = 0;
term->esc_args[0] = 0; term->esc_args[0] = 0;
term->esc_nargs = 1; 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 'X': /* SOS: Start of String */
case '^': /* PM: privacy message */ case '^': /* PM: privacy message */
case '_': /* APC: application program command */ case '_': /* APC: application program command */
/* SOS, PM, and APC sequences are just a string, terminated by /* SOS, PM, and APC sequences are just a string, terminated
* ST or (I've observed in practice for APC) ^G. That is, * by ST or (I've observed in practice for APC) ^G. That
* they have the same termination convention as * is, they have the same termination convention as OSC. So
* OSC. So we handle them by going straight into * we handle them by going straight into OSC_STRING state
* OSC_STRING state and setting a flag indicating * and setting a flag indicating that it's not really an
* that it's not really an OSC. */ * OSC. */
compatibility(OTHER); compatibility(OTHER);
term->termstate = SEEN_OSC; 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->osc_strlen = 0;
term->esc_args[0] = 0; term->esc_args[0] = 0;
term->esc_nargs = 1; term->esc_nargs = 1;
@ -5247,7 +5249,7 @@ static void term_out(Terminal *term, bool called_from_term_data)
} }
break; break;
case SEEN_OSC: case SEEN_OSC:
term->osc_w = false; term->osc_type = OSCLIKE_OSC;
switch (c) { switch (c) {
case 'P': /* Linux palette sequence */ case 'P': /* Linux palette sequence */
term->termstate = SEEN_OSC_P; term->termstate = SEEN_OSC_P;
@ -5260,7 +5262,7 @@ static void term_out(Terminal *term, bool called_from_term_data)
break; break;
case 'W': /* word-set */ case 'W': /* word-set */
term->termstate = SEEN_OSC_W; term->termstate = SEEN_OSC_W;
term->osc_w = true; term->osc_type = OSCLIKE_OSC_W;
break; break;
case '0': case '0':
case '1': case '1':

View File

@ -73,6 +73,14 @@ struct term_utf8_decode {
struct term_userpass_state; struct term_userpass_state;
typedef enum {
OSCLIKE_OSC,
OSCLIKE_OSC_W,
OSCLIKE_APC,
OSCLIKE_SOS,
OSCLIKE_PM,
} OscType;
struct terminal_tag { struct terminal_tag {
int compatibility_level; int compatibility_level;
@ -183,10 +191,9 @@ struct terminal_tag {
#define ANSI_QUE(x) ANSI(x,1) #define ANSI_QUE(x) ANSI(x,1)
#define OSC_STR_MAX 2048 #define OSC_STR_MAX 2048
bool osc_is_apc; OscType osc_type;
int osc_strlen; int osc_strlen;
char osc_string[OSC_STR_MAX + 1]; char osc_string[OSC_STR_MAX + 1];
bool osc_w;
char id_string[1024]; char id_string[1024];