NeoMutt  2020-09-25
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 "ncrypt/lib.h"
41 #include "functions.h"
42 #include "init.h"
43 #include "mutt_commands.h"
44 #include "mutt_globals.h"
45 #include "mutt_logging.h"
46 #include "opcodes.h"
47 #include "options.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 KeymapList 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 
202 static void mutt_keymap_free(struct Keymap **km)
203 {
204  if (!km || !*km)
205  return;
206 
207  FREE(&(*km)->macro);
208  FREE(&(*km)->desc);
209  FREE(&(*km)->keys);
210  FREE(km);
211 }
212 
217 static void mutt_keymaplist_free(struct KeymapList *km_list)
218 {
219  struct Keymap *np = NULL, *tmp = NULL;
220  STAILQ_FOREACH_SAFE(np, km_list, entries, tmp)
221  {
222  STAILQ_REMOVE(km_list, np, Keymap, entries);
223  mutt_keymap_free(&np);
224  }
225 }
226 
233 static struct Keymap *alloc_keys(size_t len, keycode_t *keys)
234 {
235  struct Keymap *p = mutt_mem_calloc(1, sizeof(struct Keymap));
236  p->len = len;
237  p->keys = mutt_mem_calloc(len, sizeof(keycode_t));
238  memcpy(p->keys, keys, len * sizeof(keycode_t));
239  return p;
240 }
241 
249 static int parse_fkey(char *s)
250 {
251  char *t = NULL;
252  int n = 0;
253 
254  if ((s[0] != '<') || (tolower(s[1]) != 'f'))
255  return -1;
256 
257  for (t = s + 2; *t && isdigit((unsigned char) *t); t++)
258  {
259  n *= 10;
260  n += *t - '0';
261  }
262 
263  if (*t != '>')
264  return -1;
265  return n;
266 }
267 
276 static int parse_keycode(const char *s)
277 {
278  char *end_char = NULL;
279  long int result = strtol(s + 1, &end_char, 8);
280  /* allow trailing whitespace, eg. < 1001 > */
281  while (IS_SPACE(*end_char))
282  end_char++;
283  /* negative keycodes don't make sense, also detect overflow */
284  if ((*end_char != '>') || (result < 0) || (result == LONG_MAX))
285  {
286  return -1;
287  }
288 
289  return result;
290 }
291 
299 static size_t parsekeys(const char *str, keycode_t *d, size_t max)
300 {
301  int n;
302  size_t len = max;
303  char buf[128];
304  char c;
305  char *t = NULL;
306 
307  mutt_str_copy(buf, str, sizeof(buf));
308  char *s = buf;
309 
310  while (*s && len)
311  {
312  *d = '\0';
313  if ((*s == '<') && (t = strchr(s, '>')))
314  {
315  t++;
316  c = *t;
317  *t = '\0';
318 
319  n = mutt_map_get_value(s, KeyNames);
320  if (n != -1)
321  {
322  s = t;
323  *d = n;
324  }
325  else if ((n = parse_fkey(s)) > 0)
326  {
327  s = t;
328  *d = KEY_F(n);
329  }
330  else if ((n = parse_keycode(s)) > 0)
331  {
332  s = t;
333  *d = n;
334  }
335 
336  *t = c;
337  }
338 
339  if (!*d)
340  {
341  *d = (unsigned char) *s;
342  s++;
343  }
344  d++;
345  len--;
346  }
347 
348  return max - len;
349 }
350 
358 static struct Keymap *km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
359 {
360  while (*pos < k1->len && *pos < k2->len)
361  {
362  if (k1->keys[*pos] < k2->keys[*pos])
363  return k2;
364  else if (k1->keys[*pos] > k2->keys[*pos])
365  return k1;
366  else
367  *pos = *pos + 1;
368  }
369 
370  return NULL;
371 }
372 
386 static enum CommandResult km_bind_err(const char *s, enum MenuType menu, int op,
387  char *macro, char *desc, struct Buffer *err)
388 {
390  struct Keymap *last = NULL, *np = NULL, *compare = NULL;
391  keycode_t buf[MAX_SEQ];
392  size_t pos = 0, lastpos = 0;
393 
394  size_t len = parsekeys(s, buf, MAX_SEQ);
395 
396  struct Keymap *map = alloc_keys(len, buf);
397  map->op = op;
398  map->macro = mutt_str_dup(macro);
399  map->desc = mutt_str_dup(desc);
400 
401  /* find position to place new keymap */
402  STAILQ_FOREACH(np, &Keymaps[menu], entries)
403  {
404  compare = km_compare_keys(map, np, &pos);
405 
406  if (compare == map) /* map's keycode is bigger */
407  {
408  last = np;
409  lastpos = pos;
410  if (pos > np->eq)
411  pos = np->eq;
412  }
413  else if (compare == np) /* np's keycode is bigger, found insert location */
414  {
415  map->eq = pos;
416  break;
417  }
418  else /* equal keycodes */
419  {
420  /* Don't warn on overwriting a 'noop' binding */
421  if ((np->len != len) && (np->op != OP_NULL))
422  {
423  /* Overwrite with the different lengths, warn */
424  /* TODO: MAX_SEQ here is wrong */
425  char old_binding[MAX_SEQ];
426  char new_binding[MAX_SEQ];
427  km_expand_key(old_binding, MAX_SEQ, map);
428  km_expand_key(new_binding, MAX_SEQ, np);
429  char *err_msg =
430  _("Binding '%s' will alias '%s' Before, try: 'bind %s %s noop' "
431  "https://neomutt.org/guide/configuration.html#bind-warnings");
432  if (err)
433  {
434  /* err was passed, put the string there */
435  snprintf(err->data, err->dsize, err_msg, old_binding, new_binding,
436  mutt_map_get_name(menu, Menus), new_binding);
437  }
438  else
439  {
440  mutt_error(err_msg, old_binding, new_binding,
441  mutt_map_get_name(menu, Menus), new_binding);
442  }
443  rc = MUTT_CMD_WARNING;
444  }
445 
446  map->eq = np->eq;
447  STAILQ_REMOVE(&Keymaps[menu], np, Keymap, entries);
448  mutt_keymap_free(&np);
449  break;
450  }
451  }
452 
453  if (last) /* if queue has at least one entry */
454  {
455  if (STAILQ_NEXT(last, entries))
456  STAILQ_INSERT_AFTER(&Keymaps[menu], last, map, entries);
457  else /* last entry in the queue */
458  STAILQ_INSERT_TAIL(&Keymaps[menu], map, entries);
459  last->eq = lastpos;
460  }
461  else /* queue is empty, so insert from head */
462  {
463  STAILQ_INSERT_HEAD(&Keymaps[menu], map, entries);
464  }
465 
466  return rc;
467 }
468 
478 enum CommandResult km_bind(char *s, enum MenuType menu, int op, char *macro, char *desc)
479 {
480  return km_bind_err(s, menu, op, macro, desc, NULL);
481 }
482 
491 static enum CommandResult km_bindkey_err(const char *s, enum MenuType menu,
492  int op, struct Buffer *err)
493 {
494  return km_bind_err(s, menu, op, NULL, NULL, err);
495 }
496 
504 static enum CommandResult km_bindkey(const char *s, enum MenuType menu, int op)
505 {
506  return km_bindkey_err(s, menu, op, NULL);
507 }
508 
516 static int get_op(const struct Binding *bindings, const char *start, size_t len)
517 {
518  for (int i = 0; bindings[i].name; i++)
519  {
520  if (mutt_istrn_equal(start, bindings[i].name, len) &&
521  (mutt_str_len(bindings[i].name) == len))
522  {
523  return bindings[i].op;
524  }
525  }
526 
527  return OP_NULL;
528 }
529 
539 const char *mutt_get_func(const struct Binding *bindings, int op)
540 {
541  for (int i = 0; bindings[i].name; i++)
542  {
543  if (bindings[i].op == op)
544  return bindings[i].name;
545  }
546 
547  return NULL;
548 }
549 
559 static void generic_tokenize_push_string(char *s, void (*generic_push)(int, int))
560 {
561  char *pp = NULL;
562  char *p = s + mutt_str_len(s) - 1;
563  size_t l;
564  int i, op = OP_NULL;
565 
566  while (p >= s)
567  {
568  /* if we see something like "<PageUp>", look to see if it is a real
569  * function name and return the corresponding value */
570  if (*p == '>')
571  {
572  for (pp = p - 1; pp >= s && *pp != '<'; pp--)
573  ; // do nothing
574 
575  if (pp >= s)
576  {
577  i = parse_fkey(pp);
578  if (i > 0)
579  {
580  generic_push(KEY_F(i), 0);
581  p = pp - 1;
582  continue;
583  }
584 
585  l = p - pp + 1;
586  for (i = 0; KeyNames[i].name; i++)
587  {
588  if (mutt_istrn_equal(pp, KeyNames[i].name, l))
589  break;
590  }
591  if (KeyNames[i].name)
592  {
593  /* found a match */
594  generic_push(KeyNames[i].value, 0);
595  p = pp - 1;
596  continue;
597  }
598 
599  /* See if it is a valid command
600  * skip the '<' and the '>' when comparing */
601  for (enum MenuType j = 0; Menus[j].name; j++)
602  {
603  const struct Binding *binding = km_get_table(Menus[j].value);
604  if (binding)
605  {
606  op = get_op(binding, pp + 1, l - 2);
607  if (op != OP_NULL)
608  break;
609  }
610  }
611 
612  if (op != OP_NULL)
613  {
614  generic_push(0, op);
615  p = pp - 1;
616  continue;
617  }
618  }
619  }
620  generic_push((unsigned char) *p--, 0); /* independent 8 bits chars */
621  }
622 }
623 
632 static int retry_generic(enum MenuType menu, keycode_t *keys, int keyslen, int lastkey)
633 {
634  if ((menu != MENU_EDITOR) && (menu != MENU_GENERIC) && (menu != MENU_PAGER))
635  {
636  if (lastkey)
637  mutt_unget_event(lastkey, 0);
638  for (; keyslen; keyslen--)
639  mutt_unget_event(keys[keyslen - 1], 0);
640  return km_dokey(MENU_GENERIC);
641  }
642  if (menu != MENU_EDITOR)
643  {
644  /* probably a good idea to flush input here so we can abort macros */
645  mutt_flushinp();
646  }
647  return OP_NULL;
648 }
649 
658 int km_dokey(enum MenuType menu)
659 {
660  struct KeyEvent tmp;
661  struct Keymap *map = STAILQ_FIRST(&Keymaps[menu]);
662  int pos = 0;
663  int n = 0;
664 
665  if (!map && (menu != MENU_EDITOR))
666  return retry_generic(menu, NULL, 0, 0);
667 
668  while (true)
669  {
670  int i = (C_Timeout > 0) ? C_Timeout : 60;
671 #ifdef USE_IMAP
672  /* keepalive may need to run more frequently than C_Timeout allows */
673  if (C_ImapKeepalive)
674  {
675  if (C_ImapKeepalive >= i)
676  imap_keepalive();
677  else
678  {
679  while (C_ImapKeepalive && (C_ImapKeepalive < i))
680  {
682  tmp = mutt_getch();
683  mutt_getch_timeout(-1);
684  /* If a timeout was not received, or the window was resized, exit the
685  * loop now. Otherwise, continue to loop until reaching a total of
686  * $timeout seconds. */
687  if ((tmp.ch != -2) || SigWinch)
688  goto gotkey;
689 #ifdef USE_INOTIFY
691  goto gotkey;
692 #endif
693  i -= C_ImapKeepalive;
694  imap_keepalive();
695  }
696  }
697  }
698 #endif
699 
700  mutt_getch_timeout(i * 1000);
701  tmp = mutt_getch();
702  mutt_getch_timeout(-1);
703 
704 #ifdef USE_IMAP
705  gotkey:
706 #endif
707  /* hide timeouts, but not window resizes, from the line editor. */
708  if ((menu == MENU_EDITOR) && (tmp.ch == -2) && !SigWinch)
709  continue;
710 
711  LastKey = tmp.ch;
712  if (LastKey < 0)
713  return LastKey;
714 
715  /* do we have an op already? */
716  if (tmp.op)
717  {
718  const char *func = NULL;
719  const struct Binding *bindings = NULL;
720 
721  /* is this a valid op for this menu? */
722  if ((bindings = km_get_table(menu)) && (func = mutt_get_func(bindings, tmp.op)))
723  return tmp.op;
724 
725  if ((menu == MENU_EDITOR) && mutt_get_func(OpEditor, tmp.op))
726  return tmp.op;
727 
728  if ((menu != MENU_EDITOR) && (menu != MENU_PAGER))
729  {
730  /* check generic menu */
731  bindings = OpGeneric;
732  func = mutt_get_func(bindings, tmp.op);
733  if (func)
734  return tmp.op;
735  }
736 
737  /* Sigh. Valid function but not in this context.
738  * Find the literal string and push it back */
739  for (i = 0; Menus[i].name; i++)
740  {
741  bindings = km_get_table(Menus[i].value);
742  if (bindings)
743  {
744  func = mutt_get_func(bindings, tmp.op);
745  if (func)
746  {
747  mutt_unget_event('>', 0);
748  mutt_unget_string(func);
749  mutt_unget_event('<', 0);
750  break;
751  }
752  }
753  }
754  /* continue to chew */
755  if (func)
756  continue;
757  }
758 
759  if (!map)
760  return tmp.op;
761 
762  /* Nope. Business as usual */
763  while (LastKey > map->keys[pos])
764  {
765  if ((pos > map->eq) || !STAILQ_NEXT(map, entries))
766  return retry_generic(menu, map->keys, pos, LastKey);
767  map = STAILQ_NEXT(map, entries);
768  }
769 
770  if (LastKey != map->keys[pos])
771  return retry_generic(menu, map->keys, pos, LastKey);
772 
773  if (++pos == map->len)
774  {
775  if (map->op != OP_MACRO)
776  return map->op;
777 
778  /* OptIgnoreMacroEvents turns off processing the MacroEvents buffer
779  * in mutt_getch(). Generating new macro events during that time would
780  * result in undesired behavior once the option is turned off.
781  *
782  * Originally this returned -1, however that results in an unbuffered
783  * username or password prompt being aborted. Returning OP_NULL allows
784  * mutt_enter_string_full() to display the keybinding pressed instead.
785  *
786  * It may be unexpected for a macro's keybinding to be returned,
787  * but less so than aborting the prompt. */
789  {
790  return OP_NULL;
791  }
792 
793  if (n++ == 10)
794  {
795  mutt_flushinp();
796  mutt_error(_("Macro loop detected"));
797  return -1;
798  }
799 
801  map = STAILQ_FIRST(&Keymaps[menu]);
802  pos = 0;
803  }
804  }
805 
806  /* not reached */
807 }
808 
814 static void create_bindings(const struct Binding *map, enum MenuType menu)
815 {
816  STAILQ_INIT(&Keymaps[menu]);
817 
818  for (int i = 0; map[i].name; i++)
819  if (map[i].seq)
820  km_bindkey(map[i].seq, menu, map[i].op);
821 }
822 
830 static const char *km_keyname(int c)
831 {
832  static char buf[35];
833 
834  const char *p = mutt_map_get_name(c, KeyNames);
835  if (p)
836  return p;
837 
838  if ((c < 256) && (c > -128) && iscntrl((unsigned char) c))
839  {
840  if (c < 0)
841  c += 256;
842 
843  if (c < 128)
844  {
845  buf[0] = '^';
846  buf[1] = (c + '@') & 0x7f;
847  buf[2] = '\0';
848  }
849  else
850  snprintf(buf, sizeof(buf), "\\%d%d%d", c >> 6, (c >> 3) & 7, c & 7);
851  }
852  else if ((c >= KEY_F0) && (c < KEY_F(256))) /* this maximum is just a guess */
853  sprintf(buf, "<F%d>", c - KEY_F0);
854  else if (IsPrint(c))
855  snprintf(buf, sizeof(buf), "%c", (unsigned char) c);
856  else
857  snprintf(buf, sizeof(buf), "\\x%hx", (unsigned short) c);
858  return buf;
859 }
860 
867 {
868  keycode_t buf[2];
869  size_t len = parsekeys(C_AbortKey, buf, mutt_array_size(buf));
870  if (len == 0)
871  {
872  mutt_error(_("Abort key is not set, defaulting to Ctrl-G"));
873  AbortKey = ctrl('G');
874  return;
875  }
876  if (len > 1)
877  {
878  mutt_warning(
879  _("Specified abort key sequence (%s) will be truncated to first key"), C_AbortKey);
880  }
881  AbortKey = buf[0];
882 }
883 
888 {
889  if (!nc->event_data)
890  return -1;
891  if (nc->event_type != NT_CONFIG)
892  return 0;
893 
894  struct EventConfig *ec = nc->event_data;
895 
896  if (!mutt_str_equal(ec->name, "abort_key"))
897  return 0;
898 
900  return 0;
901 }
902 
911 int km_expand_key(char *s, size_t len, struct Keymap *map)
912 {
913  if (!map)
914  return 0;
915 
916  int p = 0;
917 
918  while (true)
919  {
920  mutt_str_copy(s, km_keyname(map->keys[p]), len);
921  const size_t l = mutt_str_len(s);
922  len -= l;
923 
924  if ((++p >= map->len) || !len)
925  return 1;
926 
927  s += l;
928  }
929 
930  /* not reached */
931 }
932 
939 struct Keymap *km_find_func(enum MenuType menu, int func)
940 {
941  struct Keymap *np = NULL;
942  STAILQ_FOREACH(np, &Keymaps[menu], entries)
943  {
944  if (np->op == func)
945  break;
946  }
947  return np;
948 }
949 
950 #ifdef NCURSES_VERSION
951 
960 static const char *find_ext_name(const char *key)
961 {
962  for (int j = 0; ExtKeys[j].name; j++)
963  {
964  if (strcasecmp(key, ExtKeys[j].name) == 0)
965  return ExtKeys[j].sym;
966  }
967  return 0;
968 }
969 #endif /* NCURSES_VERSION */
970 
982 {
983 #ifdef NCURSES_VERSION
984  use_extended_names(true);
985 
986  for (int j = 0; KeyNames[j].name; j++)
987  {
988  if (KeyNames[j].value == -1)
989  {
990  const char *keyname = find_ext_name(KeyNames[j].name);
991 
992  if (keyname)
993  {
994  char *s = tigetstr((char *) keyname);
995  if (s && ((long) (s) != -1))
996  {
997  int code = key_defined(s);
998  if (code > 0)
999  KeyNames[j].value = code;
1000  }
1001  }
1002  }
1003  }
1004 #endif
1005 }
1006 
1010 void km_init(void)
1011 {
1012  memset(Keymaps, 0, sizeof(struct KeymapList) * MENU_MAX);
1013 
1022 
1025 
1028 
1029 #ifdef CRYPT_BACKEND_GPGME
1032 #endif
1033 
1034 #ifdef MIXMASTER
1036 
1037  km_bindkey("<space>", MENU_MIX, OP_GENERIC_SELECT_ENTRY);
1038  km_bindkey("h", MENU_MIX, OP_MIX_CHAIN_PREV);
1039  km_bindkey("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
1040 #endif
1041 
1042 #ifdef USE_AUTOCRYPT
1044 #endif
1045 
1046  /* bindings for the line editor */
1048 
1049  km_bindkey("<up>", MENU_EDITOR, OP_EDITOR_HISTORY_UP);
1050  km_bindkey("<down>", MENU_EDITOR, OP_EDITOR_HISTORY_DOWN);
1051  km_bindkey("<left>", MENU_EDITOR, OP_EDITOR_BACKWARD_CHAR);
1052  km_bindkey("<right>", MENU_EDITOR, OP_EDITOR_FORWARD_CHAR);
1053  km_bindkey("<home>", MENU_EDITOR, OP_EDITOR_BOL);
1054  km_bindkey("<end>", MENU_EDITOR, OP_EDITOR_EOL);
1055  km_bindkey("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1056  km_bindkey("<delete>", MENU_EDITOR, OP_EDITOR_DELETE_CHAR);
1057  km_bindkey("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1058 
1059  /* generic menu keymap */
1061 
1062  km_bindkey("<home>", MENU_GENERIC, OP_FIRST_ENTRY);
1063  km_bindkey("<end>", MENU_GENERIC, OP_LAST_ENTRY);
1064  km_bindkey("<pagedown>", MENU_GENERIC, OP_NEXT_PAGE);
1065  km_bindkey("<pageup>", MENU_GENERIC, OP_PREV_PAGE);
1066  km_bindkey("<right>", MENU_GENERIC, OP_NEXT_PAGE);
1067  km_bindkey("<left>", MENU_GENERIC, OP_PREV_PAGE);
1068  km_bindkey("<up>", MENU_GENERIC, OP_PREV_ENTRY);
1069  km_bindkey("<down>", MENU_GENERIC, OP_NEXT_ENTRY);
1070  km_bindkey("1", MENU_GENERIC, OP_JUMP);
1071  km_bindkey("2", MENU_GENERIC, OP_JUMP);
1072  km_bindkey("3", MENU_GENERIC, OP_JUMP);
1073  km_bindkey("4", MENU_GENERIC, OP_JUMP);
1074  km_bindkey("5", MENU_GENERIC, OP_JUMP);
1075  km_bindkey("6", MENU_GENERIC, OP_JUMP);
1076  km_bindkey("7", MENU_GENERIC, OP_JUMP);
1077  km_bindkey("8", MENU_GENERIC, OP_JUMP);
1078  km_bindkey("9", MENU_GENERIC, OP_JUMP);
1079 
1080  km_bindkey("<return>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1081  km_bindkey("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1082 
1083  /* Miscellaneous extra bindings */
1084 
1085  km_bindkey(" ", MENU_MAIN, OP_DISPLAY_MESSAGE);
1086  km_bindkey("<up>", MENU_MAIN, OP_MAIN_PREV_UNDELETED);
1087  km_bindkey("<down>", MENU_MAIN, OP_MAIN_NEXT_UNDELETED);
1088  km_bindkey("J", MENU_MAIN, OP_NEXT_ENTRY);
1089  km_bindkey("K", MENU_MAIN, OP_PREV_ENTRY);
1090  km_bindkey("x", MENU_MAIN, OP_EXIT);
1091 
1092  km_bindkey("<return>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1093  km_bindkey("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1094 
1095  km_bindkey("x", MENU_PAGER, OP_EXIT);
1096  km_bindkey("i", MENU_PAGER, OP_EXIT);
1097  km_bindkey("<backspace>", MENU_PAGER, OP_PREV_LINE);
1098  km_bindkey("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
1099  km_bindkey("<pageup>", MENU_PAGER, OP_PREV_PAGE);
1100  km_bindkey("<up>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
1101  km_bindkey("<right>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
1102  km_bindkey("<down>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
1103  km_bindkey("<left>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
1104  km_bindkey("<home>", MENU_PAGER, OP_PAGER_TOP);
1105  km_bindkey("<end>", MENU_PAGER, OP_PAGER_BOTTOM);
1106  km_bindkey("1", MENU_PAGER, OP_JUMP);
1107  km_bindkey("2", MENU_PAGER, OP_JUMP);
1108  km_bindkey("3", MENU_PAGER, OP_JUMP);
1109  km_bindkey("4", MENU_PAGER, OP_JUMP);
1110  km_bindkey("5", MENU_PAGER, OP_JUMP);
1111  km_bindkey("6", MENU_PAGER, OP_JUMP);
1112  km_bindkey("7", MENU_PAGER, OP_JUMP);
1113  km_bindkey("8", MENU_PAGER, OP_JUMP);
1114  km_bindkey("9", MENU_PAGER, OP_JUMP);
1115 
1116  km_bindkey("<return>", MENU_PAGER, OP_NEXT_LINE);
1117  km_bindkey("<enter>", MENU_PAGER, OP_NEXT_LINE);
1118 
1119  km_bindkey("<return>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
1120  km_bindkey("<enter>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
1121  km_bindkey("<space>", MENU_ALIAS, OP_TAG);
1122 
1123  km_bindkey("<return>", MENU_ATTACH, OP_VIEW_ATTACH);
1124  km_bindkey("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
1125  km_bindkey("<return>", MENU_COMPOSE, OP_VIEW_ATTACH);
1126  km_bindkey("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
1127 
1128  /* edit-to (default "t") hides generic tag-entry in Compose menu
1129  * This will bind tag-entry to "T" in the Compose menu */
1130  km_bindkey("T", MENU_COMPOSE, OP_TAG);
1131 }
1132 
1137 void km_error_key(enum MenuType menu)
1138 {
1139  char buf[128];
1140  int p, op;
1141 
1142  struct Keymap *key = km_find_func(menu, OP_HELP);
1143  if (!key && (menu != MENU_EDITOR) && (menu != MENU_PAGER))
1144  key = km_find_func(MENU_GENERIC, OP_HELP);
1145  if (!key)
1146  {
1147  mutt_error(_("Key is not bound"));
1148  return;
1149  }
1150 
1151  /* Make sure the key is really the help key in this menu.
1152  *
1153  * OP_END_COND is used as a barrier to ensure nothing extra
1154  * is left in the unget buffer.
1155  *
1156  * Note that km_expand_key() + tokenize_unget_string() should
1157  * not be used here: control sequences are expanded to a form
1158  * (e.g. "^H") not recognized by km_dokey(). */
1159  mutt_unget_event(0, OP_END_COND);
1160  p = key->len;
1161  while (p--)
1162  mutt_unget_event(key->keys[p], 0);
1163 
1164  /* Note, e.g. for the index menu:
1165  * bind generic ? noop
1166  * bind generic ,a help
1167  * bind index ,ab quit
1168  * The index keybinding shadows the generic binding.
1169  * OP_END_COND will be read and returned as the op.
1170  *
1171  * bind generic ? noop
1172  * bind generic dq help
1173  * bind index d delete-message
1174  * OP_DELETE will be returned as the op, leaving "q" + OP_END_COND
1175  * in the unget buffer.
1176  */
1177  op = km_dokey(menu);
1178  if (op != OP_END_COND)
1180  if (op != OP_HELP)
1181  {
1182  mutt_error(_("Key is not bound"));
1183  return;
1184  }
1185 
1186  km_expand_key(buf, sizeof(buf), key);
1187  mutt_error(_("Key is not bound. Press '%s' for help."), buf);
1188 }
1189 
1193 enum CommandResult mutt_parse_push(struct Buffer *buf, struct Buffer *s,
1194  intptr_t data, struct Buffer *err)
1195 {
1197  if (MoreArgs(s))
1198  {
1199  mutt_buffer_printf(err, _("%s: too many arguments"), "push");
1200  return MUTT_CMD_ERROR;
1201  }
1202 
1204  return MUTT_CMD_SUCCESS;
1205 }
1206 
1221 static char *parse_keymap(enum MenuType *menu, struct Buffer *s, int max_menus,
1222  int *num_menus, struct Buffer *err, bool bind)
1223 {
1224  struct Buffer buf;
1225  int i = 0;
1226  char *q = NULL;
1227 
1228  mutt_buffer_init(&buf);
1229 
1230  /* menu name */
1232  char *p = buf.data;
1233  if (MoreArgs(s))
1234  {
1235  while (i < max_menus)
1236  {
1237  q = strchr(p, ',');
1238  if (q)
1239  *q = '\0';
1240 
1241  int val = mutt_map_get_value(p, Menus);
1242  if (val == -1)
1243  {
1244  mutt_buffer_printf(err, _("%s: no such menu"), p);
1245  goto error;
1246  }
1247  menu[i] = val;
1248  i++;
1249  if (q)
1250  p = q + 1;
1251  else
1252  break;
1253  }
1254  *num_menus = i;
1255  /* key sequence */
1257 
1258  if (buf.data[0] == '\0')
1259  {
1260  mutt_buffer_printf(err, _("%s: null key sequence"), bind ? "bind" : "macro");
1261  }
1262  else if (MoreArgs(s))
1263  return buf.data;
1264  }
1265  else
1266  {
1267  mutt_buffer_printf(err, _("%s: too few arguments"), bind ? "bind" : "macro");
1268  }
1269 error:
1270  FREE(&buf.data);
1271  return NULL;
1272 }
1273 
1283 static enum CommandResult try_bind(char *key, enum MenuType menu, char *func,
1284  const struct Binding *bindings, struct Buffer *err)
1285 {
1286  for (int i = 0; bindings[i].name; i++)
1287  {
1288  if (mutt_str_equal(func, bindings[i].name))
1289  {
1290  return km_bindkey_err(key, menu, bindings[i].op, err);
1291  }
1292  }
1293  if (err)
1294  {
1295  mutt_buffer_printf(err, _("Function '%s' not available for menu '%s'"),
1296  func, mutt_map_get_name(menu, Menus));
1297  }
1298  return MUTT_CMD_ERROR; /* Couldn't find an existing function with this name */
1299 }
1300 
1306 const struct Binding *km_get_table(enum MenuType menu)
1307 {
1308  switch (menu)
1309  {
1310  case MENU_ALIAS:
1311  return OpAlias;
1312  case MENU_ATTACH:
1313  return OpAttach;
1314 #ifdef USE_AUTOCRYPT
1315  case MENU_AUTOCRYPT_ACCT:
1316  return OpAutocryptAcct;
1317 #endif
1318  case MENU_COMPOSE:
1319  return OpCompose;
1320  case MENU_EDITOR:
1321  return OpEditor;
1322  case MENU_FOLDER:
1323  return OpBrowser;
1324  case MENU_GENERIC:
1325  return OpGeneric;
1326 #ifdef CRYPT_BACKEND_GPGME
1327  case MENU_KEY_SELECT_PGP:
1328  return OpPgp;
1329  case MENU_KEY_SELECT_SMIME:
1330  return OpSmime;
1331 #endif
1332  case MENU_MAIN:
1333  return OpMain;
1334 #ifdef MIXMASTER
1335  case MENU_MIX:
1336  return OpMix;
1337 #endif
1338  case MENU_PAGER:
1339  return OpPager;
1340  case MENU_PGP:
1341  return (WithCrypto & APPLICATION_PGP) ? OpPgp : NULL;
1342  case MENU_POSTPONE:
1343  return OpPost;
1344  case MENU_QUERY:
1345  return OpQuery;
1346  default:
1347  return NULL;
1348  }
1349 }
1350 
1356 enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s,
1357  intptr_t data, struct Buffer *err)
1358 {
1359  const struct Binding *bindings = NULL;
1360  enum MenuType menu[sizeof(Menus) / sizeof(struct Mapping) - 1];
1361  int num_menus = 0;
1362  enum CommandResult rc = MUTT_CMD_SUCCESS;
1363 
1364  char *key = parse_keymap(menu, s, mutt_array_size(menu), &num_menus, err, true);
1365  if (!key)
1366  return MUTT_CMD_ERROR;
1367 
1368  /* function to execute */
1370  if (MoreArgs(s))
1371  {
1372  mutt_buffer_printf(err, _("%s: too many arguments"), "bind");
1373  rc = MUTT_CMD_ERROR;
1374  }
1375  else if (mutt_istr_equal("noop", buf->data))
1376  {
1377  for (int i = 0; i < num_menus; i++)
1378  {
1379  km_bindkey(key, menu[i], OP_NULL); /* the 'unbind' command */
1380  bindings = km_get_table(menu[i]);
1381  if (bindings)
1382  {
1383  int op = get_op(OpGeneric, buf->data, mutt_str_len(buf->data));
1384  struct EventBinding ev_bind = { menu[i], key, op };
1386  }
1387  }
1388  }
1389  else
1390  {
1391  for (int i = 0; i < num_menus; i++)
1392  {
1393  /* The pager and editor menus don't use the generic map,
1394  * however for other menus try generic first. */
1395  if ((menu[i] != MENU_PAGER) && (menu[i] != MENU_EDITOR) && (menu[i] != MENU_GENERIC))
1396  {
1397  rc = try_bind(key, menu[i], buf->data, OpGeneric, err);
1398  if (rc == MUTT_CMD_SUCCESS)
1399  {
1400  int op = get_op(OpGeneric, buf->data, mutt_str_len(buf->data));
1401  struct EventBinding ev_bind = { menu[i], key, op };
1403  continue;
1404  }
1405  if (rc == MUTT_CMD_WARNING)
1406  break;
1407  }
1408 
1409  /* Clear any error message, we're going to try again */
1410  err->data[0] = '\0';
1411  bindings = km_get_table(menu[i]);
1412  if (bindings)
1413  {
1414  rc = try_bind(key, menu[i], buf->data, bindings, err);
1415  if (rc == MUTT_CMD_SUCCESS)
1416  {
1417  int op = get_op(bindings, buf->data, mutt_str_len(buf->data));
1418  struct EventBinding ev_bind = { menu[i], key, op };
1420  continue;
1421  }
1422  }
1423  }
1424  }
1425  FREE(&key);
1426  return rc;
1427 }
1428 
1437 static void *parse_menu(bool *menu, char *s, struct Buffer *err)
1438 {
1439  char *menu_names_dup = mutt_str_dup(s);
1440  char *marker = menu_names_dup;
1441  char *menu_name = NULL;
1442 
1443  while ((menu_name = strsep(&marker, ",")))
1444  {
1445  int value = mutt_map_get_value(menu_name, Menus);
1446  if (value == -1)
1447  {
1448  mutt_buffer_printf(err, _("%s: no such menu"), menu_name);
1449  break;
1450  }
1451  else
1452  menu[value] = true;
1453  }
1454 
1455  FREE(&menu_names_dup);
1456  return NULL;
1457 }
1458 
1466 static void km_unbind_all(struct KeymapList *km_list, unsigned long mode)
1467 {
1468  struct Keymap *np = NULL, *tmp = NULL;
1469 
1470  STAILQ_FOREACH_SAFE(np, km_list, entries, tmp)
1471  {
1472  if (((mode & MUTT_UNBIND) && !np->macro) || ((mode & MUTT_UNMACRO) && np->macro))
1473  {
1474  STAILQ_REMOVE(km_list, np, Keymap, entries);
1475  mutt_keymap_free(&np);
1476  }
1477  }
1478 }
1479 
1490 enum CommandResult mutt_parse_unbind(struct Buffer *buf, struct Buffer *s,
1491  intptr_t data, struct Buffer *err)
1492 {
1493  bool menu[MENU_MAX] = { 0 };
1494  bool all_keys = false;
1495  char *key = NULL;
1496 
1498  if (mutt_str_equal(buf->data, "*"))
1499  {
1500  for (enum MenuType i = 0; i < MENU_MAX; i++)
1501  menu[i] = true;
1502  }
1503  else
1504  parse_menu(menu, buf->data, err);
1505 
1506  if (MoreArgs(s))
1507  {
1509  key = buf->data;
1510  }
1511  else
1512  all_keys = true;
1513 
1514  if (MoreArgs(s))
1515  {
1516  const char *cmd = (data & MUTT_UNMACRO) ? "unmacro" : "unbind";
1517 
1518  mutt_buffer_printf(err, _("%s: too many arguments"), cmd);
1519  return MUTT_CMD_ERROR;
1520  }
1521 
1522  for (enum MenuType i = 0; i < MENU_MAX; i++)
1523  {
1524  if (!menu[i])
1525  continue;
1526  if (all_keys)
1527  {
1528  km_unbind_all(&Keymaps[i], data);
1529  km_bindkey("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1530  km_bindkey("<return>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
1531  km_bindkey("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1532  km_bindkey("<return>", MENU_MAIN, OP_DISPLAY_MESSAGE);
1533  km_bindkey("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1534  km_bindkey("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
1535  km_bindkey(":", MENU_GENERIC, OP_ENTER_COMMAND);
1536  km_bindkey(":", MENU_PAGER, OP_ENTER_COMMAND);
1537  if (i != MENU_EDITOR)
1538  {
1539  km_bindkey("?", i, OP_HELP);
1540  km_bindkey("q", i, OP_EXIT);
1541  }
1542  struct EventBinding ev_bind = { i, NULL, OP_NULL };
1545  &ev_bind);
1546  }
1547  else
1548  {
1549  km_bindkey(key, i, OP_NULL);
1550  struct EventBinding ev_bind = { i, key, OP_NULL };
1552  (data & MUTT_UNMACRO) ? NT_MACRO_DELETED : NT_BINDING_DELETED, &ev_bind);
1553  }
1554  }
1555 
1556  return MUTT_CMD_SUCCESS;
1557 }
1558 
1564 enum CommandResult mutt_parse_macro(struct Buffer *buf, struct Buffer *s,
1565  intptr_t data, struct Buffer *err)
1566 {
1567  enum MenuType menu[sizeof(Menus) / sizeof(struct Mapping) - 1];
1568  int num_menus = 0;
1569  enum CommandResult rc = MUTT_CMD_ERROR;
1570 
1571  char *key = parse_keymap(menu, s, mutt_array_size(menu), &num_menus, err, false);
1572  if (!key)
1573  return MUTT_CMD_ERROR;
1574 
1576  /* make sure the macro sequence is not an empty string */
1577  if (buf->data[0] == '\0')
1578  {
1579  mutt_buffer_strcpy(err, _("macro: empty key sequence"));
1580  }
1581  else
1582  {
1583  if (MoreArgs(s))
1584  {
1585  char *seq = mutt_str_dup(buf->data);
1587 
1588  if (MoreArgs(s))
1589  {
1590  mutt_buffer_printf(err, _("%s: too many arguments"), "macro");
1591  }
1592  else
1593  {
1594  for (int i = 0; i < num_menus; i++)
1595  {
1596  rc = km_bind(key, menu[i], OP_MACRO, seq, buf->data);
1597  if (rc == MUTT_CMD_SUCCESS)
1598  {
1599  struct EventBinding ev_bind = { menu[i], key, OP_MACRO };
1601  continue;
1602  }
1603  }
1604  }
1605 
1606  FREE(&seq);
1607  }
1608  else
1609  {
1610  for (int i = 0; i < num_menus; i++)
1611  {
1612  rc = km_bind(key, menu[i], OP_MACRO, buf->data, NULL);
1613  if (rc == MUTT_CMD_SUCCESS)
1614  {
1615  struct EventBinding ev_bind = { menu[i], key, OP_MACRO };
1617  continue;
1618  }
1619  }
1620  }
1621  }
1622  FREE(&key);
1623  return rc;
1624 }
1625 
1629 enum CommandResult mutt_parse_exec(struct Buffer *buf, struct Buffer *s,
1630  intptr_t data, struct Buffer *err)
1631 {
1632  int ops[128];
1633  int nops = 0;
1634  const struct Binding *bindings = NULL;
1635  char *function = NULL;
1636 
1637  if (!MoreArgs(s))
1638  {
1639  mutt_buffer_strcpy(err, _("exec: no arguments"));
1640  return MUTT_CMD_ERROR;
1641  }
1642 
1643  do
1644  {
1646  function = buf->data;
1647 
1648  bindings = km_get_table(CurrentMenu);
1649  if (!bindings && (CurrentMenu != MENU_PAGER))
1650  bindings = OpGeneric;
1651 
1652  ops[nops] = get_op(bindings, function, mutt_str_len(function));
1653  if ((ops[nops] == OP_NULL) && (CurrentMenu != MENU_PAGER))
1654  ops[nops] = get_op(OpGeneric, function, mutt_str_len(function));
1655 
1656  if (ops[nops] == OP_NULL)
1657  {
1658  mutt_flushinp();
1659  mutt_error(_("%s: no such function"), function);
1660  return MUTT_CMD_ERROR;
1661  }
1662  nops++;
1663  } while (MoreArgs(s) && nops < mutt_array_size(ops));
1664 
1665  while (nops)
1666  mutt_push_macro_event(0, ops[--nops]);
1667 
1668  return MUTT_CMD_SUCCESS;
1669 }
1670 
1676 void mutt_what_key(void)
1677 {
1678  int ch;
1679 
1680  mutt_window_mvprintw(MessageWindow, 0, 0, _("Enter keys (%s to abort): "),
1681  km_keyname(AbortKey));
1682  do
1683  {
1684  ch = getch();
1685  if ((ch != ERR) && (ch != AbortKey))
1686  {
1687  mutt_message(_("Char = %s, Octal = %o, Decimal = %d"), km_keyname(ch), ch, ch);
1688  }
1689  } while (ch != ERR && ch != AbortKey);
1690 
1691  mutt_flushinp();
1692  mutt_clear_error();
1693 }
1694 
1698 void mutt_keys_free(void)
1699 {
1700  for (int i = 0; i < MENU_MAX; i++)
1701  {
1703  }
1704 }
int km_dokey(enum MenuType menu)
Determine what a keypress should do.
Definition: keymap.c:658
const struct Binding OpPager[]
Key bindings for the pager menu.
Definition: functions.c:262
short eq
number of leading keys equal to next entry
Definition: keymap.h:52
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
Convenience wrapper for the gui headers.
static const char * km_keyname(int c)
Get the human name for a key.
Definition: keymap.c:830
#define mutt_warning(...)
Definition: logging.h:82
PGP encryption menu.
Definition: keymap.h:84
Manage keymappings.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
#define WithCrypto
Definition: lib.h:123
IMAP network mailbox.
const struct Binding OpPgp[]
Key bindings for the pgp menu.
Definition: functions.c:642
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Config/command parsing.
Data passed to a notification function.
Definition: observer.h:39
struct KeymapList Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:149
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
WHERE short C_Timeout
Config: Time to wait for user input in menus.
Definition: mutt_globals.h:115
MenuType
Types of GUI selections.
Definition: keymap.h:72
#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:871
int op
function id number
Definition: keymap.h:123
static int parse_keycode(const char *s)
Parse a numeric keycode.
Definition: keymap.c:276
void imap_keepalive(void)
poll the current folder to keep the connection alive
Definition: util.c:1079
A key binding has been created.
Definition: keymap.h:144
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:919
keycode_t * keys
key sequence
Definition: keymap.h:54
int op
Operation the key&#39;s bound to (for bind), e.g. OP_DELETE.
Definition: keymap.h:134
NeoMutt Logging.
General file/mailbox browser.
Definition: keymap.h:78
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:1629
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:491
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:834
#define _(a)
Definition: message.h:28
void km_init(void)
Initialise all the menu keybindings.
Definition: keymap.c:1010
Autocrypt Account menu.
Definition: keymap.h:94
WHERE char * C_AbortKey
Config: String representation of key to abort prompts.
Definition: mutt_globals.h:84
Compose an email.
Definition: keymap.h:76
int op
function op
Definition: keymap.h:66
int ch
raw key pressed
Definition: keymap.h:65
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
A key macro has been deleted.
Definition: keymap.h:149
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:386
Index panel (list of emails)
Definition: keymap.h:80
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:1221
#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.
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:1193
const struct Binding OpCompose[]
Key bindings for the compose menu.
Definition: functions.c:454
All key bindings are about to be deleted.
Definition: keymap.h:146
const struct Binding OpSmime[]
Key bindings for the smime menu.
Definition: functions.c:651
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:1356
const char * key
Key string being bound (for new bind/macro)
Definition: keymap.h:133
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:621
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: keymap.c:981
#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:504
SMIME encryption menu.
Definition: keymap.h:85
Pager pager (email viewer)
Definition: keymap.h:81
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:539
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: mutt_globals.h:77
Select from results of external query.
Definition: keymap.h:83
const struct Binding OpMix[]
Key bindings for the mixmaster menu.
Definition: functions.c:663
Many unsorted constants and some structs.
#define STAILQ_INIT(head)
Definition: queue.h:369
const struct Binding OpAlias[]
Key bindings for the alias menu.
Definition: functions.c:533
void mutt_what_key(void)
Ask the user to press a key.
Definition: keymap.c:1676
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:53
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:299
const char * name
name of the function
Definition: keymap.h:122
short op
operation to perform
Definition: keymap.h:51
Key binding has changed, NotifyBinding, EventBinding.
Definition: notify_type.h:44
#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
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
All key macros are about to be deleted.
Definition: keymap.h:150
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
const struct Binding OpPost[]
Key bindings for the postpone menu.
Definition: functions.c:524
struct Keymap * km_find_func(enum MenuType menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:939
enum MenuType menu
Menu, e.g. MENU_PAGER.
Definition: keymap.h:132
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: keymap.c:866
#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:249
static struct Keymap * alloc_keys(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition: keymap.c:233
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
Select an attachment.
Definition: keymap.h:75
void km_error_key(enum MenuType menu)
Handle an unbound key sequence.
Definition: keymap.c:1137
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1698
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:1490
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:386
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:394
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:911
char * macro
macro expansion (op == OP_MACRO)
Definition: keymap.h:49
Select a PGP key.
Definition: keymap.h:87
int mutt_abort_key_config_observer(struct NotifyCallback *nc)
Listen for abort_key config changes - Implements observer_t.
Definition: keymap.c:887
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:559
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:814
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:380
An event such as a keypress.
Definition: keymap.h:63
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:189
short keycode_t
Definition: keymap.h:38
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
char * desc
description of a macro for the help menu
Definition: keymap.h:50
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
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
A key binding has been deleted.
Definition: keymap.h:145
Select an email address by its alias.
Definition: keymap.h:74
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:44
short C_ImapKeepalive
Config: (imap) Time to wait before polling an open IMAP connection.
Definition: config.c:47
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:37
#define IS_SPACE(ch)
Definition: string2.h:38
short len
length of key sequence (unit: sizeof (keycode_t))
Definition: keymap.h:53
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:632
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
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:1283
Success: Command worked.
Definition: mutt_commands.h:38
Definitions of user functions.
static void * parse_menu(bool *menu, char *s, struct Buffer *err)
Parse menu-names into an array.
Definition: keymap.c:1437
Warning: Help given to the user.
Definition: mutt_commands.h:37
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:716
#define mutt_error(...)
Definition: logging.h:84
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:907
void mutt_getch_timeout(int delay)
Set the getch() timeout.
Definition: curs_lib.c:146
const struct Binding OpEditor[]
Key bindings for the editor menu.
Definition: functions.c:610
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1306
Create/edit a Mixmaster chain.
Definition: keymap.h:91
const char * seq
default key binding
Definition: keymap.h:124
Select a SMIME key.
Definition: keymap.h:88
static void mutt_keymap_free(struct Keymap **km)
Free a Keymap.
Definition: keymap.c:202
#define FREE(x)
Definition: memory.h:40
static struct Keymap * km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
Compare two keymaps&#39; keyscodes and return the bigger one.
Definition: keymap.c:358
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:853
enum CommandResult km_bind(char *s, enum MenuType menu, int op, char *macro, char *desc)
Bind a key to a macro.
Definition: keymap.c:478
Text entry area.
Definition: keymap.h:77
#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:425
const struct Binding OpMain[]
Key bindings for the index menu.
Definition: functions.c:102
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:516
static void mutt_keymaplist_free(struct KeymapList *km_list)
Free a List of Keymaps.
Definition: keymap.c:217
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:75
#define STAILQ_FIRST(head)
Definition: queue.h:347
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:1564
const char * name
Name of config item that changed.
Definition: subset.h:73
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field)
Definition: queue.h:374
Mapping between a user key and a function.
Definition: keymap.h:120
const struct Binding OpAutocryptAcct[]
Key bindings for the autocrypt account.
Definition: functions.c:679
const struct Binding OpBrowser[]
Key bindings for the file browser menu.
Definition: functions.c:544
Select a postponed email.
Definition: keymap.h:82
A key macro has been created.
Definition: keymap.h:148
A key binding Event.
Definition: keymap.h:130
const struct Binding OpAttach[]
Key bindings for the attachment menu.
Definition: functions.c:418
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
static void km_unbind_all(struct KeymapList *km_list, unsigned long mode)
Free all the keys in the supplied Keymap.
Definition: keymap.c:1466
Generic selection list.
Definition: keymap.h:79
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152