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>
23 #include "keymap.h"
24 #include "telescope.h"
26 #define CTRL(n) ((n)&0x1F)
28 static struct keytable {
29 const char *p;
30 int k;
31 } keytable[] = {
32 { "<up>", KEY_UP },
33 { "<down>", KEY_DOWN },
34 { "<left>", KEY_LEFT },
35 { "<right>", KEY_RIGHT },
36 { "<prior>", KEY_PPAGE },
37 { "<next>", KEY_NPAGE },
38 { "<home>", KEY_HOME },
39 { "<end>", KEY_END },
40 /* ... */
41 { "<f0>", KEY_F(0) },
42 { "<f1>", KEY_F(1) },
43 { "<f2>", KEY_F(2) },
44 { "<f3>", KEY_F(3) },
45 { "<f4>", KEY_F(4) },
46 { "<f5>", KEY_F(5) },
47 { "<f6>", KEY_F(6) },
48 { "<f7>", KEY_F(7) },
49 { "<f8>", KEY_F(8) },
50 { "<f9>", KEY_F(9) },
51 { "<f10>", KEY_F(10) },
52 { "<f11>", KEY_F(11) },
53 { "<f12>", KEY_F(12) },
54 { "<f13>", KEY_F(13) },
55 { "<f14>", KEY_F(14) },
56 { "<f15>", KEY_F(15) },
57 { "<f16>", KEY_F(16) },
58 { "<f17>", KEY_F(17) },
59 { "<f18>", KEY_F(18) },
60 { "<f19>", KEY_F(19) },
61 { "<f20>", KEY_F(20) },
62 { "<f21>", KEY_F(21) },
63 { "<f22>", KEY_F(22) },
64 { "<f23>", KEY_F(23) },
65 { "<f24>", KEY_F(24) },
66 { "<f25>", KEY_F(25) },
67 { "<f26>", KEY_F(26) },
68 { "<f27>", KEY_F(27) },
69 { "<f28>", KEY_F(28) },
70 { "<f29>", KEY_F(29) },
71 { "<f30>", KEY_F(30) },
72 { "<f31>", KEY_F(31) },
73 { "<f32>", KEY_F(32) },
74 { "<f33>", KEY_F(33) },
75 { "<f34>", KEY_F(34) },
76 { "<f35>", KEY_F(35) },
77 { "<f36>", KEY_F(36) },
78 { "<f37>", KEY_F(37) },
79 { "<f38>", KEY_F(38) },
80 { "<f39>", KEY_F(39) },
81 { "<f40>", KEY_F(40) },
82 { "<f41>", KEY_F(41) },
83 { "<f42>", KEY_F(42) },
84 { "<f43>", KEY_F(43) },
85 { "<f44>", KEY_F(44) },
86 { "<f45>", KEY_F(45) },
87 { "<f46>", KEY_F(46) },
88 { "<f47>", KEY_F(47) },
89 { "<f48>", KEY_F(48) },
90 { "<f49>", KEY_F(49) },
91 { "<f50>", KEY_F(50) },
92 { "<f51>", KEY_F(51) },
93 { "<f52>", KEY_F(52) },
94 { "<f53>", KEY_F(53) },
95 { "<f54>", KEY_F(54) },
96 { "<f55>", KEY_F(55) },
97 { "<f56>", KEY_F(56) },
98 { "<f57>", KEY_F(57) },
99 { "<f58>", KEY_F(58) },
100 { "<f59>", KEY_F(59) },
101 { "<f60>", KEY_F(60) },
102 { "<f61>", KEY_F(61) },
103 { "<f62>", KEY_F(62) },
104 { "<f63>", KEY_F(63) },
105 /* ... */
106 { "del", KEY_BACKSPACE },
107 { "backspace", 127 },
108 { "esc", 27 },
109 { "space", ' ' },
110 { "spc", ' ' },
111 { "enter", CTRL('m') },
112 { "ret", CTRL('m' )},
113 { "tab", CTRL('i') },
114 { "backtab", KEY_BTAB },
115 /* ... */
116 { NULL, 0 },
117 };
119 int
120 kbd(const char *key)
122 struct keytable *t;
124 for (t = keytable; t->p != NULL; ++t) {
125 if (has_prefix(key, t->p))
126 return t->k;
129 return *key;
132 const char *
133 unkbd(int k)
135 struct keytable *t;
137 for (t = keytable; t->p != NULL; ++t) {
138 if (k == t->k)
139 return t->p;
142 return NULL;
145 int
146 kmap_define_key(struct kmap *map, const char *key, void (*fn)(struct buffer*))
148 int ctrl, meta, k;
149 struct keymap *entry;
151 again:
152 if ((ctrl = has_prefix(key, "C-")))
153 key += 2;
154 if ((meta = has_prefix(key, "M-")))
155 key += 2;
156 if (*key == '\0')
157 return 0;
158 k = kbd(key);
160 if (ctrl)
161 k = CTRL(k);
163 /* skip key & spaces */
164 while (*key != '\0' && !isspace(*key))
165 ++key;
166 while (*key != '\0' && isspace(*key))
167 ++key;
169 TAILQ_FOREACH(entry, &map->m, keymaps) {
170 if (entry->meta == meta && entry->key == k) {
171 if (*key == '\0') {
172 entry->fn = fn;
173 return 1;
175 map = &entry->map;
176 goto again;
180 if ((entry = calloc(1, sizeof(*entry))) == NULL)
181 return 0;
183 entry->meta = meta;
184 entry->key = k;
185 TAILQ_INIT(&entry->map.m);
187 TAILQ_INSERT_TAIL(&map->m, entry, keymaps);
189 if (*key != '\0') {
190 map = &entry->map;
191 goto again;
194 entry->fn = fn;
196 return 1;
199 int
200 lookup_key(struct kmap **map, struct thiskey *key, struct buffer *buf)
202 struct keymap *k;
204 TAILQ_FOREACH(k, &(*map)->m, keymaps) {
205 if (k->meta == key->meta &&
206 k->key == key->key) {
207 if (k->fn == NULL) {
208 *map = &k->map;
209 return LK_ADVANCED_MAP;
210 } else {
211 k->fn(buf);
212 return LK_MATCHED;
217 return LK_UNBOUND;