⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keymap.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-2000,2002 Michael R. Elkins <me@mutt.org> *  *     This program is free software; you can redistribute it and/or modify *     it under the terms of the GNU General Public License as published by *     the Free Software Foundation; either version 2 of the License, or *     (at your option) any later version. *  *     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, write to the Free Software *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_menu.h"#include "mutt_curses.h"#include "keymap.h"#include "mapping.h"#include "mutt_crypt.h"#include <stdlib.h>#include <string.h>#include <ctype.h>#include "functions.h"struct mapping_t Menus[] = { { "alias",	MENU_ALIAS }, { "attach",	MENU_ATTACH }, { "browser",	MENU_FOLDER }, { "compose",	MENU_COMPOSE }, { "editor",	MENU_EDITOR }, { "index",	MENU_MAIN }, { "pager",	MENU_PAGER }, { "postpone",	MENU_POST }, { "pgp",	MENU_PGP }, { "smime",	MENU_SMIME },#ifdef HAVE_GPGME { "key_select_pgp",	MENU_KEY_SELECT_PGP }, { "key_select_smime",	MENU_KEY_SELECT_SMIME },#endif#ifdef MIXMASTER  { "mix", 	MENU_MIX },#endif   { "query",	MENU_QUERY }, { "generic",	MENU_GENERIC }, { NULL,	0 }};#define mutt_check_menu(s) mutt_getvaluebyname(s, Menus)static struct mapping_t KeyNames[] = {  { "<PageUp>",	KEY_PPAGE },  { "<PageDown>",	KEY_NPAGE },  { "<Up>",	KEY_UP },  { "<Down>",	KEY_DOWN },  { "<Right>",	KEY_RIGHT },  { "<Left>",	KEY_LEFT },  { "<Delete>",	KEY_DC },  { "<BackSpace>",KEY_BACKSPACE },  { "<Insert>",	KEY_IC },  { "<Home>",	KEY_HOME },  { "<End>",	KEY_END },#ifdef KEY_ENTER  { "<Enter>",	KEY_ENTER },#endif  { "<Return>",	M_ENTER_C },  { "<Esc>",	'\033' },  { "<Tab>",	'\t' },  { "<Space>",	' ' },#ifdef KEY_BTAB  { "<BackTab>", KEY_BTAB },#endif#ifdef KEY_NEXT  { "<Next>",    KEY_NEXT },#endif    { NULL,	0 }};/* contains the last key the user pressed */int LastKey;struct keymap_t *Keymaps[MENU_MAX];static struct keymap_t *allocKeys (int len, keycode_t *keys){  struct keymap_t *p;  p = safe_calloc (1, sizeof (struct keymap_t));  p->len = len;  p->keys = safe_malloc (len * sizeof (keycode_t));  memcpy (p->keys, keys, len * sizeof (keycode_t));  return (p);}static int parse_fkey(char *s){  char *t;  int n = 0;  if(s[0] != '<' || ascii_tolower(s[1]) != 'f')    return -1;  for(t = s + 2; *t && isdigit((unsigned char) *t); t++)  {    n *= 10;    n += *t - '0';  }  if(*t != '>')    return -1;  else    return n;}/* * This function parses the string <NNN> and uses the octal value as the key * to bind. */static int parse_keycode (const char *s){  if (isdigit ((unsigned char) s[1]) &&      isdigit ((unsigned char) s[2]) &&      isdigit ((unsigned char) s[3]) &&      s[4] == '>')  {    return (s[3] - '0') + (s[2] - '0') * 8 + (s[1] - '0') * 64;  }  return -1;}static int parsekeys (char *str, keycode_t *d, int max){  int n, len = max;  char buff[SHORT_STRING];  char c;  char *s, *t;  strfcpy(buff, str, sizeof(buff));  s = buff;    while (*s && len)  {    *d = '\0';    if(*s == '<' && (t = strchr(s, '>')))    {      t++; c = *t; *t = '\0';            if ((n = mutt_getvaluebyname (s, KeyNames)) != -1)      {	s = t;	*d = n;      }      else if ((n = parse_fkey(s)) > 0)      {	s = t;	*d = KEY_F (n);      }      else if ((n = parse_keycode(s)) > 0)      {	s = t;	*d = n;      }            *t = c;    }    if(!*d)    {      *d = (unsigned char)*s;      s++;    }    d++;    len--;  }  return (max - len);}/* insert a key sequence into the specified map.  the map is sorted by ASCII * value (lowest to highest) */void km_bind (char *s, int menu, int op, char *macro, char *descr){  struct keymap_t *map, *tmp, *last = NULL, *next;  keycode_t buf[MAX_SEQ];  int len, pos = 0, lastpos = 0;  len = parsekeys (s, buf, MAX_SEQ);  map = allocKeys (len, buf);  map->op = op;  map->macro = safe_strdup (macro);  map->descr = safe_strdup (descr);  tmp = Keymaps[menu];  while (tmp)  {    if (pos >= len || pos >= tmp->len)    {      /* map and tmp match, but have different lengths, so overwrite */      do      {	len = tmp->eq;	next = tmp->next;	FREE (&tmp->macro);	FREE (&tmp->keys);	FREE (&tmp->descr);	FREE (&tmp);	tmp = next;      }      while (tmp && len >= pos);      map->eq = len;      break;    }    else if (buf[pos] == tmp->keys[pos])      pos++;    else if (buf[pos] < tmp->keys[pos])    {      /* found location to insert between last and tmp */      map->eq = pos;      break;    }    else /* buf[pos] > tmp->keys[pos] */    {      last = tmp;      lastpos = pos;      if (pos > tmp->eq)	pos = tmp->eq;      tmp = tmp->next;    }  }  map->next = tmp;  if (last)  {    last->next = map;    last->eq = lastpos;  }  else    Keymaps[menu] = map;}void km_bindkey (char *s, int menu, int op){  km_bind (s, menu, op, NULL, NULL);}static int get_op (struct binding_t *bindings, const char *start, size_t len){  int i;  for (i = 0; bindings[i].name; i++)  {    if (!ascii_strncasecmp (start, bindings[i].name, len) &&   	mutt_strlen (bindings[i].name) == len)      return bindings[i].op;  }  return OP_NULL;}static char *get_func (struct binding_t *bindings, int op){  int i;  for (i = 0; bindings[i].name; i++)  {    if (bindings[i].op == op)      return bindings[i].name;  }  return NULL;}static void push_string (char *s){  char *pp, *p = s + mutt_strlen (s) - 1;  size_t l;  int i, op = OP_NULL;  while (p >= s)  {    /* if we see something like "<PageUp>", look to see if it is a real       function name and return the corresponding value */    if (*p == '>')    {      for (pp = p - 1; pp >= s && *pp != '<'; pp--)	;      if (pp >= s)      {	if ((i = parse_fkey (pp)) > 0)	{	  mutt_ungetch (KEY_F (i), 0);	  p = pp - 1;	  continue;	}	l = p - pp + 1;	for (i = 0; KeyNames[i].name; i++)	{	  if (!ascii_strncasecmp (pp, KeyNames[i].name, l))	    break;	}	if (KeyNames[i].name)	{	  /* found a match */	  mutt_ungetch (KeyNames[i].value, 0);	  p = pp - 1;	  continue;	}	/* See if it is a valid command	 * skip the '<' and the '>' when comparing */	for (i = 0; Menus[i].name; i++)	{	  struct binding_t *binding = km_get_table (Menus[i].value);	  if (binding)	  {	    op = get_op (binding, pp + 1, l - 2);	    if (op != OP_NULL)	      break;	  }	}	if (op != OP_NULL)	{	  mutt_ungetch (0, op);	  p = pp - 1;	  continue;	}      }    }    mutt_ungetch ((unsigned char)*p--, 0);	/* independent 8 bits chars */  }}static int retry_generic (int menu, keycode_t *keys, int keyslen, int lastkey){  if (menu != MENU_EDITOR && menu != MENU_GENERIC && menu != MENU_PAGER)  {    if (lastkey)      mutt_ungetch (lastkey, 0);    for (; keyslen; keyslen--)      mutt_ungetch (keys[keyslen - 1], 0);    return (km_dokey (MENU_GENERIC));  }  if (menu != MENU_EDITOR)  {    /* probably a good idea to flush input here so we can abort macros */    mutt_flushinp ();  }  return OP_NULL;}/* return values: *	>0		function to execute *	OP_NULL		no function bound to key sequence *	-1		error occured while reading input */int km_dokey (int menu){  event_t tmp;  struct keymap_t *map = Keymaps[menu];  int pos = 0;  int n = 0;  int i;  if (!map)    return (retry_generic (menu, NULL, 0, 0));  FOREVER  {    /* ncurses doesn't return on resized screen when timeout is set to zero */    if (menu != MENU_EDITOR)      timeout ((Timeout > 0 ? Timeout : 60) * 1000);    tmp = mutt_getch();    if (menu != MENU_EDITOR)      timeout (-1); /* restore blocking operation */    LastKey = tmp.ch;    if (LastKey == -1)      return -1;    /* do we have an op already? */    if (tmp.op)    {      char *func = NULL;      struct binding_t *bindings;      /* is this a valid op for this menu? */      if ((bindings = km_get_table (menu)) &&	  (func = get_func (bindings, tmp.op)))	return tmp.op;      if (menu == MENU_EDITOR && get_func (OpEditor, tmp.op))	return tmp.op;      if (menu != MENU_EDITOR && menu != MENU_PAGER)      {	/* check generic menu */	bindings = OpGeneric; 	if ((func = get_func (bindings, tmp.op)))	  return tmp.op;      }      /* Sigh. Valid function but not in this context.       * Find the literal string and push it back */      for (i = 0; Menus[i].name; i++)      {	bindings = km_get_table (Menus[i].value);	if (bindings)	{	  func = get_func (bindings, tmp.op);	  if (func)	  {	    /* careful not to feed the <..> as one token. otherwise 	    * push_string() will push the bogus op right back! */	    mutt_ungetch ('>', 0);	    push_string (func);	    mutt_ungetch ('<', 0);	    break;	  }	}      }      /* continue to chew */      if (func)	continue;    }    /* Nope. Business as usual */    while (LastKey > map->keys[pos])    {      if (pos > map->eq || !map->next)	return (retry_generic (menu, map->keys, pos, LastKey));      map = map->next;    }    if (LastKey != map->keys[pos])      return (retry_generic (menu, map->keys, pos, LastKey));    if (++pos == map->len)    {      if (map->op != OP_MACRO)	return map->op;      if (n++ == 10)      {	mutt_flushinp ();	mutt_error _("Macro loop detected.");	return -1;      }      push_string (map->macro);      map = Keymaps[menu];      pos = 0;    }  }  /* not reached */}static void create_bindings (struct binding_t *map, int menu){  int i;  for (i = 0 ; map[i].name ; i++)    if (map[i].seq)      km_bindkey (map[i].seq, menu, map[i].op);}char *km_keyname (int c){  static char buf[10];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -