File indexing completed on 2024-04-14 03:55:49

0001 /*
0002     SPDX-FileCopyrightText: 2008 Erlend Hamberg <ehamberg@gmail.com>
0003     SPDX-FileCopyrightText: 2008 Evgeniy Ivanov <powerfox@kde.ru>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "definitions.h"
0009 #include <QKeyEvent>
0010 #include <QStringList>
0011 #include <vimode/keyevent.h>
0012 #include <vimode/keyparser.h>
0013 
0014 using namespace KateVi;
0015 
0016 KeyParser *KeyParser::m_instance = nullptr;
0017 
0018 KeyParser::KeyParser()
0019 {
0020     initKeyTables();
0021 }
0022 
0023 KeyParser *KeyParser::self()
0024 {
0025     if (m_instance == nullptr) {
0026         m_instance = new KeyParser();
0027     }
0028 
0029     return m_instance;
0030 }
0031 
0032 void KeyParser::initKeyTables()
0033 {
0034     m_qt2katevi = {
0035         {Qt::Key_Escape, QStringLiteral("esc")},
0036         {Qt::Key_Tab, QStringLiteral("tab")},
0037         {Qt::Key_Backtab, QStringLiteral("backtab")},
0038         {Qt::Key_Backspace, QStringLiteral("backspace")},
0039         {Qt::Key_Return, QStringLiteral("return")},
0040         {Qt::Key_Enter, QStringLiteral("enter")},
0041         {Qt::Key_Insert, QStringLiteral("insert")},
0042         {Qt::Key_Delete, QStringLiteral("delete")},
0043         {Qt::Key_Pause, QStringLiteral("pause")},
0044         {Qt::Key_Print, QStringLiteral("print")},
0045         {Qt::Key_SysReq, QStringLiteral("sysreq")},
0046         {Qt::Key_Clear, QStringLiteral("clear")},
0047         {Qt::Key_Home, QStringLiteral("home")},
0048         {Qt::Key_End, QStringLiteral("end")},
0049         {Qt::Key_Left, QStringLiteral("left")},
0050         {Qt::Key_Up, QStringLiteral("up")},
0051         {Qt::Key_Right, QStringLiteral("right")},
0052         {Qt::Key_Down, QStringLiteral("down")},
0053         {Qt::Key_PageUp, QStringLiteral("pageup")},
0054         {Qt::Key_PageDown, QStringLiteral("pagedown")},
0055         {Qt::Key_Shift, QStringLiteral("shift")},
0056         {Qt::Key_Control, QStringLiteral("control")},
0057         {Qt::Key_Meta, QStringLiteral("meta")},
0058         {Qt::Key_Alt, QStringLiteral("alt")},
0059         {Qt::Key_AltGr, QStringLiteral("altgr")},
0060         {Qt::Key_CapsLock, QStringLiteral("capslock")},
0061         {Qt::Key_NumLock, QStringLiteral("numlock")},
0062         {Qt::Key_ScrollLock, QStringLiteral("scrolllock")},
0063         {Qt::Key_F1, QStringLiteral("f1")},
0064         {Qt::Key_F2, QStringLiteral("f2")},
0065         {Qt::Key_F3, QStringLiteral("f3")},
0066         {Qt::Key_F4, QStringLiteral("f4")},
0067         {Qt::Key_F5, QStringLiteral("f5")},
0068         {Qt::Key_F6, QStringLiteral("f6")},
0069         {Qt::Key_F7, QStringLiteral("f7")},
0070         {Qt::Key_F8, QStringLiteral("f8")},
0071         {Qt::Key_F9, QStringLiteral("f9")},
0072         {Qt::Key_F10, QStringLiteral("f10")},
0073         {Qt::Key_F11, QStringLiteral("f11")},
0074         {Qt::Key_F12, QStringLiteral("f12")},
0075         {Qt::Key_F13, QStringLiteral("f13")},
0076         {Qt::Key_F14, QStringLiteral("f14")},
0077         {Qt::Key_F15, QStringLiteral("f15")},
0078         {Qt::Key_F16, QStringLiteral("f16")},
0079         {Qt::Key_F17, QStringLiteral("f17")},
0080         {Qt::Key_F18, QStringLiteral("f18")},
0081         {Qt::Key_F19, QStringLiteral("f19")},
0082         {Qt::Key_F20, QStringLiteral("f20")},
0083         {Qt::Key_F21, QStringLiteral("f21")},
0084         {Qt::Key_F22, QStringLiteral("f22")},
0085         {Qt::Key_F23, QStringLiteral("f23")},
0086         {Qt::Key_F24, QStringLiteral("f24")},
0087         {Qt::Key_F25, QStringLiteral("f25")},
0088         {Qt::Key_F26, QStringLiteral("f26")},
0089         {Qt::Key_F27, QStringLiteral("f27")},
0090         {Qt::Key_F28, QStringLiteral("f28")},
0091         {Qt::Key_F29, QStringLiteral("f29")},
0092         {Qt::Key_F30, QStringLiteral("f30")},
0093         {Qt::Key_F31, QStringLiteral("f31")},
0094         {Qt::Key_F32, QStringLiteral("f32")},
0095         {Qt::Key_F33, QStringLiteral("f33")},
0096         {Qt::Key_F34, QStringLiteral("f34")},
0097         {Qt::Key_F35, QStringLiteral("f35")},
0098         {Qt::Key_Super_L, QStringLiteral("super_l")},
0099         {Qt::Key_Super_R, QStringLiteral("super_r")},
0100         {Qt::Key_Menu, QStringLiteral("menu")},
0101         {Qt::Key_Hyper_L, QStringLiteral("hyper_l")},
0102         {Qt::Key_Hyper_R, QStringLiteral("hyper_r")},
0103         {Qt::Key_Help, QStringLiteral("help")},
0104         {Qt::Key_Direction_L, QStringLiteral("direction_l")},
0105         {Qt::Key_Direction_R, QStringLiteral("direction_r")},
0106         {Qt::Key_Multi_key, QStringLiteral("multi_key")},
0107         {Qt::Key_Codeinput, QStringLiteral("codeinput")},
0108         {Qt::Key_SingleCandidate, QStringLiteral("singlecandidate")},
0109         {Qt::Key_MultipleCandidate, QStringLiteral("multiplecandidate")},
0110         {Qt::Key_PreviousCandidate, QStringLiteral("previouscandidate")},
0111         {Qt::Key_Mode_switch, QStringLiteral("mode_switch")},
0112         {Qt::Key_Kanji, QStringLiteral("kanji")},
0113         {Qt::Key_Muhenkan, QStringLiteral("muhenkan")},
0114         {Qt::Key_Henkan, QStringLiteral("henkan")},
0115         {Qt::Key_Romaji, QStringLiteral("romaji")},
0116         {Qt::Key_Hiragana, QStringLiteral("hiragana")},
0117         {Qt::Key_Katakana, QStringLiteral("katakana")},
0118         {Qt::Key_Hiragana_Katakana, QStringLiteral("hiragana_katakana")},
0119         {Qt::Key_Zenkaku, QStringLiteral("zenkaku")},
0120         {Qt::Key_Hankaku, QStringLiteral("hankaku")},
0121         {Qt::Key_Zenkaku_Hankaku, QStringLiteral("zenkaku_hankaku")},
0122         {Qt::Key_Touroku, QStringLiteral("touroku")},
0123         {Qt::Key_Massyo, QStringLiteral("massyo")},
0124         {Qt::Key_Kana_Lock, QStringLiteral("kana_lock")},
0125         {Qt::Key_Kana_Shift, QStringLiteral("kana_shift")},
0126         {Qt::Key_Eisu_Shift, QStringLiteral("eisu_shift")},
0127         {Qt::Key_Eisu_toggle, QStringLiteral("eisu_toggle")},
0128         {Qt::Key_Hangul, QStringLiteral("hangul")},
0129         {Qt::Key_Hangul_Start, QStringLiteral("hangul_start")},
0130         {Qt::Key_Hangul_End, QStringLiteral("hangul_end")},
0131         {Qt::Key_Hangul_Hanja, QStringLiteral("hangul_hanja")},
0132         {Qt::Key_Hangul_Jamo, QStringLiteral("hangul_jamo")},
0133         {Qt::Key_Hangul_Romaja, QStringLiteral("hangul_romaja")},
0134         {Qt::Key_Hangul_Jeonja, QStringLiteral("hangul_jeonja")},
0135         {Qt::Key_Hangul_Banja, QStringLiteral("hangul_banja")},
0136         {Qt::Key_Hangul_PreHanja, QStringLiteral("hangul_prehanja")},
0137         {Qt::Key_Hangul_PostHanja, QStringLiteral("hangul_posthanja")},
0138         {Qt::Key_Hangul_Special, QStringLiteral("hangul_special")},
0139         {Qt::Key_Dead_Grave, QStringLiteral("dead_grave")},
0140         {Qt::Key_Dead_Acute, QStringLiteral("dead_acute")},
0141         {Qt::Key_Dead_Circumflex, QStringLiteral("dead_circumflex")},
0142         {Qt::Key_Dead_Tilde, QStringLiteral("dead_tilde")},
0143         {Qt::Key_Dead_Macron, QStringLiteral("dead_macron")},
0144         {Qt::Key_Dead_Breve, QStringLiteral("dead_breve")},
0145         {Qt::Key_Dead_Abovedot, QStringLiteral("dead_abovedot")},
0146         {Qt::Key_Dead_Diaeresis, QStringLiteral("dead_diaeresis")},
0147         {Qt::Key_Dead_Abovering, QStringLiteral("dead_abovering")},
0148         {Qt::Key_Dead_Doubleacute, QStringLiteral("dead_doubleacute")},
0149         {Qt::Key_Dead_Caron, QStringLiteral("dead_caron")},
0150         {Qt::Key_Dead_Cedilla, QStringLiteral("dead_cedilla")},
0151         {Qt::Key_Dead_Ogonek, QStringLiteral("dead_ogonek")},
0152         {Qt::Key_Dead_Iota, QStringLiteral("dead_iota")},
0153         {Qt::Key_Dead_Voiced_Sound, QStringLiteral("dead_voiced_sound")},
0154         {Qt::Key_Dead_Semivoiced_Sound, QStringLiteral("dead_semivoiced_sound")},
0155         {Qt::Key_Dead_Belowdot, QStringLiteral("dead_belowdot")},
0156         {Qt::Key_Dead_Hook, QStringLiteral("dead_hook")},
0157         {Qt::Key_Dead_Horn, QStringLiteral("dead_horn")},
0158         {Qt::Key_Back, QStringLiteral("back")},
0159         {Qt::Key_Forward, QStringLiteral("forward")},
0160         {Qt::Key_Stop, QStringLiteral("stop")},
0161         {Qt::Key_Refresh, QStringLiteral("refresh")},
0162         {Qt::Key_VolumeDown, QStringLiteral("volumedown")},
0163         {Qt::Key_VolumeMute, QStringLiteral("volumemute")},
0164         {Qt::Key_VolumeUp, QStringLiteral("volumeup")},
0165         {Qt::Key_BassBoost, QStringLiteral("bassboost")},
0166         {Qt::Key_BassUp, QStringLiteral("bassup")},
0167         {Qt::Key_BassDown, QStringLiteral("bassdown")},
0168         {Qt::Key_TrebleUp, QStringLiteral("trebleup")},
0169         {Qt::Key_TrebleDown, QStringLiteral("trebledown")},
0170         {Qt::Key_MediaPlay, QStringLiteral("mediaplay")},
0171         {Qt::Key_MediaStop, QStringLiteral("mediastop")},
0172         {Qt::Key_MediaPrevious, QStringLiteral("mediaprevious")},
0173         {Qt::Key_MediaNext, QStringLiteral("medianext")},
0174         {Qt::Key_MediaRecord, QStringLiteral("mediarecord")},
0175         {Qt::Key_HomePage, QStringLiteral("homepage")},
0176         {Qt::Key_Favorites, QStringLiteral("favorites")},
0177         {Qt::Key_Search, QStringLiteral("search")},
0178         {Qt::Key_Standby, QStringLiteral("standby")},
0179         {Qt::Key_OpenUrl, QStringLiteral("openurl")},
0180         {Qt::Key_LaunchMail, QStringLiteral("launchmail")},
0181         {Qt::Key_LaunchMedia, QStringLiteral("launchmedia")},
0182         {Qt::Key_Launch0, QStringLiteral("launch0")},
0183         {Qt::Key_Launch1, QStringLiteral("launch1")},
0184         {Qt::Key_Launch2, QStringLiteral("launch2")},
0185         {Qt::Key_Launch3, QStringLiteral("launch3")},
0186         {Qt::Key_Launch4, QStringLiteral("launch4")},
0187         {Qt::Key_Launch5, QStringLiteral("launch5")},
0188         {Qt::Key_Launch6, QStringLiteral("launch6")},
0189         {Qt::Key_Launch7, QStringLiteral("launch7")},
0190         {Qt::Key_Launch8, QStringLiteral("launch8")},
0191         {Qt::Key_Launch9, QStringLiteral("launch9")},
0192         {Qt::Key_LaunchA, QStringLiteral("launcha")},
0193         {Qt::Key_LaunchB, QStringLiteral("launchb")},
0194         {Qt::Key_LaunchC, QStringLiteral("launchc")},
0195         {Qt::Key_LaunchD, QStringLiteral("launchd")},
0196         {Qt::Key_LaunchE, QStringLiteral("launche")},
0197         {Qt::Key_LaunchF, QStringLiteral("launchf")},
0198         {Qt::Key_MediaLast, QStringLiteral("medialast")},
0199         {Qt::Key_unknown, QStringLiteral("unknown")},
0200         {Qt::Key_Call, QStringLiteral("call")},
0201         {Qt::Key_Context1, QStringLiteral("context1")},
0202         {Qt::Key_Context2, QStringLiteral("context2")},
0203         {Qt::Key_Context3, QStringLiteral("context3")},
0204         {Qt::Key_Context4, QStringLiteral("context4")},
0205         {Qt::Key_Flip, QStringLiteral("flip")},
0206         {Qt::Key_Hangup, QStringLiteral("hangup")},
0207         {Qt::Key_No, QStringLiteral("no")},
0208         {Qt::Key_Select, QStringLiteral("select")},
0209         {Qt::Key_Yes, QStringLiteral("yes")},
0210         {Qt::Key_Execute, QStringLiteral("execute")},
0211         {Qt::Key_Printer, QStringLiteral("printer")},
0212         {Qt::Key_Play, QStringLiteral("play")},
0213         {Qt::Key_Sleep, QStringLiteral("sleep")},
0214         {Qt::Key_Zoom, QStringLiteral("zoom")},
0215         {Qt::Key_Cancel, QStringLiteral("cancel")},
0216     };
0217 
0218     for (QHash<int, QString>::const_iterator i = m_qt2katevi.constBegin(); i != m_qt2katevi.constEnd(); ++i) {
0219         m_katevi2qt.insert(i.value(), i.key());
0220     }
0221     m_katevi2qt.insert(QStringLiteral("cr"), Qt::Key_Enter);
0222 
0223     m_nameToKeyCode = {
0224         {QStringLiteral("invalid"), -1},
0225         {QStringLiteral("esc"), 1},
0226         {QStringLiteral("tab"), 2},
0227         {QStringLiteral("backtab"), 3},
0228         {QStringLiteral("backspace"), 4},
0229         {QStringLiteral("return"), 5},
0230         {QStringLiteral("enter"), 6},
0231         {QStringLiteral("insert"), 7},
0232         {QStringLiteral("delete"), 8},
0233         {QStringLiteral("pause"), 9},
0234         {QStringLiteral("print"), 10},
0235         {QStringLiteral("sysreq"), 11},
0236         {QStringLiteral("clear"), 12},
0237         {QStringLiteral("home"), 13},
0238         {QStringLiteral("end"), 14},
0239         {QStringLiteral("left"), 15},
0240         {QStringLiteral("up"), 16},
0241         {QStringLiteral("right"), 17},
0242         {QStringLiteral("down"), 18},
0243         {QStringLiteral("pageup"), 19},
0244         {QStringLiteral("pagedown"), 20},
0245         {QStringLiteral("shift"), 21},
0246         {QStringLiteral("control"), 22},
0247         {QStringLiteral("meta"), 23},
0248         {QStringLiteral("alt"), 24},
0249         {QStringLiteral("altgr"), 25},
0250         {QStringLiteral("capslock"), 26},
0251         {QStringLiteral("numlock"), 27},
0252         {QStringLiteral("scrolllock"), 28},
0253         {QStringLiteral("f1"), 29},
0254         {QStringLiteral("f2"), 30},
0255         {QStringLiteral("f3"), 31},
0256         {QStringLiteral("f4"), 32},
0257         {QStringLiteral("f5"), 33},
0258         {QStringLiteral("f6"), 34},
0259         {QStringLiteral("f7"), 35},
0260         {QStringLiteral("f8"), 36},
0261         {QStringLiteral("f9"), 37},
0262         {QStringLiteral("f10"), 38},
0263         {QStringLiteral("f11"), 39},
0264         {QStringLiteral("f12"), 40},
0265         {QStringLiteral("f13"), 41},
0266         {QStringLiteral("f14"), 42},
0267         {QStringLiteral("f15"), 43},
0268         {QStringLiteral("f16"), 44},
0269         {QStringLiteral("f17"), 45},
0270         {QStringLiteral("f18"), 46},
0271         {QStringLiteral("f19"), 47},
0272         {QStringLiteral("f20"), 48},
0273         {QStringLiteral("f21"), 49},
0274         {QStringLiteral("f22"), 50},
0275         {QStringLiteral("f23"), 51},
0276         {QStringLiteral("f24"), 52},
0277         {QStringLiteral("f25"), 53},
0278         {QStringLiteral("f26"), 54},
0279         {QStringLiteral("f27"), 55},
0280         {QStringLiteral("f28"), 56},
0281         {QStringLiteral("f29"), 57},
0282         {QStringLiteral("f30"), 58},
0283         {QStringLiteral("f31"), 59},
0284         {QStringLiteral("f32"), 60},
0285         {QStringLiteral("f33"), 61},
0286         {QStringLiteral("f34"), 62},
0287         {QStringLiteral("f35"), 63},
0288         {QStringLiteral("super_l"), 64},
0289         {QStringLiteral("super_r"), 65},
0290         {QStringLiteral("menu"), 66},
0291         {QStringLiteral("hyper_l"), 67},
0292         {QStringLiteral("hyper_r"), 68},
0293         {QStringLiteral("help"), 69},
0294         {QStringLiteral("direction_l"), 70},
0295         {QStringLiteral("direction_r"), 71},
0296         {QStringLiteral("multi_key"), 172},
0297         {QStringLiteral("codeinput"), 173},
0298         {QStringLiteral("singlecandidate"), 174},
0299         {QStringLiteral("multiplecandidate"), 175},
0300         {QStringLiteral("previouscandidate"), 176},
0301         {QStringLiteral("mode_switch"), 177},
0302         {QStringLiteral("kanji"), 178},
0303         {QStringLiteral("muhenkan"), 179},
0304         {QStringLiteral("henkan"), 180},
0305         {QStringLiteral("romaji"), 181},
0306         {QStringLiteral("hiragana"), 182},
0307         {QStringLiteral("katakana"), 183},
0308         {QStringLiteral("hiragana_katakana"), 184},
0309         {QStringLiteral("zenkaku"), 185},
0310         {QStringLiteral("hankaku"), 186},
0311         {QStringLiteral("zenkaku_hankaku"), 187},
0312         {QStringLiteral("touroku"), 188},
0313         {QStringLiteral("massyo"), 189},
0314         {QStringLiteral("kana_lock"), 190},
0315         {QStringLiteral("kana_shift"), 191},
0316         {QStringLiteral("eisu_shift"), 192},
0317         {QStringLiteral("eisu_toggle"), 193},
0318         {QStringLiteral("hangul"), 194},
0319         {QStringLiteral("hangul_start"), 195},
0320         {QStringLiteral("hangul_end"), 196},
0321         {QStringLiteral("hangul_hanja"), 197},
0322         {QStringLiteral("hangul_jamo"), 198},
0323         {QStringLiteral("hangul_romaja"), 199},
0324         {QStringLiteral("hangul_jeonja"), 200},
0325         {QStringLiteral("hangul_banja"), 201},
0326         {QStringLiteral("hangul_prehanja"), 202},
0327         {QStringLiteral("hangul_posthanja"), 203},
0328         {QStringLiteral("hangul_special"), 204},
0329         {QStringLiteral("dead_grave"), 205},
0330         {QStringLiteral("dead_acute"), 206},
0331         {QStringLiteral("dead_circumflex"), 207},
0332         {QStringLiteral("dead_tilde"), 208},
0333         {QStringLiteral("dead_macron"), 209},
0334         {QStringLiteral("dead_breve"), 210},
0335         {QStringLiteral("dead_abovedot"), 211},
0336         {QStringLiteral("dead_diaeresis"), 212},
0337         {QStringLiteral("dead_abovering"), 213},
0338         {QStringLiteral("dead_doubleacute"), 214},
0339         {QStringLiteral("dead_caron"), 215},
0340         {QStringLiteral("dead_cedilla"), 216},
0341         {QStringLiteral("dead_ogonek"), 217},
0342         {QStringLiteral("dead_iota"), 218},
0343         {QStringLiteral("dead_voiced_sound"), 219},
0344         {QStringLiteral("dead_semivoiced_sound"), 220},
0345         {QStringLiteral("dead_belowdot"), 221},
0346         {QStringLiteral("dead_hook"), 222},
0347         {QStringLiteral("dead_horn"), 223},
0348         {QStringLiteral("back"), 224},
0349         {QStringLiteral("forward"), 225},
0350         {QStringLiteral("stop"), 226},
0351         {QStringLiteral("refresh"), 227},
0352         {QStringLiteral("volumedown"), 228},
0353         {QStringLiteral("volumemute"), 229},
0354         {QStringLiteral("volumeup"), 230},
0355         {QStringLiteral("bassboost"), 231},
0356         {QStringLiteral("bassup"), 232},
0357         {QStringLiteral("bassdown"), 233},
0358         {QStringLiteral("trebleup"), 234},
0359         {QStringLiteral("trebledown"), 235},
0360         {QStringLiteral("mediaplay"), 236},
0361         {QStringLiteral("mediastop"), 237},
0362         {QStringLiteral("mediaprevious"), 238},
0363         {QStringLiteral("medianext"), 239},
0364         {QStringLiteral("mediarecord"), 240},
0365         {QStringLiteral("homepage"), 241},
0366         {QStringLiteral("favorites"), 242},
0367         {QStringLiteral("search"), 243},
0368         {QStringLiteral("standby"), 244},
0369         {QStringLiteral("openurl"), 245},
0370         {QStringLiteral("launchmail"), 246},
0371         {QStringLiteral("launchmedia"), 247},
0372         {QStringLiteral("launch0"), 248},
0373         {QStringLiteral("launch1"), 249},
0374         {QStringLiteral("launch2"), 250},
0375         {QStringLiteral("launch3"), 251},
0376         {QStringLiteral("launch4"), 252},
0377         {QStringLiteral("launch5"), 253},
0378         {QStringLiteral("launch6"), 254},
0379         {QStringLiteral("launch7"), 255},
0380         {QStringLiteral("launch8"), 256},
0381         {QStringLiteral("launch9"), 257},
0382         {QStringLiteral("launcha"), 258},
0383         {QStringLiteral("launchb"), 259},
0384         {QStringLiteral("launchc"), 260},
0385         {QStringLiteral("launchd"), 261},
0386         {QStringLiteral("launche"), 262},
0387         {QStringLiteral("launchf"), 263},
0388         {QStringLiteral("medialast"), 264},
0389         {QStringLiteral("unknown"), 265},
0390         {QStringLiteral("call"), 266},
0391         {QStringLiteral("context1"), 267},
0392         {QStringLiteral("context2"), 268},
0393         {QStringLiteral("context3"), 269},
0394         {QStringLiteral("context4"), 270},
0395         {QStringLiteral("flip"), 271},
0396         {QStringLiteral("hangup"), 272},
0397         {QStringLiteral("no"), 273},
0398         {QStringLiteral("select"), 274},
0399         {QStringLiteral("yes"), 275},
0400         {QStringLiteral("execute"), 276},
0401         {QStringLiteral("printer"), 277},
0402         {QStringLiteral("play"), 278},
0403         {QStringLiteral("sleep"), 279},
0404         {QStringLiteral("zoom"), 280},
0405         {QStringLiteral("cancel"), 281},
0406 
0407         {QStringLiteral("a"), 282},
0408         {QStringLiteral("b"), 283},
0409         {QStringLiteral("c"), 284},
0410         {QStringLiteral("d"), 285},
0411         {QStringLiteral("e"), 286},
0412         {QStringLiteral("f"), 287},
0413         {QStringLiteral("g"), 288},
0414         {QStringLiteral("h"), 289},
0415         {QStringLiteral("i"), 290},
0416         {QStringLiteral("j"), 291},
0417         {QStringLiteral("k"), 292},
0418         {QStringLiteral("l"), 293},
0419         {QStringLiteral("m"), 294},
0420         {QStringLiteral("n"), 295},
0421         {QStringLiteral("o"), 296},
0422         {QStringLiteral("p"), 297},
0423         {QStringLiteral("q"), 298},
0424         {QStringLiteral("r"), 299},
0425         {QStringLiteral("s"), 300},
0426         {QStringLiteral("t"), 301},
0427         {QStringLiteral("u"), 302},
0428         {QStringLiteral("v"), 303},
0429         {QStringLiteral("w"), 304},
0430         {QStringLiteral("x"), 305},
0431         {QStringLiteral("y"), 306},
0432         {QStringLiteral("z"), 307},
0433         {QStringLiteral("`"), 308},
0434         {QStringLiteral("!"), 309},
0435         {QStringLiteral("\""), 310},
0436         {QStringLiteral("$"), 311},
0437         {QStringLiteral("%"), 312},
0438         {QStringLiteral("^"), 313},
0439         {QStringLiteral("&"), 314},
0440         {QStringLiteral("*"), 315},
0441         {QStringLiteral("("), 316},
0442         {QStringLiteral(")"), 317},
0443         {QStringLiteral("-"), 318},
0444         {QStringLiteral("_"), 319},
0445         {QStringLiteral("="), 320},
0446         {QStringLiteral("+"), 321},
0447         {QStringLiteral("["), 322},
0448         {QStringLiteral("]"), 323},
0449         {QStringLiteral("{"), 324},
0450         {QStringLiteral("}"), 325},
0451         {QStringLiteral(":"), 326},
0452         {QStringLiteral(";"), 327},
0453         {QStringLiteral("@"), 328},
0454         {QStringLiteral("'"), 329},
0455         {QStringLiteral("#"), 330},
0456         {QStringLiteral("~"), 331},
0457         {QStringLiteral("\\"), 332},
0458         {QStringLiteral("|"), 333},
0459         {QStringLiteral(","), 334},
0460         {QStringLiteral("."), 335},
0461         // { QLatin1String( ">" ), 336 },
0462         {QStringLiteral("/"), 337},
0463         {QStringLiteral("?"), 338},
0464         {QStringLiteral(" "), 339},
0465         // { QLatin1String( "<" ), 341 },
0466         {QStringLiteral("0"), 340},
0467         {QStringLiteral("1"), 341},
0468         {QStringLiteral("2"), 342},
0469         {QStringLiteral("3"), 343},
0470         {QStringLiteral("4"), 344},
0471         {QStringLiteral("5"), 345},
0472         {QStringLiteral("6"), 346},
0473         {QStringLiteral("7"), 347},
0474         {QStringLiteral("8"), 348},
0475         {QStringLiteral("9"), 349},
0476         {QStringLiteral("cr"), 350},
0477         {QStringLiteral("leader"), 351},
0478         {QStringLiteral("nop"), 352},
0479     };
0480 
0481     for (QHash<QString, int>::const_iterator i = m_nameToKeyCode.constBegin(); i != m_nameToKeyCode.constEnd(); ++i) {
0482         m_keyCodeToName.insert(i.value(), i.key());
0483     }
0484 }
0485 
0486 QString KeyParser::qt2vi(int key) const
0487 {
0488     auto it = m_qt2katevi.constFind(key);
0489     if (it != m_qt2katevi.cend()) {
0490         return it.value();
0491     }
0492     return QStringLiteral("invalid");
0493 }
0494 
0495 int KeyParser::vi2qt(const QString &keypress) const
0496 {
0497     auto it = m_katevi2qt.constFind(keypress);
0498     if (it != m_katevi2qt.cend()) {
0499         return it.value();
0500     }
0501     return -1;
0502 }
0503 
0504 int KeyParser::encoded2qt(const QString &keypress) const
0505 {
0506     QString key = KeyParser::self()->decodeKeySequence(keypress);
0507 
0508     if (key.length() > 2 && key.at(0) == QLatin1Char('<') && key.at(key.length() - 1) == QLatin1Char('>')) {
0509         key = key.mid(1, key.length() - 2);
0510     }
0511     auto it = m_katevi2qt.constFind(key);
0512     if (it != m_katevi2qt.cend())
0513         return it.value();
0514     return -1;
0515 }
0516 
0517 const QString KeyParser::encodeKeySequence(const QString &keys) const
0518 {
0519     QString encodedSequence;
0520     unsigned int keyCodeTemp = 0;
0521 
0522     const QStringView keysView(keys);
0523     bool insideTag = false;
0524     QChar c;
0525     for (int i = 0; i < keys.length(); i++) {
0526         c = keys.at(i);
0527         if (insideTag) {
0528             if (c == QLatin1Char('>')) {
0529                 QChar code(0xE000 + keyCodeTemp);
0530                 encodedSequence.append(code);
0531                 keyCodeTemp = 0;
0532                 insideTag = false;
0533                 continue;
0534             } else {
0535                 // contains modifiers
0536                 if (keysView.mid(i).indexOf(QLatin1Char('-')) != -1 && keysView.mid(i).indexOf(QLatin1Char('-')) < keysView.mid(i).indexOf(QLatin1Char('>'))) {
0537                     // Perform something similar to a split on '-', except that we want to keep the occurrences of '-'
0538                     // e.g. <c-s-a> will equate to the list of tokens "c-", "s-", "a".
0539                     // A straight split on '-' would give us "c", "s", "a", in which case we lose the piece of information that
0540                     // 'a' is just the 'a' key, not the 'alt' modifier.
0541                     const QString untilClosing = keys.mid(i, keysView.mid(i).indexOf(QLatin1Char('>'))).toLower();
0542                     QStringList tokens;
0543                     int currentPos = 0;
0544                     int nextHypen = -1;
0545                     while ((nextHypen = untilClosing.indexOf(QLatin1Char('-'), currentPos)) != -1) {
0546                         tokens << untilClosing.mid(currentPos, nextHypen - currentPos + 1);
0547                         currentPos = nextHypen + 1;
0548                     }
0549                     tokens << untilClosing.mid(currentPos);
0550 
0551                     for (const QString &str : std::as_const(tokens)) {
0552                         if (str == QLatin1String("s-") && (keyCodeTemp & 0x01) != 0x1) {
0553                             keyCodeTemp += 0x1;
0554                         } else if (str == QLatin1String("c-") && (keyCodeTemp & 0x02) != 0x2) {
0555                             keyCodeTemp += 0x2;
0556                         } else if (str == QLatin1String("a-") && (keyCodeTemp & 0x04) != 0x4) {
0557                             keyCodeTemp += 0x4;
0558                         } else if (str == QLatin1String("m-") && (keyCodeTemp & 0x08) != 0x8) {
0559                             keyCodeTemp += 0x8;
0560                         } else {
0561                             if (m_nameToKeyCode.contains(str) || (str.length() == 1 && str.at(0).isLetterOrNumber())) {
0562                                 if (m_nameToKeyCode.contains(str)) {
0563                                     keyCodeTemp += m_nameToKeyCode.value(str) * 0x10;
0564                                 } else {
0565                                     keyCodeTemp += str.at(0).unicode() * 0x10;
0566                                 }
0567                             } else {
0568                                 int endOfBlock = keys.indexOf(QLatin1Char('>'));
0569                                 if (endOfBlock -= -1) {
0570                                     endOfBlock = keys.length() - 1;
0571                                 }
0572                                 encodedSequence.clear();
0573                                 encodedSequence.append(QChar(m_nameToKeyCode.value(QStringLiteral("invalid"))));
0574                                 break;
0575                             }
0576                         }
0577                     }
0578                 } else {
0579                     const QString str = keys.mid(i, keys.indexOf(QLatin1Char('>'), i) - i).toLower();
0580                     if (keys.indexOf(QLatin1Char('>'), i) != -1 && (m_nameToKeyCode.contains(str) || (str.length() == 1 && str.at(0).isLetterOrNumber()))) {
0581                         if (m_nameToKeyCode.contains(str)) {
0582                             keyCodeTemp += m_nameToKeyCode.value(str) * 0x10;
0583                         } else {
0584                             keyCodeTemp += str.at(0).unicode() * 0x10;
0585                         }
0586                     } else {
0587                         int endOfBlock = keys.indexOf(QLatin1Char('>'));
0588                         if (endOfBlock -= -1) {
0589                             endOfBlock = keys.length() - 1;
0590                         }
0591                         encodedSequence.clear();
0592                         keyCodeTemp = m_nameToKeyCode.value(QStringLiteral("invalid")) * 0x10;
0593                     }
0594                 }
0595                 i += keysView.mid(i, keysView.mid(i).indexOf(QLatin1Char('>'))).length() - 1;
0596             }
0597         } else {
0598             if (c == QLatin1Char('<')) {
0599                 // If there's no closing '>', or if there is an opening '<' before the next '>', interpret as a literal '<'
0600                 // If we are <space>, encode as a literal " ".
0601                 const QStringView rest = keysView.mid(i);
0602                 if (rest.indexOf(QLatin1Char('>'), 1) != -1 && rest.mid(1, rest.indexOf(QLatin1Char('>'), 1) - 1) == QLatin1String("space")) {
0603                     encodedSequence.append(QLatin1Char(' '));
0604                     i += rest.indexOf(QLatin1Char('>'), 1);
0605                     continue;
0606                 } else if (rest.indexOf(QLatin1Char('>'), 1) == -1
0607                            || (rest.indexOf(QLatin1Char('<'), 1) < rest.indexOf(QLatin1Char('>'), 1) && rest.indexOf(QLatin1Char('<'), 1) != -1)) {
0608                     encodedSequence.append(c);
0609                     continue;
0610                 }
0611                 insideTag = true;
0612                 continue;
0613             } else {
0614                 encodedSequence.append(c);
0615             }
0616         }
0617     }
0618 
0619     return encodedSequence;
0620 }
0621 
0622 const QString KeyParser::decodeKeySequence(const QString &keys) const
0623 {
0624     QString ret;
0625     ret.reserve(keys.length());
0626 
0627     for (int i = 0; i < keys.length(); i++) {
0628         QChar c = keys.at(i);
0629         int keycode = c.unicode();
0630 
0631         if ((keycode & 0xE000) != 0xE000) {
0632             ret.append(c);
0633         } else {
0634             ret.append(QLatin1Char('<'));
0635 
0636             if ((keycode & 0x1) == 0x1) {
0637                 ret.append(QLatin1String("s-"));
0638                 // keycode -= 0x1;
0639             }
0640             if ((keycode & 0x2) == 0x2) {
0641                 ret.append(QLatin1String("c-"));
0642                 // keycode -= 0x2;
0643             }
0644             if ((keycode & 0x4) == 0x4) {
0645                 ret.append(QLatin1String("a-"));
0646                 // keycode -= 0x4;
0647             }
0648             if ((keycode & 0x8) == 0x8) {
0649                 ret.append(QLatin1String("m-"));
0650                 // keycode -= 0x8;
0651             }
0652 
0653             if ((keycode & 0xE000) == 0xE000) {
0654                 ret.append(m_keyCodeToName.value((keycode - 0xE000) / 0x10));
0655             } else {
0656                 ret.append(QChar(keycode));
0657             }
0658             ret.append(QLatin1Char('>'));
0659         }
0660     }
0661 
0662     return ret;
0663 }
0664 
0665 const QChar KeyParser::KeyEventToQChar(const QKeyEvent &keyEvent)
0666 {
0667     return KeyEventToQChar(keyEvent.key(), keyEvent.text(), keyEvent.modifiers());
0668 }
0669 
0670 const QChar KeyParser::KeyEventToQChar(const KeyEvent &keyEvent)
0671 {
0672     return KeyEventToQChar(keyEvent.key(), keyEvent.text(), keyEvent.modifiers());
0673 }
0674 
0675 const QChar KeyParser::KeyEventToQChar(int keyCode, const QString &text, Qt::KeyboardModifiers mods) const
0676 {
0677     // If previous key press was AltGr, return key value right away and don't go
0678     // down the "handle modifiers" code path. AltGr is really confusing...
0679     if (mods & Qt::GroupSwitchModifier) {
0680         return (!text.isEmpty()) ? text.at(0) : QChar();
0681     }
0682 
0683     if (text.isEmpty() || (text.length() == 1 && text.at(0) < QChar(0x20)) || keyCode == Qt::Key_Delete
0684         || (mods != Qt::NoModifier && mods != Qt::ShiftModifier && mods != Qt::KeypadModifier)) {
0685         QString keyPress;
0686         keyPress.reserve(11);
0687 
0688         keyPress.append(QLatin1Char('<'));
0689         keyPress.append((mods & Qt::ShiftModifier) ? QStringLiteral("s-") : QString());
0690         keyPress.append((mods & CONTROL_MODIFIER) ? QStringLiteral("c-") : QString());
0691         keyPress.append((mods & Qt::AltModifier) ? QStringLiteral("a-") : QString());
0692         keyPress.append((mods & META_MODIFIER) ? QStringLiteral("m-") : QString());
0693         keyPress.append(keyCode <= 0xFF ? QChar(keyCode) : qt2vi(keyCode));
0694         keyPress.append(QLatin1Char('>'));
0695 
0696         return encodeKeySequence(keyPress).at(0);
0697     } else {
0698         return text.at(0);
0699     }
0700 }