--- src/optinc.h | 1 + src/rsinc.h | 1 + src/screen.C | 63 ++++++++++++++++++++++++++++++++++++++++++++----- src/xdefaults.C | 1 + 4 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/src/optinc.h b/src/optinc.h index 09f9a26..befc68a 100644 --- a/src/optinc.h +++ b/src/optinc.h @@ -29,6 +29,7 @@ def(secondaryScroll) def(pastableTabs) def(cursorUnderline) + def(filterPastedControls) #if ENABLE_FRILLS def(insecure) // insecure esc sequences def(borderLess) // mwm borderless hints diff --git a/src/rsinc.h b/src/rsinc.h index 86d0dfe..0b40f62 100644 --- a/src/rsinc.h +++ b/src/rsinc.h @@ -67,6 +67,7 @@ #if XFT def (buffered) #endif + def(filterPastedControls) #if ENABLE_FRILLS def (depth) def (visual) diff --git a/src/screen.C b/src/screen.C index 9eb375a..4ba18bf 100644 --- a/src/screen.C +++ b/src/screen.C @@ -2703,15 +2703,66 @@ rxvt_term::selection_changed () NOTHROW void rxvt_term::tt_paste (char *data, unsigned int len) NOTHROW { - /* convert normal newline chars into common keyboard Return key sequence */ - for (unsigned int i = 0; i < len; i++) - if (data[i] == C0_LF) - data[i] = C0_CR; - if (priv_modes & PrivMode_BracketPaste) tt_printf ("\x1b[200~"); - tt_write (data, len); + if (option(Opt_filterPastedControls)) { + /* prepare lookup table for unwanted characters */ + char lookup[256]; + memset(lookup, 0, sizeof(lookup)); + char drop[] = "\x01\x02\x03\x04\x05\x06\x07\x08\x0a\x0b\x0c\x0e\x0f\x10\x11" + "\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\xc2"; + for (unsigned int i = sizeof(drop); i-- > 0u;) { + lookup[drop[i]] = 1; + } + + /* skip the first run of good characters; no change is needed there */ + char * rptr = data; + char * end = data + len; + while (rptr < end && lookup[*rptr] == 0) { + ++rptr; + } + /* encountered a bad symbol (or the end of buffer); from this point copy byte + by byte; we won't copy by segments since they are likely to overlap */ + char * wptr = rptr; + while (rptr < end) { + /* consume the current character and process it */ + switch (*rptr++) { + /* convert newline chars into common keyboard Return key sequence */ + case '\x0a': + *wptr++ = '\x0d'; + break; + /* filter pairs C2-80 to C2-9F which are UTF8 sequences for U+0080 to U+009F + codepoints (C1 Controls and Latin-1 Supplement) */ + case '\xc2': + if (rptr < end) { + const char v = *rptr++; + if (v < '\x80' || v > '\x9f') { + /* not a bad pair, keep both */ + *wptr++ = '\xc2'; + *wptr++ = v; + } + } else { + /* write consumed C2 since it's at the buffer end with no pair */ + *wptr++ = '\xc2'; + } + default: + /* skip the consumed character */ + break; + } + /* write one by one until the next bad character */ + while (rptr < end && lookup[*rptr] == 0) { + *wptr++ = *rptr++; + } + } + tt_write (data, wptr - data); + } else { + for (unsigned int i = 0; i < len; i++) + if (data[i] == C0_LF) + data[i] = C0_CR; + + tt_write (data, len); + } if (priv_modes & PrivMode_BracketPaste) tt_printf ("\x1b[201~"); diff --git a/src/xdefaults.C b/src/xdefaults.C index 894aa8d..4e973bb 100644 --- a/src/xdefaults.C +++ b/src/xdefaults.C @@ -115,6 +115,7 @@ optList[] = { BOOL (Rs_scrollTtyOutput, NULL, "si", Opt_scrollTtyOutput, Optflag_Reverse, "scroll-on-tty-output inhibit"), BOOL (Rs_scrollTtyKeypress, "scrollTtyKeypress", "sk", Opt_scrollTtyKeypress, 0, "scroll-on-keypress"), BOOL (Rs_scrollWithBuffer, "scrollWithBuffer", "sw", Opt_scrollWithBuffer, 0, "scroll-with-buffer"), + BOOL (Rs_filterPastedControls, "filterPastedControls", "fc", Opt_filterPastedControls, 0, "filter control characters on paste"), #if BG_IMAGE_FROM_ROOT BOOL (Rs_transparent, "inheritPixmap", "ip", Opt_transparent, 0, "inherit parent pixmap"), BOOL (Rs_transparent, "transparent", "tr", Opt_transparent, 0, "inherit parent pixmap"), -- 2.17.0 _______________________________________________ rxvt-unicode mailing list rxvt-unicode@lists.schmorp.de http://lists.schmorp.de/mailman/listinfo/rxvt-unicode