Blob


1 /*
2 * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include "compat.h"
19 #include <ctype.h>
20 #include <curses.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "keymap.h"
25 #include "telescope.h"
26 #include "utils.h"
28 #define CTRL(n) ((n)&0x1F)
30 static struct keytable {
31 const char *p;
32 int k;
33 } keytable[] = {
34 { "<up>", KEY_UP },
35 { "<down>", KEY_DOWN },
36 { "<left>", KEY_LEFT },
37 { "<right>", KEY_RIGHT },
38 { "<prior>", KEY_PPAGE },
39 { "<next>", KEY_NPAGE },
40 { "<home>", KEY_HOME },
41 { "<end>", KEY_END },
42 /* ... */
43 { "<f0>", KEY_F(0) },
44 { "<f1>", KEY_F(1) },
45 { "<f2>", KEY_F(2) },
46 { "<f3>", KEY_F(3) },
47 { "<f4>", KEY_F(4) },
48 { "<f5>", KEY_F(5) },
49 { "<f6>", KEY_F(6) },
50 { "<f7>", KEY_F(7) },
51 { "<f8>", KEY_F(8) },
52 { "<f9>", KEY_F(9) },
53 { "<f10>", KEY_F(10) },
54 { "<f11>", KEY_F(11) },
55 { "<f12>", KEY_F(12) },
56 { "<f13>", KEY_F(13) },
57 { "<f14>", KEY_F(14) },
58 { "<f15>", KEY_F(15) },
59 { "<f16>", KEY_F(16) },
60 { "<f17>", KEY_F(17) },
61 { "<f18>", KEY_F(18) },
62 { "<f19>", KEY_F(19) },
63 { "<f20>", KEY_F(20) },
64 { "<f21>", KEY_F(21) },
65 { "<f22>", KEY_F(22) },
66 { "<f23>", KEY_F(23) },
67 { "<f24>", KEY_F(24) },
68 { "<f25>", KEY_F(25) },
69 { "<f26>", KEY_F(26) },
70 { "<f27>", KEY_F(27) },
71 { "<f28>", KEY_F(28) },
72 { "<f29>", KEY_F(29) },
73 { "<f30>", KEY_F(30) },
74 { "<f31>", KEY_F(31) },
75 { "<f32>", KEY_F(32) },
76 { "<f33>", KEY_F(33) },
77 { "<f34>", KEY_F(34) },
78 { "<f35>", KEY_F(35) },
79 { "<f36>", KEY_F(36) },
80 { "<f37>", KEY_F(37) },
81 { "<f38>", KEY_F(38) },
82 { "<f39>", KEY_F(39) },
83 { "<f40>", KEY_F(40) },
84 { "<f41>", KEY_F(41) },
85 { "<f42>", KEY_F(42) },
86 { "<f43>", KEY_F(43) },
87 { "<f44>", KEY_F(44) },
88 { "<f45>", KEY_F(45) },
89 { "<f46>", KEY_F(46) },
90 { "<f47>", KEY_F(47) },
91 { "<f48>", KEY_F(48) },
92 { "<f49>", KEY_F(49) },
93 { "<f50>", KEY_F(50) },
94 { "<f51>", KEY_F(51) },
95 { "<f52>", KEY_F(52) },
96 { "<f53>", KEY_F(53) },
97 { "<f54>", KEY_F(54) },
98 { "<f55>", KEY_F(55) },
99 { "<f56>", KEY_F(56) },
100 { "<f57>", KEY_F(57) },
101 { "<f58>", KEY_F(58) },
102 { "<f59>", KEY_F(59) },
103 { "<f60>", KEY_F(60) },
104 { "<f61>", KEY_F(61) },
105 { "<f62>", KEY_F(62) },
106 { "<f63>", KEY_F(63) },
107 /* ... */
108 { "del", KEY_BACKSPACE },
109 { "backspace", 127 },
110 { "esc", '\e' },
111 { "space", ' ' },
112 { "spc", ' ' },
113 { "enter", CTRL('m') },
114 { "ret", CTRL('m' )},
115 { "tab", CTRL('i') },
116 { "backtab", KEY_BTAB },
117 /* ... */
118 { NULL, 0 },
119 };
121 int
122 kbd(const char *key)
124 struct keytable *t;
126 for (t = keytable; t->p != NULL; ++t) {
127 if (!strncmp(key, t->p, strlen(t->p)))
128 return t->k;
131 return *key;
134 const char *
135 unkbd(int k)
137 struct keytable *t;
139 for (t = keytable; t->p != NULL; ++t) {
140 if (k == t->k)
141 return t->p;
144 return NULL;
147 int
148 kmap_define_key(struct kmap *map, const char *key, void (*fn)(struct buffer*))
150 int ctrl, meta, k;
151 struct keymap *entry;
153 again:
154 if ((ctrl = !strncmp(key, "C-", 2)))
155 key += 2;
156 if ((meta = !strncmp(key, "M-", 2)))
157 key += 2;
158 if (*key == '\0')
159 return 0;
160 k = kbd(key);
162 if (ctrl)
163 k = CTRL(k);
165 /* skip key & spaces */
166 while (*key != '\0' && !isspace(*key))
167 ++key;
168 while (*key != '\0' && isspace(*key))
169 ++key;
171 TAILQ_FOREACH(entry, &map->m, keymaps) {
172 if (entry->meta == meta && entry->key == k) {
173 if (*key == '\0') {
174 entry->fn = fn;
175 return 1;
177 map = &entry->map;
178 goto again;
182 if ((entry = calloc(1, sizeof(*entry))) == NULL)
183 return 0;
185 entry->meta = meta;
186 entry->key = k;
187 TAILQ_INIT(&entry->map.m);
189 TAILQ_INSERT_TAIL(&map->m, entry, keymaps);
191 if (*key != '\0') {
192 map = &entry->map;
193 goto again;
196 entry->fn = fn;
198 return 1;
201 int
202 lookup_key(struct kmap **map, struct thiskey *key, struct buffer *buf)
204 struct keymap *k;
206 TAILQ_FOREACH(k, &(*map)->m, keymaps) {
207 if (k->meta == key->meta &&
208 k->key == key->key) {
209 if (k->fn == NULL) {
210 *map = &k->map;
211 return LK_ADVANCED_MAP;
212 } else {
213 k->fn(buf);
214 return LK_MATCHED;
219 return LK_UNBOUND;