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