NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
keymap.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 "mutt.h"
39 #include "keymap.h"
40 #include "functions.h"
41 #include "init.h"
42 #include "mutt_commands.h"
43 #include "mutt_globals.h"
44 #include "mutt_logging.h"
45 #include "opcodes.h"
46 #include "options.h"
47 #include "ncrypt/lib.h"
48 #ifndef USE_SLANG_CURSES
49 #include <strings.h>
50 #endif
51 #ifdef USE_IMAP
52 #include "imap/lib.h"
53 #endif
54 #ifdef USE_INOTIFY
55 #include "monitor.h"
56 #endif
57 
61 const struct Mapping Menus[] = {
62  { "alias", MENU_ALIAS },
63  { "attach", MENU_ATTACH },
64  { "browser", MENU_FOLDER },
65  { "compose", MENU_COMPOSE },
66  { "editor", MENU_EDITOR },
67  { "index", MENU_MAIN },
68  { "pager", MENU_PAGER },
69  { "postpone", MENU_POSTPONE },
70  { "pgp", MENU_PGP },
71  { "smime", MENU_SMIME },
72 #ifdef CRYPT_BACKEND_GPGME
73  { "key_select_pgp", MENU_KEY_SELECT_PGP },
74  { "key_select_smime", MENU_KEY_SELECT_SMIME },
75 #endif
76 #ifdef MIXMASTER
77  { "mix", MENU_MIX },
78 #endif
79  { "query", MENU_QUERY },
80  { "generic", MENU_GENERIC },
81  { NULL, 0 },
82 };
83 
87 static struct Mapping KeyNames[] = {
88  { "<PageUp>", KEY_PPAGE },
89  { "<PageDown>", KEY_NPAGE },
90  { "<Up>", KEY_UP },
91  { "<Down>", KEY_DOWN },
92  { "<Right>", KEY_RIGHT },
93  { "<Left>", KEY_LEFT },
94  { "<Delete>", KEY_DC },
95  { "<BackSpace>", KEY_BACKSPACE },
96  { "<Insert>", KEY_IC },
97  { "<Home>", KEY_HOME },
98  { "<End>", KEY_END },
99  { "<Enter>", '\n' },
100  { "<Return>", '\r' },
101  { "<Esc>", '\033' }, // Escape
102  { "<Tab>", '\t' },
103  { "<Space>", ' ' },
104 #ifdef KEY_BTAB
105  { "<BackTab>", KEY_BTAB },
106 #endif
107 #ifdef KEY_NEXT
108  { "<Next>", KEY_NEXT },
109 #endif
110 #ifdef NCURSES_VERSION
111  /* extensions supported by ncurses. values are filled in during initialization */
112 
113  /* CTRL+key */
114  { "<C-Up>", -1 },
115  { "<C-Down>", -1 },
116  { "<C-Left>", -1 },
117  { "<C-Right>", -1 },
118  { "<C-Home>", -1 },
119  { "<C-End>", -1 },
120  { "<C-Next>", -1 },
121  { "<C-Prev>", -1 },
122 
123  /* SHIFT+key */
124  { "<S-Up>", -1 },
125  { "<S-Down>", -1 },
126  { "<S-Left>", -1 },
127  { "<S-Right>", -1 },
128  { "<S-Home>", -1 },
129  { "<S-End>", -1 },
130  { "<S-Next>", -1 },
131  { "<S-Prev>", -1 },
132 
133  /* ALT+key */
134  { "<A-Up>", -1 },
135  { "<A-Down>", -1 },
136  { "<A-Left>", -1 },
137  { "<A-Right>", -1 },
138  { "<A-Home>", -1 },
139  { "<A-End>", -1 },
140  { "<A-Next>", -1 },
141  { "<A-Prev>", -1 },
142 #endif /* NCURSES_VERSION */
143  { NULL, 0 },
144 };
145 
146 int LastKey;
148 
149 struct Keymap *Keymaps[MENU_MAX];
150 
151 #ifdef NCURSES_VERSION
152 
155 struct Extkey
156 {
157  const char *name;
158  const char *sym;
159 };
160 
161 static const struct Extkey ExtKeys[] = {
162  { "<c-up>", "kUP5" },
163  { "<s-up>", "kUP" },
164  { "<a-up>", "kUP3" },
165 
166  { "<s-down>", "kDN" },
167  { "<a-down>", "kDN3" },
168  { "<c-down>", "kDN5" },
169 
170  { "<c-right>", "kRIT5" },
171  { "<s-right>", "kRIT" },
172  { "<a-right>", "kRIT3" },
173 
174  { "<s-left>", "kLFT" },
175  { "<a-left>", "kLFT3" },
176  { "<c-left>", "kLFT5" },
177 
178  { "<s-home>", "kHOM" },
179  { "<a-home>", "kHOM3" },
180  { "<c-home>", "kHOM5" },
181 
182  { "<s-end>", "kEND" },
183  { "<a-end>", "kEND3" },
184  { "<c-end>", "kEND5" },
185 
186  { "<s-next>", "kNXT" },
187  { "<a-next>", "kNXT3" },
188  { "<c-next>", "kNXT5" },
189 
190  { "<s-prev>", "kPRV" },
191  { "<a-prev>", "kPRV3" },
192  { "<c-prev>", "kPRV5" },
193 
194  { 0, 0 },
195 };
196 #endif
197 
204 static struct Keymap *alloc_keys(size_t len, keycode_t *keys)
205 {
206  struct Keymap *p = mutt_mem_calloc(1, sizeof(struct Keymap));
207  p->len = len;
208  p->keys = mutt_mem_malloc(len * sizeof(keycode_t));
209  memcpy(p->keys, keys, len * sizeof(keycode_t));
210  return p;
211 }
212 
220 static int parse_fkey(char *s)
221 {
222  char *t = NULL;
223  int n = 0;
224 
225  if ((s[0] != '<') || (tolower(s[1]) != 'f'))
226  return -1;
227 
228  for (t = s + 2; *t && isdigit((unsigned char) *t); t++)
229  {
230  n *= 10;
231  n += *t - '0';
232  }
233 
234  if (*t != '>')
235  return -1;
236  return n;
237 }
238 
247 static int parse_keycode(const char *s)
248 {
249  char *end_char = NULL;
250  long int result = strtol(s + 1, &end_char, 8);
251  /* allow trailing whitespace, eg. < 1001 > */
252  while (IS_SPACE(*end_char))
253  end_char++;
254  /* negative keycodes don't make sense, also detect overflow */
255  if ((*end_char != '>') || (result < 0) || (result == LONG_MAX))
256  {
257  return -1;
258  }
259 
260  return result;
261 }
262 
270 static size_t parsekeys(const char *str, keycode_t *d, size_t max)
271 {
272  int n;
273  size_t len = max;
274  char buf[128];
275  char c;
276  char *t = NULL;
277 
278  mutt_str_copy(buf, str, sizeof(buf));
279  char *s = buf;
280 
281  while (*s && len)
282  {
283  *d = '\0';
284  if ((*s == '<') && (t = strchr(s, '>')))
285  {
286  t++;
287  c = *t;
288  *t = '\0';
289 
290  n = mutt_map_get_value(s, KeyNames);
291  if (n != -1)
292  {
293  s = t;
294  *d = n;
295  }
296  else if ((n = parse_fkey(s)) > 0)
297  {
298  s = t;
299  *d = KEY_F(n);
300  }
301  else if ((n = parse_keycode(s)) > 0)
302  {
303  s = t;
304  *d = n;
305  }
306 
307  *t = c;
308  }
309 
310  if (!*d)
311  {
312  *d = (unsigned char) *s;
313  s++;
314  }
315  d++;
316  len--;
317  }
318 
319  return max - len;
320 }
321 
335 static enum CommandResult km_bind_err(const char *s, enum MenuType menu, int op,
336  char *macro, char *desc, struct Buffer *err)
337 {
339  struct Keymap *last = NULL, *next = NULL;
340  keycode_t buf[MAX_SEQ];
341  size_t pos = 0, lastpos = 0;
342 
343  size_t len = parsekeys(s, buf, MAX_SEQ);
344 
345  struct Keymap *map = alloc_keys(len, buf);
346  map->op = op;
347  map->macro = mutt_str_dup(macro);
348  map->desc = mutt_str_dup(desc);
349 
350  struct Keymap *tmp = Keymaps[menu];
351 
352  while (tmp)
353  {
354  if ((pos >= len) || (pos >= tmp->len))
355  {
356  /* map and tmp match so overwrite */
357  do
358  {
359  /* Don't warn on overwriting a 'noop' binding */
360  if ((tmp->len != len) && (tmp->op != OP_NULL))
361  {
362  /* Overwrite with the different lengths, warn */
363  /* TODO: MAX_SEQ here is wrong */
364  char old_binding[MAX_SEQ];
365  char new_binding[MAX_SEQ];
366  km_expand_key(old_binding, MAX_SEQ, map);
367  km_expand_key(new_binding, MAX_SEQ, tmp);
368  if (err)
369  {
370  /* err was passed, put the string there */
371  snprintf(
372  err->data, err->dsize,
373  _("Binding '%s' will alias '%s' Before, try: 'bind %s %s "
374  "noop' "
375  "https://neomutt.org/guide/configuration.html#bind-warnings"),
376  old_binding, new_binding, mutt_map_get_name(menu, Menus), new_binding);
377  }
378  else
379  {
380  mutt_error(
381  _("Binding '%s' will alias '%s' Before, try: 'bind %s %s "
382  "noop' "
383  "https://neomutt.org/guide/configuration.html#bind-warnings"),
384  old_binding, new_binding, mutt_map_get_name(menu, Menus), new_binding);
385  }
386  rc = MUTT_CMD_WARNING;
387  }
388  len = tmp->eq;
389  next = tmp->next;
390  FREE(&tmp->macro);
391  FREE(&tmp->keys);
392  FREE(&tmp->desc);
393  FREE(&tmp);
394  tmp = next;
395  } while (tmp && len >= pos);
396  map->eq = len;
397  break;
398  }
399  else if (buf[pos] == tmp->keys[pos])
400  pos++;
401  else if (buf[pos] < tmp->keys[pos])
402  {
403  /* found location to insert between last and tmp */
404  map->eq = pos;
405  break;
406  }
407  else /* buf[pos] > tmp->keys[pos] */
408  {
409  last = tmp;
410  lastpos = pos;
411  if (pos > tmp->eq)
412  pos = tmp->eq;
413  tmp = tmp->next;
414  }
415  }
416 
417  map->next = tmp;
418  if (last)
419  {
420  last->next = map;
421  last->eq = lastpos;
422  }
423  else
424  {
425  Keymaps[menu] = map;
426  }
427 
428  return rc;
429 }
430 
440 enum CommandResult km_bind(char *s, enum MenuType menu, int op, char *macro, char *desc)
441 {
442  return km_bind_err(s, menu, op, macro, desc, NULL);
443 }
444 
453 static enum CommandResult km_bindkey_err(const char *s, enum MenuType menu,
454  int op, struct Buffer *err)
455 {
456  return km_bind_err(s, menu, op, NULL, NULL, err);
457 }
458 
466 static enum CommandResult km_bindkey(const char *s, enum MenuType menu, int op)
467 {
468  return km_bindkey_err(s, menu, op, NULL);
469 }
470 
478 static int get_op(const struct Binding *bindings, const char *start, size_t len)
479 {
480  for (int i = 0; bindings[i].name; i++)
481  {
482  if (mutt_istrn_equal(start, bindings[i].name, len) &&
483  (mutt_str_len(bindings[i].name) == len))
484  {
485  return bindings[i].op;
486  }
487  }
488 
489  return OP_NULL;
490 }
491 
501 const char *mutt_get_func(const struct Binding *bindings, int op)
502 {
503  for (int i = 0; bindings[i].name; i++)
504  {
505  if (bindings[i].op == op)
506  return bindings[i].name;
507  }
508 
509  return NULL;
510 }
511 
521 static void generic_tokenize_push_string(char *s, void (*generic_push)(int, int))
522 {
523  char *pp = NULL;
524  char *p = s + mutt_str_len(s) - 1;
525  size_t l;
526  int i, op = OP_NULL;
527 
528  while (p >= s)
529  {
530  /* if we see something like "<PageUp>", look to see if it is a real
531  * function name and return the corresponding value */
532  if (*p == '>')
533  {
534  for (pp = p - 1; pp >= s && *pp != '<'; pp--)
535  ; // do nothing
536 
537  if (pp >= s)
538  {
539  i = parse_fkey(pp);
540  if (i > 0)
541  {
542  generic_push(KEY_F(i), 0);
543  p = pp - 1;
544  continue;
545  }
546 
547  l = p - pp + 1;
548  for (i = 0; KeyNames[i].name; i++)
549  {
550  if (mutt_istrn_equal(pp, KeyNames[i].name, l))
551  break;
552  }
553  if (KeyNames[i].name)
554  {
555  /* found a match */
556  generic_push(KeyNames[i].value, 0);
557  p = pp - 1;
558  continue;
559  }
560 
561  /* See if it is a valid command
562  * skip the '<' and the '>' when comparing */
563  for (enum MenuType j = 0; Menus[j].name; j++)
564  {
565  const struct Binding *binding = km_get_table(Menus[j].value);
566  if (binding)
567  {
568  op = get_op(binding, pp + 1, l - 2);
569  if (op != OP_NULL)
570  break;
571  }
572  }
573 
574  if (op != OP_NULL)
575  {
576  generic_push(0, op);
577  p = pp - 1;
578  continue;
579  }
580  }
581  }
582  generic_push((unsigned char) *p--, 0); /* independent 8 bits chars */
583  }
584 }
585 
594 static int retry_generic(enum MenuType menu, keycode_t *keys, int keyslen, int lastkey)
595 {
596  if ((menu != MENU_EDITOR) && (menu != MENU_GENERIC) && (menu != MENU_PAGER))
597  {
598  if (lastkey)
599  mutt_unget_event(lastkey, 0);
600  for (; keyslen; keyslen--)
601  mutt_unget_event(keys[keyslen - 1], 0);
602  return km_dokey(MENU_GENERIC);
603  }
604  if (menu != MENU_EDITOR)
605  {
606  /* probably a good idea to flush input here so we can abort macros */
607  mutt_flushinp();
608  }
609  return OP_NULL;
610 }
611 
620 int km_dokey(enum MenuType menu)
621 {
622  struct KeyEvent tmp;
623  struct Keymap *map = Keymaps[menu];
624  int pos = 0;
625  int n = 0;
626 
627  if (!map && (menu != MENU_EDITOR))
628  return retry_generic(menu, NULL, 0, 0);
629 
630  while (true)
631  {
632  int i = (C_Timeout > 0) ? C_Timeout : 60;
633 #ifdef USE_IMAP
634  /* keepalive may need to run more frequently than C_Timeout allows */
635  if (C_ImapKeepalive)
636  {
637  if (C_ImapKeepalive >= i)
638  imap_keepalive();
639  else
640  {
641  while (C_ImapKeepalive && (C_ImapKeepalive < i))
642  {
644  tmp = mutt_getch();
645  mutt_getch_timeout(-1);
646  /* If a timeout was not received, or the window was resized, exit the
647  * loop now. Otherwise, continue to loop until reaching a total of
648  * $timeout seconds. */
649  if ((tmp.ch != -2) || SigWinch)
650  goto gotkey;
651 #ifdef USE_INOTIFY
653  goto gotkey;
654 #endif
655  i -= C_ImapKeepalive;
656  imap_keepalive();
657  }
658  }
659  }
660 #endif
661 
662  mutt_getch_timeout(i * 1000);
663  tmp = mutt_getch();
664  mutt_getch_timeout(-1);
665 
666 #ifdef USE_IMAP
667  gotkey:
668 #endif
669  /* hide timeouts, but not window resizes, from the line editor. */
670  if ((menu == MENU_EDITOR) && (tmp.ch == -2) && !SigWinch)
671  continue;
672 
673  LastKey = tmp.ch;
674  if (LastKey < 0)
675  return LastKey;
676 
677  /* do we have an op already? */
678  if (tmp.op)
679  {
680  const char *func = NULL;
681  const struct Binding *bindings = NULL;
682 
683  /* is this a valid op for this menu? */
684  if ((bindings = km_get_table(menu)) && (func = mutt_get_func(bindings, tmp.op)))
685  return tmp.op;
686 
687  if ((menu == MENU_EDITOR) && mutt_get_func(OpEditor, tmp.op))
688  return tmp.op;
689 
690  if ((menu != MENU_EDITOR) && (menu != MENU_PAGER))
691  {
692  /* check generic menu */
693  bindings = OpGeneric;
694  func = mutt_get_func(bindings, tmp.op);
695  if (func)
696  return tmp.op;
697  }
698 
699  /* Sigh. Valid function but not in this context.
700  * Find the literal string and push it back */
701  for (i = 0; Menus[i].name; i++)
702  {
703  bindings = km_get_table(Menus[i].value);
704  if (bindings)
705  {
706  func = mutt_get_func(bindings, tmp.op);
707  if (func)
708  {
709  mutt_unget_event('>', 0);
710  mutt_unget_string(func);
711  mutt_unget_event('<', 0);
712  break;
713  }
714  }
715  }
716  /* continue to chew */
717  if (func)
718  continue;
719  }
720 
721  if (!map)
722  return tmp.op;
723 
724  /* Nope. Business as usual */
725  while (LastKey > map->keys[pos])
726  {
727  if ((pos > map->eq) || !map->next)
728  return retry_generic(menu, map->keys, pos, LastKey);
729  map = map->next;
730  }
731 
732  if (LastKey != map->keys[pos])
733  return retry_generic(menu, map->keys, pos, LastKey);
734 
735  if (++pos == map->len)
736  {
737  if (map->op != OP_MACRO)
738  return map->op;
739 
740  /* OptIgnoreMacroEvents turns off processing the MacroEvents buffer
741  * in mutt_getch(). Generating new macro events during that time would
742  * result in undesired behavior once the option is turned off.
743  *
744  * Originally this returned -1, however that results in an unbuffered
745  * username or password prompt being aborted. Returning OP_NULL allows
746  * mutt_enter_string_full() to display the keybinding pressed instead.
747  *
748  * It may be unexpected for a macro's keybinding to be returned,
749  * but less so than aborting the prompt. */
751  {
752  return OP_NULL;
753  }
754 
755  if (n++ == 10)
756  {
757  mutt_flushinp();
758  mutt_error(_("Macro loop detected"));
759  return -1;
760  }
761 
763  map = Keymaps[menu];
764  pos = 0;
765  }
766  }
767 
768  /* not reached */
769 }
770 
776 static void create_bindings(const struct Binding *map, enum MenuType menu)
777 {
778  for (int i = 0; map[i].name; i++)
779  if (map[i].seq)
780  km_bindkey(map[i].seq, menu, map[i].op);
781 }
782 
790 static const char *km_keyname(int c)
791 {
792  static char buf[35];
793 
794  const char *p = mutt_map_get_name(c, KeyNames);
795  if (p)
796  return p;
797 
798  if ((c < 256) && (c > -128) && iscntrl((unsigned char) c))
799  {
800  if (c < 0)
801  c += 256;
802 
803  if (c < 128)
804  {
805  buf[0] = '^';
806  buf[1] = (c + '@') & 0x7f;
807  buf[2] = '\0';
808  }
809  else
810  snprintf(buf, sizeof(buf), "\\%d%d%d", c >> 6, (c >> 3) & 7, c & 7);
811  }
812  else if ((c >= KEY_F0) && (c < KEY_F(256))) /* this maximum is just a guess */
813  sprintf(buf, "<F%d>", c - KEY_F0);
814  else if (IsPrint(c))
815  snprintf(buf, sizeof(buf), "%c", (unsigned char) c);
816  else
817  snprintf(buf, sizeof(buf), "\\x%hx", (unsigned short) c);
818  return buf;
819 }
820 
827 {
828  keycode_t buf[2];
829  size_t len = parsekeys(C_AbortKey, buf, mutt_array_size(buf));
830  if (len == 0)
831  {
832  mutt_error(_("Abort key is not set, defaulting to Ctrl-G"));
833  AbortKey = ctrl('G');
834  return;
835  }
836  if (len > 1)
837  {
838  mutt_warning(
839  _("Specified abort key sequence (%s) will be truncated to first key"), C_AbortKey);
840  }
841  AbortKey = buf[0];
842 }
843 
848 {
849  if (!nc->event_data)
850  return -1;
851  if (nc->event_type != NT_CONFIG)
852  return 0;
853 
854  struct EventConfig *ec = nc->event_data;
855 
856  if (!mutt_str_equal(ec->name, "abort_key"))
857  return 0;
858 
860  return 0;
861 }
862 
871 int km_expand_key(char *s, size_t len, struct Keymap *map)
872 {
873  if (!map)
874  return 0;
875 
876  int p = 0;
877 
878  while (true)
879  {
880  mutt_str_copy(s, km_keyname(map->keys[p]), len);
881  const size_t l = mutt_str_len(s);
882  len -= l;
883 
884  if ((++p >= map->len) || !len)
885  return 1;
886 
887  s += l;
888  }
889 
890  /* not reached */
891 }
892 
899 struct Keymap *km_find_func(enum MenuType menu, int func)
900 {
901  struct Keymap *map = Keymaps[menu];
902 
903  for (; map; map = map->next)
904  if (map->op == func)
905  break;
906  return map;
907 }
908 
909 #ifdef NCURSES_VERSION
910 
919 static const char *find_ext_name(const char *key)
920 {
921  for (int j = 0; ExtKeys[j].name; j++)
922  {
923  if (strcasecmp(key, ExtKeys[j].name) == 0)
924  return ExtKeys[j].sym;
925  }
926  return 0;
927 }
928 #endif /* NCURSES_VERSION */
929 
941 {
942 #ifdef NCURSES_VERSION
943  use_extended_names(true);
944 
945  for (int j = 0; KeyNames[j].name; j++)
946  {
947  if (KeyNames[j].value == -1)
948  {
949  const char *keyname = find_ext_name(KeyNames[j].name);
950 
951  if (keyname)
952  {
953  char *s = tigetstr((char *) keyname);
954  if (s && ((long) (s) != -1))
955  {
956  int code = key_defined(s);
957  if (code > 0)
958  KeyNames[j].value = code;
959  }
960  }
961  }
962  }
963 #endif
964 }
965 
969 void km_init(void)
970 {
971  memset(Keymaps, 0, sizeof(struct Keymap *) * MENU_MAX);
972 
981 
984 
987 
988 #ifdef CRYPT_BACKEND_GPGME
991 #endif
992 
993 #ifdef MIXMASTER
995 
996  km_bindkey("<space>", MENU_MIX, OP_GENERIC_SELECT_ENTRY);
997  km_bindkey("h", MENU_MIX, OP_MIX_CHAIN_PREV);
998  km_bindkey("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
999 #endif
1000 
1001 #ifdef USE_AUTOCRYPT
1003 #endif
1004 
1005  /* bindings for the line editor */
1007 
1008  km_bindkey("<up>", MENU_EDITOR, OP_EDITOR_HISTORY_UP);
1009  km_bindkey("<down>", MENU_EDITOR, OP_EDITOR_HISTORY_DOWN);
1010  km_bindkey("<left>", MENU_EDITOR, OP_EDITOR_BACKWARD_CHAR);
1011  km_bindkey("<right>", MENU_EDITOR, OP_EDITOR_FORWARD_CHAR);
1012  km_bindkey("<home>", MENU_EDITOR, OP_EDITOR_BOL);
1013  km_bindkey("<end>", MENU_EDITOR, OP_EDITOR_EOL);
1014  km_bindkey("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1015  km_bindkey("<delete>", MENU_EDITOR, OP_EDITOR_DELETE_CHAR);
1016  km_bindkey("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1017 
1018  /* generic menu keymap */
1020 
1021  km_bindkey("<home>", MENU_GENERIC, OP_FIRST_ENTRY);
1022  km_bindkey("<end>", MENU_GENERIC, OP_LAST_ENTRY);
1023  km_bindkey("<pagedown>", MENU_GENERIC, OP_NEXT_PAGE);
1024  km_bindkey("<pageup>", MENU_GENERIC, OP_PREV_PAGE);
1025  km_bindkey("<right>", MENU_GENERIC, OP_NEXT_PAGE);
1026  km_bindkey("<left>", MENU_GENERIC, OP_PREV_PAGE);
1027  km_bindkey("<up>", MENU_GENERIC, OP_PREV_ENTRY);
1028  km_bindkey("<down>", MENU_GENERIC, OP_NEXT_ENTRY);
1029  km_bindkey("1", MENU_GENERIC, OP_JUMP);
1030  km_bindkey("2", MENU_GENERIC, OP_JUMP);
1031  km_bindkey("3", MENU_GENERIC, OP_JUMP);
1032  km_bindkey("4", MENU_GENERIC, OP_JUMP);
1033  km_bindkey("5", MENU_GENERIC, OP_JUMP);
1034  km_bindkey("6", MENU_GENERIC, OP_JUMP);
1035  km_bindkey("7", MENU_GENERIC, OP_JUMP);
1036  km_bindkey("8", MENU_GENERIC, OP_JUMP);
1037  km_bindkey("9", MENU_GENERIC, OP_JUMP);
1038 
1039  km_bindkey("<return>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1040  km_bindkey("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1041 
1042  /* Miscellaneous extra bindings */
1043 
1044  km_bindkey(" ", MENU_MAIN, OP_DISPLAY_MESSAGE);
1045  km_bindkey("<up>", MENU_MAIN, OP_MAIN_PREV_UNDELETED);
1046  km_bindkey("<down>", MENU_MAIN, OP_MAIN_NEXT_UNDELETED);
1047  km_bindkey("J", MENU_MAIN, OP_NEXT_ENTRY);
1048  km_bindkey("K", MENU_MAIN, OP_PREV_ENTRY);
1049  km_bindkey("x", MENU_MAIN, OP_EXIT);
1050 
1051  km_bindkey("<return>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1052  km_bindkey("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1053 
1054  km_bindkey("x", MENU_PAGER, OP_EXIT);
1055  km_bindkey("i", MENU_PAGER, OP_EXIT);
1056  km_bindkey("<backspace>", MENU_PAGER, OP_PREV_LINE);
1057  km_bindkey("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
1058  km_bindkey("<pageup>", MENU_PAGER, OP_PREV_PAGE);
1059  km_bindkey("<up>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
1060  km_bindkey("<right>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
1061  km_bindkey("<down>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
1062  km_bindkey("<left>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
1063  km_bindkey("<home>", MENU_PAGER, OP_PAGER_TOP);
1064  km_bindkey("<end>", MENU_PAGER, OP_PAGER_BOTTOM);
1065  km_bindkey("1", MENU_PAGER, OP_JUMP);
1066  km_bindkey("2", MENU_PAGER, OP_JUMP);
1067  km_bindkey("3", MENU_PAGER, OP_JUMP);
1068  km_bindkey("4", MENU_PAGER, OP_JUMP);
1069  km_bindkey("5", MENU_PAGER, OP_JUMP);
1070  km_bindkey("6", MENU_PAGER, OP_JUMP);
1071  km_bindkey("7", MENU_PAGER, OP_JUMP);
1072  km_bindkey("8", MENU_PAGER, OP_JUMP);
1073  km_bindkey("9", MENU_PAGER, OP_JUMP);
1074 
1075  km_bindkey("<return>", MENU_PAGER, OP_NEXT_LINE);
1076  km_bindkey("<enter>", MENU_PAGER, OP_NEXT_LINE);
1077 
1078  km_bindkey("<return>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
1079  km_bindkey("<enter>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
1080  km_bindkey("<space>", MENU_ALIAS, OP_TAG);
1081 
1082  km_bindkey("<return>", MENU_ATTACH, OP_VIEW_ATTACH);
1083  km_bindkey("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
1084  km_bindkey("<return>", MENU_COMPOSE, OP_VIEW_ATTACH);
1085  km_bindkey("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
1086 
1087  /* edit-to (default "t") hides generic tag-entry in Compose menu
1088  * This will bind tag-entry to "T" in the Compose menu */
1089  km_bindkey("T", MENU_COMPOSE, OP_TAG);
1090 }
1091 
1096 void km_error_key(enum MenuType menu)
1097 {
1098  char buf[128];
1099  int p, op;
1100 
1101  struct Keymap *key = km_find_func(menu, OP_HELP);
1102  if (!key && (menu != MENU_EDITOR) && (menu != MENU_PAGER))
1103  key = km_find_func(MENU_GENERIC, OP_HELP);
1104  if (!key)
1105  {
1106  mutt_error(_("Key is not bound"));
1107  return;
1108  }
1109 
1110  /* Make sure the key is really the help key in this menu.
1111  *
1112  * OP_END_COND is used as a barrier to ensure nothing extra
1113  * is left in the unget buffer.
1114  *
1115  * Note that km_expand_key() + tokenize_unget_string() should
1116  * not be used here: control sequences are expanded to a form
1117  * (e.g. "^H") not recognized by km_dokey(). */
1118  mutt_unget_event(0, OP_END_COND);
1119  p = key->len;
1120  while (p--)
1121  mutt_unget_event(key->keys[p], 0);
1122 
1123  /* Note, e.g. for the index menu:
1124  * bind generic ? noop
1125  * bind generic ,a help
1126  * bind index ,ab quit
1127  * The index keybinding shadows the generic binding.
1128  * OP_END_COND will be read and returned as the op.
1129  *
1130  * bind generic ? noop
1131  * bind generic dq help
1132  * bind index d delete-message
1133  * OP_DELETE will be returned as the op, leaving "q" + OP_END_COND
1134  * in the unget buffer.
1135  */
1136  op = km_dokey(menu);
1137  if (op != OP_END_COND)
1139  if (op != OP_HELP)
1140  {
1141  mutt_error(_("Key is not bound"));
1142  return;
1143  }
1144 
1145  km_expand_key(buf, sizeof(buf), key);
1146  mutt_error(_("Key is not bound. Press '%s' for help."), buf);
1147 }
1148 
1152 enum CommandResult mutt_parse_push(struct Buffer *buf, struct Buffer *s,
1153  intptr_t data, struct Buffer *err)
1154 {
1156  if (MoreArgs(s))
1157  {
1158  mutt_buffer_printf(err, _("%s: too many arguments"), "push");
1159  return MUTT_CMD_ERROR;
1160  }
1161 
1163  return MUTT_CMD_SUCCESS;
1164 }
1165 
1180 static char *parse_keymap(enum MenuType *menu, struct Buffer *s, int max_menus,
1181  int *num_menus, struct Buffer *err, bool bind)
1182 {
1183  struct Buffer buf;
1184  int i = 0;
1185  char *q = NULL;
1186 
1187  mutt_buffer_init(&buf);
1188 
1189  /* menu name */
1191  char *p = buf.data;
1192  if (MoreArgs(s))
1193  {
1194  while (i < max_menus)
1195  {
1196  q = strchr(p, ',');
1197  if (q)
1198  *q = '\0';
1199 
1200  int val = mutt_map_get_value(p, Menus);
1201  if (val == -1)
1202  {
1203  mutt_buffer_printf(err, _("%s: no such menu"), p);
1204  goto error;
1205  }
1206  menu[i] = val;
1207  i++;
1208  if (q)
1209  p = q + 1;
1210  else
1211  break;
1212  }
1213  *num_menus = i;
1214  /* key sequence */
1216 
1217  if (buf.data[0] == '\0')
1218  {
1219  mutt_buffer_printf(err, _("%s: null key sequence"), bind ? "bind" : "macro");
1220  }
1221  else if (MoreArgs(s))
1222  return buf.data;
1223  }
1224  else
1225  {
1226  mutt_buffer_printf(err, _("%s: too few arguments"), bind ? "bind" : "macro");
1227  }
1228 error:
1229  FREE(&buf.data);
1230  return NULL;
1231 }
1232 
1242 static enum CommandResult try_bind(char *key, enum MenuType menu, char *func,
1243  const struct Binding *bindings, struct Buffer *err)
1244 {
1245  for (int i = 0; bindings[i].name; i++)
1246  {
1247  if (mutt_str_equal(func, bindings[i].name))
1248  {
1249  return km_bindkey_err(key, menu, bindings[i].op, err);
1250  }
1251  }
1252  if (err)
1253  {
1254  mutt_buffer_printf(err, _("Function '%s' not available for menu '%s'"),
1255  func, mutt_map_get_name(menu, Menus));
1256  }
1257  return MUTT_CMD_ERROR; /* Couldn't find an existing function with this name */
1258 }
1259 
1265 const struct Binding *km_get_table(enum MenuType menu)
1266 {
1267  switch (menu)
1268  {
1269  case MENU_ALIAS:
1270  return OpAlias;
1271  case MENU_ATTACH:
1272  return OpAttach;
1273 #ifdef USE_AUTOCRYPT
1274  case MENU_AUTOCRYPT_ACCT:
1275  return OpAutocryptAcct;
1276 #endif
1277  case MENU_COMPOSE:
1278  return OpCompose;
1279  case MENU_EDITOR:
1280  return OpEditor;
1281  case MENU_FOLDER:
1282  return OpBrowser;
1283  case MENU_GENERIC:
1284  return OpGeneric;
1285 #ifdef CRYPT_BACKEND_GPGME
1286  case MENU_KEY_SELECT_PGP:
1287  return OpPgp;
1288  case MENU_KEY_SELECT_SMIME:
1289  return OpSmime;
1290 #endif
1291  case MENU_MAIN:
1292  return OpMain;
1293 #ifdef MIXMASTER
1294  case MENU_MIX:
1295  return OpMix;
1296 #endif
1297  case MENU_PAGER:
1298  return OpPager;
1299  case MENU_PGP:
1300  return (WithCrypto & APPLICATION_PGP) ? OpPgp : NULL;
1301  case MENU_POSTPONE:
1302  return OpPost;
1303  case MENU_QUERY:
1304  return OpQuery;
1305  default:
1306  return NULL;
1307  }
1308 }
1309 
1315 enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s,
1316  intptr_t data, struct Buffer *err)
1317 {
1318  const struct Binding *bindings = NULL;
1319  enum MenuType menu[sizeof(Menus) / sizeof(struct Mapping) - 1];
1320  int num_menus = 0;
1321  enum CommandResult rc = MUTT_CMD_SUCCESS;
1322 
1323  char *key = parse_keymap(menu, s, mutt_array_size(menu), &num_menus, err, true);
1324  if (!key)
1325  return MUTT_CMD_ERROR;
1326 
1327  /* function to execute */
1329  if (MoreArgs(s))
1330  {
1331  mutt_buffer_printf(err, _("%s: too many arguments"), "bind");
1332  rc = MUTT_CMD_ERROR;
1333  }
1334  else if (mutt_istr_equal("noop", buf->data))
1335  {
1336  for (int i = 0; i < num_menus; i++)
1337  {
1338  km_bindkey(key, menu[i], OP_NULL); /* the 'unbind' command */
1339  }
1340  }
1341  else
1342  {
1343  for (int i = 0; i < num_menus; i++)
1344  {
1345  /* The pager and editor menus don't use the generic map,
1346  * however for other menus try generic first. */
1347  if ((menu[i] != MENU_PAGER) && (menu[i] != MENU_EDITOR) && (menu[i] != MENU_GENERIC))
1348  {
1349  rc = try_bind(key, menu[i], buf->data, OpGeneric, err);
1350  if (rc == 0)
1351  continue;
1352  if (rc == -2)
1353  break;
1354  }
1355 
1356  /* Clear any error message, we're going to try again */
1357  err->data[0] = '\0';
1358  bindings = km_get_table(menu[i]);
1359  if (bindings)
1360  {
1361  rc = try_bind(key, menu[i], buf->data, bindings, err);
1362  }
1363  }
1364  }
1365  FREE(&key);
1366  return rc;
1367 }
1368 
1377 static void *parse_menu(bool *menu, char *s, struct Buffer *err)
1378 {
1379  char *menu_names_dup = mutt_str_dup(s);
1380  char *marker = menu_names_dup;
1381  char *menu_name = NULL;
1382 
1383  while ((menu_name = strsep(&marker, ",")))
1384  {
1385  int value = mutt_map_get_value(menu_name, Menus);
1386  if (value == -1)
1387  {
1388  mutt_buffer_printf(err, _("%s: no such menu"), menu_name);
1389  break;
1390  }
1391  else
1392  menu[value] = true;
1393  }
1394 
1395  FREE(&menu_names_dup);
1396  return NULL;
1397 }
1398 
1406 static void km_unbind_all(struct Keymap **map, unsigned long mode)
1407 {
1408  struct Keymap *next = NULL;
1409  struct Keymap *first = NULL;
1410  struct Keymap *last = NULL;
1411  struct Keymap *cur = *map;
1412 
1413  while (cur)
1414  {
1415  next = cur->next;
1416  if (((mode & MUTT_UNBIND) && !cur->macro) || ((mode & MUTT_UNMACRO) && cur->macro))
1417  {
1418  FREE(&cur->macro);
1419  FREE(&cur->keys);
1420  FREE(&cur->desc);
1421  FREE(&cur);
1422  }
1423  else if (!first)
1424  {
1425  first = cur;
1426  last = cur;
1427  }
1428  else if (last)
1429  {
1430  last->next = cur;
1431  last = cur;
1432  }
1433  else
1434  {
1435  last = cur;
1436  }
1437  cur = next;
1438  }
1439 
1440  if (last)
1441  last->next = NULL;
1442 
1443  *map = first;
1444 }
1445 
1456 enum CommandResult mutt_parse_unbind(struct Buffer *buf, struct Buffer *s,
1457  intptr_t data, struct Buffer *err)
1458 {
1459  bool menu[MENU_MAX] = { 0 };
1460  bool all_keys = false;
1461  char *key = NULL;
1462 
1464  if (mutt_str_equal(buf->data, "*"))
1465  {
1466  for (enum MenuType i = 0; i < MENU_MAX; i++)
1467  menu[i] = true;
1468  }
1469  else
1470  parse_menu(menu, buf->data, err);
1471 
1472  if (MoreArgs(s))
1473  {
1475  key = buf->data;
1476  }
1477  else
1478  all_keys = true;
1479 
1480  if (MoreArgs(s))
1481  {
1482  const char *cmd = (data & MUTT_UNMACRO) ? "unmacro" : "unbind";
1483 
1484  mutt_buffer_printf(err, _("%s: too many arguments"), cmd);
1485  return MUTT_CMD_ERROR;
1486  }
1487 
1488  for (enum MenuType i = 0; i < MENU_MAX; i++)
1489  {
1490  if (!menu[i])
1491  continue;
1492  if (all_keys)
1493  {
1494  km_unbind_all(&Keymaps[i], data);
1495  km_bindkey("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1496  km_bindkey("<return>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1497  km_bindkey("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1498  km_bindkey("<return>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1499  km_bindkey("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1500  km_bindkey("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1501  km_bindkey(":", MENU_GENERIC, OP_ENTER_COMMAND);
1502  km_bindkey(":", MENU_PAGER, OP_ENTER_COMMAND);
1503  if (i != MENU_EDITOR)
1504  {
1505  km_bindkey("?", i, OP_HELP);
1506  km_bindkey("q", i, OP_EXIT);
1507  }
1508  }
1509  else
1510  km_bindkey(key, i, OP_NULL);
1511  }
1512 
1513  return MUTT_CMD_SUCCESS;
1514 }
1515 
1521 enum CommandResult mutt_parse_macro(struct Buffer *buf, struct Buffer *s,
1522  intptr_t data, struct Buffer *err)
1523 {
1524  enum MenuType menu[sizeof(Menus) / sizeof(struct Mapping) - 1];
1525  int num_menus = 0;
1526  enum CommandResult rc = MUTT_CMD_ERROR;
1527  char *seq = NULL;
1528 
1529  char *key = parse_keymap(menu, s, mutt_array_size(menu), &num_menus, err, false);
1530  if (!key)
1531  return MUTT_CMD_ERROR;
1532 
1534  /* make sure the macro sequence is not an empty string */
1535  if (buf->data[0] == '\0')
1536  {
1537  mutt_buffer_strcpy(err, _("macro: empty key sequence"));
1538  }
1539  else
1540  {
1541  if (MoreArgs(s))
1542  {
1543  seq = mutt_str_dup(buf->data);
1545 
1546  if (MoreArgs(s))
1547  {
1548  mutt_buffer_printf(err, _("%s: too many arguments"), "macro");
1549  }
1550  else
1551  {
1552  for (int i = 0; i < num_menus; i++)
1553  {
1554  rc = km_bind(key, menu[i], OP_MACRO, seq, buf->data);
1555  }
1556  }
1557 
1558  FREE(&seq);
1559  }
1560  else
1561  {
1562  for (int i = 0; i < num_menus; i++)
1563  {
1564  rc = km_bind(key, menu[i], OP_MACRO, buf->data, NULL);
1565  }
1566  }
1567  }
1568  FREE(&key);
1569  return rc;
1570 }
1571 
1575 enum CommandResult mutt_parse_exec(struct Buffer *buf, struct Buffer *s,
1576  intptr_t data, struct Buffer *err)
1577 {
1578  int ops[128];
1579  int nops = 0;
1580  const struct Binding *bindings = NULL;
1581  char *function = NULL;
1582 
1583  if (!MoreArgs(s))
1584  {
1585  mutt_buffer_strcpy(err, _("exec: no arguments"));
1586  return MUTT_CMD_ERROR;
1587  }
1588 
1589  do
1590  {
1592  function = buf->data;
1593 
1594  bindings = km_get_table(CurrentMenu);
1595  if (!bindings && (CurrentMenu != MENU_PAGER))
1596  bindings = OpGeneric;
1597 
1598  ops[nops] = get_op(bindings, function, mutt_str_len(function));
1599  if ((ops[nops] == OP_NULL) && (CurrentMenu != MENU_PAGER))
1600  ops[nops] = get_op(OpGeneric, function, mutt_str_len(function));
1601 
1602  if (ops[nops] == OP_NULL)
1603  {
1604  mutt_flushinp();
1605  mutt_error(_("%s: no such function"), function);
1606  return MUTT_CMD_ERROR;
1607  }
1608  nops++;
1609  } while (MoreArgs(s) && nops < mutt_array_size(ops));
1610 
1611  while (nops)
1612  mutt_push_macro_event(0, ops[--nops]);
1613 
1614  return MUTT_CMD_SUCCESS;
1615 }
1616 
1622 void mutt_what_key(void)
1623 {
1624  int ch;
1625 
1626  mutt_window_mvprintw(MuttMessageWindow, 0, 0, _("Enter keys (%s to abort): "),
1627  km_keyname(AbortKey));
1628  do
1629  {
1630  ch = getch();
1631  if ((ch != ERR) && (ch != AbortKey))
1632  {
1633  mutt_message(_("Char = %s, Octal = %o, Decimal = %d"), km_keyname(ch), ch, ch);
1634  }
1635  } while (ch != ERR && ch != AbortKey);
1636 
1637  mutt_flushinp();
1638  mutt_clear_error();
1639 }
1640 
1644 void mutt_keys_free(void)
1645 {
1646  struct Keymap *map = NULL;
1647  struct Keymap *next = NULL;
1648 
1649  for (int i = 0; i < MENU_MAX; i++)
1650  {
1651  for (map = Keymaps[i]; map; map = next)
1652  {
1653  next = map->next;
1654 
1655  FREE(&map->macro);
1656  FREE(&map->desc);
1657  FREE(&map->keys);
1658  FREE(&map);
1659  }
1660 
1661  Keymaps[i] = NULL;
1662  }
1663 }
int km_dokey(enum MenuType menu)
Determine what a keypress should do.
Definition: keymap.c:620
const struct Binding OpPager[]
Key bindings for the pager menu.
Definition: functions.c:264
short eq
number of leading keys equal to next entry
Definition: keymap.h:53
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
Convenience wrapper for the gui headers.
static const char * km_keyname(int c)
Get the human name for a key.
Definition: keymap.c:790
#define mutt_warning(...)
Definition: logging.h:82
PGP encryption menu.
Definition: keymap.h:82
Manage keymappings.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define WithCrypto
Definition: lib.h:118
IMAP network mailbox.
const struct Binding OpPgp[]
Key bindings for the pgp menu.
Definition: functions.c:640
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:33
Config/command parsing.
Data passed to a notification function.
Definition: observer.h:39
Error: Can&#39;t help the user.
Definition: mutt_commands.h:35
WHERE short C_Timeout
Config: Time to wait for user input in menus.
Definition: mutt_globals.h:118
MenuType
Types of GUI selections.
Definition: keymap.h:70
#define mutt_message(...)
Definition: logging.h:83
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: curs_lib.c:868
int op
function id number
Definition: keymap.h:121
static int parse_keycode(const char *s)
Parse a numeric keycode.
Definition: keymap.c:247
void imap_keepalive(void)
poll the current folder to keep the connection alive
Definition: util.c:1081
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:916
keycode_t * keys
key sequence
Definition: keymap.h:55
NeoMutt Logging.
General file/mailbox browser.
Definition: keymap.h:76
enum CommandResult mutt_parse_exec(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;exec&#39; command - Implements Command::parse()
Definition: keymap.c:1575
A config-change event.
Definition: subset.h:70
static enum CommandResult km_bindkey_err(const char *s, enum MenuType menu, int op, struct Buffer *err)
Bind a key in a Menu to an operation (with error message)
Definition: keymap.c:453
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:831
#define _(a)
Definition: message.h:28
void km_init(void)
Initialise all the menu keybindings.
Definition: keymap.c:969
Autocrypt Account menu.
Definition: keymap.h:92
WHERE char * C_AbortKey
Config: String representation of key to abort prompts.
Definition: mutt_globals.h:85
Compose an email.
Definition: keymap.h:74
int op
function op
Definition: keymap.h:64
int ch
raw key pressed
Definition: keymap.h:63
WHERE bool OptIgnoreMacroEvents
(pseudo) don&#39;t process macro/push/exec events while set
Definition: options.h:38
bool MonitorFilesChanged
true after a monitored file has changed
Definition: monitor.c:50
static void km_unbind_all(struct Keymap **map, unsigned long mode)
Free all the keys in the supplied Keymap.
Definition: keymap.c:1406
Index panel (list of emails)
Definition: keymap.h:78
static char * parse_keymap(enum MenuType *menu, struct Buffer *s, int max_menus, int *num_menus, struct Buffer *err, bool bind)
Parse a user-config key binding.
Definition: keymap.c:1180
#define MUTT_UNMACRO
Definition: keymap.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
#define IsPrint(ch)
Definition: mbyte.h:39
int value
Definition: mapping.h:34
All user-callable functions.
enum CommandResult mutt_parse_push(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;push&#39; command - Implements Command::parse()
Definition: keymap.c:1152
const struct Binding OpCompose[]
Key bindings for the compose menu.
Definition: functions.c:456
const struct Binding OpSmime[]
Key bindings for the smime menu.
Definition: functions.c:649
enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;bind&#39; command - Implements Command::parse()
Definition: keymap.c:1315
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:626
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:41
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: keymap.c:940
#define mutt_array_size(x)
Definition: memory.h:33
static enum CommandResult km_bindkey(const char *s, enum MenuType menu, int op)
Bind a key in a Menu to an operation.
Definition: keymap.c:466
SMIME encryption menu.
Definition: keymap.h:83
Pager pager (email viewer)
Definition: keymap.h:79
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
size_t dsize
Length of data.
Definition: buffer.h:37
#define MoreArgs(buf)
Definition: buffer.h:43
const char * mutt_get_func(const struct Binding *bindings, int op)
Get the name of a function.
Definition: keymap.c:501
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: mutt_globals.h:78
Select from results of external query.
Definition: keymap.h:81
const struct Binding OpMix[]
Key bindings for the mixmaster menu.
Definition: functions.c:661
Many unsorted constants and some structs.
const struct Binding OpAlias[]
Key bindings for the alias menu.
Definition: functions.c:535
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1622
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:55
int LastKey
contains the last key the user pressed
Definition: keymap.c:146
static size_t parsekeys(const char *str, keycode_t *d, size_t max)
Parse a key string into key codes.
Definition: keymap.c:270
const char * name
name of the function
Definition: keymap.h:120
short op
operation to perform
Definition: keymap.h:52
#define ctrl(ch)
Definition: mutt_curses.h:66
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
const struct Binding OpPost[]
Key bindings for the postpone menu.
Definition: functions.c:526
struct Keymap * km_find_func(enum MenuType menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:899
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: keymap.c:826
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:72
const struct Mapping Menus[]
Menu name lookup table.
Definition: keymap.c:61
static int parse_fkey(char *s)
Parse a function key string.
Definition: keymap.c:220
struct Keymap * next
next key in map
Definition: keymap.h:51
static struct Keymap * alloc_keys(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition: keymap.c:204
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
Select an attachment.
Definition: keymap.h:73
void km_error_key(enum MenuType menu)
Handle an unbound key sequence.
Definition: keymap.c:1096
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1644
enum CommandResult mutt_parse_unbind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unbind&#39; command - Implements Command::parse()
Definition: keymap.c:1456
static enum CommandResult km_bind_err(const char *s, enum MenuType menu, int op, char *macro, char *desc, struct Buffer *err)
Set up a key binding.
Definition: keymap.c:335
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:422
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:871
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * macro
macro expansion (op == OP_MACRO)
Definition: keymap.h:49
Select a PGP key.
Definition: keymap.h:85
int mutt_abort_key_config_observer(struct NotifyCallback *nc)
Listen for abort_key config changes - Implements observer_t.
Definition: keymap.c:847
char * data
Pointer to data.
Definition: buffer.h:35
static void generic_tokenize_push_string(char *s, void(*generic_push)(int, int))
Parse and queue a &#39;push&#39; command.
Definition: keymap.c:521
Definitions of NeoMutt commands.
API for encryption/signing of emails.
static void create_bindings(const struct Binding *map, enum MenuType menu)
Attach a set of keybindings to a Menu.
Definition: keymap.c:776
An event such as a keypress.
Definition: keymap.h:61
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:187
short keycode_t
Definition: keymap.h:38
char * desc
description of a macro for the help menu
Definition: keymap.h:50
const struct Binding OpQuery[]
Key bindings for the external query menu.
Definition: functions.c:597
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:147
Select an email address by its alias.
Definition: keymap.h:72
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
A keyboard mapping.
Definition: keymap.h:47
void * event_data
Data from notify_send()
Definition: observer.h:43
short C_ImapKeepalive
Config: (imap) Time to wait before polling an open IMAP connection.
Definition: config.c:46
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:36
#define IS_SPACE(ch)
Definition: string2.h:38
short len
length of key sequence (unit: sizeof (keycode_t))
Definition: keymap.h:54
static int retry_generic(enum MenuType menu, keycode_t *keys, int keyslen, int lastkey)
Try to find the key in the generic menu bindings.
Definition: keymap.c:594
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
static enum CommandResult try_bind(char *key, enum MenuType menu, char *func, const struct Binding *bindings, struct Buffer *err)
Try to make a key binding.
Definition: keymap.c:1242
Success: Command worked.
Definition: mutt_commands.h:37
Definitions of user functions.
static void * parse_menu(bool *menu, char *s, struct Buffer *err)
Parse menu-names into an array.
Definition: keymap.c:1377
Warning: Help given to the user.
Definition: mutt_commands.h:36
int n
Definition: acutest.h:492
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:721
#define mutt_error(...)
Definition: logging.h:84
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:904
void mutt_getch_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:144
const struct Binding OpEditor[]
Key bindings for the editor menu.
Definition: functions.c:608
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1265
Create/edit a Mixmaster chain.
Definition: keymap.h:89
const char * seq
default key binding
Definition: keymap.h:122
Select a SMIME key.
Definition: keymap.h:86
#define FREE(x)
Definition: memory.h:40
Mapping between user-readable string and a constant.
Definition: mapping.h:31
#define MAX_SEQ
Definition: keymap.h:35
Monitor files for changes.
void mutt_unget_string(const char *s)
Return a string to the input buffer.
Definition: curs_lib.c:850
enum CommandResult km_bind(char *s, enum MenuType menu, int op, char *macro, char *desc)
Bind a key to a macro.
Definition: keymap.c:440
Text entry area.
Definition: keymap.h:75
#define MUTT_UNBIND
Definition: keymap.h:32
int mutt_window_mvprintw(struct MuttWindow *win, int col, int row, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:395
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:46
const struct Binding OpMain[]
Key bindings for the index menu.
Definition: functions.c:104
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
const char * name
Definition: mapping.h:33
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
Convenience wrapper for the library headers.
static int get_op(const struct Binding *bindings, const char *start, size_t len)
Get the function by its name.
Definition: keymap.c:478
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:76
enum CommandResult mutt_parse_macro(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;macro&#39; command - Implements Command::parse()
Definition: keymap.c:1521
const char * name
Name of config item that changed.
Definition: subset.h:73
Mapping between a user key and a function.
Definition: keymap.h:118
const struct Binding OpAutocryptAcct[]
Key bindings for the autocrypt account.
Definition: functions.c:677
const struct Binding OpBrowser[]
Key bindings for the file browser menu.
Definition: functions.c:544
Select a postponed email.
Definition: keymap.h:80
const struct Binding OpAttach[]
Key bindings for the attachment menu.
Definition: functions.c:420
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
Generic selection list.
Definition: keymap.h:77
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85