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

📄 keytab.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000, 2001 by Martin C. Shepherd. *  * All rights reserved. *  * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Software, and to permit persons * to whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *  * Except as contained in this notice, the name of a copyright holder * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * of the copyright holder. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "keytab.h"#include "getline.h"#include "strngmem.h"static int _kt_extend_table(KeyTab *kt);#if 0static int _kt_parse_keybinding_string(const char *keyseq,				       char *binary, int *nc);#endifstatic int _kt_compare_strings(const char *s1, int n1, const char *s2, int n2);static void _kt_assign_action(KeySym *sym, KtBinder binder, KtKeyFn *keyfn);static char _kt_backslash_escape(const char *string, const char **endp);static int _kt_is_emacs_meta(const char *string);static int _kt_is_emacs_ctrl(const char *string);/*....................................................................... * Create a new key-binding symbol table. * * Output: *  return  KeyTab *  The new object, or NULL on error. */KeyTab *_new_KeyTab(void){  KeyTab *kt;  /* The object to be returned *//* * Allocate the container. */  kt = (KeyTab *) malloc(sizeof(KeyTab));  if(!kt) {    fprintf(stderr, "new_KeyTab: Insufficient memory.\n");    return NULL;  };/* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to del_KeyTab(). */  kt->size = KT_TABLE_INC;  kt->nkey = 0;  kt->table = NULL;  kt->actions = NULL;  kt->smem = NULL;/* * Allocate the table. */  kt->table = (KeySym *) malloc(sizeof(kt->table[0]) * kt->size);  if(!kt->table) {    fprintf(stderr, "new_KeyTab: Insufficient memory for table of size %d.\n",	    kt->size);    return _del_KeyTab(kt);  };/* * Allocate a hash table of actions. */  kt->actions = _new_HashTable(NULL, KT_HASH_SIZE, IGNORE_CASE, NULL, 0);  if(!kt->actions)    return _del_KeyTab(kt);/* * Allocate a string allocation object. This allows allocation of * small strings without fragmenting the heap. */  kt->smem = _new_StringMem("new_KeyTab", KT_TABLE_INC);  if(!kt->smem)    return _del_KeyTab(kt);  return kt;}/*....................................................................... * Delete a KeyTab object. * * Input: *  kt   KeyTab *  The object to be deleted. * Output: *  return KeyTab *  The deleted object (always NULL). */KeyTab *_del_KeyTab(KeyTab *kt){  if(kt) {    if(kt->table)      free(kt->table);    kt->actions = _del_HashTable(kt->actions);    kt->smem = _del_StringMem("del_KeyTab", kt->smem, 1);    free(kt);  };  return NULL;}/*....................................................................... * Increase the size of the table to accomodate more keys. * * Input: *  kt       KeyTab *  The table to be extended. * Output: *  return      int    0 - OK. *                     1 - Error. */static int _kt_extend_table(KeyTab *kt){/* * Attempt to increase the size of the table. */  KeySym *newtab = (KeySym *) realloc(kt->table, sizeof(kt->table[0]) *				      (kt->size + KT_TABLE_INC));/* * Failed? */  if(!newtab) {    fprintf(stderr,	    "getline(): Insufficient memory to extend keybinding table.\n");    return 1;  };/* * Install the resized table. */  kt->table = newtab;  kt->size += KT_TABLE_INC;  return 0;}/*....................................................................... * Add, update or remove a keybinding to the table. * * Input: *  kt           KeyTab *  The table to add the binding to. *  binder     KtBinder    The source of the binding. *  keyseq   const char *  The key-sequence to bind. *  action         char *  The action to associate with the key sequence, or *                         NULL to remove the action associated with the *                         key sequence. * Output: *  return          int    0 - OK. *                         1 - Error. */int _kt_set_keybinding(KeyTab *kt, KtBinder binder, const char *keyseq,		       const char *action){  KtKeyFn *keyfn; /* The action function *//* * Check arguments. */  if(kt==NULL || !keyseq) {    fprintf(stderr, "kt_set_keybinding: NULL argument(s).\n");    return 1;  };/* * Lookup the function that implements the specified action. */  if(!action) {    keyfn = 0;  } else {    Symbol *sym = _find_HashSymbol(kt->actions, action);    if(!sym) {      fprintf(stderr, "getline: Unknown key-binding action: %s\n", action);      return 1;    };    keyfn = (KtKeyFn *) sym->fn;  };/* * Record the action in the table. */  return _kt_set_keyfn(kt, binder, keyseq, keyfn);}/*....................................................................... * Add, update or remove a keybinding to the table, specifying an action * function directly. * * Input: *  kt       KeyTab *  The table to add the binding to. *  binder KtBinder    The source of the binding. *  keyseq     char *  The key-sequence to bind. *  keyfn   KtKeyFn *  The action function, or NULL to remove any existing *                     action function. * Output: *  return     int    0 - OK. *                    1 - Error. */int _kt_set_keyfn(KeyTab *kt, KtBinder binder, const char *keyseq,		  KtKeyFn *keyfn){  const char *kptr;  /* A pointer into keyseq[] */  char *binary;      /* The binary version of keyseq[] */  int nc;            /* The number of characters in binary[] */  int first,last;    /* The first and last entries in the table which */                     /*  minimally match. */  int size;          /* The size to allocate for the binary string *//* * Check arguments. */  if(kt==NULL || !keyseq) {    fprintf(stderr, "kt_set_keybinding: NULL argument(s).\n");    return 1;  };/* * Work out a pessimistic estimate of how much space will be needed * for the binary copy of the string, noting that binary meta characters * embedded in the input string get split into two characters. */  for(size=0,kptr = keyseq; *kptr; kptr++)    size += IS_META_CHAR(*kptr) ? 2 : 1;/* * Allocate a string that has the length of keyseq[]. */  binary = _new_StringMemString(kt->smem, size + 1);  if(!binary) {    fprintf(stderr,	    "gl_get_line: Insufficient memory to record key sequence.\n");    return 1;  };/* * Convert control and octal character specifications to binary characters. */  if(_kt_parse_keybinding_string(keyseq, binary, &nc)) {    binary = _del_StringMemString(kt->smem, binary);    return 1;  };/* * Lookup the position in the table at which to insert the binding. */  switch(_kt_lookup_keybinding(kt, binary, nc, &first, &last)) {/* * If an exact match for the key-sequence is already in the table, * simply replace its binding function (or delete the entry if * the new binding is 0). */  case KT_EXACT_MATCH:    if(keyfn) {      _kt_assign_action(kt->table + first, binder, keyfn);    } else {      _del_StringMemString(kt->smem, kt->table[first].keyseq);      memmove(kt->table + first, kt->table + first + 1,	      (kt->nkey - first - 1) * sizeof(kt->table[0]));      kt->nkey--;    };    binary = _del_StringMemString(kt->smem, binary);    break;/* * If an ambiguous match has been found and we are installing a * callback, then our new key-sequence would hide all of the ambiguous * matches, so we shouldn't allow it. */  case KT_AMBIG_MATCH:    if(keyfn) {      fprintf(stderr,	      "getline: Can't bind \"%s\", because it's a prefix of another binding.\n",	      keyseq);      binary = _del_StringMemString(kt->smem, binary);      return 1;    };    break;/* * If the entry doesn't exist, create it. */  case KT_NO_MATCH:/* * Add a new binding? */    if(keyfn) {      KeySym *sym;/* * We will need a new entry, extend the table if needed. */      if(kt->nkey + 1 > kt->size) {	if(_kt_extend_table(kt)) {	  binary = _del_StringMemString(kt->smem, binary);	  return 1;	};      };/* * Make space to insert the new key-sequence before 'last'. */      if(last < kt->nkey) {	memmove(kt->table + last + 1, kt->table + last,		(kt->nkey - last) * sizeof(kt->table[0]));      };/* * Insert the new binding in the vacated position. */      sym = kt->table + last;      sym->keyseq = binary;      sym->nc = nc;      sym->user_fn = sym->term_fn = sym->norm_fn = sym->keyfn = 0;      _kt_assign_action(sym, binder, keyfn);      kt->nkey++;    };    break;  case KT_BAD_MATCH:    binary = _del_StringMemString(kt->smem, binary);    return 1;    break;  };  return 0;}/*....................................................................... * Perform a min-match lookup of a key-binding. * * Input: *  kt          KeyTab *  The keybinding table to lookup in. *  binary_keyseq char *  The binary key-sequence to lookup. *  nc             int    the number of characters in keyseq[]. * Input/Output: *  first,last     int *  If there is an ambiguous or exact match, the indexes *                        of the first and last symbols that minimally match *                        will be assigned to *first and *last respectively. *                        If there is no match, then first and last will *                        bracket the location where the symbol should be *                        inserted. *                       * Output: *  return  KtKeyMatch    One of the following enumerators: *                         KT_EXACT_MATCH - An exact match was found. *                         KT_AMBIG_MATCH - An ambiguous match was found. *                         KT_NO_MATCH    - No match was found. *                         KT_BAD_MATCH   - An error occurred while searching. */KtKeyMatch _kt_lookup_keybinding(KeyTab *kt, const char *binary_keyseq, int nc,				 int *first, int *last){  int mid;     /* The index at which to bisect the table */  int bot;     /* The lowest index of the table not searched yet */  int top;     /* The highest index of the table not searched yet */  int test;    /* The return value of strcmp() *//* * Check the arguments. */  if(!kt || !binary_keyseq || !first || !last || nc < 0) {    fprintf(stderr, "kt_lookup_keybinding: NULL argument(s).\n");    return KT_BAD_MATCH;  };/* * Perform a binary search for the key-sequence. */  bot = 0;  top = kt->nkey - 1;  while(top >= bot) {    mid = (top + bot)/2;    test = _kt_compare_strings(kt->table[mid].keyseq, kt->table[mid].nc,			   binary_keyseq, nc);    if(test > 0)      top = mid - 1;    else if(test < 0)      bot = mid + 1;    else {      *first = *last = mid;      return KT_EXACT_MATCH;    };  };/* * An exact match wasn't found, but top is the index just below the * index where a match would be found, and bot is the index just above * where the match ought to be found. */  *first = top;  *last = bot;/* * See if any ambiguous matches exist, and if so make *first and *last * refer to the first and last matches. */  if(*last < kt->nkey && kt->table[*last].nc > nc &&     _kt_compare_strings(kt->table[*last].keyseq, nc, binary_keyseq, nc)==0) {    *first = *last;    while(*last+1 < kt->nkey && kt->table[*last+1].nc > nc &&	  _kt_compare_strings(kt->table[*last+1].keyseq, nc, binary_keyseq, nc)==0)      (*last)++;    return KT_AMBIG_MATCH;  };/* * No match. */  return KT_NO_MATCH;}/*....................................................................... * Convert a keybinding string into a uniq binary representation. * * Control characters can be given directly in their binary form, * expressed as either ^ or C-, followed by the character, expressed in * octal, like \129 or via C-style backslash escapes, with the addition

⌨️ 快捷键说明

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