From f665f147ffb542024a754f227186950e222927b4 Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Sun, 4 Oct 2020 12:04:24 +0200 Subject: degesch: resolve the issue with less(1) and SO/SI Now that I've learnt what exactly these characters are and how they ended up in attribute strings, we can just eliminate them and disable `backlog_helper_strip_formatting`. Saner defaults, again. I've also added skipping of terminfo delay sequences, so now it's less of an issue to pipe raw attribute sequences into backlog helpers. --- degesch.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/degesch.c b/degesch.c index 5c172f5..4639da7 100644 --- a/degesch.c +++ b/degesch.c @@ -2445,11 +2445,6 @@ static struct config_schema g_config_behaviour[] = .default_ = "off", .on_change = on_config_debug_mode_change }, - // GNU screen has an ^O in its formatting attributes reset string, - // therefore we can't just pipe raw formatting to `less -R`. - // You can use the -r switch, however that makes `less` very confused - // about line wrapping, and the result is suboptimal. - { .name = "backlog_limit", .comment = "Maximum number of lines stored in the backlog", .type = CONFIG_ITEM_INTEGER, @@ -2463,7 +2458,7 @@ static struct config_schema g_config_behaviour[] = { .name = "backlog_helper_strip_formatting", .comment = "Strip formatting from backlog helper input", .type = CONFIG_ITEM_BOOLEAN, - .default_ = "on" }, + .default_ = "off" }, { .name = "reconnect_delay_growing", .comment = "Growing factor for reconnect delay", @@ -2784,6 +2779,26 @@ struct attr_printer #define ATTR_PRINTER_INIT(ctx, stream) { ctx->attrs, stream, true } +static void +attr_printer_filtered_puts (FILE *stream, const char *attr) +{ + for (; *attr; attr++) + { + // sgr/set_attributes and sgr0/exit_attribute_mode like to enable or + // disable the ACS with SO/SI (e.g. for TERM=screen), however `less -R` + // does not skip over these characters and it screws up word wrapping + if (*attr == 14 /* SO */ || *attr == 15 /* SI */) + continue; + + // Trivially skip delay sequences intended to be processed by tputs() + const char *end = NULL; + if (attr[0] == '$' && attr[1] == '<' && (end = strchr (attr, '>'))) + attr = end; + else + fputc (*attr, stream); + } +} + static void attr_printer_tputs (struct attr_printer *self, const char *attr) { @@ -2791,9 +2806,9 @@ attr_printer_tputs (struct attr_printer *self, const char *attr) if (printer) tputs (attr, 1, printer); else - // We shouldn't really do this but we need it to - // output formatting to the backlog - fputs (attr, self->stream); + // We shouldn't really do this but we need it to output formatting + // to the backlog helper--it should be SGR-only + attr_printer_filtered_puts (self->stream, attr); } static void @@ -3604,7 +3619,7 @@ explode_text (struct exploder *self, const char *text) // Throw away any potentially harmful control characters first struct str filtered = str_make (); for (const char *p = text; *p; p++) - if (!strchr ("\a\b\x1b", *p)) + if (!strchr ("\a\b\x0e\x0f\x1b" /* BEL BS SO SI ESC */, *p)) str_append_c (&filtered, *p); size_t term_len = 0; -- cgit v1.2.3-70-g09d2