Skip to content

Commit

Permalink
Add support for Kitty keyboard protocol and XTerm PC-style function keys
Browse files Browse the repository at this point in the history
  • Loading branch information
magiblot committed Apr 1, 2021
1 parent 525623c commit 6e5a7b4
Show file tree
Hide file tree
Showing 3 changed files with 429 additions and 181 deletions.
58 changes: 47 additions & 11 deletions include/tvision/internal/terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ struct MouseState

class GetChBuf
{
enum { maxSize = 31 };
enum { maxSize = 63 };

int keys[maxSize];
uint size {0};
int keys[maxSize];

protected:

Expand All @@ -26,20 +26,20 @@ class GetChBuf

public:

int get();
int get(bool keepErr);
int last(size_t i);
void unget();
void reject();
int getNum();

};

inline int GetChBuf::get()
inline int GetChBuf::get(bool keepErr=false)
{
if (size < maxSize)
{
int k = do_getch();
if (k != -1)
if (keepErr || k != -1)
keys[size++] = k;
return k;
}
Expand All @@ -55,21 +55,22 @@ inline int GetChBuf::last(size_t i=0)

inline void GetChBuf::unget()
{
if (size)
do_ungetch(keys[--size]);
int k;
if (size && (k = keys[--size]) != -1)
do_ungetch(k);
}

inline void GetChBuf::reject()
{
while (size)
do_ungetch(keys[--size]);
unget();
}

inline int GetChBuf::getNum()
{
int num = 0, digits = 0;
int k;
while ((k = get()) != -1 && '0' <= k && k <= '9')
while ((k = get(true)) != -1 && '0' <= k && k <= '9')
{
num = 10 * num + (k - '0');
++digits;
Expand All @@ -79,22 +80,57 @@ inline int GetChBuf::getNum()

enum ParseResult { Rejected = 0, Accepted, Ignored };

struct CSIData
{
// Represents the data stored in a CSI escape sequence:
// \x1B [ val[0] sep[0] val[1] sep[1]

// CSIs can be longer, but this is the largest we need for now.
enum { maxLength = 2 };

uint val[maxLength];
uint sep[maxLength];
uint length;

bool readFrom(GetChBuf &buf)
{
length = 0;
for (uint i = 0; i < maxLength; ++i)
{
int k;
if (val[i] = uint(k = buf.getNum()), k == -1) return false;
if (sep[i] = uint(k = buf.last()), k == -1) return false;
if (sep[i] != ';')
return (length = i + 1), true;
}
return false;
}

uint terminator() const
{
return length ? sep[length - 1] : 0;
}
};

namespace TermIO
{

void mouseOn();
void mouseOff();
void kittyKeysOn();
void kittyKeysOff();

ParseResult parseEscapeSeq(GetChBuf&, TEvent&, MouseState&);
ParseResult parseX10Mouse(GetChBuf&, TEvent&, MouseState&);
ParseResult parseSGRMouse(GetChBuf&, TEvent&, MouseState&);
ParseResult parseCSIKey(const CSIData &csi, TEvent&);
ParseResult parseFKeyA(GetChBuf&, TEvent&);
ParseResult parseFKeyB(GetChBuf&, TEvent&);
ParseResult parseArrowKeyA(GetChBuf&, TEvent&);
ParseResult parseHomeEndA(GetChBuf&, TEvent&);
ParseResult parseFixTermKey(const CSIData &csi, TEvent&);

bool acceptMouseEvent(TEvent &ev, MouseState &oldm, const MouseState &newm);
void setAltModifier(TEvent &ev);
void setAltModifier(KeyDownEvent &keyDown);

#ifdef _TV_UNIX
namespace Unix
Expand Down
58 changes: 36 additions & 22 deletions source/platform/ncursinp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,19 @@ static const const_unordered_map<ushort, KeyDownEvent> fromCursesKeyCode = {
{ KEY_F0 + 34, {{kbCtrlF10}, kbCtrlShift}},
{ KEY_F0 + 35, {{kbCtrlF11}, kbCtrlShift}},
{ KEY_F0 + 36, {{kbCtrlF12}, kbCtrlShift}},
// Ctrl+Shift+F(n) supported by ncurses but not Turbo Vision
// Ctrl+Shift+F1-12
{ KEY_F0 + 37, {{kbCtrlF1}, kbShift | kbCtrlShift}},
{ KEY_F0 + 38, {{kbCtrlF2}, kbShift | kbCtrlShift}},
{ KEY_F0 + 39, {{kbCtrlF3}, kbShift | kbCtrlShift}},
{ KEY_F0 + 40, {{kbCtrlF4}, kbShift | kbCtrlShift}},
{ KEY_F0 + 41, {{kbCtrlF5}, kbShift | kbCtrlShift}},
{ KEY_F0 + 42, {{kbCtrlF6}, kbShift | kbCtrlShift}},
{ KEY_F0 + 43, {{kbCtrlF7}, kbShift | kbCtrlShift}},
{ KEY_F0 + 44, {{kbCtrlF8}, kbShift | kbCtrlShift}},
{ KEY_F0 + 45, {{kbCtrlF9}, kbShift | kbCtrlShift}},
{ KEY_F0 + 46, {{kbCtrlF10}, kbShift | kbCtrlShift}},
{ KEY_F0 + 47, {{kbCtrlF11}, kbShift | kbCtrlShift}},
{ KEY_F0 + 48, {{kbCtrlF12}, kbShift | kbCtrlShift}},
// Alt+F1-F12
{ KEY_F0 + 49, {{kbAltF1}, kbAltShift} },
{ KEY_F0 + 50, {{kbAltF2}, kbAltShift} },
Expand Down Expand Up @@ -176,16 +188,16 @@ static const auto fromCursesHighKey =
{ "kRIT3", {{kbAltRight}, kbAltShift}},
{ "kUP3", {{kbAltUp}, kbAltShift}},
{ "kDN3", {{kbAltDown}, kbAltShift}},
{ "kDC4", {{kbShiftDel}, kbShift | kbAltShift}},
{ "kEND4", {{kbEnd}, kbShift | kbAltShift}},
{ "kHOM4", {{kbHome}, kbShift | kbAltShift}},
{ "kIC4", {{kbShiftIns}, kbShift | kbAltShift}},
{ "kLFT4", {{kbLeft}, kbShift | kbAltShift}},
{ "kNXT4", {{kbPgDn}, kbShift | kbAltShift}},
{ "kPRV4", {{kbPgUp}, kbShift | kbAltShift}},
{ "kRIT4", {{kbRight}, kbShift | kbAltShift}},
{ "kUP4", {{kbUp}, kbShift | kbAltShift}},
{ "kDN4", {{kbDown}, kbShift | kbAltShift}},
{ "kDC4", {{kbAltDel}, kbShift | kbAltShift}},
{ "kEND4", {{kbAltEnd}, kbShift | kbAltShift}},
{ "kHOM4", {{kbAltHome}, kbShift | kbAltShift}},
{ "kIC4", {{kbAltIns}, kbShift | kbAltShift}},
{ "kLFT4", {{kbAltLeft}, kbShift | kbAltShift}},
{ "kNXT4", {{kbAltPgDn}, kbShift | kbAltShift}},
{ "kPRV4", {{kbAltPgUp}, kbShift | kbAltShift}},
{ "kRIT4", {{kbAltRight}, kbShift | kbAltShift}},
{ "kUP4", {{kbAltUp}, kbShift | kbAltShift}},
{ "kDN4", {{kbAltDown}, kbShift | kbAltShift}},
{ "kDC5", {{kbCtrlDel}, kbCtrlShift}},
{ "kEND5", {{kbCtrlEnd}, kbCtrlShift}},
{ "kHOM5", {{kbCtrlHome}, kbCtrlShift}},
Expand All @@ -206,16 +218,16 @@ static const auto fromCursesHighKey =
{ "kRIT6", {{kbCtrlRight}, kbCtrlShift | kbShift}},
{ "kUP6", {{kbCtrlUp}, kbCtrlShift | kbShift}},
{ "kDN6", {{kbCtrlDown}, kbCtrlShift | kbShift}},
{ "kDC7", {{kbDel}, kbCtrlShift | kbAltShift}}, // Please do not attempt this one
{ "kEND7", {{kbEnd}, kbCtrlShift | kbAltShift}},
{ "kHOM7", {{kbHome}, kbCtrlShift | kbAltShift}},
{ "kIC7", {{kbIns}, kbCtrlShift | kbAltShift}},
{ "kLFT7", {{kbLeft}, kbCtrlShift | kbAltShift}},
{ "kNXT7", {{kbPgDn}, kbCtrlShift | kbAltShift}},
{ "kPRV7", {{kbPgUp}, kbCtrlShift | kbAltShift}},
{ "kRIT7", {{kbRight}, kbCtrlShift | kbAltShift}},
{ "kUP7", {{kbUp}, kbCtrlShift | kbAltShift}},
{ "kDN7", {{kbDown}, kbCtrlShift | kbAltShift}},
{ "kDC7", {{kbAltDel}, kbCtrlShift | kbAltShift}}, // Please do not attempt this one
{ "kEND7", {{kbAltEnd}, kbCtrlShift | kbAltShift}},
{ "kHOM7", {{kbAltHome}, kbCtrlShift | kbAltShift}},
{ "kIC7", {{kbAltIns}, kbCtrlShift | kbAltShift}},
{ "kLFT7", {{kbAltLeft}, kbCtrlShift | kbAltShift}},
{ "kNXT7", {{kbAltPgDn}, kbCtrlShift | kbAltShift}},
{ "kPRV7", {{kbAltPgUp}, kbCtrlShift | kbAltShift}},
{ "kRIT7", {{kbAltRight}, kbCtrlShift | kbAltShift}},
{ "kUP7", {{kbAltUp}, kbCtrlShift | kbAltShift}},
{ "kDN7", {{kbAltDown}, kbCtrlShift | kbAltShift}},
{ "kpADD", {{'+'}, 0, {'+'}, 1}},
{ "kpSUB", {{'-'}, 0, {'-'}, 1}},
{ "kpMUL", {{'*'}, 0, {'*'}, 1}},
Expand Down Expand Up @@ -244,6 +256,7 @@ NcursesInput::NcursesInput(bool mouse) :
* special key sequences, I believe. */
set_escdelay(getEnv<int>("TVISION_ESCDELAY", 10));

TermIO::kittyKeysOn();
if (mouseEnabled)
{
mstate.where = {-1, -1};
Expand All @@ -261,6 +274,7 @@ NcursesInput::~NcursesInput()
{
if (mouseEnabled)
TermIO::mouseOff();
TermIO::kittyKeysOff();
}

int NcursesInput::getButtonCount()
Expand Down Expand Up @@ -348,7 +362,7 @@ bool NcursesInput::getEvent(TEvent &ev)
parsePrintableChar(ev, keys, num_keys);

if (Alt)
TermIO::setAltModifier(ev);
TermIO::setAltModifier(ev.keyDown);

return ev.keyDown.keyCode != kbNoKey || ev.keyDown.textLength;
}
Expand Down
Loading

0 comments on commit 6e5a7b4

Please sign in to comment.