NeoMutt  2025-01-09-41-g086358
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.c
Go to the documentation of this file.
1
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 "key/lib.h"
38#include "menu/lib.h"
39#include "ncrypt/lib.h"
40
41extern const struct MenuFuncOp OpAlias[];
42extern const struct MenuFuncOp OpAttachment[];
43#ifdef USE_AUTOCRYPT
44extern const struct MenuFuncOp OpAutocrypt[];
45#endif
46extern const struct MenuFuncOp OpBrowser[];
47extern const struct MenuFuncOp OpCompose[];
48extern const struct MenuFuncOp OpEditor[];
49extern const struct MenuFuncOp OpIndex[];
50extern const struct MenuFuncOp OpPager[];
51extern const struct MenuFuncOp OpPgp[];
52extern const struct MenuFuncOp OpPostponed[];
53extern const struct MenuFuncOp OpQuery[];
54extern const struct MenuFuncOp OpSmime[];
55
59struct Mapping KeyNames[] = {
60 { "<PageUp>", KEY_PPAGE },
61 { "<PageDown>", KEY_NPAGE },
62 { "<Up>", KEY_UP },
63 { "<Down>", KEY_DOWN },
64 { "<Right>", KEY_RIGHT },
65 { "<Left>", KEY_LEFT },
66 { "<Delete>", KEY_DC },
67 { "<BackSpace>", KEY_BACKSPACE },
68 { "<Insert>", KEY_IC },
69 { "<Home>", KEY_HOME },
70 { "<End>", KEY_END },
71 { "<Enter>", '\n' },
72 { "<Return>", '\r' },
73#ifdef KEY_ENTER
74 { "<KeypadEnter>", KEY_ENTER },
75#else
76 { "<KeypadEnter>", '\n' },
77#endif
78 { "<Esc>", '\033' }, // Escape
79 { "<Tab>", '\t' },
80 { "<Space>", ' ' },
81#ifdef KEY_BTAB
82 { "<BackTab>", KEY_BTAB },
83#endif
84#ifdef KEY_NEXT
85 { "<Next>", KEY_NEXT },
86#endif
87 /* extensions supported by ncurses. values are filled in during initialization */
88
89 /* CTRL+key */
90 { "<C-Up>", -1 },
91 { "<C-Down>", -1 },
92 { "<C-Left>", -1 },
93 { "<C-Right>", -1 },
94 { "<C-Home>", -1 },
95 { "<C-End>", -1 },
96 { "<C-Next>", -1 },
97 { "<C-Prev>", -1 },
98
99 /* SHIFT+key */
100 { "<S-Up>", -1 },
101 { "<S-Down>", -1 },
102 { "<S-Left>", -1 },
103 { "<S-Right>", -1 },
104 { "<S-Home>", -1 },
105 { "<S-End>", -1 },
106 { "<S-Next>", -1 },
107 { "<S-Prev>", -1 },
108
109 /* ALT+key */
110 { "<A-Up>", -1 },
111 { "<A-Down>", -1 },
112 { "<A-Left>", -1 },
113 { "<A-Right>", -1 },
114 { "<A-Home>", -1 },
115 { "<A-End>", -1 },
116 { "<A-Next>", -1 },
117 { "<A-Prev>", -1 },
118 { NULL, 0 },
119};
120
122
124struct KeymapList Keymaps[MENU_MAX];
125
130void mutt_keymap_free(struct Keymap **ptr)
131{
132 if (!ptr || !*ptr)
133 return;
134
135 struct Keymap *km = *ptr;
136 FREE(&km->macro);
137 FREE(&km->desc);
138 FREE(&km->keys);
139
140 FREE(ptr);
141}
142
150{
151 struct Keymap *p = MUTT_MEM_CALLOC(1, struct Keymap);
152 p->len = len;
154 memcpy(p->keys, keys, len * sizeof(keycode_t));
155 return p;
156}
157
165static int parse_fkey(char *s)
166{
167 char *t = NULL;
168 int n = 0;
169
170 if ((s[0] != '<') || (tolower(s[1]) != 'f'))
171 return -1;
172
173 for (t = s + 2; *t && isdigit((unsigned char) *t); t++)
174 {
175 n *= 10;
176 n += *t - '0';
177 }
178
179 if (*t != '>')
180 return -1;
181 return n;
182}
183
192static int parse_keycode(const char *s)
193{
194 char *end_char = NULL;
195 long int result = strtol(s + 1, &end_char, 8);
196 /* allow trailing whitespace, eg. < 1001 > */
197 while (isspace(*end_char))
198 end_char++;
199 /* negative keycodes don't make sense, also detect overflow */
200 if ((*end_char != '>') || (result < 0) || (result == LONG_MAX))
201 {
202 return -1;
203 }
204
205 return result;
206}
207
215size_t parsekeys(const char *str, keycode_t *d, size_t max)
216{
217 int n;
218 size_t len = max;
219 char buf[128] = { 0 };
220 char c;
221 char *t = NULL;
222
223 mutt_str_copy(buf, str, sizeof(buf));
224 char *s = buf;
225
226 while (*s && len)
227 {
228 *d = '\0';
229 if ((*s == '<') && (t = strchr(s, '>')))
230 {
231 t++;
232 c = *t;
233 *t = '\0';
234
236 if (n != -1)
237 {
238 s = t;
239 *d = n;
240 }
241 else if ((n = parse_fkey(s)) > 0)
242 {
243 s = t;
244 *d = KEY_F(n);
245 }
246 else if ((n = parse_keycode(s)) > 0)
247 {
248 s = t;
249 *d = n;
250 }
251
252 *t = c;
253 }
254
255 if (!*d)
256 {
257 *d = (unsigned char) *s;
258 s++;
259 }
260 d++;
261 len--;
262 }
263
264 return max - len;
265}
266
274struct Keymap *km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
275{
276 *pos = 0;
277
278 while (*pos < k1->len && *pos < k2->len)
279 {
280 if (k1->keys[*pos] < k2->keys[*pos])
281 return k2;
282 else if (k1->keys[*pos] > k2->keys[*pos])
283 return k1;
284 else
285 *pos = *pos + 1;
286 }
287
288 return NULL;
289}
290
298int get_op(const struct MenuFuncOp *funcs, const char *start, size_t len)
299{
300 for (int i = 0; funcs[i].name; i++)
301 {
302 if (mutt_istrn_equal(start, funcs[i].name, len) && (mutt_str_len(funcs[i].name) == len))
303 {
304 return funcs[i].op;
305 }
306 }
307
308 return OP_NULL;
309}
310
320const char *mutt_get_func(const struct MenuFuncOp *funcs, int op)
321{
322 for (int i = 0; funcs[i].name; i++)
323 {
324 if (funcs[i].op == op)
325 return funcs[i].name;
326 }
327
328 return NULL;
329}
330
338{
339 char *pp = NULL;
340 char *p = s + mutt_str_len(s) - 1;
341 size_t l;
342 int i, op = OP_NULL;
343
344 while (p >= s)
345 {
346 /* if we see something like "<PageUp>", look to see if it is a real
347 * function name and return the corresponding value */
348 if (*p == '>')
349 {
350 for (pp = p - 1; pp >= s && *pp != '<'; pp--)
351 ; // do nothing
352
353 if (pp >= s)
354 {
355 i = parse_fkey(pp);
356 if (i > 0)
357 {
358 mutt_push_macro_event(KEY_F(i), 0);
359 p = pp - 1;
360 continue;
361 }
362
363 l = p - pp + 1;
364 for (i = 0; KeyNames[i].name; i++)
365 {
366 if (mutt_istrn_equal(pp, KeyNames[i].name, l))
367 break;
368 }
369 if (KeyNames[i].name)
370 {
371 /* found a match */
372 mutt_push_macro_event(KeyNames[i].value, 0);
373 p = pp - 1;
374 continue;
375 }
376
377 /* See if it is a valid command
378 * skip the '<' and the '>' when comparing */
379 for (enum MenuType j = 0; MenuNames[j].name; j++)
380 {
381 const struct MenuFuncOp *funcs = km_get_table(MenuNames[j].value);
382 if (funcs)
383 {
384 op = get_op(funcs, pp + 1, l - 2);
385 if (op != OP_NULL)
386 break;
387 }
388 }
389
390 if (op != OP_NULL)
391 {
393 p = pp - 1;
394 continue;
395 }
396 }
397 }
398 mutt_push_macro_event((unsigned char) *p--, 0); /* independent 8 bits chars */
399 }
400}
401
407void km_keyname(int c, struct Buffer *buf)
408{
409 const char *name = mutt_map_get_name(c, KeyNames);
410 if (name)
411 {
412 buf_addstr(buf, name);
413 return;
414 }
415
416 if ((c < 256) && (c > -128) && iscntrl((unsigned char) c))
417 {
418 if (c < 0)
419 c += 256;
420
421 if (c < 128)
422 {
423 buf_addch(buf, '^');
424 buf_addch(buf, (c + '@') & 0x7f);
425 }
426 else
427 {
428 buf_add_printf(buf, "\\%d%d%d", c >> 6, (c >> 3) & 7, c & 7);
429 }
430 }
431 else if ((c >= KEY_F0) && (c < KEY_F(256))) /* this maximum is just a guess */
432 {
433 buf_add_printf(buf, "<F%d>", c - KEY_F0);
434 }
435 else if ((c < 256) && (c >= -128) && IsPrint(c))
436 {
437 buf_add_printf(buf, "%c", (unsigned char) c);
438 }
439 else
440 {
441 buf_add_printf(buf, "<%ho>", (unsigned short) c);
442 }
443}
444
451bool km_expand_key(struct Keymap *map, struct Buffer *buf)
452{
453 if (!map || !buf)
454 return false;
455
456 for (int i = 0; i < map->len; i++)
457 {
458 km_keyname(map->keys[i], buf);
459 }
460
461 return true;
462}
463
469void km_expand_key_string(char *str, struct Buffer *buf)
470{
471 for (; *str; str++)
472 {
473 km_keyname(*str, buf);
474 }
475}
476
483struct Keymap *km_find_func(enum MenuType mtype, int func)
484{
485 struct Keymap *np = NULL;
486 STAILQ_FOREACH(np, &Keymaps[mtype], entries)
487 {
488 if (np->op == func)
489 break;
490 }
491 return np;
492}
493
499const struct MenuFuncOp *km_get_table(enum MenuType mtype)
500{
501 switch (mtype)
502 {
503 case MENU_ALIAS:
504 return OpAlias;
505 case MENU_ATTACHMENT:
506 return OpAttachment;
507#ifdef USE_AUTOCRYPT
508 case MENU_AUTOCRYPT:
509 return OpAutocrypt;
510#endif
511 case MENU_COMPOSE:
512 return OpCompose;
513 case MENU_DIALOG:
514 return OpDialog;
515 case MENU_EDITOR:
516 return OpEditor;
517 case MENU_FOLDER:
518 return OpBrowser;
519 case MENU_GENERIC:
520 return OpGeneric;
521 case MENU_INDEX:
522 return OpIndex;
523#ifdef CRYPT_BACKEND_GPGME
525 return OpPgp;
527 return OpSmime;
528#endif
529 case MENU_PAGER:
530 return OpPager;
531 case MENU_PGP:
532 return (WithCrypto & APPLICATION_PGP) ? OpPgp : NULL;
533 case MENU_POSTPONED:
534 return OpPostponed;
535 case MENU_QUERY:
536 return OpQuery;
537 default:
538 return NULL;
539 }
540}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:204
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: get.c:155
const struct MenuFuncOp OpGeneric[]
Functions for the Generic Menu.
Definition: functions.c:68
const struct MenuFuncOp OpDialog[]
Functions for Simple Dialogs.
Definition: functions.c:60
Convenience wrapper for the gui headers.
const struct MenuFuncOp OpQuery[]
Functions for the external Query Menu.
Definition: functions.c:76
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition: lib.c:483
void generic_tokenize_push_string(char *s)
Parse and queue a 'push' command.
Definition: lib.c:337
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: lib.c:121
const struct MenuFuncOp OpPostponed[]
Functions for the Postpone Menu.
Definition: functions.c:52
const struct MenuFuncOp OpIndex[]
Functions for the Index Menu.
Definition: functions.c:90
struct Keymap * km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
Compare two keymaps' keyscodes and return the bigger one.
Definition: lib.c:274
struct Keymap * alloc_keys(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition: lib.c:149
const struct MenuFuncOp OpCompose[]
Functions for the Compose Menu.
Definition: functions.c:87
void mutt_keymap_free(struct Keymap **ptr)
Free a Keymap.
Definition: lib.c:130
const struct MenuFuncOp OpSmime[]
Functions for the Smime Menu.
Definition: functions.c:52
const struct MenuFuncOp OpBrowser[]
Functions for the file Browser Menu.
Definition: functions.c:72
const struct MenuFuncOp OpAutocrypt[]
Functions for the Autocrypt Account.
Definition: functions.c:54
static int parse_keycode(const char *s)
Parse a numeric keycode.
Definition: lib.c:192
const struct MenuFuncOp OpPager[]
Functions for the Pager Menu.
Definition: functions.c:71
struct KeymapList Keymaps[MENU_MAX]
Array of key mappings, one for each MenuType.
Definition: lib.c:124
size_t parsekeys(const char *str, keycode_t *d, size_t max)
Parse a key string into key codes.
Definition: lib.c:215
const struct MenuFuncOp OpEditor[]
Functions for the Editor Menu.
Definition: functions.c:53
const char * mutt_get_func(const struct MenuFuncOp *funcs, int op)
Get the name of a function.
Definition: lib.c:320
const struct MenuFuncOp OpAttachment[]
Functions for the Attachment Menu.
Definition: functions.c:62
void km_keyname(int c, struct Buffer *buf)
Get the human name for a key.
Definition: lib.c:407
const struct MenuFuncOp OpPgp[]
Functions for the Pgp Menu.
Definition: functions.c:42
const struct MenuFuncOp * km_get_table(enum MenuType mtype)
Lookup a Menu's functions.
Definition: lib.c:499
struct Mapping KeyNames[]
Key name lookup table.
Definition: lib.c:59
int get_op(const struct MenuFuncOp *funcs, const char *start, size_t len)
Get the function by its name.
Definition: lib.c:298
const struct MenuFuncOp OpAlias[]
Functions for the Alias Menu.
Definition: functions.c:60
static int parse_fkey(char *s)
Parse a function key string.
Definition: lib.c:165
bool km_expand_key(struct Keymap *map, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition: lib.c:451
void km_expand_key_string(char *str, struct Buffer *buf)
Get a human-readable key string.
Definition: lib.c:469
Manage keymappings.
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition: lib.h:56
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:40
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
GUI present the user with a selectable list.
Convenience wrapper for the library headers.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
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:581
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:453
API for encryption/signing of emails.
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:96
#define WithCrypto
Definition: lib.h:122
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
String manipulation buffer.
Definition: buffer.h:36
A keyboard mapping.
Definition: lib.h:66
keycode_t * keys
key sequence
Definition: lib.h:72
char * macro
Macro expansion (op == OP_MACRO)
Definition: lib.h:67
char * desc
Description of a macro for the help menu.
Definition: lib.h:68
short len
Length of key sequence (unit: sizeof (keycode_t))
Definition: lib.h:71
short op
Operation to perform.
Definition: lib.h:69
Mapping between user-readable string and a constant.
Definition: mapping.h:33
const char * name
String value.
Definition: mapping.h:34
Mapping between a function and an operation.
Definition: lib.h:102
const char * name
Name of the function.
Definition: lib.h:103
int op
Operation, e.g. OP_DELETE.
Definition: lib.h:104
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:37
MenuType
Types of GUI selections.
Definition: type.h:36
@ MENU_KEY_SELECT_PGP
Select a PGP key.
Definition: type.h:48
@ MENU_INDEX
Index panel (list of emails)
Definition: type.h:51
@ MENU_DIALOG
Simple Dialog.
Definition: type.h:43
@ MENU_KEY_SELECT_SMIME
Select a SMIME key.
Definition: type.h:49
@ MENU_QUERY
Select from results of external query.
Definition: type.h:55
@ MENU_AUTOCRYPT
Autocrypt Account menu.
Definition: type.h:40
@ MENU_COMPOSE
Compose an email.
Definition: type.h:42
@ MENU_ATTACHMENT
Select an attachment.
Definition: type.h:38
@ MENU_PGP
PGP encryption menu.
Definition: type.h:53
@ MENU_GENERIC
Generic selection list.
Definition: type.h:46
@ MENU_PAGER
Pager pager (email viewer)
Definition: type.h:52
@ MENU_MAX
Definition: type.h:57
@ MENU_EDITOR
Text entry area.
Definition: type.h:44
@ MENU_ALIAS
Select an email address by its alias.
Definition: type.h:37
@ MENU_FOLDER
General file/mailbox browser.
Definition: type.h:45
@ MENU_POSTPONED
Select a postponed email.
Definition: type.h:54