NeoMutt  2024-12-12-14-g7b49f7
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 <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include "mutt/lib.h"
37#include "gui/lib.h"
38#include "key/lib.h"
39#include "menu/lib.h"
40#include "ncrypt/lib.h"
41
42extern const struct MenuFuncOp OpAlias[];
43extern const struct MenuFuncOp OpAttachment[];
44#ifdef USE_AUTOCRYPT
45extern const struct MenuFuncOp OpAutocrypt[];
46#endif
47extern const struct MenuFuncOp OpBrowser[];
48extern const struct MenuFuncOp OpCompose[];
49extern const struct MenuFuncOp OpEditor[];
50extern const struct MenuFuncOp OpIndex[];
51extern const struct MenuFuncOp OpPager[];
52extern const struct MenuFuncOp OpPgp[];
53extern const struct MenuFuncOp OpPostponed[];
54extern const struct MenuFuncOp OpQuery[];
55extern const struct MenuFuncOp OpSmime[];
56
60struct Mapping KeyNames[] = {
61 { "<PageUp>", KEY_PPAGE },
62 { "<PageDown>", KEY_NPAGE },
63 { "<Up>", KEY_UP },
64 { "<Down>", KEY_DOWN },
65 { "<Right>", KEY_RIGHT },
66 { "<Left>", KEY_LEFT },
67 { "<Delete>", KEY_DC },
68 { "<BackSpace>", KEY_BACKSPACE },
69 { "<Insert>", KEY_IC },
70 { "<Home>", KEY_HOME },
71 { "<End>", KEY_END },
72 { "<Enter>", '\n' },
73 { "<Return>", '\r' },
74#ifdef KEY_ENTER
75 { "<KeypadEnter>", KEY_ENTER },
76#else
77 { "<KeypadEnter>", '\n' },
78#endif
79 { "<Esc>", '\033' }, // Escape
80 { "<Tab>", '\t' },
81 { "<Space>", ' ' },
82#ifdef KEY_BTAB
83 { "<BackTab>", KEY_BTAB },
84#endif
85#ifdef KEY_NEXT
86 { "<Next>", KEY_NEXT },
87#endif
88 /* extensions supported by ncurses. values are filled in during initialization */
89
90 /* CTRL+key */
91 { "<C-Up>", -1 },
92 { "<C-Down>", -1 },
93 { "<C-Left>", -1 },
94 { "<C-Right>", -1 },
95 { "<C-Home>", -1 },
96 { "<C-End>", -1 },
97 { "<C-Next>", -1 },
98 { "<C-Prev>", -1 },
99
100 /* SHIFT+key */
101 { "<S-Up>", -1 },
102 { "<S-Down>", -1 },
103 { "<S-Left>", -1 },
104 { "<S-Right>", -1 },
105 { "<S-Home>", -1 },
106 { "<S-End>", -1 },
107 { "<S-Next>", -1 },
108 { "<S-Prev>", -1 },
109
110 /* ALT+key */
111 { "<A-Up>", -1 },
112 { "<A-Down>", -1 },
113 { "<A-Left>", -1 },
114 { "<A-Right>", -1 },
115 { "<A-Home>", -1 },
116 { "<A-End>", -1 },
117 { "<A-Next>", -1 },
118 { "<A-Prev>", -1 },
119 { NULL, 0 },
120};
121
123
125struct KeymapList Keymaps[MENU_MAX];
126
131void mutt_keymap_free(struct Keymap **ptr)
132{
133 if (!ptr || !*ptr)
134 return;
135
136 struct Keymap *km = *ptr;
137 FREE(&km->macro);
138 FREE(&km->desc);
139 FREE(&km->keys);
140
141 FREE(ptr);
142}
143
151{
152 struct Keymap *p = MUTT_MEM_CALLOC(1, struct Keymap);
153 p->len = len;
155 memcpy(p->keys, keys, len * sizeof(keycode_t));
156 return p;
157}
158
166static int parse_fkey(char *s)
167{
168 char *t = NULL;
169 int n = 0;
170
171 if ((s[0] != '<') || (tolower(s[1]) != 'f'))
172 return -1;
173
174 for (t = s + 2; *t && isdigit((unsigned char) *t); t++)
175 {
176 n *= 10;
177 n += *t - '0';
178 }
179
180 if (*t != '>')
181 return -1;
182 return n;
183}
184
193static int parse_keycode(const char *s)
194{
195 char *end_char = NULL;
196 long int result = strtol(s + 1, &end_char, 8);
197 /* allow trailing whitespace, eg. < 1001 > */
198 while (isspace(*end_char))
199 end_char++;
200 /* negative keycodes don't make sense, also detect overflow */
201 if ((*end_char != '>') || (result < 0) || (result == LONG_MAX))
202 {
203 return -1;
204 }
205
206 return result;
207}
208
216size_t parsekeys(const char *str, keycode_t *d, size_t max)
217{
218 int n;
219 size_t len = max;
220 char buf[128] = { 0 };
221 char c;
222 char *t = NULL;
223
224 mutt_str_copy(buf, str, sizeof(buf));
225 char *s = buf;
226
227 while (*s && len)
228 {
229 *d = '\0';
230 if ((*s == '<') && (t = strchr(s, '>')))
231 {
232 t++;
233 c = *t;
234 *t = '\0';
235
237 if (n != -1)
238 {
239 s = t;
240 *d = n;
241 }
242 else if ((n = parse_fkey(s)) > 0)
243 {
244 s = t;
245 *d = KEY_F(n);
246 }
247 else if ((n = parse_keycode(s)) > 0)
248 {
249 s = t;
250 *d = n;
251 }
252
253 *t = c;
254 }
255
256 if (!*d)
257 {
258 *d = (unsigned char) *s;
259 s++;
260 }
261 d++;
262 len--;
263 }
264
265 return max - len;
266}
267
275struct Keymap *km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
276{
277 *pos = 0;
278
279 while (*pos < k1->len && *pos < k2->len)
280 {
281 if (k1->keys[*pos] < k2->keys[*pos])
282 return k2;
283 else if (k1->keys[*pos] > k2->keys[*pos])
284 return k1;
285 else
286 *pos = *pos + 1;
287 }
288
289 return NULL;
290}
291
299int get_op(const struct MenuFuncOp *funcs, const char *start, size_t len)
300{
301 for (int i = 0; funcs[i].name; i++)
302 {
303 if (mutt_istrn_equal(start, funcs[i].name, len) && (mutt_str_len(funcs[i].name) == len))
304 {
305 return funcs[i].op;
306 }
307 }
308
309 return OP_NULL;
310}
311
321const char *mutt_get_func(const struct MenuFuncOp *funcs, int op)
322{
323 for (int i = 0; funcs[i].name; i++)
324 {
325 if (funcs[i].op == op)
326 return funcs[i].name;
327 }
328
329 return NULL;
330}
331
339{
340 char *pp = NULL;
341 char *p = s + mutt_str_len(s) - 1;
342 size_t l;
343 int i, op = OP_NULL;
344
345 while (p >= s)
346 {
347 /* if we see something like "<PageUp>", look to see if it is a real
348 * function name and return the corresponding value */
349 if (*p == '>')
350 {
351 for (pp = p - 1; pp >= s && *pp != '<'; pp--)
352 ; // do nothing
353
354 if (pp >= s)
355 {
356 i = parse_fkey(pp);
357 if (i > 0)
358 {
359 mutt_push_macro_event(KEY_F(i), 0);
360 p = pp - 1;
361 continue;
362 }
363
364 l = p - pp + 1;
365 for (i = 0; KeyNames[i].name; i++)
366 {
367 if (mutt_istrn_equal(pp, KeyNames[i].name, l))
368 break;
369 }
370 if (KeyNames[i].name)
371 {
372 /* found a match */
373 mutt_push_macro_event(KeyNames[i].value, 0);
374 p = pp - 1;
375 continue;
376 }
377
378 /* See if it is a valid command
379 * skip the '<' and the '>' when comparing */
380 for (enum MenuType j = 0; MenuNames[j].name; j++)
381 {
382 const struct MenuFuncOp *funcs = km_get_table(MenuNames[j].value);
383 if (funcs)
384 {
385 op = get_op(funcs, pp + 1, l - 2);
386 if (op != OP_NULL)
387 break;
388 }
389 }
390
391 if (op != OP_NULL)
392 {
394 p = pp - 1;
395 continue;
396 }
397 }
398 }
399 mutt_push_macro_event((unsigned char) *p--, 0); /* independent 8 bits chars */
400 }
401}
402
410const char *km_keyname(int c)
411{
412 static char buf[35];
413
414 const char *p = mutt_map_get_name(c, KeyNames);
415 if (p)
416 return p;
417
418 if ((c < 256) && (c > -128) && iscntrl((unsigned char) c))
419 {
420 if (c < 0)
421 c += 256;
422
423 if (c < 128)
424 {
425 buf[0] = '^';
426 buf[1] = (c + '@') & 0x7f;
427 buf[2] = '\0';
428 }
429 else
430 {
431 snprintf(buf, sizeof(buf), "\\%d%d%d", c >> 6, (c >> 3) & 7, c & 7);
432 }
433 }
434 else if ((c >= KEY_F0) && (c < KEY_F(256))) /* this maximum is just a guess */
435 {
436 snprintf(buf, sizeof(buf), "<F%d>", c - KEY_F0);
437 }
438 else if ((c < 256) && (c >= -128) && IsPrint(c))
439 {
440 snprintf(buf, sizeof(buf), "%c", (unsigned char) c);
441 }
442 else
443 {
444 snprintf(buf, sizeof(buf), "<%ho>", (unsigned short) c);
445 }
446 return buf;
447}
448
457int km_expand_key(char *s, size_t len, struct Keymap *map)
458{
459 if (!map)
460 return 0;
461
462 int p = 0;
463
464 while (true)
465 {
466 mutt_str_copy(s, km_keyname(map->keys[p]), len);
467 const size_t l = mutt_str_len(s);
468 len -= l;
469
470 if ((++p >= map->len) || !len)
471 return 1;
472
473 s += l;
474 }
475
476 /* not reached */
477}
478
486int km_expand_key_string(char *str, char *buf, size_t buflen)
487{
488 size_t len = 0;
489 for (; *str; str++)
490 {
491 const char *key = km_keyname(*str);
492 size_t keylen = mutt_str_len(key);
493
494 mutt_str_copy(buf, key, buflen);
495 buf += keylen;
496 buflen -= keylen;
497 len += keylen;
498 }
499
500 return len;
501}
502
509struct Keymap *km_find_func(enum MenuType mtype, int func)
510{
511 struct Keymap *np = NULL;
512 STAILQ_FOREACH(np, &Keymaps[mtype], entries)
513 {
514 if (np->op == func)
515 break;
516 }
517 return np;
518}
519
525const struct MenuFuncOp *km_get_table(enum MenuType mtype)
526{
527 switch (mtype)
528 {
529 case MENU_ALIAS:
530 return OpAlias;
531 case MENU_ATTACHMENT:
532 return OpAttachment;
533#ifdef USE_AUTOCRYPT
534 case MENU_AUTOCRYPT:
535 return OpAutocrypt;
536#endif
537 case MENU_COMPOSE:
538 return OpCompose;
539 case MENU_DIALOG:
540 return OpDialog;
541 case MENU_EDITOR:
542 return OpEditor;
543 case MENU_FOLDER:
544 return OpBrowser;
545 case MENU_GENERIC:
546 return OpGeneric;
547 case MENU_INDEX:
548 return OpIndex;
549#ifdef CRYPT_BACKEND_GPGME
551 return OpPgp;
553 return OpSmime;
554#endif
555 case MENU_PAGER:
556 return OpPager;
557 case MENU_PGP:
558 return (WithCrypto & APPLICATION_PGP) ? OpPgp : NULL;
559 case MENU_POSTPONED:
560 return OpPostponed;
561 case MENU_QUERY:
562 return OpQuery;
563 default:
564 return NULL;
565 }
566}
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
const char * km_keyname(int c)
Get the human name for a key.
Definition: lib.c:410
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition: lib.c:509
void generic_tokenize_push_string(char *s)
Parse and queue a 'push' command.
Definition: lib.c:338
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: lib.c:122
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:275
struct Keymap * alloc_keys(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition: lib.c:150
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:131
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:193
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:125
size_t parsekeys(const char *str, keycode_t *d, size_t max)
Parse a key string into key codes.
Definition: lib.c:216
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: lib.c:457
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:321
const struct MenuFuncOp OpAttachment[]
Functions for the Attachment Menu.
Definition: functions.c:62
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:525
struct Mapping KeyNames[]
Key name lookup table.
Definition: lib.c:60
int get_op(const struct MenuFuncOp *funcs, const char *start, size_t len)
Get the function by its name.
Definition: lib.c:299
int km_expand_key_string(char *str, char *buf, size_t buflen)
Get a human-readable key string.
Definition: lib.c:486
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:166
Manage keymappings.
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition: lib.h:55
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:352
A keyboard mapping.
Definition: lib.h:65
keycode_t * keys
key sequence
Definition: lib.h:71
char * macro
Macro expansion (op == OP_MACRO)
Definition: lib.h:66
char * desc
Description of a macro for the help menu.
Definition: lib.h:67
short len
Length of key sequence (unit: sizeof (keycode_t))
Definition: lib.h:70
short op
Operation to perform.
Definition: lib.h:68
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:101
const char * name
Name of the function.
Definition: lib.h:102
int op
Operation, e.g. OP_DELETE.
Definition: lib.h:103
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