NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
keymap.c File Reference

Manage keymappings. More...

#include "config.h"
#include <ctype.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "keymap.h"
#include "color/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "pager/lib.h"
#include "parse/lib.h"
#include "functions.h"
#include "globals.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "opcodes.h"
#include "imap/lib.h"
#include "monitor.h"
+ Include dependency graph for keymap.c:

Go to the source code of this file.

Data Structures

struct  Extkey
 Map key names from NeoMutt's style to Curses style. More...
 

Functions

static void mutt_keymap_free (struct Keymap **km)
 Free a Keymap. More...
 
static void mutt_keymaplist_free (struct KeymapList *km_list)
 Free a List of Keymaps. More...
 
static struct Keymapalloc_keys (size_t len, keycode_t *keys)
 Allocate space for a sequence of keys. More...
 
static int parse_fkey (char *s)
 Parse a function key string. More...
 
static int parse_keycode (const char *s)
 Parse a numeric keycode. More...
 
static size_t parsekeys (const char *str, keycode_t *d, size_t max)
 Parse a key string into key codes. More...
 
static struct Keymapkm_compare_keys (struct Keymap *k1, struct Keymap *k2, size_t *pos)
 Compare two keymaps' keyscodes and return the bigger one. More...
 
static enum CommandResult km_bind_err (const char *s, enum MenuType mtype, int op, char *macro, char *desc, struct Buffer *err)
 Set up a key binding. More...
 
enum CommandResult km_bind (char *s, enum MenuType mtype, int op, char *macro, char *desc)
 Bind a key to a macro. More...
 
static enum CommandResult km_bindkey_err (const char *s, enum MenuType mtype, int op, struct Buffer *err)
 Bind a key in a Menu to an operation (with error message) More...
 
static enum CommandResult km_bindkey (const char *s, enum MenuType mtype, int op)
 Bind a key in a Menu to an operation. More...
 
static int get_op (const struct MenuFuncOp *funcs, const char *start, size_t len)
 Get the function by its name. More...
 
const char * mutt_get_func (const struct MenuFuncOp *funcs, int op)
 Get the name of a function. More...
 
static void generic_tokenize_push_string (char *s, void(*generic_push)(int, int))
 Parse and queue a 'push' command. More...
 
static struct KeyEvent retry_generic (enum MenuType mtype, keycode_t *keys, int keyslen, int lastkey)
 Try to find the key in the generic menu bindings. More...
 
struct KeyEvent km_dokey_event (enum MenuType mtype)
 Determine what a keypress should do. More...
 
int km_dokey (enum MenuType mtype)
 Determine what a keypress should do. More...
 
static void create_bindings (const struct MenuOpSeq *map, enum MenuType mtype)
 Attach a set of keybindings to a Menu. More...
 
static const char * km_keyname (int c)
 Get the human name for a key. More...
 
void mutt_init_abort_key (void)
 Parse the abort_key config string. More...
 
int main_config_observer (struct NotifyCallback *nc)
 Notification that a Config Variable has changed - Implements observer_t -. More...
 
static int km_expand_key_string (char *str, char *buf, size_t buflen)
 Get a human-readable key string. More...
 
int km_expand_key (char *s, size_t len, struct Keymap *map)
 Get the key string bound to a Keymap. More...
 
struct Keymapkm_find_func (enum MenuType mtype, int func)
 Find a function's mapping in a Menu. More...
 
static const char * find_ext_name (const char *key)
 Find the curses name for a key. More...
 
void init_extended_keys (void)
 Initialise map of ncurses extended keys. More...
 
void km_init (void)
 Initialise all the menu keybindings. More...
 
void km_error_key (enum MenuType mtype)
 Handle an unbound key sequence. More...
 
