NeoMutt  2025-12-11-924-g64e75a
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
get.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 <string.h>
34#include <unistd.h>
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "core/lib.h"
38#include "gui/lib.h"
39#include "get.h"
40#include "menu/lib.h"
41#include "globals.h"
42#include "keymap.h"
43#include "menu.h"
44#include "module_data.h"
45#include "notify.h"
46#ifdef USE_INOTIFY
47#include "monitor.h"
48#endif
49
51static const int MaxKeyLoop = 64;
52
60void mutt_push_macro_repeated(char *macro, int count)
61{
62 int repeat = (count > 0) ? count : 1;
63
64 const short c_macro_repeat_max = cs_subset_number(NeoMutt->sub, "macro_repeat_max");
65 if ((c_macro_repeat_max > 0) && (repeat > c_macro_repeat_max))
66 repeat = c_macro_repeat_max;
67
68 for (int i = 0; i < repeat; i++)
70}
71
72// It's not possible to unget more than one char under some curses libs,
73// so roll our own input buffering routines.
74
77
81void mutt_flushinp(void)
82{
84 const size_t unget_count = ARRAY_SIZE(&mod_data->unget_key_events);
85 const size_t macro_count = ARRAY_SIZE(&mod_data->macro_events);
87 ARRAY_SHRINK(&mod_data->macro_events, ARRAY_SIZE(&mod_data->macro_events));
88
89 if ((unget_count + macro_count) > 0)
90 {
91 mutt_debug(LL_DEBUG1, "Flushed %zu queued key events (%zu unget, %zu macro)\n",
92 unget_count + macro_count, unget_count, macro_count);
93 }
94 flushinp();
95}
96
102struct KeyEvent *array_pop(struct KeyEventArray *a)
103{
104 if (ARRAY_EMPTY(a))
105 {
106 return NULL;
107 }
108
109 struct KeyEvent *event = ARRAY_LAST(a);
110 ARRAY_SHRINK(a, 1);
111 return event;
112}
113
120void array_add(struct KeyEventArray *a, int ch, int op)
121{
122 struct KeyEvent event = { ch, op, 0 };
123 ARRAY_ADD(a, event);
124}
125
130void array_to_endcond(struct KeyEventArray *a)
131{
132 while (!ARRAY_EMPTY(a))
133 {
134 if (array_pop(a)->op == OP_END_COND)
135 {
136 return;
137 }
138 }
139}
140
148{
150 array_add(&mod_data->unget_key_events, ch, OP_NULL);
151}
152
159void mutt_unget_op(int op)
160{
162 array_add(&mod_data->unget_key_events, 0, op);
163}
164
173void mutt_push_macro_event(int ch, int op)
174{
176 array_add(&mod_data->macro_events, ch, op);
177}
178
190
191#ifdef USE_INOTIFY
198static int mutt_monitor_getch_timeout(int timeout_ms)
199{
200 /* ncurses has its own internal buffer, so before we perform a poll,
201 * we need to make sure there isn't a character waiting */
202 timeout(0);
203 int ch = getch();
204 timeout(timeout_ms);
205 if (ch == ERR)
206 {
207 if (mutt_monitor_poll() != 0)
208 ch = ERR;
209 else
210 ch = getch();
211 }
212 return ch;
213}
214#endif /* USE_INOTIFY */
215
222static struct KeyEvent mutt_getch_timeout(GetChFlags flags, int timeout_ms)
223{
224 static const struct KeyEvent event_abort = { 0, OP_ABORT, 0 };
225 static const struct KeyEvent event_repaint = { 0, OP_REPAINT, 0 };
226 static const struct KeyEvent event_timeout = { 0, OP_TIMEOUT, 0 };
227
228 if (!OptGui)
229 return event_abort;
230
232
233 struct KeyEvent *event_key = array_pop(&mod_data->unget_key_events);
234 if (event_key)
235 return *event_key;
236
237 if (!(flags & GETCH_IGNORE_MACRO))
238 {
239 event_key = array_pop(&mod_data->macro_events);
240 if (event_key)
241 return *event_key;
242 }
243
244 int ch;
245 SigInt = false;
247 timeout(timeout_ms);
248#ifdef USE_INOTIFY
249 ch = mutt_monitor_getch_timeout(timeout_ms);
250#else
251 ch = getch();
252#endif
254
255 if (SigInt)
256 {
258 return event_abort;
259 }
260
261 if (ch == KEY_RESIZE)
262 {
263 timeout(0);
264 while ((ch = getch()) == KEY_RESIZE)
265 {
266 // do nothing
267 }
268 }
269
270 if (ch == ERR)
271 {
272 if (!isatty(STDIN_FILENO)) // terminal was lost
273 mutt_exit(1);
274
275 if (SigWinch)
276 {
277 SigWinch = false;
279 return event_repaint;
280 }
281
283 return event_timeout;
284 }
285
286 if (ch == mod_data->abort_key)
287 return event_abort;
288
289 if (ch & 0x80)
290 {
291 const bool c_meta_key = cs_subset_bool(NeoMutt->sub, "meta_key");
292 if (c_meta_key)
293 {
294 /* send ALT-x as ESC-x */
295 ch &= ~0x80;
297 return (struct KeyEvent) { '\033', OP_NULL, 0 }; // Escape
298 }
299 }
300
301 return (struct KeyEvent) { ch, OP_NULL, 0 };
302}
303
320{
321 return mutt_getch_timeout(flags, 1000);
322}
323
328void km_error_key(const struct MenuDefinition *md)
329{
330 if (!md)
331 return;
332
333 struct Keymap *key = km_find_func(md, OP_HELP);
334 if (!key)
335 {
336 mutt_error(_("Key is not bound"));
337 return;
338 }
339
340 struct Buffer *buf = buf_pool_get();
341 keymap_expand_key(key, buf);
342 mutt_error(_("Key is not bound. Press '%s' for help."), buf_string(buf));
343 buf_pool_release(&buf);
344}
345
353{
355 char *pp = NULL;
356 char *p = s + mutt_str_len(s) - 1;
357 size_t l;
358 int i, op = OP_NULL;
359
360 while (p >= s)
361 {
362 /* if we see something like "<PageUp>", look to see if it is a real
363 * function name and return the corresponding value */
364 if (*p == '>')
365 {
366 for (pp = p - 1; pp >= s && *pp != '<'; pp--)
367 ; // do nothing
368
369 if (pp >= s)
370 {
371 i = parse_fkey(pp);
372 if (i > 0)
373 {
374 mutt_push_macro_event(KEY_F(i), 0);
375 p = pp - 1;
376 continue;
377 }
378
379 l = p - pp + 1;
380 for (i = 0; mod_data->key_names[i].name; i++)
381 {
382 if (mutt_istrn_equal(pp, mod_data->key_names[i].name, l))
383 break;
384 }
385 if (mod_data->key_names[i].name)
386 {
387 /* found a match */
388 mutt_push_macro_event(mod_data->key_names[i].value, 0);
389 p = pp - 1;
390 continue;
391 }
392
393 /* See if it is a valid command
394 * skip the '<' and the '>' when comparing */
395 struct Buffer *buf = buf_pool_get();
396 buf_strcpy_n(buf, pp + 1, l - 2);
397
398 for (enum MenuType j = 0; j < MENU_MAX; j++)
399 {
400 op = km_get_op_menu(j, buf_string(buf));
401 if (op != OP_NULL)
402 break;
403 }
404
405 buf_pool_release(&buf);
406
407 if (op != OP_NULL)
408 {
410 p = pp - 1;
411 continue;
412 }
413 }
414 }
415 mutt_push_macro_event((unsigned char) *p--, 0); /* independent 8 bits chars */
416 }
417}
418
428 int key_len, struct KeymapMatchArray *kma)
429{
430 if (!md || !keys || !kma)
431 return 0;
432
433 struct SubMenu **smp = NULL;
435
436 ARRAY_FOREACH(smp, &md->submenus)
437 {
438 struct Keymap *km = NULL;
439
440 STAILQ_FOREACH(km, &(*smp)->keymaps, entries)
441 {
442 if (key_len > km->len)
443 continue;
444
445 bool match = true;
446
447 for (int i = 0; i < key_len; i++)
448 {
449 if (keys[i] != km->keys[i])
450 {
451 match = false;
452 break;
453 }
454 }
455
456 if (match)
457 {
459 if (km->len == key_len)
460 fmatch = KEY_GATHER_MATCH;
461 else
462 fmatch = KEY_GATHER_LONGER;
463
464 flags |= fmatch;
465
466 struct KeymapMatch kmatch = { md->id, fmatch, km };
467 ARRAY_ADD(kma, kmatch);
468 }
469 }
470 }
471
472 return flags;
473}
474
484
493static void key_progress_notify(const struct MenuDefinition *md, int count,
494 const keycode_t *keys, int key_len, GetChFlags flags)
495{
497 return;
498
499 struct EventKeyProgress ev_k = { 0 };
500 ev_k.md = md;
501 ev_k.count = count;
503
504 for (int i = 0; i < ev_k.key_len; i++)
505 {
506 ev_k.keys[i] = keys[i];
507 }
508
510}
511
518struct KeyEvent km_dokey(const struct MenuDefinition *md, GetChFlags flags)
519{
520 struct KeyEvent event = { 0, OP_NULL, 0 };
521 enum DokeyState state = DKS_START;
522 int count = 0;
523 int count_digits = 0;
524 int key_len = 0;
525 struct Keymap *pending_exact = NULL;
526 bool feedback_active = false;
528
529 const short c_key_timeout_idle = cs_subset_number(NeoMutt->sub, "key_timeout_idle");
530 const short c_key_timeout_progress = cs_subset_number(NeoMutt->sub, "key_timeout_partial");
531
532 if (!md)
533 return event;
534
535 for (int n = 0; n < MaxKeyLoop; n++)
536 {
537 const int timeout_ms = (state == DKS_START) ? c_key_timeout_idle : c_key_timeout_progress;
538 event = mutt_getch_timeout(flags, timeout_ms);
539
540 // abort, timeout, repaint
541 if (event.op < OP_NULL)
542 {
543 if (event.op == OP_TIMEOUT)
544 {
545 if ((state == DKS_NEED_MORE) && pending_exact)
546 {
547 if (pending_exact->op != OP_MACRO)
548 {
549 key_progress_notify(md, count, keys, key_len, flags);
550 key_progress_notify(md, 0, NULL, 0, flags);
551 return (struct KeyEvent) { 0, pending_exact->op, count };
552 }
553
554 if (flags & GETCH_IGNORE_MACRO)
555 {
556 key_progress_notify(md, 0, NULL, 0, flags);
557 return (struct KeyEvent) { 0, OP_NULL, 0 };
558 }
559
560 mutt_push_macro_repeated(pending_exact->macro, count_digits > 0 ? count : 0);
561 state = DKS_START;
562 count = 0;
563 count_digits = 0;
564 key_len = 0;
565 pending_exact = NULL;
566 memset(keys, 0, sizeof(keys));
567 feedback_active = false;
568 key_progress_notify(md, 0, NULL, 0, flags);
569 continue;
570 }
571 }
572
573 if (feedback_active || (state != DKS_START))
574 {
575 key_progress_notify(md, 0, NULL, 0, flags);
576 }
577 mutt_debug(LL_DEBUG3, "KEY: getch() %s\n", opcodes_get_name(event.op));
578 return event;
579 }
580
581 // macro op pushed into queue (e.g. from `exec`)
582 if (event.op > OP_NULL)
583 {
584 if (feedback_active || (state != DKS_START))
585 {
586 key_progress_notify(md, 0, NULL, 0, flags);
587 }
588 // Apply any count digits that arrived ahead of this op
589 // (e.g. "5<next-entry>" inside a macro body),
590 // preserving an explicit count already attached to the event.
591 if ((event.count == 0) && (count_digits > 0))
592 event.count = count;
593 return event;
594 }
595
596 mutt_debug(LL_DEBUG3, "KEY: getch() '%c'\n", isprint(event.ch) ? event.ch : '?');
597
598 // Check if digit keys have explicit bindings before using them as a counter
599 if (!(flags & GETCH_NO_COUNTER) && (state != DKS_NEED_MORE) &&
600 (event.ch >= '0') && (event.ch <= '9'))
601 {
602 keycode_t digit_key = event.ch;
603 struct KeymapMatchArray digit_kma = ARRAY_HEAD_INITIALIZER;
604 KeyGatherFlags digit_kgf = gather_functions(md, &digit_key, 1, &digit_kma);
605 bool digit_bound = (digit_kgf & KEY_GATHER_MATCH);
606 ARRAY_FREE(&digit_kma);
607
608 if (!digit_bound)
609 {
610 if (count_digits >= KEY_COUNT_MAX_DIGITS)
611 {
612 key_progress_notify(md, count, keys, key_len, flags);
613 key_progress_notify(md, 0, NULL, 0, flags);
614 return (struct KeyEvent) { event.ch, OP_NULL, 0 };
615 }
616
617 const int digit = event.ch - '0';
618 if ((count > (INT_MAX / 10)) ||
619 ((count == (INT_MAX / 10)) && (digit > (INT_MAX % 10))))
620 {
621 key_progress_notify(md, count, keys, key_len, flags);
622 key_progress_notify(md, 0, NULL, 0, flags);
623 return (struct KeyEvent) { event.ch, OP_NULL, 0 };
624 }
625
626 count = (count * 10) + digit;
627 count_digits++;
628 state = DKS_COUNTER;
629 feedback_active = true;
630 key_progress_notify(md, count, keys, key_len, flags);
631 continue;
632 }
633 }
634
635 if (key_len >= KEY_SEQ_MAX_LEN)
636 {
637 key_progress_notify(md, count, keys, key_len, flags);
638 key_progress_notify(md, 0, NULL, 0, flags);
639 return (struct KeyEvent) { event.ch, OP_NULL, 0 };
640 }
641
642 keys[key_len] = event.ch;
643 key_len++;
644
645 struct KeymapMatchArray kma = ARRAY_HEAD_INITIALIZER;
646 KeyGatherFlags kgf = gather_functions(md, keys, key_len, &kma);
647
648 mutt_debug(LL_DEBUG3, "KEY: flags = %x\n", kgf);
649
650 bool has_exact = false;
651 bool has_longer = false;
652 pending_exact = NULL;
653
654 struct KeymapMatch *kmatch = NULL;
655 ARRAY_FOREACH(kmatch, &kma)
656 {
657 if (kmatch->flags == KEY_GATHER_MATCH)
658 {
659 has_exact = true;
660 if (!pending_exact)
661 pending_exact = kmatch->keymap;
662 }
663 else if (kmatch->flags == KEY_GATHER_LONGER)
664 {
665 has_longer = true;
666 }
667 }
668
669 if (!has_exact && !has_longer)
670 {
671 key_progress_notify(md, count, keys, key_len, flags);
672 key_progress_notify(md, 0, NULL, 0, flags);
673 mutt_debug(LL_DEBUG3, "KEY: FAIL1: ('%c', %s)\n",
674 isprint(event.ch) ? event.ch : '?', opcodes_get_name(event.op));
675 ARRAY_FREE(&kma);
676 return event;
677 }
678
679 if (has_exact && has_longer)
680 {
681 state = DKS_NEED_MORE;
682 feedback_active = true;
683 key_progress_notify(md, count, keys, key_len, flags);
684 ARRAY_FREE(&kma);
685 continue;
686 }
687
688 if (!has_exact && has_longer)
689 {
690 state = DKS_NEED_MORE;
691 feedback_active = true;
692 key_progress_notify(md, count, keys, key_len, flags);
693 ARRAY_FREE(&kma);
694 continue;
695 }
696
697 if (has_exact && pending_exact)
698 {
699 struct Keymap *map = pending_exact;
700
701 if (map->op != OP_MACRO)
702 {
703 key_progress_notify(md, count, keys, key_len, flags);
704 key_progress_notify(md, 0, NULL, 0, flags);
705 mutt_debug(LL_DEBUG3, "KEY: SUCCESS: ('%c', %s)\n",
706 isprint(event.ch) ? event.ch : '?', opcodes_get_name(map->op));
707 ARRAY_FREE(&kma);
708 return (struct KeyEvent) { event.ch, map->op, count_digits > 0 ? count : 0 };
709 }
710
711 /* #GETCH_IGNORE_MACRO turns off processing the MacroEvents buffer
712 * in mutt_getch(). Generating new macro events during that time would
713 * result in undesired behavior once the option is turned off.
714 *
715 * Originally this returned -1, however that results in an unbuffered
716 * username or password prompt being aborted. Returning OP_NULL allows
717 * mw_get_field() to display the keybinding pressed instead.
718 *
719 * It may be unexpected for a macro's keybinding to be returned,
720 * but less so than aborting the prompt. */
721 if (flags & GETCH_IGNORE_MACRO)
722 {
723 key_progress_notify(md, 0, NULL, 0, flags);
724 ARRAY_FREE(&kma);
725 return (struct KeyEvent) { event.ch, OP_NULL, 0 };
726 }
727
728 mutt_push_macro_repeated(map->macro, count_digits > 0 ? count : 0);
729 state = DKS_START;
730 count = 0;
731 count_digits = 0;
732 key_len = 0;
733 pending_exact = NULL;
734 memset(keys, 0, sizeof(keys));
735 feedback_active = false;
736 key_progress_notify(md, 0, NULL, 0, flags);
737 ARRAY_FREE(&kma);
738 continue;
739 }
740
741 ARRAY_FREE(&kma);
742 }
743
744 key_progress_notify(md, 0, NULL, 0, flags);
746 mutt_error(_("Macro loop detected"));
747 return (struct KeyEvent) { '\0', OP_ABORT, 0 };
748}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_LAST(head)
Convenience method to get the last element.
Definition array.h:145
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
#define ARRAY_SHRINK(head, n)
Mark a number of slots at the end of the array as unused.
Definition array.h:174
size_t buf_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition buffer.c:424
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
int digit(const char *s)
void mutt_query_exit(void)
Ask the user if they want to leave NeoMutt.
Definition curs_lib.c:139
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition exit.c:41
KeyGatherFlags gather_functions(const struct MenuDefinition *md, const keycode_t *keys, int key_len, struct KeymapMatchArray *kma)
Find functions whose keybindings match.
Definition get.c:427
void generic_tokenize_push_string(char *s)
Parse and queue a 'push' command.
Definition get.c:352
void mutt_push_macro_repeated(char *macro, int count)
Push a macro string into the input queue, optionally repeated.
Definition get.c:60
void mutt_flushinp(void)
MacroEvents moved to KeyModuleData UngetKeyEvents moved to KeyModuleData.
Definition get.c:81
static struct KeyEvent mutt_getch_timeout(GetChFlags flags, int timeout_ms)
Read a character from the input buffer with timeout.
Definition get.c:222
static const int MaxKeyLoop
XXX.
Definition get.c:51
void array_add(struct KeyEventArray *a, int ch, int op)
Add an event to the end of the array.
Definition get.c:120
void array_to_endcond(struct KeyEventArray *a)
Clear the array until an OP_END_COND.
Definition get.c:130
DokeyState
Internal state for km_dokey()
Definition get.c:479
@ DKS_START
Initial state, no input received yet.
Definition get.c:480
@ DKS_COUNTER
Reading count prefix digits.
Definition get.c:481
@ DKS_NEED_MORE
Prefix matches an exact and/or longer keybinding.
Definition get.c:482
static void key_progress_notify(const struct MenuDefinition *md, int count, const keycode_t *keys, int key_len, GetChFlags flags)
Send key matching progress notification.
Definition get.c:493
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition get.c:173
struct KeyEvent mutt_getch(GetChFlags flags)
Read a character from the input buffer.
Definition get.c:319
struct KeyEvent km_dokey(const struct MenuDefinition *md, GetChFlags flags)
Determine what a keypress should do.
Definition get.c:518
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition get.c:159
void km_error_key(const struct MenuDefinition *md)
Handle an unbound key sequence.
Definition get.c:328
static int mutt_monitor_getch_timeout(int timeout_ms)
Get a character and poll the filesystem monitor.
Definition get.c:198
void mutt_flush_macro_to_endcond(void)
Drop a macro from the input buffer.
Definition get.c:185
struct KeyEvent * array_pop(struct KeyEventArray *a)
Remove an event from the array.
Definition get.c:102
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition get.c:147
Get a key from the user.
uint8_t GetChFlags
Definition get.h:43
@ GETCH_IGNORE_MACRO
Don't use MacroEvents.
Definition get.h:39
@ GETCH_NO_FEEDBACK
km_dokey(): suppress key progress notifications
Definition get.h:41
@ GETCH_NO_COUNTER
km_dokey(): disable numeric count prefix parsing
Definition get.h:40
@ KEY_GATHER_NO_MATCH
No bindings match the search string.
Definition get.h:55
@ KEY_GATHER_LONGER
No bindings match, but longer strings might.
Definition get.h:57
@ KEY_GATHER_MATCH
Binding matches the search string.
Definition get.h:56
#define KEY_COUNT_MAX_DIGITS
Maximum number of digits in a key count prefix, e.g. 123j
Definition get.h:46
#define KEY_SEQ_MAX_LEN
Maximum number of keys in a key sequence, e.g. abc
Definition get.h:48
uint8_t KeyGatherFlags
Definition get.h:59
struct KeyEvent * array_pop(struct KeyEventArray *a)
Remove an event from the array.
Definition get.c:102
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition get.c:147
bool OptGui
(pseudo) when the gui (and curses) are started
Definition globals.c:48
Global variables.
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
Convenience wrapper for the gui headers.
bool keymap_expand_key(struct Keymap *km, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition keymap.c:248
int parse_fkey(char *str)
Parse a function key string.
Definition keymap.c:285
int km_get_op_menu(int mtype, const char *func)
Get the OpCode for a Function from a Menu.
Definition menu.c:198
struct Keymap * km_find_func(const struct MenuDefinition *md, int func)
Find a function's mapping in a Menu.
Definition menu.c:141
Key private Module data.
Key binding notifications.
@ NT_KEY_PROGRESS
Key state has changed.
Definition notify.h:72
Keymap handling.
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition keymap.h:31
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
GUI present the user with a selectable list.
Maniplate Menus and SubMenus.
@ MODULE_ID_KEY
ModuleKey, Key mappings
Definition module_api.h:73
int mutt_monitor_poll(void)
Check for filesystem changes.
Definition monitor.c:401
Monitor files for changes.
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
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:457
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
@ NT_TIMEOUT
Timeout has occurred.
Definition notify_type.h:57
@ NT_KEY
Runtime key handling changed, NotifyKey, EventKeyProgress.
Definition notify_type.h:49
@ NT_RESIZE
Window has been resized.
Definition notify_type.h:53
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition opcodes.c:48
#define OP_TIMEOUT
1 second with no events
Definition opcodes.h:35
#define OP_REPAINT
Repaint is needed.
Definition opcodes.h:34
#define OP_ABORT
$abort_key pressed (Ctrl-G)
Definition opcodes.h:36
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
volatile sig_atomic_t SigWinch
true after SIGWINCH is received
Definition signal.c:69
volatile sig_atomic_t SigInt
true after SIGINT is received
Definition signal.c:68
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition signal.c:315
String manipulation buffer.
Definition buffer.h:36
Runtime key progress event.
Definition notify.h:58
short key_len
Number of keys entered.
Definition notify.h:61
keycode_t keys[KEY_SEQ_MAX_LEN]
Entered keys.
Definition notify.h:62
const struct MenuDefinition * md
Menu being matched.
Definition notify.h:59
int count
Parsed count prefix, if any.
Definition notify.h:60
An event such as a keypress.
Definition get.h:75
int count
Optional count prefix, e.g. 3 for 3j
Definition get.h:78
int op
Function opcode, e.g. OP_HELP.
Definition get.h:77
int ch
Raw key pressed.
Definition get.h:76
Key private Module data.
Definition module_data.h:34
struct KeyEventArray macro_events
Macro event buffer.
Definition module_data.h:36
keycode_t abort_key
Key to abort prompts, normally Ctrl-G.
Definition module_data.h:38
struct Mapping * key_names
Key name lookup table.
Definition module_data.h:41
struct KeyEventArray unget_key_events
Unget key event buffer.
Definition module_data.h:37
Result of Matching Keybinding.
Definition get.h:88
KeyGatherFlags flags
Flags, e.g. KEY_GATHER_MATCH.
Definition get.h:90
struct Keymap * keymap
Keymap defining bind or `macro.
Definition get.h:91
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
short len
Length of key sequence (unit: sizeof (keycode_t))
Definition keymap.h:48
short op
Operation to perform.
Definition keymap.h:46
int value
Integer value.
Definition mapping.h:35
const char * name
String value.
Definition mapping.h:34
Functions for a Dialog or Window.
Definition menu.h:77
int id
Menu ID, e.g. MENU_ALIAS.
Definition menu.h:78
struct SubMenuPArray submenus
Parts making up the Menu.
Definition menu.h:80
Container for Accounts, Notifications.
Definition neomutt.h:41
struct Notify * notify_timeout
Timeout notifications handler.
Definition neomutt.h:47
struct Notify * notify_resize
Window resize notifications handler.
Definition neomutt.h:46
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Collection of related functions.
Definition menu.h:65
MenuType
Types of GUI selections.
Definition type.h:33
@ MENU_MAX
Definition type.h:52