summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keycodes.c62
-rw-r--r--keymap.c2
-rw-r--r--keytypes.c43
-rw-r--r--misc.c25
-rw-r--r--symbols.c61
-rw-r--r--vmod.c36
6 files changed, 211 insertions, 18 deletions
diff --git a/keycodes.c b/keycodes.c
index 6fe15fb..d848a0c 100644
--- a/keycodes.c
+++ b/keycodes.c
@@ -64,17 +64,17 @@ typedef struct _IndicatorNameInfo
typedef struct _KeyNamesInfo
{
- char *name;
+ char *name; /* e.g. evdev+aliases(qwerty) */
int errorCount;
unsigned fileID;
unsigned merge;
- int computedMin;
- int computedMax;
+ int computedMin; /* lowest keycode stored */
+ int computedMax; /* highest keycode stored */
int explicitMin;
int explicitMax;
int effectiveMin;
int effectiveMax;
- unsigned long names[XkbMaxLegalKeyCode + 1];
+ unsigned long names[XkbMaxLegalKeyCode + 1]; /* 4-letter name of key, keycode is the index */
unsigned files[XkbMaxLegalKeyCode + 1];
unsigned char has_alt_forms[XkbMaxLegalKeyCode + 1];
IndicatorNameInfo *leds;
@@ -315,6 +315,7 @@ FindKeyByLong(KeyNamesInfo * info, unsigned long name)
/**
* Store the name of the key as a long in the info struct under the given
* keycode. If the same keys is referred to twice, print a warning.
+ * Note that the key's name is stored as a long, the keycode is the index.
*/
static Bool
AddKeyName(KeyNamesInfo * info,
@@ -488,6 +489,13 @@ typedef void (*FileHandler) (XkbFile * /* rtrn */ ,
KeyNamesInfo * /* included */
);
+/**
+ * Handle the given include statement (e.g. "include "evdev+aliases(qwerty)").
+ *
+ * @param stmt The include statement from the keymap file.
+ * @param xkb Unused for all but the xkb->flags.
+ * @param info Struct to store the key info in.
+ */
static Bool
HandleIncludeKeycodes(IncludeStmt * stmt,
XkbDescPtr xkb, KeyNamesInfo * info, FileHandler hndlr)
@@ -510,7 +518,7 @@ HandleIncludeKeycodes(IncludeStmt * stmt,
info->explicitMin = XkbMinLegalKeyCode;
info->explicitMax = XkbMaxLegalKeyCode;
return (info->errorCount == 0);
- }
+ } /* parse file, store returned info in the xkb struct */
else if (ProcessIncludeFile(stmt, XkmKeyNamesIndex, &rtrn, &newMerge))
{
InitKeyNamesInfo(&included);
@@ -525,9 +533,10 @@ HandleIncludeKeycodes(IncludeStmt * stmt,
}
else
{
- info->errorCount += 10;
+ info->errorCount += 10; /* XXX: why 10?? */
return False;
}
+ /* Do we have more than one include statement? */
if ((stmt->next != NULL) && (included.errorCount < 1))
{
IncludeStmt *next;
@@ -551,7 +560,7 @@ HandleIncludeKeycodes(IncludeStmt * stmt,
}
else
{
- info->errorCount += 10;
+ info->errorCount += 10; /* XXX: Why 10?? */
return False;
}
}
@@ -602,6 +611,12 @@ HandleKeycodeDef(KeycodeDef * stmt, unsigned merge, KeyNamesInfo * info)
#define MIN_KEYCODE_DEF 0
#define MAX_KEYCODE_DEF 1
+/**
+ * Handle the minimum/maximum statement of the xkb file.
+ * Sets explicitMin/Max and effectiveMin/Max of the info struct.
+ *
+ * @return 1 on success, 0 otherwise.
+ */
static int
HandleKeyNameVar(VarDef * stmt, unsigned merge, KeyNamesInfo * info)
{
@@ -722,6 +737,19 @@ HandleIndicatorNameDef(IndicatorNameDef * def,
return True;
}
+/**
+ * Handle the xkb_keycodes section of a xkb file.
+ * All information about parsed keys is stored in the info struct.
+ *
+ * Such a section may have include statements, in which case this function is
+ * semi-recursive (it calls HandleIncludeKeycodes, which may call
+ * HandleKeycodesFile again).
+ *
+ * @param file The input file (parsed xkb_keycodes section)
+ * @param xkb Necessary to pass down, may have flags changed.
+ * @param merge Merge strategy (MergeOverride, etc.)
+ * @param info Struct to contain the fully parsed key information.
+ */
static void
HandleKeycodesFile(XkbFile * file,
XkbDescPtr xkb, unsigned merge, KeyNamesInfo * info)
@@ -734,7 +762,7 @@ HandleKeycodesFile(XkbFile * file,
{
switch (stmt->stmtType)
{
- case StmtInclude:
+ case StmtInclude: /* e.g. include "evdev+aliases(qwerty)" */
if (!HandleIncludeKeycodes((IncludeStmt *) stmt, xkb, info,
HandleKeycodesFile))
info->errorCount++;
@@ -786,23 +814,35 @@ HandleKeycodesFile(XkbFile * file,
return;
}
+/**
+ * Compile the xkb_keycodes section, parse it's output, return the results.
+ *
+ * @param file The parsed XKB file (may have include statements requiring
+ * further parsing)
+ * @param result The effective keycodes, as gathered from the file.
+ * @param merge Merge strategy.
+ *
+ * @return True on success, False otherwise.
+ */
Bool
CompileKeycodes(XkbFile * file, XkbFileInfo * result, unsigned merge)
{
- KeyNamesInfo info;
+ KeyNamesInfo info; /* contains all the info after parsing */
XkbDescPtr xkb;
xkb = result->xkb;
InitKeyNamesInfo(&info);
HandleKeycodesFile(file, xkb, merge, &info);
+ /* all the keys are now stored in info */
+
if (info.errorCount == 0)
{
- if (info.explicitMin > 0)
+ if (info.explicitMin > 0) /* if "minimum" statement was present */
xkb->min_key_code = info.effectiveMin;
else
xkb->min_key_code = info.computedMin;
- if (info.explicitMax > 0)
+ if (info.explicitMax > 0) /* if "maximum" statement was present */
xkb->max_key_code = info.effectiveMax;
else
xkb->max_key_code = info.computedMax;
diff --git a/keymap.c b/keymap.c
index a1f3865..4736eb8 100644
--- a/keymap.c
+++ b/keymap.c
@@ -43,6 +43,8 @@ XkbFile *sections[MAX_SECTIONS];
/**
* Compile the given file and store the output in result.
+ * @param file A list of XkbFiles, each denoting one type (e.g.
+ * XkmKeyNamesIdx, etc.)
*/
Bool
CompileKeymap(XkbFile * file, XkbFileInfo * result, unsigned merge)
diff --git a/keytypes.c b/keytypes.c
index f51a7d5..3065d29 100644
--- a/keytypes.c
+++ b/keytypes.c
@@ -508,6 +508,10 @@ DeleteLevel1MapEntries(KeyTypeInfo * type)
return;
}
+/**
+ * Return a pointer to the next free XkbKTMapEntry, reallocating space if
+ * necessary.
+ */
static XkbKTMapEntryPtr
NextMapEntry(KeyTypeInfo * type)
{
@@ -603,6 +607,14 @@ AddPreserve(XkbDescPtr xkb,
return True;
}
+/**
+ * Add a new KTMapEntry to the given key type. If an entry with the same mods
+ * already exists, the level is updated (if clobber is TRUE). Otherwise, a new
+ * entry is created.
+ *
+ * @param clobber Overwrite existing entry.
+ * @param report True if a warning is to be printed on.
+ */
Bool
AddMapEntry(XkbDescPtr xkb,
KeyTypeInfo * type,
@@ -679,8 +691,8 @@ SetMapEntry(KeyTypeInfo * type,
return ReportTypeShouldBeArray(type, "map entry");
if (!ExprResolveModMask(arrayNdx, &rtrn, LookupVModMask, (XPointer) xkb))
return ReportTypeBadType(type, "map entry", "modifier mask");
- entry.mods.real_mods = rtrn.uval & 0xff;
- entry.mods.vmods = (rtrn.uval >> 8) & 0xffff;
+ entry.mods.real_mods = rtrn.uval & 0xff; /* modifiers < 512 */
+ entry.mods.vmods = (rtrn.uval >> 8) & 0xffff; /* modifiers > 512 */
if ((entry.mods.real_mods & (~type->mask)) ||
((entry.mods.vmods & (~type->vmask)) != 0))
{
@@ -859,6 +871,11 @@ SetLevelName(KeyTypeInfo * type, ExprDef * arrayNdx, ExprDef * value)
/***====================================================================***/
+/**
+ * Parses the fields in a type "..." { } description.
+ *
+ * @param field The field to parse (e.g. modifiers, map, level_name)
+ */
static Bool
SetKeyTypeField(KeyTypeInfo * type,
XkbDescPtr xkb,
@@ -875,14 +892,15 @@ SetKeyTypeField(KeyTypeInfo * type,
WARN("The modifiers field of a key type is not an array\n");
ACTION("Illegal array subscript ignored\n");
}
+ /* get modifier mask for current type */
if (!ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb))
{
ERROR("Key type mask field must be a modifier mask\n");
ACTION("Key type definition ignored\n");
return False;
}
- mods = tmp.uval & 0xff;
- vmods = (tmp.uval >> 8) & 0xffff;
+ mods = tmp.uval & 0xff; /* core mods */
+ vmods = (tmp.uval >> 8) & 0xffff; /* xkb virtual mods */
if (type->defs.defined & _KT_Mask)
{
WARN1("Multiple modifier mask definitions for key type %s\n",
@@ -966,6 +984,10 @@ HandleKeyTypeBody(VarDef * def,
return ok;
}
+/**
+ * Process a type "XYZ" { } specification in the xkb_types section.
+ *
+ */
static int
HandleKeyTypeDef(KeyTypeDef * def,
XkbDescPtr xkb, unsigned merge, KeyTypesInfo * info)
@@ -992,6 +1014,7 @@ HandleKeyTypeDef(KeyTypeDef * def,
type.lvlNames = NULL;
type.preserve = NULL;
+ /* Parse the actual content. */
if (!HandleKeyTypeBody(def->body, xkb, &type, info))
{
info->errorCount++;
@@ -1030,6 +1053,7 @@ HandleKeyTypeDef(KeyTypeDef * def,
AddLevelName(&type, i, info->dflt.lvlNames[i], False, False);
}
}
+ /* Now add the new keytype to the info struct */
if (!AddKeyType(xkb, info, &type))
{
info->errorCount++;
@@ -1038,6 +1062,13 @@ HandleKeyTypeDef(KeyTypeDef * def,
return True;
}
+/**
+ * Process an xkb_types section.
+ *
+ * @param file The parsed xkb_types section.
+ * @param merge Merge Strategy (e.g. MergeOverride)
+ * @param info Pointer to memory where the outcome will be stored.
+ */
static void
HandleKeyTypesFile(XkbFile * file,
XkbDescPtr xkb, unsigned merge, KeyTypesInfo * info)
@@ -1055,7 +1086,7 @@ HandleKeyTypesFile(XkbFile * file,
HandleKeyTypesFile))
info->errorCount++;
break;
- case StmtKeyTypeDef:
+ case StmtKeyTypeDef: /* e.g. type "ONE_LEVEL" */
if (!HandleKeyTypeDef((KeyTypeDef *) stmt, xkb, merge, info))
info->errorCount++;
break;
@@ -1063,7 +1094,7 @@ HandleKeyTypesFile(XkbFile * file,
if (!HandleKeyTypeVar((VarDef *) stmt, xkb, info))
info->errorCount++;
break;
- case StmtVModDef:
+ case StmtVModDef: /* virtual_modifiers NumLock, ... */
if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods))
info->errorCount++;
break;
diff --git a/misc.c b/misc.c
index fe07812..c7b41dd 100644
--- a/misc.c
+++ b/misc.c
@@ -36,6 +36,18 @@
/***====================================================================***/
+/**
+ * Open the file given in the include statement and parse it's content.
+ * If the statement defines a specific map to use, this map is returned in
+ * file_rtrn. Otherwise, the default map is returned.
+ *
+ * @param stmt The include statement, specifying the file name to look for.
+ * @param file_type Type of file (XkmKeyNamesIdx, etc.)
+ * @param file_rtrn Returns the key map to be used.
+ * @param merge_rtrn Always returns stmt->merge.
+ *
+ * @return True on success or False otherwise.
+ */
Bool
ProcessIncludeFile(IncludeStmt * stmt,
unsigned file_type,
@@ -438,6 +450,18 @@ ComputeKbdDefaults(XkbDescPtr xkb)
return Success;
}
+/**
+ * Find the key with the given name and return its keycode in kc_rtrn.
+ *
+ * @param name The 4-letter name of the key as a long.
+ * @param kc_rtrn Set to the keycode if the key was found, otherwise 0.
+ * @param use_aliases True if the key aliases should be searched too.
+ * @param create If True and the key is not found, it is added to the
+ * xkb->names at the first free keycode.
+ * @param start_from Keycode to start searching from.
+ *
+ * @return True if found, False otherwise.
+ */
Bool
FindNamedKey(XkbDescPtr xkb,
unsigned long name,
@@ -495,6 +519,7 @@ FindNamedKey(XkbDescPtr xkb,
return False;
}
}
+ /* Find first unused keycode and store our key here */
for (n = xkb->min_key_code; n <= xkb->max_key_code; n++)
{
if (xkb->names->keys[n].name[0] == '\0')
diff --git a/symbols.c b/symbols.c
index 883285e..e11ba85 100644
--- a/symbols.c
+++ b/symbols.c
@@ -219,7 +219,7 @@ typedef struct _ModMapEntry
#define SYMBOLS_CHUNK 20
typedef struct _SymbolsInfo
{
- char *name;
+ char *name; /* e.g. pc+us+inet(evdev) */
int errorCount;
unsigned fileID;
unsigned merge;
@@ -1722,6 +1722,14 @@ FindKeyForSymbol(XkbDescPtr xkb, KeySym sym, unsigned int *kc_rtrn)
return False;
}
+/**
+ * Find the given name in the xkb->map->types and return its index.
+ *
+ * @param name The atom to search for.
+ * @param type_rtrn Set to the index of the name if found.
+ *
+ * @return True if found, False otherwise.
+ */
static Bool
FindNamedType(XkbDescPtr xkb, Atom name, unsigned *type_rtrn)
{
@@ -1763,6 +1771,22 @@ KSIsUpper(KeySym ks)
return (ks == upper ? True : False);
}
+/**
+ * Assign a type to the given sym and return the Atom for the type assigned.
+ *
+ * Simple recipe:
+ * - ONE_LEVEL for width 0/1
+ * - ALPHABETIC for 2 shift levels, with lower/upercase
+ * - KEYPAD for keypad keys.
+ * - TWO_LEVEL for other 2 shift level keys.
+ * and the same for four level keys.
+ *
+ * @param width Number of sysms in syms.
+ * @param syms The keysyms for the given key (must be size width).
+ * @param typeNameRtrn Set to the Atom of the type name.
+ *
+ * @returns True if a type could be found, False otherwise.
+ */
static Bool
FindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn,
Bool * autoType)
@@ -1805,10 +1829,15 @@ FindAutomaticType(int width, KeySym * syms, Atom * typeNameRtrn,
*typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL_KEYPAD", False);
else
*typeNameRtrn = XkbInternAtom(NULL, "FOUR_LEVEL", False);
+ /* XXX: why not set autoType here? */
}
return ((width >= 0) && (width <= 4));
}
+/**
+ * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
+ * groups, and reduce to one group if all groups are identical anyway.
+ */
static void
PrepareKeyDef(KeyInfo * key)
{
@@ -1816,6 +1845,7 @@ PrepareKeyDef(KeyInfo * key)
Bool identical;
defined = key->symsDefined | key->actsDefined | key->typesDefined;
+ /* get highest group number */
for (i = XkbNumKbdGroups - 1; i >= 0; i--)
{
if (defined & (1 << i))
@@ -1913,6 +1943,11 @@ PrepareKeyDef(KeyInfo * key)
return;
}
+/**
+ * Copy the KeyInfo into result.
+ *
+ * This function recurses.
+ */
static Bool
CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
{
@@ -1927,6 +1962,8 @@ CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
xkb = result->xkb;
useAlias = (start_from == 0);
+
+ /* get the keycode for the key. */
if (!FindNamedKey(xkb, key->name, &kc, useAlias, CreateKeyNames(xkb),
start_from))
{
@@ -1950,6 +1987,7 @@ CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
if (key->acts[i])
haveActions = True;
autoType = False;
+ /* Assign the type to the key, if it is missing. */
if (key->types[i] == None)
{
if (key->dfltType != None)
@@ -1987,6 +2025,7 @@ CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
}
types[i] = XkbTwoLevelIndex;
}
+ /* if the type specifies less syms than the key has, shrink the key */
type = &xkb->map->types[types[i]];
if (type->num_levels < key->numLevels[i])
{
@@ -2008,6 +2047,8 @@ CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
width = type->num_levels;
}
+ /* width is now the largest width found */
+
i = width * nGroups;
outSyms = XkbResizeKeySyms(xkb, kc, i);
if (outSyms == NULL)
@@ -2033,13 +2074,16 @@ CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
i = key->groupInfo;
else
i = xkb->map->key_sym_map[kc].group_info;
+
xkb->map->key_sym_map[kc].group_info = XkbSetNumGroups(i, nGroups);
xkb->map->key_sym_map[kc].width = width;
for (i = 0; i < nGroups; i++)
{
+ /* assign kt_index[i] to the index of the type in map->types */
xkb->map->key_sym_map[kc].kt_index[i] = types[i];
if (key->syms[i] != NULL)
{
+ /* fill key to "width" symbols*/
for (tmp = 0; tmp < width; tmp++)
{
if (tmp < key->numLevels[i])
@@ -2098,6 +2142,8 @@ CopySymbolsDef(XkbFileInfo * result, KeyInfo * key, int start_from)
xkb->ctrls->per_key_repeat[kc / 8] &= ~(1 << (kc % 8));
xkb->server->explicit[kc] |= XkbExplicitAutoRepeatMask;
}
+
+ /* do the same thing for the next key */
CopySymbolsDef(result, key, kc + 1);
return True;
}
@@ -2141,6 +2187,13 @@ CopyModMapDef(XkbFileInfo * result, ModMapEntry * entry)
return True;
}
+/**
+ * Handle the xkb_symbols section of an xkb file.
+ *
+ * @param file The parsed xkb_symbols section of the xkb file.
+ * @param result Handle to the data to store the result in.
+ * @param merge Merge strategy (e.g. MergeOverride).
+ */
Bool
CompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge)
{
@@ -2159,6 +2212,8 @@ CompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge)
if (info.errorCount == 0)
{
KeyInfo *key;
+
+ /* alloc memory in the xkb struct */
if (XkbAllocNames(xkb, XkbSymbolsNameMask | XkbGroupNamesMask, 0, 0)
!= Success)
{
@@ -2185,6 +2240,8 @@ CompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge)
ACTION("Symbols not added\n");
return False;
}
+
+ /* now copy info into xkb. */
xkb->names->symbols = XkbInternAtom(xkb->dpy, info.name, False);
if (info.aliases)
ApplyAliases(xkb, False, &info.aliases);
@@ -2193,10 +2250,12 @@ CompileSymbols(XkbFile * file, XkbFileInfo * result, unsigned merge)
if (info.groupNames[i] != None)
xkb->names->groups[i] = info.groupNames[i];
}
+ /* sanitize keys */
for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
{
PrepareKeyDef(key);
}
+ /* copy! */
for (key = info.keys, i = 0; i < info.nKeys; i++, key++)
{
if (!CopySymbolsDef(result, key, 0))
diff --git a/vmod.c b/vmod.c
index 1f237f5..4ade0a8 100644
--- a/vmod.c
+++ b/vmod.c
@@ -70,6 +70,14 @@ ClearVModInfo(VModInfo * info, XkbDescPtr xkb)
/***====================================================================***/
+/**
+ * Handle one entry in the virtualModifiers line (e.g. NumLock).
+ * If the entry is e.g. NumLock=Mod1, stmt->value is not NULL, and the
+ * XkbServerMap's vmod is set to the given modifier. Otherwise, the vmod is 0.
+ *
+ * @param stmt The statement specifying the name and (if any the value).
+ * @param mergeMode Merge strategy (e.g. MergeOverride)
+ */
Bool
HandleVModDef(VModDef * stmt, unsigned mergeMode, VModInfo * info)
{
@@ -147,6 +155,18 @@ HandleVModDef(VModDef * stmt, unsigned mergeMode, VModInfo * info)
return False;
}
+/**
+ * Returns the index of the given modifier in the xkb->names->vmods array.
+ *
+ * @param priv Pointer to the xkb data structure.
+ * @param elem Must be None, otherwise return False.
+ * @param field The Atom of the modifier's name (e.g. Atom for LAlt)
+ * @param type Must be TypeInt, otherwise return False.
+ * @param val_rtrn Set to the index of the modifier that matches.
+ *
+ * @return True on success, False otherwise. If False is returned, val_rtrn is
+ * undefined.
+ */
int
LookupVModIndex(XPointer priv,
Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)
@@ -162,9 +182,15 @@ LookupVModIndex(XPointer priv,
{
return False;
}
+ /* get the actual name */
fieldStr = XkbAtomGetString(xkb->dpy, field);
if (fieldStr == NULL)
return False;
+ /* For each named modifier, get the name and compare it to the one passed
+ * in. If we get a match, return the index of the modifier.
+ * The order of modifiers is the same as in the virtual_modifiers line in
+ * the xkb_types section.
+ */
for (i = 0; i < XkbNumVirtualMods; i++)
{
modStr = XkbAtomGetString(xkb->dpy, xkb->names->vmods[i]);
@@ -177,6 +203,16 @@ LookupVModIndex(XPointer priv,
return False;
}
+/**
+ * Get the mask for the given modifier and set val_rtrn.uval to the mask.
+ * Note that the mask returned is always > 512.
+ *
+ * @param priv Pointer to xkb data structure.
+ * @param val_rtrn Set to the mask returned.
+ *
+ * @return True on success, False otherwise. If False is returned, val_rtrn is
+ * undefined.
+ */
int
LookupVModMask(XPointer priv,
Atom elem, Atom field, unsigned type, ExprResult * val_rtrn)