This is slkeymap.c in view mode; [Download] [Up]
/* Keymap routines for SLang. The role of these keymap routines is simple:
* Just read keys from the tty and return a pointer to a keymap structure.
* That is, a keymap is simple a mapping of strings (keys from tty) to
* structures. Also included are routines for managing the keymaps.
*/
/* Copyright (c) 1992, 1995 John E. Davis
* All rights reserved.
*
* You may distribute under the terms of either the GNU General Public
* License or the Perl Artistic License.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "slang.h"
#include "_slang.h"
/* We need a define a rule for upperand lower case chars that user cannot
change! This could be a problem for international chars! */
#define UPPER_CASE_KEY(x) (((x) >= 'a') && ((x) <= 'z') ? (x) - 32 : (x))
#define LOWER_CASE_KEY(x) (((x) >= 'A') && ((x) <= 'Z') ? (x) + 32 : (x))
int SLang_Key_TimeOut_Flag = 0; /* true if more than 1 sec has elapsed
without key in multikey sequence */
int SLang_Last_Key_Char;
SLKeyMap_List_Type SLKeyMap_List[SLANG_MAX_KEYMAPS]; /* these better be inited to 0! */
static SLang_Key_Type *malloc_key(unsigned char *str)
{
SLang_Key_Type *neew;
if (NULL == (neew = (SLang_Key_Type *) SLMALLOC(sizeof(SLang_Key_Type))))
{
SLang_Error = SL_MALLOC_ERROR;
return NULL;
}
SLMEMCPY((char *) neew->str, (char *) str, (unsigned int) *str);
return(neew);
}
static SLKeyMap_List_Type *add_keymap(char *name, SLang_Key_Type *map)
{
int i;
for (i = 0; i < SLANG_MAX_KEYMAPS; i++)
{
if (SLKeyMap_List[i].keymap == NULL)
{
SLKeyMap_List[i].keymap = map;
strncpy((char *) SLKeyMap_List[i].name, (char *) name, MAX_KEYMAP_NAME_LEN);
SLKeyMap_List[i].name[MAX_KEYMAP_NAME_LEN] = 0;
return &SLKeyMap_List[i];
}
}
SLang_Error = UNKNOWN_ERROR;
/* SLang_doerror ("Keymap quota exceeded."); */
return NULL;
}
#ifdef SLKEYMAP_OBSOLETE
VOID_STAR
#else
FVOID_STAR
#endif
SLang_find_key_function(char *name, SLKeyMap_List_Type *keymap)
{
SLKeymap_Function_Type *fp = keymap -> functions;
while ((fp != NULL) && (fp->name != NULL))
{
if ((*fp->name == *name) && !strcmp(fp->name, name))
{
#ifdef SLKEYMAP_OBSOLETE
return (VOID_STAR) fp->f;
#else
return (FVOID_STAR) fp->f;
#endif
}
fp++;
}
return(NULL);
}
/* convert things like "^A" to 1 etc... The 0th char is the strlen INCLUDING
* the length character itself.
*/
char *SLang_process_keystring(char *s)
{
static char str[30];
unsigned char ch;
int i;
i = 1;
while (*s != 0)
{
ch = (unsigned char) *s++;
if (*s) ch = UPPER_CASE_KEY(ch);
if (ch == '^')
{
ch = *s++;
if (ch == 0)
{
str[i++] = '^';
break;
}
if (ch == '?') ch = 127; else ch = ch - 'A' + 1;
}
str[i++] = ch;
}
str[0] = i;
return(str);
}
static char *Define_Key_Error = "Inconsistency in define key.";
static int find_the_key (char *s, SLKeyMap_List_Type *kml, SLang_Key_Type **keyp)
{
int cmp, i, m, n, len;
SLang_Key_Type *key, *last, *neew;
unsigned char *str;
*keyp = NULL;
str = (unsigned char *) SLang_process_keystring(s);
if (1 == (n = str[0])) return 0;
i = *(str + 1);
key = &((kml->keymap)[i]);
if (n == 2)
{
if (key->next != NULL)
{
SLang_doerror (Define_Key_Error);
return -2;
}
/* copy keymap uses the pointers so do not free these if copied */
if ((SLKeyMap_List[1].keymap == NULL)
&& (key->type == SLKEY_F_INTERPRET))
{
#ifdef SLKEYMAP_OBSOLETE
SLFREE(key->f);
#else
SLFREE (key->f.s);
#endif
}
SLMEMCPY((char *) key->str, (char *) str, 2);
*keyp = key;
return 0;
}
/* insert the key definition */
while(1)
{
last = key;
key = key->next;
if ((key == NULL) || (key->str == NULL)) cmp = -1;
else
{
m = key->str[0];
len = m;
if (m > n) len = n;
cmp = SLMEMCMP((char *) (str + 1), (char *)(key->str + 1), len - 1);
if ((m != n) && !cmp)
{
SLang_doerror (Define_Key_Error);
return -2;
}
if ((m == n) && (!cmp)) cmp = SLMEMCMP((char *) str, (char *) key->str, n);
}
if (cmp == 0)
{
/* copy keymap uses the pointers so do not free these if copied */
if ((SLKeyMap_List[1].keymap == NULL)
&& (key->type == SLKEY_F_INTERPRET))
{
#ifdef SLKEYMAP_OBSOLETE
SLFREE(key->f);
#else
SLFREE(key->f.s);
#endif
}
*keyp = key;
return 0;
}
else if (cmp < 0)
{
if (NULL == (neew = malloc_key(str))) return -1;
neew -> next = key;
last -> next = neew;
*keyp = neew;
return 0;
} /* else cmp > 0 */
}
}
/* returns -2 if inconsistent, -1 if malloc error, 0 upon success */
#ifdef SLKEYMAP_OBSOLETE
int SLang_define_key1 (char *s, VOID_STAR f, unsigned int type, SLKeyMap_List_Type *kml)
#else
int SLkm_define_key (char *s, FVOID_STAR f, SLKeyMap_List_Type *kml)
#endif
{
SLang_Key_Type *key;
#ifndef SLKEYMAP_OBSOLETE
unsigned int type = SLKEY_F_INTRINSIC;
#endif
int ret;
ret = find_the_key (s, kml, &key);
if ((ret != 0) || (key == NULL))
return ret;
key->type = type;
#ifdef SLKEYMAP_OBSOLETE
key->f = f;
#else
key->f.f = f;
#endif
return 0;
}
int SLang_define_key(char *s, char *funct, SLKeyMap_List_Type *kml)
{
SLang_Key_Type *key;
#ifdef SLKEYMAP_OBSOLETE
VOID_STAR f;
#else
FVOID_STAR f;
#endif
int ret;
ret = find_the_key (s, kml, &key);
if ((ret != 0) || (key == NULL))
return ret;
f = SLang_find_key_function(funct, kml);
if (f == NULL) /* assume interpreted */
{
char *str = SLmake_string (funct);
if (str == NULL) return -1;
key->type = SLKEY_F_INTERPRET;
#ifdef SLKEYMAP_OBSOLETE
key->f = (VOID_STAR) str;
#else
key->f.s = str;
#endif
}
else
{
key->type = SLKEY_F_INTRINSIC;
#ifdef SLKEYMAP_OBSOLETE
key->f = f;
#else
key->f.f = f;
#endif
}
return 0;
}
SLang_Key_Type *SLang_do_key(SLKeyMap_List_Type *kml, int (*getkey)(void))
{
register SLang_Key_Type *key, *next;
int i;
unsigned char ch1, ch;
register unsigned char chi, chup, chlow;
ch = (unsigned char) (*getkey)();
SLang_Last_Key_Char = (int) ch;
i = ch1 = (unsigned char) ch;
key = (SLang_Key_Type *) &((kml->keymap)[i]);
/* if the next one is null, then we know this is it. */
if (key->next == NULL)
{
/* check its uppercase counterpart if null and return it */
if (
#ifdef SLKEYMAP_OBSOLETE
(key->f == NULL)
#else
(key->f.f == NULL)
#endif
&& (i >= 'a') && (i <= 'z'))
key = (SLang_Key_Type *) &((kml->keymap)[i - 32]);
SLang_Key_TimeOut_Flag = 0;
return(key);
}
key = key->next;
SLang_Key_TimeOut_Flag = 1;
SLang_Last_Key_Char = (*getkey)();
i = 2; /* 0 is keylen, 1 matches, so 2 */
ch1 = (unsigned char) SLang_Last_Key_Char;
chup = UPPER_CASE_KEY(ch1); chlow = LOWER_CASE_KEY(ch1);
while(key != NULL)
{
if (SLKeyBoard_Quit) break;
chi = key->str[i];
if ((chup == chi) || (chlow == chi))
{
if (*key->str == i + 1)
{
/* look for exact match if possible */
if (ch1 != chi)
{
next = key->next;
while (next != NULL)
{
if (next->str[i] == ch1)
{
if (next->str[0] == i + 1)
{
SLang_Key_TimeOut_Flag = 0;
return(next);
}
break;
}
next = next->next;
}
}
SLang_Key_TimeOut_Flag = 0;
return(key);
}
/* before reading a new key, check to see if it is lowercase
* and try to find a match for it. Note that this works because
* only the LAST character in a key sequence can be lowercase */
else if ((ch1 == chlow) && (ch1 != chup))
{
next = key->next;
/* look for the lowercase one */
while (next != NULL)
{
if ((next->str[i] == chlow) &&
(next->str[0] == i + 1))
{
SLang_Key_TimeOut_Flag = 0;
return(next);
}
next = next->next;
}
}
SLang_Last_Key_Char = ch1 = (*getkey)();
i++;
chup = UPPER_CASE_KEY(ch1);
chlow = LOWER_CASE_KEY(ch1);
continue;
}
else if (chlow < chi) break; /* not found */
/* else */
key = key->next;
}
/* not found */
SLang_Key_TimeOut_Flag = 0;
return(NULL);
}
void SLang_undefine_key(char *s, SLKeyMap_List_Type *kml)
{
int n, i;
SLang_Key_Type *key, *next, *last, *key_root, *keymap;
unsigned char *str;
keymap = kml -> keymap;
str = (unsigned char *) SLang_process_keystring(s);
if (0 == (n = *str++ - 1)) return;
i = *str;
key = key_root = (SLang_Key_Type *) &(keymap[i]);
last = key_root;
key = key_root->next;
while (key != NULL)
{
next = key->next;
if (!SLMEMCMP((char *)(key->str + 1), (char *) str, n))
{
if ((SLKeyMap_List[1].keymap == NULL)
&& (key->type == SLKEY_F_INTERPRET))
{
#ifdef SLKEYMAP_OBSOLETE
SLFREE(key->f);
#else
SLFREE (key->f.s);
#endif
}
SLFREE(key);
last->next = next;
}
else last = key;
key = next;
}
if (n == 1)
{
*key_root->str = 0;
#ifdef SLKEYMAP_OBSOLETE
key_root->f = NULL;
#else
key_root->f.f = NULL;
#endif
key_root->type = 0;
}
}
char *SLang_make_keystring(unsigned char *s)
{
static char buf[40];
char *b;
int n;
b = buf;
n = *s++ - 1;
while (n--)
{
if (*s < 32)
{
*b++ = '^';
*b++ = *s + 'A' - 1;
}
else *b++ = *s;
s++;
}
*b = 0;
return(buf);
}
static SLang_Key_Type *copy_keymap(SLKeyMap_List_Type *kml)
{
int i;
SLang_Key_Type *neew, *old, *new_root, *km;
if (NULL == (new_root = (SLang_Key_Type *) SLCALLOC(256, sizeof(SLang_Key_Type))))
{
SLang_Error = SL_MALLOC_ERROR;
return NULL;
}
if (kml == NULL) return new_root;
km = kml->keymap;
for (i = 0; i < 256; i++)
{
old = &(km[i]);
neew = &(new_root[i]);
#ifdef SLKEYMAP_OBSOLETE
neew->f = old->f;
#else
if (old->type == SLKEY_F_INTERPRET)
neew->f.s = old->f.s;
else
neew->f.f = old->f.f;
#endif
neew->type = old->type;
SLMEMCPY((char *) neew->str, (char *) old->str, (unsigned int) *old->str);
old = old->next;
while (old != NULL)
{
neew->next = malloc_key((unsigned char *) old->str);
neew = neew->next;
#ifdef SLKEYMAP_OBSOLETE
neew->f = old->f;
#else
if (old->type == SLKEY_F_INTERPRET)
neew->f.s = old->f.s;
else
neew->f.f = old->f.f;
#endif
neew->type = old->type;
old = old->next;
}
neew->next = NULL;
}
return(new_root);
}
SLKeyMap_List_Type *SLang_create_keymap(char *name, SLKeyMap_List_Type *map)
{
SLang_Key_Type *neew;
SLKeyMap_List_Type *new_map;
if ((NULL == (neew = copy_keymap(map)))
|| (NULL == (new_map = add_keymap(name, neew)))) return NULL;
if (map != NULL) new_map -> functions = map -> functions;
return new_map;
}
SLKeyMap_List_Type *SLang_find_keymap(char *name)
{
int i;
for (i = 0; i < SLANG_MAX_KEYMAPS; i++)
{
if (!strncmp(SLKeyMap_List[i].name, name, 8)) return &SLKeyMap_List[i];
}
return(NULL);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.