decode method
Decode the first event in buf.
Returns (bytesConsumed, event) where event may be null if more data is needed.
Implementation
(int, Event?) decode(List<int> buf, {bool allowIncompleteEsc = false}) {
if (buf.isEmpty) return (0, null);
final b0 = buf[0];
// 8-bit control sequence introducers (C1).
switch (b0) {
case 0x9b: // CSI
final (n, ev) = _parseCsi(
_to7Bit(buf, 0x5b),
allowIncompleteEsc: allowIncompleteEsc,
);
return (n == 0 ? 0 : n - 1, ev);
case 0x8f: // SS3
final (n, ev) = _parseSs3(
_to7Bit(buf, 0x4f),
allowIncompleteEsc: allowIncompleteEsc,
);
return (n == 0 ? 0 : n - 1, ev);
case 0x9d: // OSC
return _parseOsc(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x90: // DCS
return _parseDcs(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x9f: // APC
return _parseApc(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x9e: // PM
return _parseStTerminated(
intro8: 0x9e,
intro7: 0x5e, // '^'
kind: 'pm',
makeUnknown: (s) => UnknownPmEvent(s),
buf: buf,
allowIncompleteEsc: allowIncompleteEsc,
);
case 0x98: // SOS
return _parseStTerminated(
intro8: 0x98,
intro7: 0x58, // 'X'
kind: 'sos',
makeUnknown: (s) => UnknownSosEvent(s),
buf: buf,
allowIncompleteEsc: allowIncompleteEsc,
);
}
if (b0 == 0x1b) {
// ESC
if (buf.length == 1) {
return (1, KeyPressEvent(Key(code: keyEscape)));
}
// ESC ESC => a literal Escape key followed by another sequence.
if (buf[1] == 0x1b) {
return (1, KeyPressEvent(Key(code: keyEscape)));
}
// Broken escape-sequence introducers should be treated as Alt-modified keys.
if (buf.length == 2) {
final intro = buf[1];
final shortcut = _brokenEscIntroducerAsKey(intro);
if (shortcut != null) return (2, shortcut);
}
final b1 = buf[1];
switch (b1) {
case 0x4f: // 'O' SS3
return _parseSs3(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x50: // 'P' DCS
return _parseDcs(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x5b: // '[' CSI
return _parseCsi(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x5d: // ']' OSC
return _parseOsc(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x5f: // '_' APC
return _parseApc(buf, allowIncompleteEsc: allowIncompleteEsc);
case 0x5e: // '^' PM
return _parseStTerminated(
intro8: 0x9e,
intro7: 0x5e,
kind: 'pm',
makeUnknown: (s) => UnknownPmEvent(s),
buf: buf,
allowIncompleteEsc: allowIncompleteEsc,
);
case 0x58: // 'X' SOS
return _parseStTerminated(
intro8: 0x98,
intro7: 0x58,
kind: 'sos',
makeUnknown: (s) => UnknownSosEvent(s),
buf: buf,
allowIncompleteEsc: allowIncompleteEsc,
);
default:
// Alt-modified sequences: ESC + <utf8/control>
final (n, ev) = parseUtf8(buf.sublist(1));
if (n == 0) {
return allowIncompleteEsc
? (1, KeyPressEvent(Key(code: keyEscape)))
: (0, null);
}
if (ev is KeyPressEvent) {
final k = ev.key();
return (
1 + n,
KeyPressEvent(
Key(
code: k.code,
text: k.text,
mod: k.mod | KeyMod.alt,
shiftedCode: k.shiftedCode,
baseCode: k.baseCode,
isRepeat: k.isRepeat,
),
),
);
}
return (1 + n, ev);
}
}
return parseUtf8(buf);
}