enum CommandResult mutt_parse_push (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'push' command - Implements Command::parse() -. More...
 
static char * parse_keymap (enum MenuType *mtypes, struct Buffer *s, int max_menus, int *num_menus, struct Buffer *err, bool bind)
 Parse a user-config key binding. More...
 
static enum CommandResult try_bind (char *key, enum MenuType mtype, char *func, const struct MenuFuncOp *funcs, struct Buffer *err)
 Try to make a key binding. More...
 
const struct MenuFuncOpkm_get_table (enum MenuType mtype)
 Lookup a Menu's functions. More...
 
static bool dump_bind (struct Buffer *buf, struct Mapping *menu)
 Dumps all the binds maps of a menu into a buffer. More...
 
static void dump_all_binds (struct Buffer *buf)
 Dumps all the binds inside every menu. More...
 
static bool dump_macro (struct Buffer *buf, struct Mapping *menu)
 Dumps all the macros maps of a menu into a buffer. More...
 
static void dump_all_macros (struct Buffer *buf)
 Dumps all the macros inside every menu. More...
 
static enum CommandResult dump_bind_macro (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse 'bind' and 'macro' commands - Implements ICommand::parse() More...
 
enum CommandResult mutt_parse_bind (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'bind' command - Implements Command::parse() -. More...
 
static void * parse_menu (bool *menus, char *s, struct Buffer *err)
 Parse menu-names into an array. More...
 
static void km_unbind_all (struct KeymapList *km_list, unsigned long mode)
 Free all the keys in the supplied Keymap. More...
 
enum CommandResult mutt_parse_unbind (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'unbind' command - Implements Command::parse() -. More...
 
enum CommandResult mutt_parse_macro (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'macro' command - Implements Command::parse() -. More...
 
enum CommandResult mutt_parse_exec (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'exec' command - Implements Command::parse() -. More...
 
void mutt_what_key (void)
 Ask the user to press a key. More...
 
void mutt_keys_free (void)
 Free the key maps. More...
 

Variables

static struct Mapping KeyNames []
 Key name lookup table. More...
 
keycode_t AbortKey
 code of key to abort prompts, normally Ctrl-G More...
 
struct KeymapList Keymaps [MENU_MAX]
 Array of Keymap keybindings, one for each Menu. More...
 
static const struct Extkey ExtKeys []
 

Detailed Description

Manage keymappings.

Authors
  • Michael R. Elkins

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file keymap.c.

Function Documentation

◆ mutt_keymap_free()

static void mutt_keymap_free ( struct Keymap **  km)
static

Free a Keymap.

Parameters
kmKeymap to free

Definition at line 178 of file keymap.c.

179{
180 if (!km || !*km)
181 return;
182
183 FREE(&(*km)->macro);
184 FREE(&(*km)->desc);
185 FREE(&(*km)->keys);
186 FREE(km);
187}
#define FREE(x)
Definition: memory.h:43
+ Here is the caller graph for this function:

◆ mutt_keymaplist_free()

static void mutt_keymaplist_free ( struct KeymapList *  km_list)
static

Free a List of Keymaps.

Parameters
km_listList of Keymaps to free

Definition at line 193 of file keymap.c.

194{
195 struct Keymap *np = NULL, *tmp = NULL;
196 STAILQ_FOREACH_SAFE(np, km_list, entries, tmp)
197 {
198 STAILQ_REMOVE(km_list, np, Keymap, entries);
199 mutt_keymap_free(&np);
200 }
201}
static void mutt_keymap_free(struct Keymap **km)
Free a Keymap.
Definition: keymap.c:178
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
A keyboard mapping.
Definition: keymap.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alloc_keys()

static struct Keymap * alloc_keys ( size_t  len,
keycode_t keys 
)
static

Allocate space for a sequence of keys.

Parameters
lenNumber of keys
keysArray of keys
Return values
ptrSequence of keys

Definition at line 209 of file keymap.c.

210{
211 struct Keymap *p = mutt_mem_calloc(1, sizeof(struct Keymap));
212 p->len = len;
213 p->keys = mutt_mem_calloc(len, sizeof(keycode_t));
214 memcpy(p->keys, keys, len * sizeof(keycode_t));
215 return p;
216}
short keycode_t
Type for key storage, the rest of neomutt works fine with int type.
Definition: keymap.h:39
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
keycode_t * keys
key sequence
Definition: keymap.h:55
short len
length of key sequence (unit: sizeof (keycode_t))
Definition: keymap.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_fkey()

static int parse_fkey ( char *  s)
static

Parse a function key string.

Parameters
sString to parse
Return values
numNumber of the key

Given "<f8>", it will return 8.

Definition at line 225 of file keymap.c.

226{
227 char *t = NULL;
228 int n = 0;
229
230 if ((s[0] != '<') || (tolower(s[1]) != 'f'))
231 return -1;
232
233 for (t = s + 2; *t && isdigit((unsigned char) *t); t++)
234 {
235 n *= 10;
236 n += *t - '0';
237 }
238
239 if (*t != '>')
240 return -1;
241 return n;
242}
+ Here is the caller graph for this function:

◆ parse_keycode()

static int parse_keycode ( const char *  s)
static

Parse a numeric keycode.

Parameters
sString to parse
Return values
numNumber of the key

This function parses the string <NNN> and uses the octal value as the key to bind.

Definition at line 252 of file keymap.c.

253{
254 char *end_char = NULL;
255 long int result = strtol(s + 1, &end_char, 8);
256 /* allow trailing whitespace, eg. < 1001 > */
257 while (IS_SPACE(*end_char))
258 end_char++;
259 /* negative keycodes don't make sense, also detect overflow */
260 if ((*end_char != '>') || (result < 0) || (result == LONG_MAX))
261 {
262 return -1;
263 }
264
265 return result;
266}
#define IS_SPACE(ch)
Definition: string2.h:38
+ Here is the caller graph for this function:

◆ parsekeys()

static size_t parsekeys ( const char *  str,
keycode_t d,
size_t  max 
)
static

Parse a key string into key codes.

Parameters
strKey string
dArray for key codes
maxMaximum length of key sequence
Return values
numLength of key sequence

Definition at line 275 of file keymap.c.

276{
277 int n;
278 size_t len = max;
279 char buf[128] = { 0 };
280 char c;
281 char *t = NULL;
282
283 mutt_str_copy(buf, str, sizeof(buf));
284 char *s = buf;
285
286 while (*s && len)
287 {
288 *d = '\0';
289 if ((*s == '<') && (t = strchr(s, '>')))
290 {
291 t++;
292 c = *t;
293 *t = '\0';
294
296 if (n != -1)
297 {
298 s = t;
299 *d = n;
300 }
301 else if ((n = parse_fkey(s)) > 0)
302 {
303 s = t;
304 *d = KEY_F(n);
305 }
306 else if ((n = parse_keycode(s)) > 0)
307 {
308 s = t;
309 *d = n;
310 }
311
312 *t = c;
313 }
314
315 if (!*d)
316 {
317 *d = (unsigned char) *s;
318 s++;
319 }
320 d++;
321 len--;
322 }
323
324 return max - len;
325}
static int parse_keycode(const char *s)
Parse a numeric keycode.
Definition: keymap.c:252
static struct Mapping KeyNames[]
Key name lookup table.
Definition: keymap.c:63
static int parse_fkey(char *s)
Parse a function key string.
Definition: keymap.c:225
int mutt_map_get_value(const char *name, const struct Mapping *map)
Lookup the constant for a string.
Definition: mapping.c:85
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:652
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_compare_keys()

static struct Keymap * km_compare_keys ( struct Keymap k1,
struct Keymap k2,
size_t *  pos 
)
static

Compare two keymaps' keyscodes and return the bigger one.

Parameters
k1first keymap to compare
k2second keymap to compare
posposition where the two keycodes differ
Return values
ptrKeymap with a bigger ASCII keycode

Definition at line 334 of file keymap.c.

335{
336 while (*pos < k1->len && *pos < k2->len)
337 {
338 if (k1->keys[*pos] < k2->keys[*pos])
339 return k2;
340 else if (k1->keys[*pos] > k2->keys[*pos])
341 return k1;
342 else
343 *pos = *pos + 1;
344 }
345
346 return NULL;
347}
+ Here is the caller graph for this function:

◆ km_bind_err()

static enum CommandResult km_bind_err ( const char *  s,
enum MenuType  mtype,
int  op,
char *  macro,
char *  desc,
struct Buffer err 
)
static

Set up a key binding.

Parameters
sKey string
mtypeMenu type, e.g. MENU_EDITOR
opOperation, e.g. OP_DELETE
macroMacro string
descDescription of macro (OPTIONAL)
errBuffer for error message
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Insert a key sequence into the specified map. The map is sorted by ASCII value (lowest to highest)

Definition at line 362 of file keymap.c.

364{
366 struct Keymap *last = NULL, *np = NULL, *compare = NULL;
367 keycode_t buf[MAX_SEQ];
368 size_t pos = 0, lastpos = 0;
369
370 size_t len = parsekeys(s, buf, MAX_SEQ);
371
372 struct Keymap *map = alloc_keys(len, buf);
373 map->op = op;
374 map->macro = mutt_str_dup(macro);
375 map->desc = mutt_str_dup(desc);
376
377 /* find position to place new keymap */
378 STAILQ_FOREACH(np, &Keymaps[mtype], entries)
379 {
380 compare = km_compare_keys(map, np, &pos);
381
382 if (compare == map) /* map's keycode is bigger */
383 {
384 last = np;
385 lastpos = pos;
386 if (pos > np->eq)
387 pos = np->eq;
388 }
389 else if (compare == np) /* np's keycode is bigger, found insert location */
390 {
391 map->eq = pos;
392 break;
393 }
394 else /* equal keycodes */
395 {
396 /* Don't warn on overwriting a 'noop' binding */
397 if ((np->len != len) && (np->op != OP_NULL))
398 {
399 /* Overwrite with the different lengths, warn */
400 /* TODO: MAX_SEQ here is wrong */
401 char old_binding[MAX_SEQ] = { 0 };
402 char new_binding[MAX_SEQ] = { 0 };
403 km_expand_key(old_binding, MAX_SEQ, map);
404 km_expand_key(new_binding, MAX_SEQ, np);
405 char *err_msg = _("Binding '%s' will alias '%s' Before, try: 'bind %s %s noop' https://neomutt.org/guide/configuration.html#bind-warnings");
406 if (err)
407 {
408 /* err was passed, put the string there */
409 mutt_buffer_printf(err, err_msg, old_binding, new_binding,
410 mutt_map_get_name(mtype, MenuNames), new_binding);
411 }
412 else
413 {
414 mutt_error(err_msg, old_binding, new_binding,
415 mutt_map_get_name(mtype, MenuNames), new_binding);
416 }
417 rc = MUTT_CMD_WARNING;
418 }
419
420 map->eq = np->eq;
421 STAILQ_REMOVE(&Keymaps[mtype], np, Keymap, entries);
422 mutt_keymap_free(&np);
423 break;
424 }
425 }
426
427 if (map->op == OP_NULL)
428 {
429 mutt_keymap_free(&map);
430 }
431 else
432 {
433 if (last) /* if queue has at least one entry */
434 {
435 if (STAILQ_NEXT(last, entries))
436 STAILQ_INSERT_AFTER(&Keymaps[mtype], last, map, entries);
437 else /* last entry in the queue */
438 STAILQ_INSERT_TAIL(&Keymaps[mtype], map, entries);
439 last->eq = lastpos;
440 }
441 else /* queue is empty, so insert from head */
442 {
443 STAILQ_INSERT_HEAD(&Keymaps[mtype], map, entries);
444 }
445 }
446
447 return rc;
448}
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
#define mutt_error(...)
Definition: logging.h:87
static struct Keymap * alloc_keys(size_t len, keycode_t *keys)
Allocate space for a sequence of keys.
Definition: keymap.c:209
struct KeymapList Keymaps[MENU_MAX]
Array of Keymap keybindings, one for each Menu.
Definition: keymap.c:127
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:929
static struct Keymap * km_compare_keys(struct Keymap *k1, struct Keymap *k2, size_t *pos)
Compare two keymaps' keyscodes and return the bigger one.
Definition: keymap.c:334
static size_t parsekeys(const char *str, keycode_t *d, size_t max)
Parse a key string into key codes.
Definition: keymap.c:275
#define MAX_SEQ
Definition: keymap.h:36
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:383
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field)
Definition: queue.h:377
char * macro
macro expansion (op == OP_MACRO)
Definition: keymap.h:50
short eq
number of leading keys equal to next entry
Definition: keymap.h:53
char * desc
description of a macro for the help menu
Definition: keymap.h:51
short op
operation to perform
Definition: keymap.h:52
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_bind()

enum CommandResult km_bind ( char *  s,
enum MenuType  mtype,
int  op,
char *  macro,
char *  desc 
)

Bind a key to a macro.

Parameters
sKey string
mtypeMenu type, e.g. MENU_EDITOR
opOperation, e.g. OP_DELETE
macroMacro string
descDescription of macro (OPTIONAL)
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 459 of file keymap.c.

460{
461 return km_bind_err(s, mtype, op, macro, desc, NULL);
462}
static enum CommandResult km_bind_err(const char *s, enum MenuType mtype, int op, char *macro, char *desc, struct Buffer *err)
Set up a key binding.
Definition: keymap.c:362
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_bindkey_err()

static enum CommandResult km_bindkey_err ( const char *  s,
enum MenuType  mtype,
int  op,
struct Buffer err 
)
static

Bind a key in a Menu to an operation (with error message)

Parameters
sKey string
mtypeMenu type, e.g. MENU_PAGER
opOperation, e.g. OP_DELETE
errBuffer for error message
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 472 of file keymap.c.

474{
475 return km_bind_err(s, mtype, op, NULL, NULL, err);
476}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_bindkey()

static enum CommandResult km_bindkey ( const char *  s,
enum MenuType  mtype,
int  op 
)
static

Bind a key in a Menu to an operation.

Parameters
sKey string
mtypeMenu type, e.g. MENU_PAGER
opOperation, e.g. OP_DELETE
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 485 of file keymap.c.

486{
487 return km_bindkey_err(s, mtype, op, NULL);
488}
static enum CommandResult km_bindkey_err(const char *s, enum MenuType mtype, int op, struct Buffer *err)
Bind a key in a Menu to an operation (with error message)
Definition: keymap.c:472
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_op()

static int get_op ( const struct MenuFuncOp funcs,
const char *  start,
size_t  len 
)
static

Get the function by its name.

Parameters
funcsFunctions table
startName of function to find
lenLength of string to match
Return values
numOperation, e.g. OP_DELETE

Definition at line 497 of file keymap.c.

498{
499 for (int i = 0; funcs[i].name; i++)
500 {
501 if (mutt_istrn_equal(start, funcs[i].name, len) && (mutt_str_len(funcs[i].name) == len))
502 {
503 return funcs[i].op;
504 }
505 }
506
507 return OP_NULL;
508}
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:524
const char * name
Name of the function.
Definition: keymap.h:93
int op
Operation, e.g. OP_DELETE.
Definition: keymap.h:94
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_func()

const char * mutt_get_func ( const struct MenuFuncOp funcs,
int  op 
)

Get the name of a function.

Parameters
funcsFunctions table
opOperation, e.g. OP_DELETE
Return values
ptrName of function
NULLOperation not found
Note
This returns a static string.

Definition at line 519 of file keymap.c.

520{
521 for (int i = 0; funcs[i].name; i++)
522 {
523 if (funcs[i].op == op)
524 return funcs[i].name;
525 }
526
527 return NULL;
528}
+ Here is the caller graph for this function:

◆ generic_tokenize_push_string()

static void generic_tokenize_push_string ( char *  s,
void(*)(int, int)  generic_push 
)
static

Parse and queue a 'push' command.

Parameters
sString to push into the key queue
generic_pushCallback function to add events to macro queue

Parses s for <function> syntax and adds the whole sequence to either the macro or unget buffer. This function is invoked by the next two defines below.

Definition at line 539 of file keymap.c.

540{
541 char *pp = NULL;
542 char *p = s + mutt_str_len(s) - 1;
543 size_t l;
544 int i, op = OP_NULL;
545
546 while (p >= s)
547 {
548 /* if we see something like "<PageUp>", look to see if it is a real
549 * function name and return the corresponding value */
550 if (*p == '>')
551 {
552 for (pp = p - 1; pp >= s && *pp != '<'; pp--)
553 ; // do nothing
554
555 if (pp >= s)
556 {
557 i = parse_fkey(pp);
558 if (i > 0)
559 {
560 generic_push(KEY_F(i), 0);
561 p = pp - 1;
562 continue;
563 }
564
565 l = p - pp + 1;
566 for (i = 0; KeyNames[i].name; i++)
567 {
568 if (mutt_istrn_equal(pp, KeyNames[i].name, l))
569 break;
570 }
571 if (KeyNames[i].name)
572 {
573 /* found a match */
574 generic_push(KeyNames[i].value, 0);
575 p = pp - 1;
576 continue;
577 }
578
579 /* See if it is a valid command
580 * skip the '<' and the '>' when comparing */
581 for (enum MenuType j = 0; MenuNames[j].name; j++)
582 {
583 const struct MenuFuncOp *funcs = km_get_table(MenuNames[j].value);
584 if (funcs)
585 {
586 op = get_op(funcs, pp + 1, l - 2);
587 if (op != OP_NULL)
588 break;
589 }
590 }
591
592 if (op != OP_NULL)
593 {
594 generic_push(0, op);
595 p = pp - 1;
596 continue;
597 }
598 }
599 }
600 generic_push((unsigned char) *p--, 0); /* independent 8 bits chars */
601 }
602}
const struct MenuFuncOp * km_get_table(enum MenuType mtype)
Lookup a Menu's functions.
Definition: keymap.c:1231
static int get_op(const struct MenuFuncOp *funcs, const char *start, size_t len)
Get the function by its name.
Definition: keymap.c:497
const char * name
String value.
Definition: mapping.h:33
Mapping between a function and an operation.
Definition: keymap.h:92
MenuType
Types of GUI selections.
Definition: type.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ retry_generic()

static struct KeyEvent retry_generic ( enum MenuType  mtype,
keycode_t keys,
int  keyslen,
int  lastkey 
)
static

Try to find the key in the generic menu bindings.

Parameters
mtypeMenu type, e.g. MENU_PAGER
keysArray of keys to return to the input queue
keyslenNumber of keys in the array
lastkeyLast key pressed (to return to input queue)
Return values
numOperation, e.g. OP_DELETE

Definition at line 612 of file keymap.c.

614{
615 if (lastkey)
616 mutt_unget_ch(lastkey);
617 for (; keyslen; keyslen--)
618 mutt_unget_ch(keys[keyslen - 1]);
619
620 if ((mtype != MENU_EDITOR) && (mtype != MENU_GENERIC) && (mtype != MENU_PAGER))
621 {
623 }
624 if ((mtype != MENU_EDITOR) && (mtype != MENU_GENERIC))
625 {
626 /* probably a good idea to flush input here so we can abort macros */
628 }
629
630 return (struct KeyEvent){ .ch = mutt_getch().ch, .op = OP_NULL };
631}
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:591
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:241
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: curs_lib.c:520
struct KeyEvent km_dokey_event(enum MenuType mtype)
Determine what a keypress should do.
Definition: keymap.c:638
An event such as a keypress.
Definition: keymap.h:65
int ch
Raw key pressed.
Definition: keymap.h:66
@ MENU_GENERIC
Generic selection list.
Definition: type.h:45
@ MENU_PAGER
Pager pager (email viewer)
Definition: type.h:54
@ MENU_EDITOR
Text entry area.
Definition: type.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_dokey_event()

struct KeyEvent km_dokey_event ( enum MenuType  mtype)

Determine what a keypress should do.

Parameters
mtypeMenu type, e.g. MENU_EDITOR
Return values
ptrEvent

Definition at line 638 of file keymap.c.

639{
640 struct KeyEvent tmp = { OP_NULL, OP_NULL };
641 struct Keymap *map = STAILQ_FIRST(&Keymaps[mtype]);
642 int pos = 0;
643 int n = 0;
644
645 if (!map && (mtype != MENU_EDITOR))
646 return retry_generic(mtype, NULL, 0, 0);
647
648#ifdef USE_IMAP
649 const short c_imap_keepalive = cs_subset_number(NeoMutt->sub, "imap_keepalive");
650#endif
651
652 while (true)
653 {
654 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
655 int i = (c_timeout > 0) ? c_timeout : 60;
656#ifdef USE_IMAP
657 /* keepalive may need to run more frequently than `$timeout` allows */
658 if (c_imap_keepalive)
659 {
660 if (c_imap_keepalive >= i)
662 else
663 {
664 while (c_imap_keepalive && (c_imap_keepalive < i))
665 {
666 tmp = mutt_getch_timeout(c_imap_keepalive * 1000);
667 /* If a timeout was not received, or the window was resized, exit the
668 * loop now. Otherwise, continue to loop until reaching a total of
669 * $timeout seconds. */
670 if ((tmp.op != OP_TIMEOUT) || SigWinch)
671 goto gotkey;
672#ifdef USE_INOTIFY
674 goto gotkey;
675#endif
676 i -= c_imap_keepalive;
678 }
679 }
680 }
681#endif
682
683 tmp = mutt_getch_timeout(i * 1000);
684
685#ifdef USE_IMAP
686 gotkey:
687#endif
688 /* hide timeouts, but not window resizes, from the line editor. */
689 if ((mtype == MENU_EDITOR) && (tmp.op == OP_TIMEOUT) && !SigWinch)
690 continue;
691
692 if ((tmp.op == OP_TIMEOUT) || (tmp.op == OP_ABORT))
693 {
694 return tmp;
695 }
696
697 /* do we have an op already? */
698 if (tmp.op != OP_NULL)
699 {
700 const char *func = NULL;
701 const struct MenuFuncOp *funcs = NULL;
702
703 /* is this a valid op for this menu type? */
704 if ((funcs = km_get_table(mtype)) && (func = mutt_get_func(funcs, tmp.op)))
705 return tmp;
706
707 if ((mtype != MENU_EDITOR) && (mtype != MENU_PAGER) && (mtype != MENU_GENERIC))
708 {
709 /* check generic menu type */
710 funcs = OpGeneric;
711 func = mutt_get_func(funcs, tmp.op);
712 if (func)
713 return tmp;
714 }
715
716 /* Sigh. Valid function but not in this context.
717 * Find the literal string and push it back */
718 for (i = 0; MenuNames[i].name; i++)
719 {
720 funcs = km_get_table(MenuNames[i].value);
721 if (funcs)
722 {
723 func = mutt_get_func(funcs, tmp.op);
724 if (func)
725 {
726 mutt_unget_ch('>');
727 mutt_unget_string(func);
728 mutt_unget_ch('<');
729 break;
730 }
731 }
732 }
733 /* continue to chew */
734 if (func)
735 continue;
736 }
737
738 if (!map)
739 return tmp;
740
741 /* Nope. Business as usual */
742 while (tmp.ch > map->keys[pos])
743 {
744 if ((pos > map->eq) || !STAILQ_NEXT(map, entries))
745 return retry_generic(mtype, map->keys, pos, tmp.ch);
746 map = STAILQ_NEXT(map, entries);
747 }
748
749 if (tmp.ch != map->keys[pos])
750 return retry_generic(mtype, map->keys, pos, tmp.ch);
751
752 if (++pos == map->len)
753 {
754 if (map->op != OP_MACRO)
755 return (struct KeyEvent){ .ch = tmp.ch, .op = map->op };
756
757 /* OptIgnoreMacroEvents turns off processing the MacroEvents buffer
758 * in mutt_getch(). Generating new macro events during that time would
759 * result in undesired behavior once the option is turned off.
760 *
761 * Originally this returned -1, however that results in an unbuffered
762 * username or password prompt being aborted. Returning OP_NULL allows
763 * mutt_enter_string_full() to display the keybinding pressed instead.
764 *
765 * It may be unexpected for a macro's keybinding to be returned,
766 * but less so than aborting the prompt. */
768 {
769 return (struct KeyEvent){ .ch = tmp.ch, .op = OP_NULL };
770 }
771
772 if (n++ == 10)
773 {
775 mutt_error(_("Macro loop detected"));
776 return (struct KeyEvent){ .ch = '\0', .op = -1 };
777 }
778
780 map = STAILQ_FIRST(&Keymaps[mtype]);
781 pos = 0;
782 }
783 }
784
785 /* not reached */
786}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
struct KeyEvent mutt_getch_timeout(int delay)
Get an event with a timeout.
Definition: curs_lib.c:196
void mutt_unget_string(const char *s)
Return a string to the input buffer.
Definition: curs_lib.c:542
void mutt_push_macro_event(int ch, int op)
Add the character/operation to the macro buffer.
Definition: curs_lib.c:560
const struct MenuFuncOp OpGeneric[]
Functions for the Generic Menu.
Definition: functions.c:288
SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.c:59
bool OptIgnoreMacroEvents
(pseudo) don't process macro/push/exec events while set
Definition: globals.c:71
void imap_keepalive(void)
Poll the current folder to keep the connection alive.
Definition: util.c:937
static void generic_tokenize_push_string(char *s, void(*generic_push)(int, int))
Parse and queue a 'push' command.
Definition: keymap.c:539
const char * mutt_get_func(const struct MenuFuncOp *funcs, int op)
Get the name of a function.
Definition: keymap.c:519
static struct KeyEvent retry_generic(enum MenuType mtype, keycode_t *keys, int keyslen, int lastkey)
Try to find the key in the generic menu bindings.
Definition: keymap.c:612
bool MonitorFilesChanged
true after a monitored file has changed
Definition: monitor.c:49
#define OP_TIMEOUT
Definition: opcodes.h:32
#define OP_ABORT
Definition: opcodes.h:33
#define STAILQ_FIRST(head)
Definition: queue.h:350
int op
Function opcode, e.g. OP_HELP.
Definition: keymap.h:67
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_dokey()

int km_dokey ( enum MenuType  mtype)

Determine what a keypress should do.

Parameters
mtypeMenu type, e.g. MENU_EDITOR
Return values
>0Function to execute
OP_NULLNo function bound to key sequence
-1Error occurred while reading input
-2A timeout or sigwinch occurred

Definition at line 796 of file keymap.c.

797{
798 return km_dokey_event(mtype).op;
799}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_bindings()

static void create_bindings ( const struct MenuOpSeq map,
enum MenuType  mtype 
)
static

Attach a set of keybindings to a Menu.

Parameters
mapKey bindings
mtypeMenu type, e.g. MENU_PAGER

Definition at line 806 of file keymap.c.

807{
808 STAILQ_INIT(&Keymaps[mtype]);
809
810 for (int i = 0; map[i].op != 0; i++)
811 if (map[i].seq)
812 km_bindkey(map[i].seq, mtype, map[i].op);
813}
static enum CommandResult km_bindkey(const char *s, enum MenuType mtype, int op)
Bind a key in a Menu to an operation.
Definition: keymap.c:485
#define STAILQ_INIT(head)
Definition: queue.h:372
int op
Operation, e.g. OP_DELETE.
Definition: keymap.h:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_keyname()

static const char * km_keyname ( int  c)
static

Get the human name for a key.

Parameters
cKey code
Return values
ptrName of the key
Note
This returns a pointer to a static buffer.

Definition at line 822 of file keymap.c.

823{
824 static char buf[35];
825
826 const char *p = mutt_map_get_name(c, KeyNames);
827 if (p)
828 return p;
829
830 if ((c < 256) && (c > -128) && iscntrl((unsigned char) c))
831 {
832 if (c < 0)
833 c += 256;
834
835 if (c < 128)
836 {
837 buf[0] = '^';
838 buf[1] = (c + '@') & 0x7f;
839 buf[2] = '\0';
840 }
841 else
842 snprintf(buf, sizeof(buf), "\\%d%d%d", c >> 6, (c >> 3) & 7, c & 7);
843 }
844 else if ((c >= KEY_F0) && (c < KEY_F(256))) /* this maximum is just a guess */
845 sprintf(buf, "<F%d>", c - KEY_F0);
846 else if (IsPrint(c))
847 snprintf(buf, sizeof(buf), "%c", (unsigned char) c);
848 else
849 snprintf(buf, sizeof(buf), "\\x%hx", (unsigned short) c);
850 return buf;
851}
#define IsPrint(ch)
Definition: mbyte.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_init_abort_key()

void mutt_init_abort_key ( void  )

Parse the abort_key config string.

Parse the string into $abort_key and put the keycode into AbortKey.

Definition at line 858 of file keymap.c.

859{
860 keycode_t buf[2];
861 const char *const c_abort_key = cs_subset_string(NeoMutt->sub, "abort_key");
862 size_t len = parsekeys(c_abort_key, buf, mutt_array_size(buf));
863 if (len == 0)
864 {
865 mutt_error(_("Abort key is not set, defaulting to Ctrl-G"));
866 AbortKey = ctrl('G');
867 return;
868 }
869 if (len > 1)
870 {
871 mutt_warning(_("Specified abort key sequence (%s) will be truncated to first key"),
872 c_abort_key);
873 }
874 AbortKey = buf[0];
875}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_warning(...)
Definition: logging.h:85
keycode_t AbortKey
code of key to abort prompts, normally Ctrl-G
Definition: keymap.c:125
#define mutt_array_size(x)
Definition: memory.h:36
#define ctrl(ch)
Definition: mutt_curses.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_expand_key_string()

static int km_expand_key_string ( char *  str,
char *  buf,
size_t  buflen 
)
static

Get a human-readable key string.

Parameters
strRaw key string
bufBuffer for the key string
buflenLength of buffer
Return values
numLength of string

Definition at line 904 of file keymap.c.

905{
906 size_t len = 0;
907 for (; *str; str++)
908 {
909 const char *key = km_keyname(*str);
910 size_t keylen = mutt_str_len(key);
911
912 mutt_str_copy(buf, key, buflen);
913 buf += keylen;
914 buflen -= keylen;
915 len += keylen;
916 }
917
918 return len;
919}
static const char * km_keyname(int c)
Get the human name for a key.
Definition: keymap.c:822
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_expand_key()

int km_expand_key ( char *  s,
size_t  len,
struct Keymap map 
)

Get the key string bound to a Keymap.

Parameters
sBuffer for the key string
lenLength of buffer
mapKeybinding map
Return values
1Success
0Error

Definition at line 929 of file keymap.c.

930{
931 if (!map)
932 return 0;
933
934 int p = 0;
935
936 while (true)
937 {
938 mutt_str_copy(s, km_keyname(map->keys[p]), len);
939 const size_t l = mutt_str_len(s);
940 len -= l;
941
942 if ((++p >= map->len) || !len)
943 return 1;
944
945 s += l;
946 }
947
948 /* not reached */
949}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_find_func()

struct Keymap * km_find_func ( enum MenuType  mtype,
int  func 
)

Find a function's mapping in a Menu.

Parameters
mtypeMenu type, e.g. MENU_PAGER
funcFunction, e.g. OP_DELETE
Return values
ptrKeymap for the function

Definition at line 957 of file keymap.c.

958{
959 struct Keymap *np = NULL;
960 STAILQ_FOREACH(np, &Keymaps[mtype], entries)
961 {
962 if (np->op == func)
963 break;
964 }
965 return np;
966}
+ Here is the caller graph for this function:

◆ find_ext_name()

static const char * find_ext_name ( const char *  key)
static

Find the curses name for a key.

Parameters
keyKey name
Return values
ptrCurses name

Look up NeoMutt's name for a key and find the ncurses extended name for it.

Note
This returns a static string.

Definition at line 977 of file keymap.c.

978{
979 for (int j = 0; ExtKeys[j].name; j++)
980 {
981 if (strcasecmp(key, ExtKeys[j].name) == 0)
982 return ExtKeys[j].sym;
983 }
984 return 0;
985}
static const struct Extkey ExtKeys[]
Definition: keymap.c:138
const char * sym
Curses key name.
Definition: keymap.c:135
const char * name
NeoMutt key name.
Definition: keymap.c:134
+ Here is the caller graph for this function:

◆ init_extended_keys()

void init_extended_keys ( void  )

Initialise map of ncurses extended keys.

Determine the keycodes for ncurses extended keys and fill in the KeyNames array.

This function must be called after initscr(), or tigetstr() returns -1. This creates a bit of a chicken-and-egg problem because km_init() is called prior to start_curses(). This means that the default keybindings can't include any of the extended keys because they won't be defined until later.

Definition at line 997 of file keymap.c.

998{
999#ifdef HAVE_USE_EXTENDED_NAMES
1000 use_extended_names(true);
1001
1002 for (int j = 0; KeyNames[j].name; j++)
1003 {
1004 if (KeyNames[j].value == -1)
1005 {
1006 const char *keyname = find_ext_name(KeyNames[j].name);
1007
1008 if (keyname)
1009 {
1010 char *s = tigetstr((char *) keyname);
1011 if (s && ((long) (s) != -1))
1012 {
1013 int code = key_defined(s);
1014 if (code > 0)
1015 KeyNames[j].value = code;
1016 }
1017 }
1018 }
1019 }
1020#endif
1021}
static const char * find_ext_name(const char *key)
Find the curses name for a key.
Definition: keymap.c:977
int value
Integer value.
Definition: mapping.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_init()

void km_init ( void  )

Initialise all the menu keybindings.

Definition at line 1026 of file keymap.c.

1027{
1028 memset(Keymaps, 0, sizeof(struct KeymapList) * MENU_MAX);
1029
1032#ifdef USE_AUTOCRYPT
1034#endif
1040#ifdef MIXMASTER
1042#endif
1046
1051
1052#ifdef CRYPT_BACKEND_GPGME
1055#endif
1056}
const struct MenuOpSeq AutocryptAcctDefaultBindings[]
Key bindings for the Autocrypt Account.
Definition: functions.c:794
const struct MenuOpSeq PostDefaultBindings[]
Key bindings for the Postpone Menu.
Definition: functions.c:1224
const struct MenuOpSeq EditorDefaultBindings[]
Key bindings for the Editor Menu.
Definition: functions.c:907
const struct MenuOpSeq QueryDefaultBindings[]
Key bindings for the external Query Menu.
Definition: functions.c:1234
const struct MenuOpSeq BrowserDefaultBindings[]
Key bindings for the file Browser Menu.
Definition: functions.c:807
const struct MenuOpSeq AliasDefaultBindings[]
Key bindings for the Alias Menu.
Definition: functions.c:748
const struct MenuOpSeq PagerDefaultBindings[]
Key bindings for the Pager Menu.
Definition: functions.c:1110
const struct MenuOpSeq GenericDefaultBindings[]
Key bindings for the Generic Menu.
Definition: functions.c:945
const struct MenuOpSeq AttachDefaultBindings[]
Key bindings for the Attachment Menu.
Definition: functions.c:763
const struct MenuOpSeq IndexDefaultBindings[]
Key bindings for the Index Menu.
Definition: functions.c:994
const struct MenuOpSeq MixDefaultBindings[]
Key bindings for the Mixmaster Menu.
Definition: functions.c:1090
const struct MenuOpSeq PgpDefaultBindings[]
Key bindings for the Pgp Menu.
Definition: functions.c:1214
const struct MenuOpSeq ComposeDefaultBindings[]
Key bindings for the Compose Menu.
Definition: functions.c:844
const struct MenuOpSeq SmimeDefaultBindings[]
Key bindings for the Smime Menu.
Definition: functions.c:1249
static void create_bindings(const struct MenuOpSeq *map, enum MenuType mtype)
Attach a set of keybindings to a Menu.
Definition: keymap.c:806
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define WithCrypto
Definition: lib.h:116
@ MENU_KEY_SELECT_PGP
Select a PGP key.
Definition: type.h:47
@ MENU_INDEX
Index panel (list of emails)
Definition: type.h:50
@ MENU_KEY_SELECT_SMIME
Select a SMIME key.
Definition: type.h:48
@ MENU_ATTACH
Select an attachment.
Definition: type.h:38
@ MENU_QUERY
Select from results of external query.
Definition: type.h:57
@ MENU_COMPOSE
Compose an email.
Definition: type.h:42
@ MENU_MIX
Create/edit a Mixmaster chain.
Definition: type.h:52
@ MENU_PGP
PGP encryption menu.
Definition: type.h:55
@ MENU_SMIME
SMIME encryption menu.
Definition: type.h:58
@ MENU_MAX
Definition: type.h:59
@ MENU_POSTPONE
Select a postponed email.
Definition: type.h:56
@ MENU_ALIAS
Select an email address by its alias.
Definition: type.h:37
@ MENU_FOLDER
General file/mailbox browser.
Definition: type.h:44
@ MENU_AUTOCRYPT_ACCT
Autocrypt Account menu.
Definition: type.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_error_key()

void km_error_key ( enum MenuType  mtype)

Handle an unbound key sequence.

Parameters
mtypeMenu type, e.g. MENU_PAGER

Definition at line 1062 of file keymap.c.

1063{
1064 char buf[128] = { 0 };
1065 int p, op;
1066
1067 struct Keymap *key = km_find_func(mtype, OP_HELP);
1068 if (!key && (mtype != MENU_EDITOR) && (mtype != MENU_PAGER))
1069 key = km_find_func(MENU_GENERIC, OP_HELP);
1070 if (!key)
1071 {
1072 mutt_error(_("Key is not bound"));
1073 return;
1074 }
1075
1076 /* Make sure the key is really the help key in this menu.
1077 *
1078 * OP_END_COND is used as a barrier to ensure nothing extra
1079 * is left in the unget buffer.
1080 *
1081 * Note that km_expand_key() + tokenize_unget_string() should
1082 * not be used here: control sequences are expanded to a form
1083 * (e.g. "^H") not recognized by km_dokey(). */
1084 mutt_unget_op(OP_END_COND);
1085 p = key->len;
1086 while (p--)
1087 mutt_unget_ch(key->keys[p]);
1088
1089 /* Note, e.g. for the index menu:
1090 * bind generic ? noop
1091 * bind generic ,a help
1092 * bind index ,ab quit
1093 * The index keybinding shadows the generic binding.
1094 * OP_END_COND will be read and returned as the op.
1095 *
1096 * bind generic ? noop
1097 * bind generic dq help
1098 * bind index d delete-message
1099 * OP_DELETE will be returned as the op, leaving "q" + OP_END_COND
1100 * in the unget buffer.
1101 */
1102 op = km_dokey(mtype);
1103 if (op != OP_END_COND)
1105 if (op != OP_HELP)
1106 {
1107 mutt_error(_("Key is not bound"));
1108 return;
1109 }
1110
1111 km_expand_key(buf, sizeof(buf), key);
1112 mutt_error(_("Key is not bound. Press '%s' for help."), buf);
1113}
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:531
void mutt_flush_unget_to_endcond(void)
Clear entries from UngetKeyEvents.
Definition: curs_lib.c:583
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition: keymap.c:957
int km_dokey(enum MenuType mtype)
Determine what a keypress should do.
Definition: keymap.c:796
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_keymap()

static char * parse_keymap ( enum MenuType mtypes,
struct Buffer s,
int  max_menus,
int *  num_menus,
struct Buffer err,
bool  bind 
)
static

Parse a user-config key binding.

Parameters
mtypesArray for results
sBuffer containing config string
max_menusTotal number of menus
num_menusNumber of menus this config applies to
errBuffer for error messages
bindIf true 'bind', otherwise 'macro'
Return values
ptrKey string for the binding

Expects to see: <menu-string>,<menu-string>,... <key-string>

Note
Caller needs to free the returned string

Definition at line 1146 of file keymap.c.

1148{
1149 struct Buffer buf;
1150 int i = 0;
1151 char *q = NULL;
1152
1153 mutt_buffer_init(&buf);
1154
1155 /* menu name */
1157 char *p = buf.data;
1158 if (MoreArgs(s))
1159 {
1160 while (i < max_menus)
1161 {
1162 q = strchr(p, ',');
1163 if (q)
1164 *q = '\0';
1165
1166 int val = mutt_map_get_value(p, MenuNames);
1167 if (val == -1)
1168 {
1169 mutt_buffer_printf(err, _("%s: no such menu"), p);
1170 goto error;
1171 }
1172 mtypes[i] = val;
1173 i++;
1174 if (q)
1175 p = q + 1;
1176 else
1177 break;
1178 }
1179 *num_menus = i;
1180 /* key sequence */
1182
1183 if (buf.data[0] == '\0')
1184 {
1185 mutt_buffer_printf(err, _("%s: null key sequence"), bind ? "bind" : "macro");
1186 }
1187 else if (MoreArgs(s))
1188 return buf.data;
1189 }
1190 else
1191 {
1192 mutt_buffer_printf(err, _("%s: too few arguments"), bind ? "bind" : "macro");
1193 }
1194error:
1195 FREE(&buf.data);
1196 return NULL;
1197}
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:52
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:48
#define MoreArgs(buf)
Definition: extract.h:30
#define TOKEN_NO_FLAGS
No flags are set.
Definition: extract.h:33
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ try_bind()

static enum CommandResult try_bind ( char *  key,
enum MenuType  mtype,
char *  func,
const struct MenuFuncOp funcs,
struct Buffer err 
)
static

Try to make a key binding.

Parameters
keyKey name
mtypeMenu type, e.g. MENU_PAGER
funcFunction name
funcsFunctions table
errBuffer for error message
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 1208 of file keymap.c.

1210{
1211 for (int i = 0; funcs[i].name; i++)
1212 {
1213 if (mutt_str_equal(func, funcs[i].name))
1214 {
1215 return km_bindkey_err(key, mtype, funcs[i].op, err);
1216 }
1217 }
1218 if (err)
1219 {
1220 mutt_buffer_printf(err, _("Function '%s' not available for menu '%s'"),
1221 func, mutt_map_get_name(mtype, MenuNames));
1222 }
1223 return MUTT_CMD_ERROR; /* Couldn't find an existing function with this name */
1224}
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_get_table()

const struct MenuFuncOp * km_get_table ( enum MenuType  mtype)

Lookup a Menu's functions.

Parameters
mtypeMenu type, e.g. MENU_EDITOR
Return values
ptrArray of functions

Definition at line 1231 of file keymap.c.

1232{
1233 switch (mtype)
1234 {
1235 case MENU_ALIAS:
1236 return OpAlias;
1237 case MENU_ATTACH:
1238 return OpAttach;
1239#ifdef USE_AUTOCRYPT
1241 return OpAutocrypt;
1242#endif
1243 case MENU_COMPOSE:
1244 return OpCompose;
1245 case MENU_EDITOR:
1246 return OpEditor;
1247 case MENU_FOLDER:
1248 return OpBrowser;
1249 case MENU_GENERIC:
1250 return OpGeneric;
1251 case MENU_INDEX:
1252 return OpIndex;
1253#ifdef CRYPT_BACKEND_GPGME
1255 return OpPgp;
1257 return OpSmime;
1258#endif
1259#ifdef MIXMASTER
1260 case MENU_MIX:
1261 return OpMix;
1262#endif
1263 case MENU_PAGER:
1264 return OpPager;
1265 case MENU_PGP:
1266 return (WithCrypto & APPLICATION_PGP) ? OpPgp : NULL;
1267 case MENU_POSTPONE:
1268 return OpPostpone;
1269 case MENU_QUERY:
1270 return OpQuery;
1271 default:
1272 return NULL;
1273 }
1274}
const struct MenuFuncOp OpQuery[]
Functions for the external Query Menu.
Definition: functions.c:721
const struct MenuFuncOp OpMix[]
Functions for the Mixmaster Menu.
Definition: functions.c:514
const struct MenuFuncOp OpAttach[]
Functions for the Attachment Menu.
Definition: functions.c:69
const struct MenuFuncOp OpIndex[]
Functions for the Index Menu.
Definition: functions.c:349
const struct MenuFuncOp OpCompose[]
Functions for the Compose Menu.
Definition: functions.c:177
const struct MenuFuncOp OpSmime[]
Functions for the Smime Menu.
Definition: functions.c:736
const struct MenuFuncOp OpBrowser[]
Functions for the file Browser Menu.
Definition: functions.c:123
const struct MenuFuncOp OpAutocrypt[]
Functions for the Autocrypt Account.
Definition: functions.c:110
const struct MenuFuncOp OpPager[]
Functions for the Pager Menu.
Definition: functions.c:529
const struct MenuFuncOp OpEditor[]
Functions for the Editor Menu.
Definition: functions.c:254
const struct MenuFuncOp OpPgp[]
Functions for the Pgp Menu.
Definition: functions.c:701
const struct MenuFuncOp OpPostpone[]
Functions for the Postpone Menu.
Definition: functions.c:711
const struct MenuFuncOp OpAlias[]
Functions for the Alias Menu.
Definition: functions.c:55
+ Here is the caller graph for this function:

◆ dump_bind()

static bool dump_bind ( struct Buffer buf,
struct Mapping menu 
)
static

Dumps all the binds maps of a menu into a buffer.

Parameters
bufOutput buffer
menuMenu to dump
Return values
trueMenu is empty
falseMenu is not empty

Definition at line 1283 of file keymap.c.

1284{
1285 bool empty = true;
1286 struct Keymap *map = NULL;
1287
1288 STAILQ_FOREACH(map, &Keymaps[menu->value], entries)
1289 {
1290 if (map->op == OP_MACRO)
1291 continue;
1292
1293 char key_binding[32] = { 0 };
1294 const char *fn_name = NULL;
1295
1296 km_expand_key(key_binding, sizeof(key_binding), map);
1297 if (map->op == OP_NULL)
1298 {
1299 mutt_buffer_add_printf(buf, "bind %s %s noop\n", menu->name, key_binding);
1300 continue;
1301 }
1302
1303 /* The pager and editor menus don't use the generic map,
1304 * however for other menus try generic first. */
1305 if ((menu->value != MENU_PAGER) && (menu->value != MENU_EDITOR) &&
1306 (menu->value != MENU_GENERIC))
1307 {
1308 fn_name = mutt_get_func(OpGeneric, map->op);
1309 }
1310
1311 /* if it's one of the menus above or generic doesn't find
1312 * the function, try with its own menu. */
1313 if (!fn_name)
1314 {
1315 const struct MenuFuncOp *funcs = km_get_table(menu->value);
1316 if (!funcs)
1317 continue;
1318
1319 fn_name = mutt_get_func(funcs, map->op);
1320 }
1321
1322 mutt_buffer_add_printf(buf, "bind %s %s %s\n", menu->name, key_binding, fn_name);
1323 empty = false;
1324 }
1325
1326 return empty;
1327}
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:211
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_all_binds()

static void dump_all_binds ( struct Buffer buf)
static

Dumps all the binds inside every menu.

Parameters
bufOutput buffer

Definition at line 1333 of file keymap.c.

1334{
1335 for (int i = 0; i < MENU_MAX; i++)
1336 {
1337 const char *menu_name = mutt_map_get_name(i, MenuNames);
1338 struct Mapping menu = { menu_name, i };
1339
1340 const bool empty = dump_bind(buf, &menu);
1341
1342 /* Add a new line for readability between menus. */
1343 if (!empty && (i < (MENU_MAX - 1)))
1344 mutt_buffer_addch(buf, '\n');
1345 }
1346}
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
static bool dump_bind(struct Buffer *buf, struct Mapping *menu)
Dumps all the binds maps of a menu into a buffer.
Definition: keymap.c:1283
Mapping between user-readable string and a constant.
Definition: mapping.h:32
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_macro()

static bool dump_macro ( struct Buffer buf,
struct Mapping menu 
)
static

Dumps all the macros maps of a menu into a buffer.

Parameters
bufOutput buffer
menuMenu to dump
Return values
trueMenu is empty
falseMenu is not empty

Definition at line 1355 of file keymap.c.

1356{
1357 bool empty = true;
1358 struct Keymap *map = NULL;
1359
1360 STAILQ_FOREACH(map, &Keymaps[menu->value], entries)
1361 {
1362 if (map->op != OP_MACRO)
1363 continue;
1364
1365 char key_binding[MAX_SEQ] = { 0 };
1366 km_expand_key(key_binding, MAX_SEQ, map);
1367
1368 struct Buffer tmp = mutt_buffer_make(0);
1369 escape_string(&tmp, map->macro);
1370
1371 if (map->desc)
1372 {
1373 mutt_buffer_add_printf(buf, "macro %s %s \"%s\" \"%s\"\n", menu->name,
1374 key_binding, tmp.data, map->desc);
1375 }
1376 else
1377 {
1378 mutt_buffer_add_printf(buf, "macro %s %s \"%s\"\n", menu->name, key_binding, tmp.data);
1379 }
1380
1381 mutt_buffer_dealloc(&tmp);
1382 empty = false;
1383 }
1384
1385 return empty;
1386}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:347
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition: dump.c:46
char * data
Pointer to data.
Definition: buffer.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_all_macros()

static void dump_all_macros ( struct Buffer buf)
static

Dumps all the macros inside every menu.

Parameters
bufOutput buffer

Definition at line 1392 of file keymap.c.

1393{
1394 for (int i = 0; i < MENU_MAX; i++)
1395 {
1396 const char *menu_name = mutt_map_get_name(i, MenuNames);
1397 struct Mapping menu = { menu_name, i };
1398
1399 const bool empty = dump_macro(buf, &menu);
1400
1401 /* Add a new line for legibility between menus. */
1402 if (!empty && (i < (MENU_MAX - 1)))
1403 mutt_buffer_addch(buf, '\n');
1404 }
1405}
static bool dump_macro(struct Buffer *buf, struct Mapping *menu)
Dumps all the macros maps of a menu into a buffer.
Definition: keymap.c:1355
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_bind_macro()

static enum CommandResult dump_bind_macro ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)
static

Parse 'bind' and 'macro' commands - Implements ICommand::parse()

Definition at line 1410 of file keymap.c.

1412{
1413 FILE *fp_out = NULL;
1414 char tempfile[PATH_MAX] = { 0 };
1415 bool dump_all = false, bind = (data == 0);
1416
1417 if (!MoreArgs(s))
1418 dump_all = true;
1419 else
1421
1422 if (MoreArgs(s))
1423 {
1424 /* More arguments potentially means the user is using the
1425 * ::command_t :bind command thus we delegate the task. */
1426 return MUTT_CMD_ERROR;
1427 }
1428
1429 struct Buffer filebuf = mutt_buffer_make(4096);
1430 if (dump_all || mutt_istr_equal(buf->data, "all"))
1431 {
1432 if (bind)
1433 dump_all_binds(&filebuf);
1434 else
1435 dump_all_macros(&filebuf);
1436 }
1437 else
1438 {
1439 const int menu_index = mutt_map_get_value(buf->data, MenuNames);
1440 if (menu_index == -1)
1441 {
1442 // L10N: '%s' is the (misspelled) name of the menu, e.g. 'index' or 'pager'
1443 mutt_buffer_printf(err, _("%s: no such menu"), buf->data);
1444 mutt_buffer_dealloc(&filebuf);
1445 return MUTT_CMD_ERROR;
1446 }
1447
1448 struct Mapping menu = { buf->data, menu_index };
1449 if (bind)
1450 dump_bind(&filebuf, &menu);
1451 else
1452 dump_macro(&filebuf, &menu);
1453 }
1454
1455 if (mutt_buffer_is_empty(&filebuf))
1456 {
1457 // L10N: '%s' is the name of the menu, e.g. 'index' or 'pager',
1458 // it might also be 'all' when all menus are affected.
1459 mutt_buffer_printf(err, bind ? _("%s: no binds for this menu") : _("%s: no macros for this menu"),
1460 dump_all ? "all" : buf->data);
1461 mutt_buffer_dealloc(&filebuf);
1462 return MUTT_CMD_ERROR;
1463 }
1464
1465 mutt_mktemp(tempfile, sizeof(tempfile));
1466 fp_out = mutt_file_fopen(tempfile, "w");
1467 if (!fp_out)
1468 {
1469 // L10N: '%s' is the file name of the temporary file
1470 mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
1471 mutt_buffer_dealloc(&filebuf);
1472 return MUTT_CMD_ERROR;
1473 }
1474 fputs(filebuf.data, fp_out);
1475
1476 mutt_file_fclose(&fp_out);
1477 mutt_buffer_dealloc(&filebuf);
1478
1479 struct PagerData pdata = { 0 };
1480 struct PagerView pview = { &pdata };
1481
1482 pdata.fname = tempfile;
1483
1484 pview.banner = (bind) ? "bind" : "macro";
1485 pview.flags = MUTT_PAGER_NO_FLAGS;
1486 pview.mode = PAGER_MODE_OTHER;
1487
1488 mutt_do_pager(&pview, NULL);
1489 return MUTT_CMD_SUCCESS;
1490}
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:298
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:123
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:151
static void dump_all_macros(struct Buffer *buf)
Dumps all the macros inside every menu.
Definition: keymap.c:1392
static void dump_all_binds(struct Buffer *buf)
Dumps all the binds inside every menu.
Definition: keymap.c:1333
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
#define PATH_MAX
Definition: mutt.h:41
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:71
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:58
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:139
Data to be displayed by PagerView.
Definition: lib.h:158
const char * fname
Name of the file to read.
Definition: lib.h:162
Paged view into some data.
Definition: lib.h:169
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:170
enum PagerMode mode
Pager mode.
Definition: lib.h:171
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:172
const char * banner
Title to display in status bar.
Definition: lib.h:173
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_menu()

static void * parse_menu ( bool *  menus,
char *  s,
struct Buffer err 
)
static

Parse menu-names into an array.

Parameters
menusArray for results
sString containing menu-names
errBuffer for error messages
Return values
NULLAlways

Expects to see: <menu-string>[,<menu-string>]

Definition at line 1605 of file keymap.c.

1606{
1607 char *menu_names_dup = mutt_str_dup(s);
1608 char *marker = menu_names_dup;
1609 char *menu_name = NULL;
1610
1611 while ((menu_name = mutt_str_sep(&marker, ",")))
1612 {
1613 int value = mutt_map_get_value(menu_name, MenuNames);
1614 if (value == -1)
1615 {
1616 mutt_buffer_printf(err, _("%s: no such menu"), menu_name);
1617 break;
1618 }
1619 else
1620 menus[value] = true;
1621 }
1622
1623 FREE(&menu_names_dup);
1624 return NULL;
1625}
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Definition: string.c:183
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ km_unbind_all()

static void km_unbind_all ( struct KeymapList *  km_list,
unsigned long  mode 
)
static

Free all the keys in the supplied Keymap.

Parameters
km_listKeymap mapping
modeUndo bind or macro, e.g. MUTT_UNBIND, MUTT_UNMACRO

Iterate through Keymap and free keys defined either by "macro" or "bind".

Definition at line 1634 of file keymap.c.

1635{
1636 struct Keymap *np = NULL, *tmp = NULL;
1637
1638 STAILQ_FOREACH_SAFE(np, km_list, entries, tmp)
1639 {
1640 if (((mode & MUTT_UNBIND) && !np->macro) || ((mode & MUTT_UNMACRO) && np->macro))
1641 {
1642 STAILQ_REMOVE(km_list, np, Keymap, entries);
1643 mutt_keymap_free(&np);
1644 }
1645 }
1646}
#define MUTT_UNBIND
Definition: keymap.h:33
#define MUTT_UNMACRO
Definition: keymap.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_what_key()

void mutt_what_key ( void  )

Ask the user to press a key.

Displays the octal value back to the user.

Definition at line 1877 of file keymap.c.

1878{
1879 int ch;
1880
1881 struct MuttWindow *win = msgwin_get_window();
1882 if (!win)
1883 return;
1884
1886 mutt_window_mvprintw(win, 0, 0, _("Enter keys (%s to abort): "), km_keyname(AbortKey));
1889 do
1890 {
1891 ch = getch();
1892 if ((ch != ERR) && (ch != AbortKey))
1893 {
1894 mutt_message(_("Char = %s, Octal = %o, Decimal = %d"), km_keyname(ch), ch, ch);
1895 mutt_window_move(win, 0, 0);
1896 }
1897 } while (ch != ERR && ch != AbortKey);
1898 mutt_curses_set_cursor(cursor);
1899
1900 mutt_flushinp();
1902}
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:57
@ MT_COLOR_PROMPT
Question/user input.
Definition: color.h:60
#define mutt_message(...)
Definition: logging.h:86
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:260
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:96
struct AttrColor * mutt_curses_set_normal_backed_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:65
struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:81
MuttCursorState
Cursor states for mutt_curses_set_cursor()
Definition: mutt_curses.h:52
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition: mutt_curses.h:54
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:292
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:321
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_keys_free()

void mutt_keys_free ( void  )

Free the key maps.

Definition at line 1907 of file keymap.c.

1908{
1909 for (int i = 0; i < MENU_MAX; i++)
1910 {
1912 }
1913}
static void mutt_keymaplist_free(struct KeymapList *km_list)
Free a List of Keymaps.
Definition: keymap.c:193
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ KeyNames

struct Mapping KeyNames[]
static

Key name lookup table.

Definition at line 63 of file keymap.c.

◆ AbortKey

keycode_t AbortKey

code of key to abort prompts, normally Ctrl-G

key to abort edits etc, normally Ctrl-G

Definition at line 125 of file keymap.c.

◆ Keymaps

struct KeymapList Keymaps[MENU_MAX]

Array of Keymap keybindings, one for each Menu.

Definition at line 127 of file keymap.c.

◆ ExtKeys

const struct Extkey ExtKeys[]
static

Definition at line 138 of file keymap.c.