diff options
-rw-r--r-- | keycodes.c | 62 | ||||
-rw-r--r-- | keymap.c | 2 | ||||
-rw-r--r-- | keytypes.c | 43 | ||||
-rw-r--r-- | misc.c | 25 | ||||
-rw-r--r-- | symbols.c | 61 | ||||
-rw-r--r-- | vmod.c | 36 |
6 files changed, 211 insertions, 18 deletions
@@ -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; @@ -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) @@ -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; @@ -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') @@ -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)) @@ -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) |