parseUtf8 method

(int, Event?) parseUtf8(
  1. List<int> buf
)

Implementation

(int, Event?) parseUtf8(List<int> buf) {
  if (buf.isEmpty) return (0, null);
  final b = buf[0];

  // Control codes + DEL (0x7F).
  if (b <= 0x1f || b == 0x7f) {
    return (1, parseControl(b));
  }

  // ASCII printable characters.
  if (b >= 0x20 && b < 0x7f) {
    if (b >= 0x41 && b <= 0x5a) {
      // Uppercase A-Z => lower code + shift modifier.
      final lower = b + 0x20;
      return (
        1,
        KeyPressEvent(
          Key(
            code: lower,
            shiftedCode: b,
            text: String.fromCharCode(b),
            mod: KeyMod.shift,
          ),
        ),
      );
    }
    return (1, KeyPressEvent(Key(code: b, text: String.fromCharCode(b))));
  }

  // UTF-8 grapheme clusters: decode runes until we have at least 2 clusters,
  // then return the first one.
  var consumed = 0;
  final sb = StringBuffer();

  while (consumed < buf.length) {
    final decoded = _decodeOneRune(buf.sublist(consumed));
    if (!decoded.ok) {
      if (decoded.consumed == 0) return (0, null); // need more bytes
      return (1, UnknownEvent(String.fromCharCode(b)));
    }
    consumed += decoded.consumed;
    sb.writeCharCode(decoded.rune);

    final s = sb.toString();
    final it = uni.graphemes(s).iterator;
    if (!it.moveNext()) continue;
    final firstCluster = it.current;
    if (it.moveNext()) {
      final bytesConsumed = utf8.encode(firstCluster).length;
      return (bytesConsumed, _keyFromCluster(firstCluster));
    }
  }

  // Only one grapheme cluster in the available buffer.
  final cluster = sb.toString();
  return (consumed, _keyFromCluster(cluster));
}