summaryrefslogtreecommitdiff
path: root/console-client/xkb/xkbdata.c
diff options
context:
space:
mode:
Diffstat (limited to 'console-client/xkb/xkbdata.c')
-rw-r--r--console-client/xkb/xkbdata.c456
1 files changed, 456 insertions, 0 deletions
diff --git a/console-client/xkb/xkbdata.c b/console-client/xkb/xkbdata.c
new file mode 100644
index 00000000..97545e52
--- /dev/null
+++ b/console-client/xkb/xkbdata.c
@@ -0,0 +1,456 @@
+/* xkbdata.c -- Manage XKB datastructures.
+
+ Copyright (C) 2003 Marco Gerards
+
+ Written by Marco Gerards <marco@student.han.nl>
+
+ 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. */
+
+/* Generate a key for the string S. XXX: The are many more effecient
+ algoritms, this one should be replaced by one of those. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <hurd/ihash.h>
+#include "xkb.h"
+
+static int
+name_hash (char *s)
+{
+ int i = 0;
+ while (*s)
+ i += *(s++);
+ return i;
+}
+
+
+/* A keyname with a keycode and realmodifier bound to it. */
+struct keyname
+{
+ int keycode;
+ int rmods;
+};
+
+static struct hurd_ihash kn_mapping;
+
+/* Initialize the keyname hashtable. */
+static void
+keyname_init ()
+{
+ hurd_ihash_init (&kn_mapping, HURD_IHASH_NO_LOCP);
+ debug_printf ("Kn_mapping init");
+ /* XXX: error. */
+}
+
+/* Assign the name KEYNAME to the keycode KEYCODE. */
+error_t
+keyname_add (char *keyname, int keycode)
+{
+ struct keyname *kn;
+ int kn_int;
+
+ kn = malloc (sizeof (struct keyname));
+ if (!kn)
+ return ENOMEM;
+
+ /* XXX: 4 characters can be mapped into a int, it is safe to assume
+ this will not be changed. */
+ if (strlen (keyname) > 4)
+ {
+ debug_printf ("The keyname `%s' consist of more than 4 characters;"
+ " 4 characters is the maximum.\n", keyname);
+ /* XXX: Abort? */
+ return 0;
+ }
+
+ kn->keycode = keycode;
+ kn->rmods = 0;
+
+ kn_int = keyname[0] + (keyname[1] << 8) + (keyname[2] << 16) + (keyname[3] << 24);
+ debug_printf ("add : %d\n", kn_mapping.locp_offset);
+ hurd_ihash_add (&kn_mapping, kn_int, kn);
+
+ return 0;
+}
+
+/* Find the numberic representation of the keycode with the name
+ KEYNAME. */
+int
+keyname_find (char *keyname)
+{
+ struct keyname *kn;
+ int kn_int;
+
+ /* XXX: 4 characters can be mapped into a int, it is safe to assume
+ this will not be changed. */
+ if (strlen (keyname) > 4)
+ {
+ debug_printf ("The keyname `%s' consist of more than 4 characters;"
+ " 4 characters is the maximum.\n", keyname);
+ /* XXX: Abort? */
+ return 0;
+ }
+ kn_int = keyname[0] + (keyname[1] << 8) + (keyname[2] << 16) + (keyname[3] << 24);
+
+ kn = hurd_ihash_find (&kn_mapping, kn_int);
+ if (kn)
+ return kn->keycode;
+/* int h = name_hash (keyname); */
+/* struct keyname *kn; */
+/* for (kn = knhash[KNHASH(h)]; kn; kn = kn->hnext) */
+/* { */
+/* if (strcmp (kn->keyname, keyname)) */
+/* continue; */
+
+/* return kn->keycode; */
+/* } */
+
+ /* XXX: Is 0 an invalid keycode? */
+ return 0;
+}
+
+
+/* Keytypes and keytype maps. */
+
+/* The dummy gets used when the original may not be overwritten. */
+static struct keytype dummy_keytype;
+
+#define KTHSZ 16
+#if ((KTHSZ&(KTHSZ-1)) == 0)
+#define KTHASH(ktttl) ((ktttl)&(KTHSZ-1))
+#else
+#define KTHASH(ktttl) (((unsigned)(kt))%KTHSZ)
+#endif
+
+/* All keytypes. */
+struct keytype *kthash[KTHSZ];
+
+/* Initialize the keytypes hashtable. */
+static void
+keytype_init ()
+{
+ int n;
+ for (n = 0; n < KTHSZ; n++)
+ kthash[n] = 0;
+}
+
+/* Search the keytype with the name NAME. */
+struct keytype *
+keytype_find (char *name)
+{
+ int nhash = name_hash (name);
+ struct keytype *kt;
+
+ for (kt = kthash[KTHASH(nhash)]; kt; kt = kt->hnext)
+ if (!strcmp (name, kt->name))
+ return kt;
+ return NULL;
+}
+
+/* Remove the keytype KT. */
+void
+keytype_delete (struct keytype *kt)
+{
+ struct typemap *map;
+
+
+ *kt->prevp = kt->hnext;
+ if (kt->hnext)
+ kt->hnext->prevp = kt->prevp;
+
+ map = kt->maps;
+ while (map)
+ {
+ struct typemap *nextmap = map->next;
+ free (map);
+ map = nextmap;
+ }
+
+}
+
+/* Create a new keytype with the name NAME. */
+error_t
+keytype_new (char *name, struct keytype **new_kt)
+{
+ struct keytype *kt;
+ struct keytype *ktlist;
+ int nhash;
+
+ nhash = name_hash (name);
+ debug_printf ("New: %s\n", name);
+
+ kt = keytype_find (name);
+
+ if (kt)
+ {
+ /* If the merge mode is augement don't replace it. */
+ if (merge_mode == augment)
+ {
+ *new_kt = &dummy_keytype;
+ return 0;
+ }
+ else /* This keytype should replace the old one, remove the old one. */
+ keytype_delete (kt);
+ }
+
+ ktlist = kthash[KTHASH(nhash)];
+ kt = calloc (1, sizeof (struct keytype));
+ if (kt == NULL)
+ return ENOMEM;
+
+ kt->hnext = ktlist;
+ kt->name = strdup (name);
+ kt->prevp = &kthash[KTHASH(nhash)];
+ kt->maps = NULL;
+ if (kthash[KTHASH(nhash)])
+ kthash[KTHASH(nhash)]->prevp = &(kt->hnext);
+ kthash[KTHASH(nhash)] = kt;
+
+ *new_kt = kt;
+ return 0;
+}
+
+/* Add a level (LEVEL) to modifiers (MODS) mapping to the current
+ keytype. */
+error_t
+keytype_mapadd (struct keytype *kt, modmap_t mods, int level)
+{
+ struct typemap *map;
+ modmap_t nulmap = {0, 0};
+
+ map = malloc (sizeof (struct typemap));
+ if (!map)
+ return ENOMEM;
+
+ map->level = level;
+ map->mods = mods;
+ map->preserve = nulmap;
+ /* By default modifiers shouldn't be preserved. */
+ map->next = kt->maps;
+
+ kt->maps = map;
+
+ return 0;
+}
+
+/* For the current keytype the modifiers PRESERVE should be preserved
+ when the modifiers MODS are pressed. */
+error_t
+keytype_preserve_add (struct keytype *kt, modmap_t mods, modmap_t preserve)
+{
+ error_t err;
+ struct typemap *map;
+
+ map = kt->maps;
+ while (map)
+ {
+ if (mods.rmods == map->mods.rmods && mods.vmods == map->mods.vmods)
+ {
+ map->preserve = preserve;
+ return 0;
+ }
+ map = map->next;
+ }
+
+ /* No map has been found, add the default map. */
+ err = keytype_mapadd (kt, mods, 0);
+ if (err)
+ return err;
+
+ keytype_preserve_add (kt, mods, preserve);
+
+ return 0;
+}
+
+
+/* Interpretations. */
+
+struct xkb_interpret *last_interp;
+struct xkb_interpret default_interpretation;
+
+
+/* Add a new interpretation. */
+error_t
+interpret_new (xkb_interpret_t **new_interpret, symbol ks)
+{
+ struct xkb_interpret *new_interp;
+
+ new_interp = malloc (sizeof (struct xkb_interpret));
+ if (!new_interp)
+ return ENOMEM;
+
+ memcpy (new_interp, &default_interpretation, sizeof (struct xkb_interpret));
+ new_interp->symbol = ks;
+
+ if (ks)
+ {
+ new_interp->next = interpretations;
+ interpretations = new_interp;
+
+ if (!last_interp)
+ last_interp = new_interp;
+ }
+ else
+ {
+ if (last_interp)
+ last_interp->next = new_interp;
+
+ last_interp = new_interp;
+
+ if (!interpretations)
+ interpretations = new_interp;
+ }
+
+ *new_interpret = new_interp;
+
+ return 0;
+}
+
+
+/* XXX: Dead code!? */
+/* Virtual modifiers name to number mapping. */
+/* Last number assigned to a virtual modifier. */
+static int lastvmod = 0;
+
+/* One virtual modifiername -> vmod number mapping. */
+struct vmodname
+{
+ char *name;
+ struct vmodname *next;
+};
+
+/* A list of virtualmodifier names and its numberic representation. */
+static struct vmodname *vmodnamel;
+
+/* Get the number assigned to the virtualmodifier with the name
+ VMODNAME. */
+int
+vmod_find (char *vmodname)
+{
+ int i = 0;
+ struct vmodname *vmn = vmodnamel;
+
+ while (vmn)
+ {
+ if (!strcmp (vmn->name, vmodname))
+ return (lastvmod - i);
+ vmn = vmn->next;
+ i++;
+ }
+
+ return 0;
+}
+
+/* Give the virtualmodifier VMODNAME a number and add it to the
+ hashtable. */
+error_t
+vmod_add (char *vmodname)
+{
+ struct vmodname *vmn;
+
+ if (vmod_find (vmodname))
+ return 0;
+
+ vmn = malloc (sizeof (struct vmodname));
+ if (vmn == NULL)
+ return ENOMEM;
+
+ vmn->name = vmodname;
+ vmn->next = vmodnamel;
+ vmodnamel = vmn;
+
+ lastvmod++;
+
+ return 0;
+}
+
+
+/* XXX: Use this, no pointers. */
+struct ksrm
+{
+ symbol ks;
+
+ int rmods;
+};
+static struct hurd_ihash ksrm_mapping;
+
+/* Initialize the list for keysyms to realmodifiers mappings. */
+void
+ksrm_init ()
+{
+ hurd_ihash_init (&ksrm_mapping, HURD_IHASH_NO_LOCP);
+ debug_printf ("KSRM MAP IHASH CREATED \n");
+}
+
+/* Add keysym to realmodifier mapping. */
+error_t
+ksrm_add (symbol ks, int rmod)
+{
+ hurd_ihash_add (&ksrm_mapping, ks, (void *) rmod);
+
+ return 0;
+}
+
+/* Apply the rkms (realmods to keysyms) table to all keysyms. */
+void
+ksrm_apply (void)
+{
+ keycode_t kc;
+ for (kc = 0; kc < max_keys; kc++)
+ {
+ int group;
+ for (group = 0; group < 4; group++)
+ {
+ int cursym;
+ for (cursym = 0; cursym < keys[kc].groups[group].width; cursym++)
+ {
+ symbol ks = keys[kc].groups[group].symbols[cursym];
+ int rmods = (int) hurd_ihash_find (&ksrm_mapping, ks);
+ struct ksrm *ksrm;
+
+ if (rmods)
+ {
+ keys[kc].mods.rmods = rmods;
+ debug_printf ("kss %d = %d\n", kc, ksrm->rmods);
+ }
+ }
+ }
+ }
+}
+
+
+/* void */
+/* indicator_new (xkb_indicator_t **, */
+
+
+/* Keycode to realmodifier mapping. */
+
+/* Set the current rmod for the key with keyname KEYNAME. */
+/* XXX: It shouldn't be applied immediatly because the key can be
+ replaced. */
+void
+set_rmod_keycode (char *keyname, int rmod)
+{
+ keycode_t kc = keyname_find (keyname);
+ keys[kc].mods.rmods = rmod;
+ debug_printf ("kc %d = %d\n", kc, rmod);
+}
+
+/* Initialize XKB data structures. */
+error_t
+xkb_data_init (void)
+{
+ keyname_init ();
+ keytype_init ();
+ ksrm_init ();
+
+ return 0;
+}