use crate::win::WinMode;
use std::os::raw::*;
use x11::keysym::*;
use x11::xlib::*;
const XK_ANY_MOD: u32 = u32::MAX;
const XK_NO_MOD: u32 = 0;
const XK_SWITCH_MOD: u32 = 1 << 13;
const IGNORE_MOD: u32 = Mod2Mask | XK_SWITCH_MOD;
struct Key {
k: c_uint,
mask: c_uint,
s: &'static [u8],
appkeypad: i8,
appcursor: i8,
}
macro_rules! make_keys {
{
$({ $k:expr, $mask:expr, $s:expr, $appkeypad:expr, $appcursor:expr },)*
} => {
&[
$(Key {
k: $k,
mask: $mask,
s: $s,
appkeypad: $appkeypad,
appcursor: $appcursor,
},)*
]
}
}
const KEYS: &[Key] = make_keys! {
{ XK_KP_Home, ShiftMask, b"\x1B[2J", 0, -1},
{ XK_KP_Home, ShiftMask, b"\x1B[1;2H", 0, 1},
{ XK_KP_Home, XK_ANY_MOD, b"\x1B[H", 0, -1},
{ XK_KP_Home, XK_ANY_MOD, b"\x1B[1~", 0, 1},
{ XK_KP_Up, XK_ANY_MOD, b"\x1BOx", 1, 0},
{ XK_KP_Up, XK_ANY_MOD, b"\x1B[A", 0, -1},
{ XK_KP_Up, XK_ANY_MOD, b"\x1BOA", 0, 1},
{ XK_KP_Down, XK_ANY_MOD, b"\x1BOr", 1, 0},
{ XK_KP_Down, XK_ANY_MOD, b"\x1B[B", 0, -1},
{ XK_KP_Down, XK_ANY_MOD, b"\x1BOB", 0, 1},
{ XK_KP_Left, XK_ANY_MOD, b"\x1BOt", 1, 0},
{ XK_KP_Left, XK_ANY_MOD, b"\x1B[D", 0, -1},
{ XK_KP_Left, XK_ANY_MOD, b"\x1BOD", 0, 1},
{ XK_KP_Right, XK_ANY_MOD, b"\x1BOv", 1, 0},
{ XK_KP_Right, XK_ANY_MOD, b"\x1B[C", 0, -1},
{ XK_KP_Right, XK_ANY_MOD, b"\x1BOC", 0, 1},
{ XK_KP_Prior, ShiftMask, b"\x1B[5;2~", 0, 0},
{ XK_KP_Prior, XK_ANY_MOD, b"\x1B[5~", 0, 0},
{ XK_KP_Begin, XK_ANY_MOD, b"\x1B[E", 0, 0},
{ XK_KP_End, ControlMask, b"\x1B[J", -1, 0},
{ XK_KP_End, ControlMask, b"\x1B[1;5F", 1, 0},
{ XK_KP_End, ShiftMask, b"\x1B[K", -1, 0},
{ XK_KP_End, ShiftMask, b"\x1B[1;2F", 1, 0},
{ XK_KP_End, XK_ANY_MOD, b"\x1B[4~", 0, 0},
{ XK_KP_Next, ShiftMask, b"\x1B[6;2~", 0, 0},
{ XK_KP_Next, XK_ANY_MOD, b"\x1B[6~", 0, 0},
{ XK_KP_Insert, ShiftMask, b"\x1B[2;2~", 1, 0},
{ XK_KP_Insert, ShiftMask, b"\x1B[4l", -1, 0},
{ XK_KP_Insert, ControlMask, b"\x1B[L", -1, 0},
{ XK_KP_Insert, ControlMask, b"\x1B[2;5~", 1, 0},
{ XK_KP_Insert, XK_ANY_MOD, b"\x1B[4h", -1, 0},
{ XK_KP_Insert, XK_ANY_MOD, b"\x1B[2~", 1, 0},
{ XK_KP_Delete, ControlMask, b"\x1B[M", -1, 0},
{ XK_KP_Delete, ControlMask, b"\x1B[3;5~", 1, 0},
{ XK_KP_Delete, ShiftMask, b"\x1B[2K", -1, 0},
{ XK_KP_Delete, ShiftMask, b"\x1B[3;2~", 1, 0},
{ XK_KP_Delete, XK_ANY_MOD, b"\x1B[P", -1, 0},
{ XK_KP_Delete, XK_ANY_MOD, b"\x1B[3~", 1, 0},
{ XK_KP_Multiply, XK_ANY_MOD, b"\x1BOj", 2, 0},
{ XK_KP_Add, XK_ANY_MOD, b"\x1BOk", 2, 0},
{ XK_KP_Enter, XK_ANY_MOD, b"\x1BOM", 2, 0},
{ XK_KP_Enter, XK_ANY_MOD, b"\r", -1, 0},
{ XK_KP_Subtract, XK_ANY_MOD, b"\x1BOm", 2, 0},
{ XK_KP_Decimal, XK_ANY_MOD, b"\x1BOn", 2, 0},
{ XK_KP_Divide, XK_ANY_MOD, b"\x1BOo", 2, 0},
{ XK_KP_0, XK_ANY_MOD, b"\x1BOp", 2, 0},
{ XK_KP_1, XK_ANY_MOD, b"\x1BOq", 2, 0},
{ XK_KP_2, XK_ANY_MOD, b"\x1BOr", 2, 0},
{ XK_KP_3, XK_ANY_MOD, b"\x1BOs", 2, 0},
{ XK_KP_4, XK_ANY_MOD, b"\x1BOt", 2, 0},
{ XK_KP_5, XK_ANY_MOD, b"\x1BOu", 2, 0},
{ XK_KP_6, XK_ANY_MOD, b"\x1BOv", 2, 0},
{ XK_KP_7, XK_ANY_MOD, b"\x1BOw", 2, 0},
{ XK_KP_8, XK_ANY_MOD, b"\x1BOx", 2, 0},
{ XK_KP_9, XK_ANY_MOD, b"\x1BOy", 2, 0},
{ XK_Up, ShiftMask, b"\x1B[1;2A", 0, 0},
{ XK_Up, Mod1Mask, b"\x1B[1;3A", 0, 0},
{ XK_Up, ShiftMask|Mod1Mask,b"\x1B[1;4A", 0, 0},
{ XK_Up, ControlMask, b"\x1B[1;5A", 0, 0},
{ XK_Up, ShiftMask|ControlMask,b"\x1B[1;6A", 0, 0},
{ XK_Up, ControlMask|Mod1Mask,b"\x1B[1;7A", 0, 0},
{ XK_Up,ShiftMask|ControlMask|Mod1Mask,b"\x1B[1;8A", 0, 0},
{ XK_Up, XK_ANY_MOD, b"\x1B[A", 0, -1},
{ XK_Up, XK_ANY_MOD, b"\x1BOA", 0, 1},
{ XK_Down, ShiftMask, b"\x1B[1;2B", 0, 0},
{ XK_Down, Mod1Mask, b"\x1B[1;3B", 0, 0},
{ XK_Down, ShiftMask|Mod1Mask,b"\x1B[1;4B", 0, 0},
{ XK_Down, ControlMask, b"\x1B[1;5B", 0, 0},
{ XK_Down, ShiftMask|ControlMask,b"\x1B[1;6B", 0, 0},
{ XK_Down, ControlMask|Mod1Mask,b"\x1B[1;7B", 0, 0},
{ XK_Down,ShiftMask|ControlMask|Mod1Mask,b"\x1B[1;8B",0, 0},
{ XK_Down, XK_ANY_MOD, b"\x1B[B", 0, -1},
{ XK_Down, XK_ANY_MOD, b"\x1BOB", 0, 1},
{ XK_Left, ShiftMask, b"\x1B[1;2D", 0, 0},
{ XK_Left, Mod1Mask, b"\x1B[1;3D", 0, 0},
{ XK_Left, ShiftMask|Mod1Mask,b"\x1B[1;4D", 0, 0},
{ XK_Left, ControlMask, b"\x1B[1;5D", 0, 0},
{ XK_Left, ShiftMask|ControlMask,b"\x1B[1;6D", 0, 0},
{ XK_Left, ControlMask|Mod1Mask,b"\x1B[1;7D", 0, 0},
{ XK_Left,ShiftMask|ControlMask|Mod1Mask,b"\x1B[1;8D",0, 0},
{ XK_Left, XK_ANY_MOD, b"\x1B[D", 0, -1},
{ XK_Left, XK_ANY_MOD, b"\x1BOD", 0, 1},
{ XK_Right, ShiftMask, b"\x1B[1;2C", 0, 0},
{ XK_Right, Mod1Mask, b"\x1B[1;3C", 0, 0},
{ XK_Right, ShiftMask|Mod1Mask,b"\x1B[1;4C", 0, 0},
{ XK_Right, ControlMask, b"\x1B[1;5C", 0, 0},
{ XK_Right, ShiftMask|ControlMask,b"\x1B[1;6C", 0, 0},
{ XK_Right, ControlMask|Mod1Mask,b"\x1B[1;7C", 0, 0},
{ XK_Right,ShiftMask|ControlMask|Mod1Mask,b"\x1B[1;8C",0, 0},
{ XK_Right, XK_ANY_MOD, b"\x1B[C", 0, -1},
{ XK_Right, XK_ANY_MOD, b"\x1BOC", 0, 1},
{ XK_ISO_Left_Tab, ShiftMask, b"\x1B[Z", 0, 0},
{ XK_Return, Mod1Mask, b"\x1B\r", 0, 0},
{ XK_Return, XK_ANY_MOD, b"\r", 0, 0},
{ XK_Insert, ShiftMask, b"\x1B[4l", -1, 0},
{ XK_Insert, ShiftMask, b"\x1B[2;2~", 1, 0},
{ XK_Insert, ControlMask, b"\x1B[L", -1, 0},
{ XK_Insert, ControlMask, b"\x1B[2;5~", 1, 0},
{ XK_Insert, XK_ANY_MOD, b"\x1B[4h", -1, 0},
{ XK_Insert, XK_ANY_MOD, b"\x1B[2~", 1, 0},
{ XK_Delete, ControlMask, b"\x1B[M", -1, 0},
{ XK_Delete, ControlMask, b"\x1B[3;5~", 1, 0},
{ XK_Delete, ShiftMask, b"\x1B[2K", -1, 0},
{ XK_Delete, ShiftMask, b"\x1B[3;2~", 1, 0},
{ XK_Delete, XK_ANY_MOD, b"\x1B[P", -1, 0},
{ XK_Delete, XK_ANY_MOD, b"\x1B[3~", 1, 0},
{ XK_BackSpace, XK_NO_MOD, b"\x7F", 0, 0},
{ XK_BackSpace, Mod1Mask, b"\x1B\x7F", 0, 0},
{ XK_Home, ShiftMask, b"\x1B[2J", 0, -1},
{ XK_Home, ShiftMask, b"\x1B[1;2H", 0, 1},
{ XK_Home, XK_ANY_MOD, b"\x1B[H", 0, -1},
{ XK_Home, XK_ANY_MOD, b"\x1B[1~", 0, 1},
{ XK_End, ControlMask, b"\x1B[J", -1, 0},
{ XK_End, ControlMask, b"\x1B[1;5F", 1, 0},
{ XK_End, ShiftMask, b"\x1B[K", -1, 0},
{ XK_End, ShiftMask, b"\x1B[1;2F", 1, 0},
{ XK_End, XK_ANY_MOD, b"\x1B[4~", 0, 0},
{ XK_Prior, ControlMask, b"\x1B[5;5~", 0, 0},
{ XK_Prior, ShiftMask, b"\x1B[5;2~", 0, 0},
{ XK_Prior, XK_ANY_MOD, b"\x1B[5~", 0, 0},
{ XK_Next, ControlMask, b"\x1B[6;5~", 0, 0},
{ XK_Next, ShiftMask, b"\x1B[6;2~", 0, 0},
{ XK_Next, XK_ANY_MOD, b"\x1B[6~", 0, 0},
{ XK_F1, XK_NO_MOD, b"\x1BOP" , 0, 0},
{ XK_F1, ShiftMask, b"\x1B[1;2P", 0, 0},
{ XK_F1, ControlMask, b"\x1B[1;5P", 0, 0},
{ XK_F1, Mod4Mask, b"\x1B[1;6P", 0, 0},
{ XK_F1, Mod1Mask, b"\x1B[1;3P", 0, 0},
{ XK_F1, Mod3Mask, b"\x1B[1;4P", 0, 0},
{ XK_F2, XK_NO_MOD, b"\x1BOQ" , 0, 0},
{ XK_F2, ShiftMask, b"\x1B[1;2Q", 0, 0},
{ XK_F2, ControlMask, b"\x1B[1;5Q", 0, 0},
{ XK_F2, Mod4Mask, b"\x1B[1;6Q", 0, 0},
{ XK_F2, Mod1Mask, b"\x1B[1;3Q", 0, 0},
{ XK_F2, Mod3Mask, b"\x1B[1;4Q", 0, 0},
{ XK_F3, XK_NO_MOD, b"\x1BOR" , 0, 0},
{ XK_F3, ShiftMask, b"\x1B[1;2R", 0, 0},
{ XK_F3, ControlMask, b"\x1B[1;5R", 0, 0},
{ XK_F3, Mod4Mask, b"\x1B[1;6R", 0, 0},
{ XK_F3, Mod1Mask, b"\x1B[1;3R", 0, 0},
{ XK_F3, Mod3Mask, b"\x1B[1;4R", 0, 0},
{ XK_F4, XK_NO_MOD, b"\x1BOS" , 0, 0},
{ XK_F4, ShiftMask, b"\x1B[1;2S", 0, 0},
{ XK_F4, ControlMask, b"\x1B[1;5S", 0, 0},
{ XK_F4, Mod4Mask, b"\x1B[1;6S", 0, 0},
{ XK_F4, Mod1Mask, b"\x1B[1;3S", 0, 0},
{ XK_F5, XK_NO_MOD, b"\x1B[15~", 0, 0},
{ XK_F5, ShiftMask, b"\x1B[15;2~", 0, 0},
{ XK_F5, ControlMask, b"\x1B[15;5~", 0, 0},
{ XK_F5, Mod4Mask, b"\x1B[15;6~", 0, 0},
{ XK_F5, Mod1Mask, b"\x1B[15;3~", 0, 0},
{ XK_F6, XK_NO_MOD, b"\x1B[17~", 0, 0},
{ XK_F6, ShiftMask, b"\x1B[17;2~", 0, 0},
{ XK_F6, ControlMask, b"\x1B[17;5~", 0, 0},
{ XK_F6, Mod4Mask, b"\x1B[17;6~", 0, 0},
{ XK_F6, Mod1Mask, b"\x1B[17;3~", 0, 0},
{ XK_F7, XK_NO_MOD, b"\x1B[18~", 0, 0},
{ XK_F7, ShiftMask, b"\x1B[18;2~", 0, 0},
{ XK_F7, ControlMask, b"\x1B[18;5~", 0, 0},
{ XK_F7, Mod4Mask, b"\x1B[18;6~", 0, 0},
{ XK_F7, Mod1Mask, b"\x1B[18;3~", 0, 0},
{ XK_F8, XK_NO_MOD, b"\x1B[19~", 0, 0},
{ XK_F8, ShiftMask, b"\x1B[19;2~", 0, 0},
{ XK_F8, ControlMask, b"\x1B[19;5~", 0, 0},
{ XK_F8, Mod4Mask, b"\x1B[19;6~", 0, 0},
{ XK_F8, Mod1Mask, b"\x1B[19;3~", 0, 0},
{ XK_F9, XK_NO_MOD, b"\x1B[20~", 0, 0},
{ XK_F9, ShiftMask, b"\x1B[20;2~", 0, 0},
{ XK_F9, ControlMask, b"\x1B[20;5~", 0, 0},
{ XK_F9, Mod4Mask, b"\x1B[20;6~", 0, 0},
{ XK_F9, Mod1Mask, b"\x1B[20;3~", 0, 0},
{ XK_F10, XK_NO_MOD, b"\x1B[21~", 0, 0},
{ XK_F10, ShiftMask, b"\x1B[21;2~", 0, 0},
{ XK_F10, ControlMask, b"\x1B[21;5~", 0, 0},
{ XK_F10, Mod4Mask, b"\x1B[21;6~", 0, 0},
{ XK_F10, Mod1Mask, b"\x1B[21;3~", 0, 0},
{ XK_F11, XK_NO_MOD, b"\x1B[23~", 0, 0},
{ XK_F11, ShiftMask, b"\x1B[23;2~", 0, 0},
{ XK_F11, ControlMask, b"\x1B[23;5~", 0, 0},
{ XK_F11, Mod4Mask, b"\x1B[23;6~", 0, 0},
{ XK_F11, Mod1Mask, b"\x1B[23;3~", 0, 0},
{ XK_F12, XK_NO_MOD, b"\x1B[24~", 0, 0},
{ XK_F12, ShiftMask, b"\x1B[24;2~", 0, 0},
{ XK_F12, ControlMask, b"\x1B[24;5~", 0, 0},
{ XK_F12, Mod4Mask, b"\x1B[24;6~", 0, 0},
{ XK_F12, Mod1Mask, b"\x1B[24;3~", 0, 0},
{ XK_F13, XK_NO_MOD, b"\x1B[1;2P", 0, 0},
{ XK_F14, XK_NO_MOD, b"\x1B[1;2Q", 0, 0},
{ XK_F15, XK_NO_MOD, b"\x1B[1;2R", 0, 0},
{ XK_F16, XK_NO_MOD, b"\x1B[1;2S", 0, 0},
{ XK_F17, XK_NO_MOD, b"\x1B[15;2~", 0, 0},
{ XK_F18, XK_NO_MOD, b"\x1B[17;2~", 0, 0},
{ XK_F19, XK_NO_MOD, b"\x1B[18;2~", 0, 0},
{ XK_F20, XK_NO_MOD, b"\x1B[19;2~", 0, 0},
{ XK_F21, XK_NO_MOD, b"\x1B[20;2~", 0, 0},
{ XK_F22, XK_NO_MOD, b"\x1B[21;2~", 0, 0},
{ XK_F23, XK_NO_MOD, b"\x1B[23;2~", 0, 0},
{ XK_F24, XK_NO_MOD, b"\x1B[24;2~", 0, 0},
{ XK_F25, XK_NO_MOD, b"\x1B[1;5P", 0, 0},
{ XK_F26, XK_NO_MOD, b"\x1B[1;5Q", 0, 0},
{ XK_F27, XK_NO_MOD, b"\x1B[1;5R", 0, 0},
{ XK_F28, XK_NO_MOD, b"\x1B[1;5S", 0, 0},
{ XK_F29, XK_NO_MOD, b"\x1B[15;5~", 0, 0},
{ XK_F30, XK_NO_MOD, b"\x1B[17;5~", 0, 0},
{ XK_F31, XK_NO_MOD, b"\x1B[18;5~", 0, 0},
{ XK_F32, XK_NO_MOD, b"\x1B[19;5~", 0, 0},
{ XK_F33, XK_NO_MOD, b"\x1B[20;5~", 0, 0},
{ XK_F34, XK_NO_MOD, b"\x1B[21;5~", 0, 0},
{ XK_F35, XK_NO_MOD, b"\x1B[23;5~", 0, 0},
};
#[allow(clippy::collapsible_else_if)]
pub fn map_key(k: KeySym, state: c_uint, mode: &WinMode) -> Option<&'static [u8]> {
let k = k as c_uint;
if k & 0xFFFF < 0xFD00 {
return None;
}
let state = state & !IGNORE_MOD;
let numlock = mode.contains(WinMode::NUMLOCK);
let appkeypad = mode.contains(WinMode::APPKEYPAD);
let appcursor = mode.contains(WinMode::APPCURSOR);
for key in KEYS {
if key.k != k {
continue;
}
if key.mask != XK_ANY_MOD && key.mask != state {
continue;
}
if numlock && key.appkeypad == 2 {
continue;
}
if appkeypad {
if key.appkeypad < 0 {
continue;
}
} else {
if key.appkeypad > 0 {
continue;
}
}
if appcursor {
if key.appcursor < 0 {
continue;
}
} else {
if key.appcursor > 0 {
continue;
}
}
return Some(key.s);
}
None
}