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