Skip to content

Commit

Permalink
rewrite parsing of winterm sequences
Browse files Browse the repository at this point in the history
  • Loading branch information
elfmz committed Apr 2, 2023
1 parent edf9b73 commit b5f7ba3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 19 deletions.
70 changes: 51 additions & 19 deletions WinPort/src/Backend/TTY/TTYInputSequenceParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,30 +309,56 @@ void TTYInputSequenceParser::ParseAPC(const char *s, size_t l)
}
}

size_t TTYInputSequenceParser::ParseEscapeSequence(const char *s, size_t l)
size_t TTYInputSequenceParser::TryParseAsWinTermEscapeSequence(const char *s, size_t l)
{
if (s[0] == '[' && s[l-1] == '_') {

// win32-input-mode sequence

INPUT_RECORD ir = {};
ir.EventType = KEY_EVENT;

int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
sscanf(s, "[%d;%d;%d;%d;%d;%d_", &a, &b, &c, &d, &e, &f);
// check for nasty win32-input-mode sequence: as described in
// https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md
// [Vk;Sc;Uc;Kd;Cs;Rc_
// First char assured to be [ by the caller so need to check that it followed
// by up to 6 semicolon-separated integer values ended with underscore, keeping
// in mind that some values can be omitted or be empty meaning they're set to zero

int args[6] = {0};
int args_cnt = 0;

size_t n;
for (size_t i = n = 1;; ++i) {
if (i == l) {
return LIKELY(l < 32) ? TTY_PARSED_WANTMORE : TTY_PARSED_BADSEQUENCE;
}
if (s[i] == '_' || s[i] == ';') {
if (args_cnt == ARRAYSIZE(args)) {
return TTY_PARSED_BADSEQUENCE;
}
if (i > n) {
args[args_cnt] = atoi(&s[n]);
}
++args_cnt;
n = i + 1;
if (s[i] == '_') {
break;
}

ir.Event.KeyEvent.wVirtualKeyCode = a;
ir.Event.KeyEvent.wVirtualScanCode = b;
ir.Event.KeyEvent.uChar.UnicodeChar = c;
ir.Event.KeyEvent.bKeyDown = d;
ir.Event.KeyEvent.dwControlKeyState = e;
ir.Event.KeyEvent.wRepeatCount = f;
} else if (s[i] < '0' && s[i] > '9') {
return TTY_PARSED_BADSEQUENCE;
}
}

_ir_pending.emplace_back(ir); // g_winport_con_in->Enqueue(&ir, 1);
INPUT_RECORD ir = {};
ir.EventType = KEY_EVENT;
ir.Event.KeyEvent.wVirtualKeyCode = args[0];
ir.Event.KeyEvent.wVirtualScanCode = args[1];
ir.Event.KeyEvent.uChar.UnicodeChar = args[2];
ir.Event.KeyEvent.bKeyDown = (args[3] ? TRUE : FALSE);
ir.Event.KeyEvent.dwControlKeyState = args[4];
ir.Event.KeyEvent.wRepeatCount = args[5];

return l;
}
_ir_pending.emplace_back(ir);
return n;
}

size_t TTYInputSequenceParser::ParseEscapeSequence(const char *s, size_t l)
{
if (l > 2 && s[0] == '[' && s[2] == 'n') {
return 3;
}
Expand Down Expand Up @@ -364,6 +390,12 @@ size_t TTYInputSequenceParser::ParseEscapeSequence(const char *s, size_t l)
if (r != 0)
return r;

if (l > 1 && s[0] == '[') {
r = TryParseAsWinTermEscapeSequence(s, l);
if (r != TTY_PARSED_BADSEQUENCE)
return r;
}

// be well-responsive on panic-escaping
for (size_t i = 0; (i + 1) < l; ++i) {
if (s[i] == 0x1b && s[i + 1] == 0x1b) {
Expand Down
1 change: 1 addition & 0 deletions WinPort/src/Backend/TTY/TTYInputSequenceParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class TTYInputSequenceParser
size_t ParseNChars2Key(const char *s, size_t l);
void ParseMouse(char action, char col, char raw);
void ParseAPC(const char *s, size_t l);
size_t TryParseAsWinTermEscapeSequence(const char *s, size_t l);
size_t ParseEscapeSequence(const char *s, size_t l);
void OnBracketedPaste(bool start);

Expand Down

1 comment on commit b5f7ba3

@unxed
Copy link
Contributor

@unxed unxed commented on b5f7ba3 Apr 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original bug report:
https://t.me/far2l_ru/6587

Reporter wrote me that the problem is solved now.

Also it looks like mouse handling in Windows Terminal in win32-input-mode is buggy:
microsoft/terminal#15083

Please sign in to comment.