summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/slang/slkeymap.c
diff options
context:
space:
mode:
authorGuillaume Cottenceau <gc@mandriva.com>2001-05-14 21:47:42 +0000
committerGuillaume Cottenceau <gc@mandriva.com>2001-05-14 21:47:42 +0000
commit98a18b797c63ea9baab31768ed720ad32c0004e8 (patch)
tree2d8b0d9e845b332060ac668a429ef65ca4c47ed1 /mdk-stage1/slang/slkeymap.c
parent12cf594c688f3bc3e0b26d35305d5d6db7036fc4 (diff)
downloaddrakx-backup-do-not-use-98a18b797c63ea9baab31768ed720ad32c0004e8.tar
drakx-backup-do-not-use-98a18b797c63ea9baab31768ed720ad32c0004e8.tar.gz
drakx-backup-do-not-use-98a18b797c63ea9baab31768ed720ad32c0004e8.tar.bz2
drakx-backup-do-not-use-98a18b797c63ea9baab31768ed720ad32c0004e8.tar.xz
drakx-backup-do-not-use-98a18b797c63ea9baab31768ed720ad32c0004e8.zip
i can compile slang and newt with dietlibc now
Diffstat (limited to 'mdk-stage1/slang/slkeymap.c')
-rw-r--r--mdk-stage1/slang/slkeymap.c596
1 files changed, 596 insertions, 0 deletions
diff --git a/mdk-stage1/slang/slkeymap.c b/mdk-stage1/slang/slkeymap.c
new file mode 100644
index 000000000..dff65433e
--- /dev/null
+++ b/mdk-stage1/slang/slkeymap.c
@@ -0,0 +1,596 @@
+/* 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, 1999, 2001 John E. Davis
+ * This file is part of the S-Lang library.
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Perl Artistic License.
+ */
+
+#include "slinclud.h"
+
+#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];
+
+static SLang_Key_Type *malloc_key(unsigned char *str)
+{
+ SLang_Key_Type *neew;
+
+ if (NULL == (neew = (SLang_Key_Type *) SLmalloc(sizeof(SLang_Key_Type))))
+ return NULL;
+
+ SLMEMSET ((char *) neew, 0, sizeof (SLang_Key_Type));
+ 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)
+ {
+ if (NULL == (name = SLang_create_slstring (name)))
+ return NULL;
+
+ SLKeyMap_List[i].keymap = map;
+ SLKeyMap_List[i].name = name;
+ return &SLKeyMap_List[i];
+ }
+ }
+ SLang_Error = SL_UNKNOWN_ERROR;
+ /* SLang_doerror ("Keymap quota exceeded."); */
+ return NULL;
+}
+
+FVOID_STAR SLang_find_key_function(char *name, SLKeyMap_List_Type *keymap)
+{
+ SLKeymap_Function_Type *fp = keymap -> functions;
+ char ch = *name;
+
+ while ((fp != NULL) && (fp->name != NULL))
+ {
+ if ((ch == *fp->name)
+ && (0 == strcmp(fp->name, name)))
+ return (FVOID_STAR) fp->f;
+
+ fp++;
+ }
+ return NULL;
+}
+
+#ifdef REAL_UNIX_SYSTEM
+/* Expand termcap string specified by s. s as passed will have the format:
+ * "XY)..." where XY represents a termcap keyname.
+ */
+static char *process_termcap_string (char *s, char *str, int *ip, int imax)
+{
+ char c[3], *val;
+ int i;
+
+ if ((0 == (c[0] = s[0]))
+ || (0 == (c[1] = s[1]))
+ || (s[2] != ')'))
+ {
+ SLang_verror (SL_SYNTAX_ERROR, "setkey: ^(%s is badly formed", s);
+ return NULL;
+ }
+ s += 3;
+
+ c[2] = 0;
+ if ((NULL == (val = SLtt_tgetstr (c)))
+ || (*val == 0))
+ return NULL;
+
+ i = *ip;
+ while ((i < imax) && (*val != 0))
+ {
+ str[i++] = *val++;
+ }
+ *ip = i;
+
+ return s;
+}
+#endif
+
+/* convert things like "^A" to 1 etc... The 0th char is the strlen INCLUDING
+ * the length character itself.
+ */
+char *SLang_process_keystring(char *s)
+{
+ /* FIXME: v2.0, make this thread safe */
+ static char str[32];
+ unsigned char ch;
+ int i;
+
+ i = 1;
+ while (*s != 0)
+ {
+ ch = (unsigned char) *s++;
+ if (ch == '^')
+ {
+ ch = *s++;
+ if (ch == 0)
+ {
+ if (i < 32)
+ str[i++] = '^';
+ break;
+ }
+#ifdef REAL_UNIX_SYSTEM
+ if (ch == '(')
+ {
+ s = process_termcap_string (s, str, &i, 32);
+ if (s == NULL)
+ {
+ str[0] = 1;
+ return str;
+ }
+ continue;
+ }
+#endif
+ ch = UPPER_CASE_KEY(ch);
+ if (ch == '?') ch = 127; else ch = ch - 'A' + 1;
+ }
+
+ if (i >= 32) break;
+ str[i++] = ch;
+ }
+
+ if (i > SLANG_MAX_KEYMAP_KEY_SEQ)
+ {
+ SLang_verror (SL_INVALID_PARM, "Key sequence is too long");
+ return NULL;
+ }
+
+ str[0] = i;
+ return(str);
+}
+
+static int key_string_compare (unsigned char *a, unsigned char *b, unsigned int len)
+{
+ unsigned char *amax = a + len;
+ int cha, chb, cha_up, chb_up;
+
+ while (a < amax)
+ {
+ cha = *a++;
+ chb = *b++;
+
+ if (cha == chb) continue;
+
+ cha_up = UPPER_CASE_KEY(cha);
+ chb_up = UPPER_CASE_KEY(chb);
+
+ if (cha_up == chb_up)
+ {
+ /* Use case-sensitive result. */
+ return cha - chb;
+ }
+ /* Use case-insensitive result. */
+ return cha_up - chb_up;
+ }
+ return 0;
+}
+
+static char *Define_Key_Error = "Inconsistency in define key.";
+
+/* This function also performs an insertion in an ordered way. */
+static int find_the_key (char *s, SLKeyMap_List_Type *kml, SLang_Key_Type **keyp)
+{
+ unsigned char ch;
+ unsigned int str_len;
+ SLang_Key_Type *key, *last, *neew;
+ unsigned char *str;
+
+ *keyp = NULL;
+
+ if (NULL == (str = (unsigned char *) SLang_process_keystring(s)))
+ return -2;
+
+ if (1 == (str_len = str[0]))
+ return 0;
+
+ ch = str[1];
+ key = kml->keymap + ch;
+
+ if (str_len == 2)
+ {
+ if (key->next != NULL)
+ {
+ SLang_doerror (Define_Key_Error);
+ return -2;
+ }
+
+ if (key->type == SLKEY_F_INTERPRET)
+ SLang_free_slstring (key->f.s);
+
+ key->str[0] = str_len;
+ key->str[1] = ch;
+
+ *keyp = key;
+ return 0;
+ }
+
+ /* insert the key definition */
+ while (1)
+ {
+ int cmp;
+ unsigned int key_len, len;
+
+ last = key;
+ key = key->next;
+
+ if ((key != NULL) && (key->str != NULL))
+ {
+ len = key_len = key->str[0];
+ if (len > str_len) len = str_len;
+
+ cmp = key_string_compare (str + 1, key->str + 1, len - 1);
+
+ if (cmp > 0)
+ continue;
+
+ if (cmp == 0)
+ {
+ if (key_len != str_len)
+ {
+ SLang_doerror (Define_Key_Error);
+ return -2;
+ }
+
+ if (key->type == SLKEY_F_INTERPRET)
+ SLang_free_slstring (key->f.s);
+
+ *keyp = key;
+ return 0;
+ }
+ /* Drop to cmp < 0 case */
+ }
+
+ if (NULL == (neew = malloc_key(str))) return -1;
+
+ neew -> next = key;
+ last -> next = neew;
+
+ *keyp = neew;
+ return 0;
+ }
+}
+
+/* returns -2 if inconsistent, -1 if malloc error, 0 upon success */
+int SLkm_define_key (char *s, FVOID_STAR f, SLKeyMap_List_Type *kml)
+{
+ SLang_Key_Type *key;
+ unsigned int type = SLKEY_F_INTRINSIC;
+ int ret;
+
+ ret = find_the_key (s, kml, &key);
+ if ((ret != 0) || (key == NULL))
+ return ret;
+
+ key->type = type;
+ key->f.f = f;
+ return 0;
+}
+
+int SLang_define_key (char *s, char *funct, SLKeyMap_List_Type *kml)
+{
+ SLang_Key_Type *key;
+ FVOID_STAR f;
+ 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 = SLang_create_slstring (funct);
+ if (str == NULL) return -1;
+ key->type = SLKEY_F_INTERPRET;
+ key->f.s = str;
+ }
+ else
+ {
+ key->type = SLKEY_F_INTRINSIC;
+ key->f.f = f;
+ }
+ return 0;
+}
+
+int SLkm_define_keysym (char *s, unsigned int keysym, SLKeyMap_List_Type *kml)
+{
+ SLang_Key_Type *key;
+ int ret;
+
+ ret = find_the_key (s, kml, &key);
+
+ if ((ret != 0) || (key == NULL))
+ return ret;
+
+ key->type = SLKEY_F_KEYSYM;
+ key->f.keysym = keysym;
+ return 0;
+}
+
+SLang_Key_Type *SLang_do_key(SLKeyMap_List_Type *kml, int (*getkey)(void))
+{
+ register SLang_Key_Type *key, *next, *kmax;
+ unsigned int len;
+ unsigned char input_ch;
+ register unsigned char chup, chlow;
+ unsigned char key_ch = 0;
+
+ SLang_Last_Key_Char = (*getkey)();
+ SLang_Key_TimeOut_Flag = 0;
+
+ if (SLANG_GETKEY_ERROR == (unsigned int) SLang_Last_Key_Char)
+ return NULL;
+
+ input_ch = (unsigned char) SLang_Last_Key_Char;
+
+ key = (SLang_Key_Type *) &((kml->keymap)[input_ch]);
+
+ /* if the next one is null, then we know this MAY be it. */
+ while (key->next == NULL)
+ {
+ if (key->type != 0)
+ return key;
+
+ /* Try its opposite case counterpart */
+ chlow = LOWER_CASE_KEY(input_ch);
+ if (input_ch == chlow)
+ input_ch = UPPER_CASE_KEY(input_ch);
+
+ key = kml->keymap + input_ch;
+ if (key->type == 0)
+ return NULL;
+ }
+
+ /* It appears to be a prefix character in a key sequence. */
+
+ len = 1; /* already read one character */
+ key = key->next; /* Now we are in the key list */
+ kmax = NULL; /* set to end of list */
+
+ while (1)
+ {
+ SLang_Key_TimeOut_Flag = 1;
+ SLang_Last_Key_Char = (*getkey)();
+ SLang_Key_TimeOut_Flag = 0;
+
+ len++;
+
+ if ((SLANG_GETKEY_ERROR == (unsigned int) SLang_Last_Key_Char)
+ || SLKeyBoard_Quit)
+ break;
+
+ input_ch = (unsigned char) SLang_Last_Key_Char;
+
+ chup = UPPER_CASE_KEY(input_ch); chlow = LOWER_CASE_KEY(input_ch);
+
+ while (key != kmax)
+ {
+ if (key->str[0] > len)
+ {
+ key_ch = key->str[len];
+ if (chup == UPPER_CASE_KEY(key_ch))
+ break;
+ }
+ key = key->next;
+ }
+
+ if (key == kmax) break;
+
+ /* If the input character is lowercase, check to see if there is
+ * a lowercase match. If so, set key to it. Note: the
+ * algorithm assumes the sorting performed by key_string_compare.
+ */
+ if (input_ch != key_ch)
+ {
+ next = key->next;
+ while (next != kmax)
+ {
+ if (next->str[0] > len)
+ {
+ unsigned char next_ch = next->str[len];
+ if (next_ch == input_ch)
+ {
+ key = next;
+ break;
+ }
+ if (next_ch != chup)
+ break;
+ }
+ next = next->next;
+ }
+ }
+
+ /* Ok, we found the first position of a possible match. If it
+ * is exact, we are done.
+ */
+ if ((unsigned int) key->str[0] == len + 1)
+ return key;
+
+ /* Apparantly, there are some ambiguities. Read next key to resolve
+ * the ambiguity. Adjust kmax to encompass ambiguities.
+ */
+
+ next = key->next;
+ while (next != kmax)
+ {
+ if ((unsigned int) next->str[0] > len)
+ {
+ key_ch = next->str[len];
+ if (chup != UPPER_CASE_KEY(key_ch))
+ break;
+ }
+ next = next->next;
+ }
+ kmax = next;
+ }
+
+ 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;
+ if (NULL == (str = (unsigned char *) SLang_process_keystring(s)))
+ return;
+
+ if (0 == (n = *str++ - 1)) return;
+ i = *str;
+
+ last = key_root = (SLang_Key_Type *) &(keymap[i]);
+ key = key_root->next;
+
+ while (key != NULL)
+ {
+ next = key->next;
+ if (0 == SLMEMCMP ((char *)(key->str + 1), (char *) str, n))
+ {
+ if (key->type == SLKEY_F_INTERPRET)
+ SLang_free_slstring (key->f.s);
+
+ SLfree((char *) key);
+ last->next = next;
+ }
+ else last = key;
+ key = next;
+ }
+
+ if (n == 1)
+ {
+ *key_root->str = 0;
+ key_root->f.f = NULL;
+ key_root->type = 0;
+ }
+}
+
+char *SLang_make_keystring(unsigned char *s)
+{
+ static char buf [3 * SLANG_MAX_KEYMAP_KEY_SEQ + 1];
+ char *b;
+ int n;
+
+ n = *s++ - 1;
+
+ if (n > SLANG_MAX_KEYMAP_KEY_SEQ)
+ {
+ SLang_verror (SL_INVALID_PARM, "Key sequence is too long");
+ return NULL;
+ }
+
+ b = buf;
+ 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))))
+ return NULL;
+
+ if (kml == NULL) return new_root;
+ km = kml->keymap;
+
+ for (i = 0; i < 256; i++)
+ {
+ old = &(km[i]);
+ neew = &(new_root[i]);
+
+ if (old->type == SLKEY_F_INTERPRET)
+ neew->f.s = SLang_create_slstring (old->f.s);
+ else
+ neew->f.f = old->f.f;
+
+ 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;
+
+ if (old->type == SLKEY_F_INTERPRET)
+ neew->f.s = SLang_create_slstring (old->f.s);
+ else
+ neew->f.f = old->f.f;
+
+ 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)
+{
+ SLKeyMap_List_Type *kmap, *kmap_max;
+
+ kmap = SLKeyMap_List;
+ kmap_max = kmap + SLANG_MAX_KEYMAPS;
+
+ while (kmap < kmap_max)
+ {
+ if ((kmap->name != NULL)
+ && (0 == strcmp (kmap->name, name)))
+ return kmap;
+
+ kmap++;
+ }
+ return NULL;
+}