in src/agent/ConsoleInput.cc [380:486]
int ConsoleInput::scanInput(std::vector<INPUT_RECORD> &records,
const char *input,
int inputSize,
bool isEof)
{
ASSERT(inputSize >= 1);
// Ctrl-C.
//
// In processed mode, use GenerateConsoleCtrlEvent so that Ctrl-C handlers
// are called. GenerateConsoleCtrlEvent unfortunately doesn't interrupt
// ReadConsole calls[1]. Using WM_KEYDOWN/UP fixes the ReadConsole
// problem, but breaks in background window stations/desktops.
//
// In unprocessed mode, there's an entry for Ctrl-C in the SimpleEncoding
// table in DefaultInputMap.
//
// [1] https://github.com/rprichard/winpty/issues/116
if (input[0] == '\x03' && (inputConsoleMode() & ENABLE_PROCESSED_INPUT)) {
flushInputRecords(records);
trace("Ctrl-C");
const BOOL ret = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
trace("GenerateConsoleCtrlEvent: %d", ret);
return 1;
}
if (input[0] == '\x1B') {
// Attempt to match the Device Status Report (DSR) reply.
int dsrLen = matchDsr(input, inputSize);
if (dsrLen > 0) {
trace("Received a DSR reply");
m_dsrSent = false;
return dsrLen;
} else if (!isEof && dsrLen == -1) {
// Incomplete DSR match.
trace("Incomplete DSR match");
return -1;
}
int mouseLen = scanMouseInput(records, input, inputSize);
if (mouseLen > 0 || (!isEof && mouseLen == -1)) {
return mouseLen;
}
}
// Search the input map.
InputMap::Key match;
bool incomplete;
int matchLen = m_inputMap.lookupKey(input, inputSize, match, incomplete);
if (!isEof && incomplete) {
// Incomplete match -- need more characters (or wait for a
// timeout to signify flushed input).
trace("Incomplete escape sequence");
return -1;
} else if (matchLen > 0) {
uint32_t winCodePointDn = match.unicodeChar;
if ((match.keyState & LEFT_CTRL_PRESSED) && (match.keyState & LEFT_ALT_PRESSED)) {
winCodePointDn = '\0';
}
uint32_t winCodePointUp = winCodePointDn;
if (match.keyState & LEFT_ALT_PRESSED) {
winCodePointUp = '\0';
}
appendKeyPress(records, match.virtualKey,
winCodePointDn, winCodePointUp, match.keyState,
match.unicodeChar, match.keyState);
return matchLen;
}
// Recognize Alt-<character>.
//
// This code doesn't match Alt-ESC, which is encoded as `ESC ESC`, but
// maybe it should. I was concerned that pressing ESC rapidly enough could
// accidentally trigger Alt-ESC. (e.g. The user would have to be faster
// than the DSR flushing mechanism or use a decrepit terminal. The user
// might be on a slow network connection.)
if (input[0] == '\x1B' && inputSize >= 2 && input[1] != '\x1B') {
const int len = utf8CharLength(input[1]);
if (len > 0) {
if (1 + len > inputSize) {
// Incomplete character.
trace("Incomplete UTF-8 character in Alt-<Char>");
return -1;
}
appendUtf8Char(records, &input[1], len, true);
return 1 + len;
}
}
// A UTF-8 character.
const int len = utf8CharLength(input[0]);
if (len == 0) {
static bool debugInput = isTracingEnabled() && hasDebugFlag("input");
if (debugInput) {
trace("Discarding invalid input byte: %02X",
static_cast<unsigned char>(input[0]));
}
return 1;
}
if (len > inputSize) {
// Incomplete character.
trace("Incomplete UTF-8 character");
return -1;
}
appendUtf8Char(records, &input[0], len, false);
return len;
}