NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
keymap.c
Go to the documentation of this file.
1
22
28
29#include "config.h"
30#include <ctype.h>
31#include <limits.h>
32#include <stdbool.h>
33#include <stdlib.h>
34#include <string.h>
35#include "mutt/lib.h"
36#include "gui/lib.h"
37#include "keymap.h"
38
42static struct Mapping KeyNames[] = {
43 // clang-format off
44 { "<PageUp>", KEY_PPAGE },
45 { "<PageDown>", KEY_NPAGE },
46 { "<Up>", KEY_UP },
47 { "<Down>", KEY_DOWN },
48 { "<Right>", KEY_RIGHT },
49 { "<Left>", KEY_LEFT },
50 { "<Delete>", KEY_DC },
51 { "<BackSpace>", KEY_BACKSPACE },
52 { "<Insert>", KEY_IC },
53 { "<Home>", KEY_HOME },
54 { "<End>", KEY_END },
55 { "<Enter>", '\n' },
56 { "<Return>", '\r' },
57#ifdef KEY_ENTER
58 { "<KeypadEnter>", KEY_ENTER },
59#else
60 { "<KeypadEnter>", '\n' },
61#endif
62 { "<Esc>", '\033' }, // Escape
63 { "<Tab>", '\t' },
64 { "<Space>", ' ' },
65 { "<Hash>", '#' },
66 { "<Semicolon>", ';' },
67 { "<DoubleQuote>", '"' },
68 { "<Quote>", '\'' },
69 { "<Backslash>", '\\' },
70 { "<Backtick>", '`' },
71 { "<Dollar>", '$' },
72 { "<Less>", '<' },
73 { "<Greater>", '>' },
74#ifdef KEY_BTAB
75 { "<BackTab>", KEY_BTAB },
76#endif
77#ifdef KEY_NEXT
78 { "<Next>", KEY_NEXT },
79#endif
80 /* extensions supported by ncurses. values are filled in during initialization */
81
82 /* CTRL+key */
83 { "<C-Up>", -1 },
84 { "<C-Down>", -1 },
85 { "<C-Left>", -1 },
86 { "<C-Right>", -1 },
87 { "<C-Home>", -1 },
88 { "<C-End>", -1 },
89 { "<C-Next>", -1 },
90 { "<C-Prev>", -1 },
91
92 /* SHIFT+key */
93 { "<S-Up>", -1 },
94 { "<S-Down>", -1 },
95 { "<S-Left>", -1 },
96 { "<S-Right>", -1 },
97 { "<S-Home>", -1 },
98 { "<S-End>", -1 },
99 { "<S-Next>", -1 },
100 { "<S-Prev>", -1 },
101
102 /* ALT+key */
103 { "<A-Up>", -1 },
104 { "<A-Down>", -1 },
105 { "<A-Left>", -1 },
106 { "<A-Right>", -1 },
107 { "<A-Home>", -1 },
108 { "<A-End>", -1 },
109 { "<A-Next>", -1 },
110 { "<A-Prev>", -1 },
111 { NULL, 0 },
112 // clang-format on
113};
114
120{
121 return KeyNames;
122}
123
131{
132 struct Keymap *km = MUTT_MEM_CALLOC(1, struct Keymap);
133
134 km->len = len;
136 memcpy(km->keys, keys, len * sizeof(keycode_t));
137
138 return km;
139}
140
145void keymap_free(struct Keymap **pptr)
146{
147 if (!pptr || !*pptr)
148 return;
149
150 struct Keymap *km = *pptr;
151 FREE(&km->macro);
152 FREE(&km->desc);
153 FREE(&km->keys);
154
155 FREE(pptr);
156}
157
162void keymaplist_free(struct KeymapList *kml)
163{
164 struct Keymap *km = NULL;
165 struct Keymap *km_tmp = NULL;
166 STAILQ_FOREACH_SAFE(km, kml, entries, km_tmp)
167 {
168 STAILQ_REMOVE(kml, km, Keymap, entries);
169 keymap_free(&km);
170 }
171}
172
180struct Keymap *keymap_compare(struct Keymap *km1, struct Keymap *km2, size_t *pos)
181{
182 *pos = 0;
183
184 while ((*pos < km1->len) && (*pos < km2->len))
185 {
186 if (km1->keys[*pos] < km2->keys[*pos])
187 return km2;
188
189 if (km1->keys[*pos] > km2->keys[*pos])
190 return km1;
191
192 *pos = *pos + 1;
193 }
194
195 return NULL;
196}
197
203void keymap_get_name(int c, struct Buffer *buf)
204{
205 const char *name = mutt_map_get_name(c, KeyNames);
206 if (name)
207 {
208 buf_addstr(buf, name);
209 return;
210 }
211
212 if ((c < 256) && (c > -128) && iscntrl((unsigned char) c))
213 {
214 if (c < 0)
215 c += 256;
216
217 if (c < 128)
218 {
219 buf_addch(buf, '^');
220 buf_addch(buf, (c + '@') & 0x7f);
221 }
222 else
223 {
224 buf_add_printf(buf, "\\%d%d%d", c >> 6, (c >> 3) & 7, c & 7);
225 }
226 }
227 else if ((c >= KEY_F0) && (c < KEY_F(256))) /* this maximum is just a guess */
228 {
229 buf_add_printf(buf, "<F%d>", c - KEY_F0);
230 }
231 else if ((c < 256) && (c >= -128) && IsPrint(c))
232 {
233 buf_add_printf(buf, "%c", (unsigned char) c);
234 }
235 else
236 {
237 buf_add_printf(buf, "<%ho>", (unsigned short) c);
238 }
239}
240
247bool keymap_expand_key(struct Keymap *km, struct Buffer *buf)
248{
249 if (!km || !buf)
250 return false;
251
252 for (int i = 0; i < km->len; i++)
253 {
254 keymap_get_name(km->keys[i], buf);
255 }
256
257 return true;
258}
259
265void keymap_expand_string(const char *str, struct Buffer *buf)
266{
267 if (!str)
268 return;
269
270 for (; *str; str++)
271 {
272 keymap_get_name(*str, buf);
273 }
274}
275
284int parse_fkey(char *str)
285{
286 char *t = NULL;
287 int n = 0;
288
289 if ((str[0] != '<') || (mutt_tolower(str[1]) != 'f'))
290 return -1;
291
292 for (t = str + 2; *t && mutt_isdigit(*t); t++)
293 {
294 n *= 10;
295 n += *t - '0';
296 }
297
298 if (*t != '>')
299 return -1;
300 return n;
301}
302
311int parse_keycode(const char *str)
312{
313 char *end_char = NULL;
314 long int result = strtol(str + 1, &end_char, 8);
315
316 /* allow trailing whitespace, eg. < 1001 > */
317 while (mutt_isspace(*end_char))
318 end_char++;
319
320 /* negative keycodes don't make sense, also detect overflow */
321 if ((*end_char != '>') || (result < 0) || (result == LONG_MAX))
322 {
323 return -1;
324 }
325
326 return result;
327}
328
336size_t parse_keys(const char *str, keycode_t *d, size_t max)
337{
338 int n;
339 size_t len = max;
340 char buf[128] = { 0 };
341 char c;
342 char *t = NULL;
343
344 mutt_str_copy(buf, str, sizeof(buf));
345 char *s = buf;
346
347 while (*s && len)
348 {
349 *d = '\0';
350 if ((*s == '<') && (t = strchr(s, '>')))
351 {
352 t++;
353 c = *t;
354 *t = '\0';
355
357 if (n != -1)
358 {
359 s = t;
360 *d = n;
361 }
362 else if ((n = parse_fkey(s)) > 0)
363 {
364 s = t;
365 *d = KEY_F(n);
366 }
367 else if ((n = parse_keycode(s)) > 0)
368 {
369 s = t;
370 *d = n;
371 }
372
373 *t = c;
374 }
375
376 if (!*d)
377 {
378 *d = (unsigned char) *s;
379 s++;
380 }
381 d++;
382 len--;
383 }
384
385 return max - len;
386}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:211
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:248
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
bool mutt_isspace(int arg)
Wrapper for isspace(3)
Definition ctype.c:96
int mutt_tolower(int arg)
Wrapper for tolower(3)
Definition ctype.c:126
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition ctype.c:66
Convenience wrapper for the gui headers.
void keymap_get_name(int c, struct Buffer *buf)
Get the human name for a key.
Definition keymap.c:203
void keymaplist_free(struct KeymapList *kml)
Free a List of Keymaps.
Definition keymap.c:162
struct Mapping * keymap_get_key_names(void)
Get the KeyNames lookup table.
Definition keymap.c:119
void keymap_expand_string(const char *str, struct Buffer *buf)
Get a human-readable key string.
Definition keymap.c:265
bool keymap_expand_key(struct Keymap *km, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition keymap.c:247
void keymap_free(struct Keymap **pptr)
Free a Keymap.
Definition keymap.c:145
struct Keymap * keymap_compare(struct Keymap *km1, struct Keymap *km2, size_t *pos)
Compare two keymaps' keyscodes and return the bigger one.
Definition keymap.c:180
size_t parse_keys(const char *str, keycode_t *d, size_t max)
Parse a key string into key codes.
Definition keymap.c:336
int parse_fkey(char *str)
Parse a function key string.
Definition keymap.c:284
struct Keymap * keymap_alloc(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition keymap.c:130
static struct Mapping KeyNames[]
Key name lookup table.
Definition keymap.c:42
int parse_keycode(const char *str)
Parse a numeric keycode.
Definition keymap.c:311
Keymap handling.
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition keymap.h:31
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition mapping.c:85
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition mapping.c:42
#define IsPrint(ch)
Definition mbyte.h:39
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
Convenience wrapper for the library headers.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition string.c:587
#define STAILQ_REMOVE(head, elm, type, field)
Definition queue.h:441
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:400
String manipulation buffer.
Definition buffer.h:36
A keyboard mapping.
Definition keymap.h:43
keycode_t * keys
Key sequence.
Definition keymap.h:49
char * macro
Macro expansion (op == OP_MACRO)
Definition keymap.h:44
char * desc
Description of a macro for the help menu.
Definition keymap.h:45
short len
Length of key sequence (unit: sizeof (keycode_t))
Definition keymap.h:48
Mapping between user-readable string and a constant.
Definition mapping.h:33