ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

keys_basic_config.h (39217B)


      1 /*
      2  * These are all the regular keys used in normal, visual, and insert mode.
      3  */
      4 
      5 /*
      6  * Note: The key types are currently very inconsistent and don't always make
      7  * sense. This will hopefully be fixed sometime. (FIXME)
      8  */
      9 
     10 enum key_type {
     11 	KEY_INVALID = 0,
     12 	KEY_NONE = 2, /* FIXME: perhaps rather KEY_EMPTY? */
     13 	KEY_MOTION_CHAR = 4,
     14 	KEY_MOTION_LINE = 8,
     15 	KEY_MOTION = 4|8,
     16 	KEY_MOTIONALLOWED = 16,
     17 	KEY_NUMBER = 32,
     18 	KEY_NUMBERALLOWED = 64,
     19 	KEY_ENSURE_CURSOR_SHOWN = 128, /* jump to cursor if it is off screen */ /* FIXME: maybe rather KEY_JUMP_TO_CURSOR? */
     20 	KEY_ANY = 0xFF
     21 };
     22 
     23 struct key {
     24 	char *text;                                          /* for keys that correspond with text */
     25 	unsigned int mods;                                   /* modifier mask */
     26 	KeySym keysym;                                       /* for other keys, e.g. arrow keys */
     27 	ledit_mode modes;                                    /* modes in which this keybinding is functional */
     28 	enum key_type prev_keys;                             /* allowed previous keys */
     29 	enum key_type type;                                  /* type of key - mainly used for ensure_cursor_shown */
     30 	struct action (*func)(ledit_view *, char *, size_t); /* callback function */
     31 };
     32 
     33 static struct action backspace(ledit_view *view, char *text, size_t len);
     34 static struct action cursor_left(ledit_view *view, char *text, size_t len);
     35 static struct action cursor_right(ledit_view *view, char *text, size_t len);
     36 static struct action cursor_up(ledit_view *view, char *text, size_t len);
     37 static struct action cursor_down(ledit_view *view, char *text, size_t len);
     38 static struct action return_key(ledit_view *view, char *text, size_t len);
     39 static struct action delete_key(ledit_view *view, char *text, size_t len);
     40 static struct action escape_key(ledit_view *view, char *text, size_t len);
     41 static struct action enter_insert(ledit_view *view, char *text, size_t len);
     42 static struct action cursor_to_beginning(ledit_view *view, char *text, size_t len);
     43 static struct action push_0(ledit_view *view, char *text, size_t len);
     44 static struct action push_1(ledit_view *view, char *text, size_t len);
     45 static struct action push_2(ledit_view *view, char *text, size_t len);
     46 static struct action push_3(ledit_view *view, char *text, size_t len);
     47 static struct action push_4(ledit_view *view, char *text, size_t len);
     48 static struct action push_5(ledit_view *view, char *text, size_t len);
     49 static struct action push_6(ledit_view *view, char *text, size_t len);
     50 static struct action push_7(ledit_view *view, char *text, size_t len);
     51 static struct action push_8(ledit_view *view, char *text, size_t len);
     52 static struct action push_9(ledit_view *view, char *text, size_t len);
     53 static struct action delete(ledit_view *view, char *text, size_t len);
     54 static struct action enter_visual(ledit_view *view, char *text, size_t len);
     55 static struct action switch_selection_end(ledit_view *view, char *text, size_t len);
     56 static struct action clipcopy(ledit_view *view, char *text, size_t len);
     57 static struct action clippaste(ledit_view *view, char *text, size_t len);
     58 static struct action show_line(ledit_view *view, char *text, size_t len);
     59 static struct action enter_commandedit(ledit_view *view, char *text, size_t len);
     60 static struct action enter_searchedit_backward(ledit_view *view, char *text, size_t len);
     61 static struct action enter_searchedit_forward(ledit_view *view, char *text, size_t len);
     62 static struct action key_search_next(ledit_view *view, char *text, size_t len);
     63 static struct action key_search_prev(ledit_view *view, char *text, size_t len);
     64 static struct action undo(ledit_view *view, char *text, size_t len);
     65 static struct action redo(ledit_view *view, char *text, size_t len);
     66 static struct action insert_mode_insert_text(ledit_view *view, char *text, size_t len);
     67 static struct action repeat_command(ledit_view *view, char *text, size_t len);
     68 static struct action screen_up(ledit_view *view, char *text, size_t len);
     69 static struct action screen_down(ledit_view *view, char *text, size_t len);
     70 static struct action scroll_with_cursor_up(ledit_view *view, char *text, size_t len);
     71 static struct action scroll_with_cursor_down(ledit_view *view, char *text, size_t len);
     72 static struct action scroll_lines_up(ledit_view *view, char *text, size_t len);
     73 static struct action scroll_lines_down(ledit_view *view, char *text, size_t len);
     74 static struct action move_to_line(ledit_view *view, char *text, size_t len);
     75 static struct action paste_normal(ledit_view *view, char *text, size_t len);
     76 static struct action paste_normal_backwards(ledit_view *view, char *text, size_t len);
     77 static struct action change(ledit_view *view, char *text, size_t len);
     78 static struct action move_to_eol(ledit_view *view, char *text, size_t len);
     79 static struct action mark_line(ledit_view *view, char *text, size_t len);
     80 static struct action jump_to_mark(ledit_view *view, char *text, size_t len);
     81 static struct action next_word(ledit_view *view, char *text, size_t len);
     82 static struct action next_word_end(ledit_view *view, char *text, size_t len);
     83 static struct action next_bigword(ledit_view *view, char *text, size_t len);
     84 static struct action next_bigword_end(ledit_view *view, char *text, size_t len);
     85 static struct action prev_word(ledit_view *view, char *text, size_t len);
     86 static struct action prev_bigword(ledit_view *view, char *text, size_t len);
     87 static struct action append_after_eol(ledit_view *view, char *text, size_t len);
     88 static struct action append_after_cursor(ledit_view *view, char *text, size_t len);
     89 static struct action append_line_above(ledit_view *view, char *text, size_t len);
     90 static struct action append_line_below(ledit_view *view, char *text, size_t len);
     91 static struct action find_next_char_forwards(ledit_view *view, char *text, size_t len);
     92 static struct action find_next_char_backwards(ledit_view *view, char *text, size_t len);
     93 static struct action find_char_forwards(ledit_view *view, char *text, size_t len);
     94 static struct action find_char_backwards(ledit_view *view, char *text, size_t len);
     95 static struct action change_to_eol(ledit_view *view, char *text, size_t len);
     96 static struct action delete_to_eol(ledit_view *view, char *text, size_t len);
     97 static struct action delete_chars_forwards(ledit_view *view, char *text, size_t len);
     98 static struct action delete_chars_backwards(ledit_view *view, char *text, size_t len);
     99 static struct action yank(ledit_view *view, char *text, size_t len);
    100 static struct action yank_lines(ledit_view *view, char *text, size_t len);
    101 static struct action replace(ledit_view *view, char *text, size_t len);
    102 static struct action cursor_to_first_non_ws(ledit_view *view, char *text, size_t len);
    103 static struct action join_lines(ledit_view *view, char *text, size_t len);
    104 static struct action insert_at_beginning(ledit_view *view, char *text, size_t len);
    105 static struct action toggle_hard_line_based(ledit_view *view, char *text, size_t len);
    106 
    107 /* FIXME: maybe sort these and use binary search
    108    -> but that would mess with the catch-all keys */
    109 static struct key keys_en[] = {
    110 	{NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &backspace},
    111 	{NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    112 	{NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    113 	{NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    114 	{NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    115 	{NULL, XK_ANY_MOD, XK_Return, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &return_key},
    116 	{NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &delete_key},
    117 	{NULL, 0, XK_Escape, NORMAL|VISUAL|INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &escape_key},
    118 	{"i",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_insert},
    119 	{"h",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    120 	{"l",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    121 	{"j",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    122 	{"k",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    123 	{"h",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    124 	{"t",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &toggle_hard_line_based},
    125 	{NULL,  0, XK_space, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    126 	{"j",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    127 	{"n",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    128 	{"p",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    129 	{"0",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_beginning},
    130 	{"0",  0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &push_0},
    131 	{"1",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_1},
    132 	{"2",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_2},
    133 	{"3",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_3},
    134 	{"4",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_4},
    135 	{"5",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_5},
    136 	{"6",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_6},
    137 	{"7",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_7},
    138 	{"8",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_8},
    139 	{"9",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_9},
    140 	{"x",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_forwards},
    141 	{"X",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_backwards},
    142 	{"d",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &delete},
    143 	{"y",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &yank},
    144 	{"Y",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &yank_lines},
    145 	{"c",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &change},
    146 	{"v",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_visual},
    147 	{"o",  0, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &switch_selection_end},
    148 	{"c",  ControlMask, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clipcopy},
    149 	{"v",  ControlMask, 0, INSERT, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clippaste},
    150 	{"g",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &show_line},
    151 	{":",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &enter_commandedit},
    152 	{"?",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_backward},
    153 	{"/",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_forward},
    154 	{"n",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_next},
    155 	{"N",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_prev},
    156 	{"u",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &undo},
    157 	{"U",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &redo},
    158 	{".",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &repeat_command}, /* FIXME: only allow after finished key sequence */
    159 	{"z",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &undo},
    160 	{"y",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &redo}, /* FIXME: this is confusing with ctrl+y in normal mode */
    161 	{"b",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_up},
    162 	{"f",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_down},
    163 	{"e",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_down},
    164 	{"y",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_up},
    165 	{"d",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_down},
    166 	{"u",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_up},
    167 	{"$",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_eol},
    168 	{"w",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word},
    169 	{"e",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word_end},
    170 	{"W",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword},
    171 	{"E",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword_end},
    172 	{"b",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_word},
    173 	{"B",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_bigword},
    174 	{"G",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_line},
    175 	{"J",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &join_lines},
    176 	{"I",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &insert_at_beginning},
    177 	{"p",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal},
    178 	{"P",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal_backwards},
    179 	{"A",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_eol},
    180 	{"a",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_cursor},
    181 	{"O",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_above},
    182 	{"o",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_below},
    183 	{"m",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &mark_line},
    184 	{"'",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &jump_to_mark},
    185 	{"C",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &change_to_eol},
    186 	{"D",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &delete_to_eol},
    187 	{"r",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &replace},
    188 	{"^",  0, 0, NORMAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_first_non_ws},
    189 	{"t",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_forwards},
    190 	{"T",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_backwards},
    191 	{"f",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_forwards},
    192 	{"F",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_backwards},
    193 	{"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text}
    194 };
    195 
    196 static struct key keys_de[] = {
    197 	{NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &backspace},
    198 	{NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    199 	{NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    200 	{NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    201 	{NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    202 	{NULL, XK_ANY_MOD, XK_Return, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &return_key},
    203 	{NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &delete_key},
    204 	{NULL, 0, XK_Escape, NORMAL|VISUAL|INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &escape_key},
    205 	{"i",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_insert},
    206 	{"h",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    207 	{"l",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    208 	{"j",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    209 	{"k",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    210 	{"h",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    211 	{"t",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &toggle_hard_line_based},
    212 	{NULL,  0, XK_space, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    213 	{"j",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    214 	{"n",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    215 	{"p",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    216 	{"0",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_beginning},
    217 	{"0",  0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &push_0},
    218 	{"1",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_1},
    219 	{"2",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_2},
    220 	{"3",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_3},
    221 	{"4",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_4},
    222 	{"5",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_5},
    223 	{"6",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_6},
    224 	{"7",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_7},
    225 	{"8",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_8},
    226 	{"9",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_9},
    227 	{"x",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_forwards},
    228 	{"X",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_backwards},
    229 	{"d",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &delete},
    230 	{"z",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &yank},
    231 	{"Z",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &yank_lines},
    232 	{"c",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &change},
    233 	{"v",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_visual},
    234 	{"o",  0, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &switch_selection_end},
    235 	{"c",  ControlMask, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clipcopy},
    236 	{"v",  ControlMask, 0, INSERT, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clippaste},
    237 	{"g",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &show_line},
    238 	{"Ö",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &enter_commandedit},
    239 	{"_",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_backward},
    240 	{"-",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_forward},
    241 	{"n",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_next},
    242 	{"N",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_prev},
    243 	{"u",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &undo},
    244 	{"U",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &redo},
    245 	{".",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &repeat_command},
    246 	{"y",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &undo},
    247 	{"z",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &redo},
    248 	{"b",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_up},
    249 	{"f",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_down},
    250 	{"e",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_down},
    251 	{"z",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_up},
    252 	{"d",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_down},
    253 	{"u",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_up},
    254 	{"$",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_eol},
    255 	{"w",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word},
    256 	{"e",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word_end},
    257 	{"W",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword},
    258 	{"E",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword_end},
    259 	{"b",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_word},
    260 	{"B",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_bigword},
    261 	{"G",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_line},
    262 	{"J",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &join_lines},
    263 	{"I",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &insert_at_beginning},
    264 	{"p",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal},
    265 	{"P",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal_backwards},
    266 	{"A",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_eol},
    267 	{"a",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_cursor},
    268 	{"O",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_above},
    269 	{"o",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_below},
    270 	{"m",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &mark_line},
    271 	{"ä",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &jump_to_mark},
    272 	{"C",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &change_to_eol},
    273 	{"D",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &delete_to_eol},
    274 	{"r",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &replace},
    275 	{"&",  0, 0, NORMAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_first_non_ws},
    276 	{"t",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_forwards},
    277 	{"T",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_backwards},
    278 	{"f",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_forwards},
    279 	{"F",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_backwards},
    280 	{"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text}
    281 };
    282 
    283 static struct key keys_ur[] = {
    284 	{NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &backspace},
    285 	{NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    286 	{NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    287 	{NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    288 	{NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    289 	{NULL, XK_ANY_MOD, XK_Return, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &return_key},
    290 	{NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &delete_key},
    291 	{NULL, 0, XK_Escape, NORMAL|VISUAL|INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &escape_key},
    292 	{"ی",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_insert},
    293 	{"ح",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    294 	{"ل",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    295 	{"ج",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    296 	{"ک",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    297 	{"ح",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    298 	{"ت",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &toggle_hard_line_based},
    299 	{NULL,  0, XK_space, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    300 	{"ج",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    301 	{"ن",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    302 	{"پ",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    303 	{"0",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_beginning},
    304 	{"0",  0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &push_0},
    305 	{"1",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_1},
    306 	{"2",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_2},
    307 	{"3",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_3},
    308 	{"4",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_4},
    309 	{"5",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_5},
    310 	{"6",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_6},
    311 	{"7",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_7},
    312 	{"8",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_8},
    313 	{"9",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_9},
    314 	{"ش",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_forwards},
    315 	{"ژ",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_backwards},
    316 	{"د",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &delete},
    317 	{"ے",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &yank},
    318 	{"َ",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &yank_lines},
    319 	{"چ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &change},
    320 	{"ط",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_visual},
    321 	{"ہ",  0, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &switch_selection_end},
    322 	{"چ",  ControlMask, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clipcopy},
    323 	{"ط",  ControlMask, 0, INSERT, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clippaste},
    324 	{"گ",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &show_line},
    325 	{":",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &enter_commandedit},
    326 	{"؟",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_backward},
    327 	{"/",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_forward},
    328 	{"ن",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_next},
    329 	{"ں",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_prev},
    330 	{"ء",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &undo},
    331 	{"ئ",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &redo},
    332 	{"۔",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &repeat_command},
    333 	{"ز",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &undo},
    334 	{"َ",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &redo},
    335 	{"ب",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_up},
    336 	{"ف",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_down},
    337 	{"ع",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_down},
    338 	{"ے",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_up},
    339 	{"د",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_down},
    340 	{"ء",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_up},
    341 	{"$",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_eol},
    342 	{"و",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word},
    343 	{"ع",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word_end},
    344 	{"ؤ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword},
    345 	{"ٰ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword_end},
    346 	{"ب",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_word},
    347 	{".",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_bigword},
    348 	{"غ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_line},
    349 	{"ض",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &join_lines},
    350 	{"ِ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &insert_at_beginning},
    351 	{"پ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal},
    352 	{"ُ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal_backwards},
    353 	{"آ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_eol},
    354 	{"ا",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_cursor},
    355 	{"ۃ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_above},
    356 	{"ہ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_below},
    357 	{"م",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &mark_line},
    358 	{"'",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &jump_to_mark},
    359 	{"ث",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &change_to_eol},
    360 	{"ڈ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &delete_to_eol},
    361 	{"ر",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &replace},
    362 	{"^",  0, 0, NORMAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_first_non_ws},
    363 	{"ت",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_forwards},
    364 	{"ٹ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_backwards},
    365 	{"ف",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_forwards},
    366 	{"ّ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_backwards},
    367 	{"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text}
    368 };
    369 
    370 static struct key keys_hi[] = {
    371 	{NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &backspace},
    372 	{NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    373 	{NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    374 	{NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    375 	{NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    376 	{NULL, XK_ANY_MOD, XK_Return, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &return_key},
    377 	{NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &delete_key},
    378 	{NULL, 0, XK_Escape, NORMAL|VISUAL|INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &escape_key},
    379 	{"ि",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_insert},
    380 	{"ह",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    381 	{"ल",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    382 	{"ज",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    383 	{"क",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    384 	{"ह",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left},
    385 	{"त",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &toggle_hard_line_based},
    386 	{NULL,  0, XK_space, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right},
    387 	{"ज",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    388 	{"न",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down},
    389 	{"प",  ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up},
    390 	{"0",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_beginning},
    391 	{"0",  0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &push_0},
    392 	{"1",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_1},
    393 	{"2",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_2},
    394 	{"3",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_3},
    395 	{"4",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_4},
    396 	{"5",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_5},
    397 	{"6",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_6},
    398 	{"7",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_7},
    399 	{"8",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_8},
    400 	{"9",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_9},
    401 	{"्",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_forwards},
    402 	{"ॉ",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_backwards},
    403 	{"द",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &delete},
    404 	{"य",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &yank},
    405 	{"ञ",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &yank_lines},
    406 	{"च",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &change},
    407 	{"ड",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_visual},
    408 	{"ो",  0, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &switch_selection_end},
    409 	{"च",  ControlMask, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clipcopy},
    410 	{"ड",  ControlMask, 0, INSERT, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clippaste},
    411 	{"ग",  ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &show_line},
    412 	{":",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &enter_commandedit},
    413 	{"?",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_backward},
    414 	{"/",  0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_forward},
    415 	{"न",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_next},
    416 	{"ण",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_prev},
    417 	{"ु",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &undo},
    418 	{"ू",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &redo},
    419 	{".",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &repeat_command},
    420 	{"श",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &undo},
    421 	{"य",  ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &redo},
    422 	{"ब",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_up},
    423 	{"ट",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_down},
    424 	{"े",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_down},
    425 	{"य",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_up},
    426 	{"द",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_down},
    427 	{"ु",  ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_up},
    428 	{"$",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_eol},
    429 	{"व",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word},
    430 	{"े",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word_end},
    431 	{"ॐ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword},
    432 	{"ै",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword_end},
    433 	{"ब",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_word},
    434 	{"भ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_bigword},
    435 	{"घ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_line},
    436 	{"झ",  0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &join_lines},
    437 	{"ी",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &insert_at_beginning},
    438 	{"प",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal},
    439 	{"फ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal_backwards},
    440 	{"आ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_eol},
    441 	{"ा",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_cursor},
    442 	{"ौ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_above},
    443 	{"ो",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_below},
    444 	{"म",  0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &mark_line},
    445 	{"'",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &jump_to_mark},
    446 	{"छ",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &change_to_eol},
    447 	{"ध",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &delete_to_eol},
    448 	{"र",  0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &replace},
    449 	{"^",  0, 0, NORMAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_first_non_ws},
    450 	{"त",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_forwards},
    451 	{"थ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_backwards},
    452 	{"ट",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_forwards},
    453 	{"ठ",  0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_backwards},
    454 	{"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text}
    455 };
    456 
    457 GEN_KEY_ARRAY(struct key, keys_en, keys_de, keys_ur, keys_hi);