Correct handling of SGR mouse tracking events

They are of variable length, taking semicolon-separated ASCII characters
and not single chars/bytes as the parameters. Additionally, the global
maximum size for a CSI is 16 characters (NPAR), even though I believe
the maximum possible mouse-tracking CSI is 12 characters.
This commit is contained in:
Mahmoud Al-Qudsi 2021-02-17 12:55:40 -06:00
parent 7e77dc8964
commit 774488686c

View file

@ -509,6 +509,10 @@ class event_queue_peeker_t {
return count;
}
constexpr size_t max_len() const {
return N;
}
void consume() {
consumed_ = true;
}
@ -528,7 +532,9 @@ class event_queue_peeker_t {
};
bool inputter_t::have_mouse_tracking_csi() {
event_queue_peeker_t<12> peeker(event_queue_);
// Maximum length of any CSI is NPAR (which is nominally 16), although this does not account for
// user input intermixed with pseudo input generated by the tty emulator.
event_queue_peeker_t<16> peeker(event_queue_);
// Check for the CSI first
if (peeker.next().maybe_char() != L'\x1B'
@ -540,11 +546,24 @@ bool inputter_t::have_mouse_tracking_csi() {
size_t length = 0;
if (next == L'M') {
// Generic X10 or modified VT200 sequence. It doesn't matter which, they're both 6 chars
// reporting the button that was clicked and its location.
// (although in mode 1005, the characters may be unicode and not necessarily just one byte
// long) reporting the button that was clicked and its location.
length = 6;
} else if (next == L'P') {
// VT200 mouse highlighting. 12 characters, comes after generic button press event.
length = 12;
} else if (next == L'<') {
// Extended (SGR/1006) mouse reporting mode, with semicolon-separated parameters for button
// code, Px, and Py, ending with 'M' for button press or 'm' for button release.
while (true) {
next = peeker.next().maybe_char();
if (next == L'M' || next == L'm') {
// However much we've read, we've consumed the CSI in its entirety.
length = peeker.len();
break;
}
if (peeker.len() == 16) {
// This is likely a malformed mouse-reporting CSI but we can't do anything about it.
return false;
}
}
} else if (next == L't') {
// VT200 button released in mouse highlighting mode at valid text location. 5 chars.
length = 5;