parseWin32InputKeyEvent function

Event? parseWin32InputKeyEvent(
  1. int vkc,
  2. int sc,
  3. int uc,
  4. bool keyDown,
  5. int cks,
  6. int repeatCount,
)

Implementation

Event? parseWin32InputKeyEvent(
  int vkc,
  int sc,
  int uc,
  bool keyDown,
  int cks,
  int repeatCount,
) {
  // Partial port of `parseWin32InputKeyEvent` for VT input mode sequences.
  //
  final mod = translateControlKeyState(cks);

  bool isControl(int r) => r <= 0x1f || (r >= 0x7f && r <= 0x9f);
  bool isPrintable(int r) => r >= 0x20 && !isControl(r) && r <= 0x10ffff;

  // vkc==0 indicates a serialized UTF-16 code unit; upstream defers decoding
  // these in the TerminalReader. We still surface them as a "base code" event.
  if (vkc == 0) {
    final k = Key(code: 0, baseCode: uc, mod: mod);
    if (repeatCount > 1 && keyDown) {
      return MultiEvent(
        List<Event>.generate(repeatCount, (_) => KeyPressEvent(k)),
      );
    }
    return keyDown ? KeyPressEvent(k) : KeyReleaseEvent(k);
  }

  var baseCode = 0;
  var shiftedCode = 0;
  var text = '';

  switch (vkc) {
    case 0x08: // VK_BACK
      baseCode = keyBackspace;
      break;
    case 0x09: // VK_TAB
      baseCode = keyTab;
      break;
    case 0x0d: // VK_RETURN
      baseCode = keyEnter;
      break;
    case 0x1b: // VK_ESCAPE
      baseCode = keyEscape;
      break;
    case 0x20: // VK_SPACE
      baseCode = keySpace;
      text = ' ';
      break;
    default:
      if (vkc >= 0x30 && vkc <= 0x39) {
        // 0-9
        baseCode = vkc;
      } else if (vkc >= 0x41 && vkc <= 0x5a) {
        // A-Z => lowercase base code.
        baseCode = vkc + 0x20;
      } else if (vkc >= 0x70 && vkc <= 0x87) {
        // F1..F24
        baseCode = keyF1 + (vkc - 0x70);
      } else {
        baseCode = uc != 0 ? uc : vkc;
      }
  }

  var code = baseCode;
  if (uc != 0 && !isControl(uc)) {
    code = uc;
    if (text.isEmpty && isPrintable(code) && mod == 0) {
      text = String.fromCharCode(code);
    }
  }

  // If the key is printable and only shift/caps locks are active, keep text.
  if (text.isEmpty && isPrintable(code) && (mod == 0 || mod == KeyMod.shift)) {
    text = String.fromCharCode(code);
  }

  var key = Key(
    code: code,
    text: text,
    mod: mod,
    shiftedCode: shiftedCode,
    baseCode: baseCode,
  );
  key = ensureKeyCase(key, cks);

  if (repeatCount > 1 && keyDown) {
    return MultiEvent(
      List<Event>.generate(
        repeatCount,
        (_) => KeyPressEvent(key),
        growable: false,
      ),
    );
  }

  return keyDown ? KeyPressEvent(key) : KeyReleaseEvent(key);
}