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