diff options
Diffstat (limited to 'xkbcomp/keycodes.c')
-rw-r--r-- | xkbcomp/keycodes.c | 1792 |
1 files changed, 896 insertions, 896 deletions
diff --git a/xkbcomp/keycodes.c b/xkbcomp/keycodes.c index 0cffa8131..4081ea1b5 100644 --- a/xkbcomp/keycodes.c +++ b/xkbcomp/keycodes.c @@ -1,896 +1,896 @@ -/************************************************************
- Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
-
- Permission to use, copy, modify, and distribute this
- software and its documentation for any purpose and without
- fee is hereby granted, provided that the above copyright
- notice appear in all copies and that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
- THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ********************************************************/
-
-#include "xkbcomp.h"
-#include "tokens.h"
-#include "expr.h"
-#include "keycodes.h"
-#include "misc.h"
-#include "alias.h"
-
-char *
-longText(unsigned long val, unsigned format)
-{
- char buf[4];
-
- LongToKeyName(val, buf);
- return XkbKeyNameText(buf, format);
-}
-
-/***====================================================================***/
-
-void
-LongToKeyName(unsigned long val, char *name)
-{
- name[0] = ((val >> 24) & 0xff);
- name[1] = ((val >> 16) & 0xff);
- name[2] = ((val >> 8) & 0xff);
- name[3] = (val & 0xff);
- return;
-}
-
-/***====================================================================***/
-
-typedef struct _IndicatorNameInfo
-{
- CommonInfo defs;
- int ndx;
- Atom name;
- Bool virtual;
-} IndicatorNameInfo;
-
-typedef struct _KeyNamesInfo
-{
- char *name; /* e.g. evdev+aliases(qwerty) */
- int errorCount;
- unsigned fileID;
- unsigned merge;
- int computedMin; /* lowest keycode stored */
- int computedMax; /* highest keycode stored */
- int explicitMin;
- int explicitMax;
- int effectiveMin;
- int effectiveMax;
- 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;
- AliasInfo *aliases;
-} KeyNamesInfo;
-
-static void HandleKeycodesFile(XkbFile * file,
- XkbDescPtr xkb,
- unsigned merge,
- KeyNamesInfo * info);
-
-static void
-InitIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
-{
- ii->defs.defined = 0;
- ii->defs.merge = info->merge;
- ii->defs.fileID = info->fileID;
- ii->defs.next = NULL;
- ii->ndx = 0;
- ii->name = None;
- ii->virtual = False;
- return;
-}
-
-static void
-ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
-{
- if (ii == info->leds)
- {
- ClearCommonInfo(&ii->defs);
- info->leds = NULL;
- }
- return;
-}
-
-static IndicatorNameInfo *
-NextIndicatorName(KeyNamesInfo * info)
-{
- IndicatorNameInfo *ii;
-
- ii = uTypedAlloc(IndicatorNameInfo);
- if (ii)
- {
- InitIndicatorNameInfo(ii, info);
- info->leds = (IndicatorNameInfo *) AddCommonInfo(&info->leds->defs,
- (CommonInfo *) ii);
- }
- return ii;
-}
-
-static IndicatorNameInfo *
-FindIndicatorByIndex(KeyNamesInfo * info, int ndx)
-{
- IndicatorNameInfo *old;
-
- for (old = info->leds; old != NULL;
- old = (IndicatorNameInfo *) old->defs.next)
- {
- if (old->ndx == ndx)
- return old;
- }
- return NULL;
-}
-
-static IndicatorNameInfo *
-FindIndicatorByName(KeyNamesInfo * info, Atom name)
-{
- IndicatorNameInfo *old;
-
- for (old = info->leds; old != NULL;
- old = (IndicatorNameInfo *) old->defs.next)
- {
- if (old->name == name)
- return old;
- }
- return NULL;
-}
-
-static Bool
-AddIndicatorName(KeyNamesInfo * info, IndicatorNameInfo * new)
-{
- IndicatorNameInfo *old;
- Bool replace;
-
- replace = (new->defs.merge == MergeReplace) ||
- (new->defs.merge == MergeOverride);
- old = FindIndicatorByName(info, new->name);
- if (old)
- {
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN1("Multiple indicators named %s\n",
- XkbAtomText(NULL, new->name, XkbMessage));
- if (old->ndx == new->ndx)
- {
- if (old->virtual != new->virtual)
- {
- if (replace)
- old->virtual = new->virtual;
- ACTION2("Using %s instead of %s\n",
- (old->virtual ? "virtual" : "real"),
- (old->virtual ? "real" : "virtual"));
- }
- else
- {
- ACTION("Identical definitions ignored\n");
- }
- return True;
- }
- else
- {
- if (replace)
- ACTION2("Ignoring %d, using %d\n", old->ndx, new->ndx);
- else
- ACTION2("Using %d, ignoring %d\n", old->ndx, new->ndx);
- }
- if (replace)
- {
- if (info->leds == old)
- info->leds = (IndicatorNameInfo *) old->defs.next;
- else
- {
- IndicatorNameInfo *tmp;
- tmp = info->leds;
- for (; tmp != NULL;
- tmp = (IndicatorNameInfo *) tmp->defs.next)
- {
- if (tmp->defs.next == (CommonInfo *) old)
- {
- tmp->defs.next = old->defs.next;
- break;
- }
- }
- }
- uFree(old);
- }
- }
- }
- old = FindIndicatorByIndex(info, new->ndx);
- if (old)
- {
- if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
- || (warningLevel > 9))
- {
- WARN1("Multiple names for indicator %d\n", new->ndx);
- if ((old->name == new->name) && (old->virtual == new->virtual))
- ACTION("Identical definitions ignored\n");
- else
- {
- const char *oldType, *newType;
- Atom using, ignoring;
- if (old->virtual)
- oldType = "virtual indicator";
- else
- oldType = "real indicator";
- if (new->virtual)
- newType = "virtual indicator";
- else
- newType = "real indicator";
- if (replace)
- {
- using = new->name;
- ignoring = old->name;
- }
- else
- {
- using = old->name;
- ignoring = new->name;
- }
- ACTION4("Using %s %s, ignoring %s %s\n",
- oldType, XkbAtomText(NULL, using, XkbMessage),
- newType, XkbAtomText(NULL, ignoring, XkbMessage));
- }
- }
- if (replace)
- {
- old->name = new->name;
- old->virtual = new->virtual;
- }
- return True;
- }
- old = new;
- new = NextIndicatorName(info);
- if (!new)
- {
- WSGO1("Couldn't allocate name for indicator %d\n", new->ndx);
- ACTION("Ignored\n");
- return False;
- }
- new->name = old->name;
- new->ndx = old->ndx;
- new->virtual = old->virtual;
- return True;
-}
-
-static void
-ClearKeyNamesInfo(KeyNamesInfo * info)
-{
- if (info->name != NULL)
- uFree(info->name);
- info->name = NULL;
- info->computedMax = info->explicitMax = info->explicitMin = -1;
- info->computedMin = 256;
- info->effectiveMin = 8;
- info->effectiveMax = 255;
- bzero((char *) info->names, sizeof(info->names));
- bzero((char *) info->files, sizeof(info->files));
- bzero((char *) info->has_alt_forms, sizeof(info->has_alt_forms));
- if (info->leds)
- ClearIndicatorNameInfo(info->leds, info);
- if (info->aliases)
- ClearAliases(&info->aliases);
- return;
-}
-
-static void
-InitKeyNamesInfo(KeyNamesInfo * info)
-{
- info->name = NULL;
- info->leds = NULL;
- info->aliases = NULL;
- info->fileID=-1;
- info->merge=0;
- ClearKeyNamesInfo(info);
- info->errorCount = 0;
- return;
-}
-
-static int
-FindKeyByLong(KeyNamesInfo * info, unsigned long name)
-{
- register int i;
-
- for (i = info->effectiveMin; i <= info->effectiveMax; i++)
- {
- if (info->names[i] == name)
- return i;
- }
- return 0;
-}
-
-/**
- * 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,
- int kc,
- char *name, unsigned merge, unsigned fileID, Bool reportCollisions)
-{
- int old;
- unsigned long lval;
-
- if ((kc < info->effectiveMin) || (kc > info->effectiveMax))
- {
- ERROR2("Illegal keycode %d for name <%s>\n", kc, name);
- ACTION2("Must be in the range %d-%d inclusive\n",
- info->effectiveMin, info->effectiveMax);
- return False;
- }
- if (kc < info->computedMin)
- info->computedMin = kc;
- if (kc > info->computedMax)
- info->computedMax = kc;
- lval = KeyNameToLong(name);
-
- if (reportCollisions)
- {
- reportCollisions = ((warningLevel > 7) ||
- ((warningLevel > 0)
- && (fileID == info->files[kc])));
- }
-
- if (info->names[kc] != 0)
- {
- char buf[6];
-
- LongToKeyName(info->names[kc], buf);
- buf[4] = '\0';
- if (info->names[kc] == lval)
- {
- if (info->has_alt_forms[kc] || (merge == MergeAltForm))
- {
- info->has_alt_forms[kc] = True;
- }
- else if (reportCollisions)
- {
- WARN("Multiple identical key name definitions\n");
- ACTION2("Later occurences of \"<%s> = %d\" ignored\n",
- buf, kc);
- }
- return True;
- }
- if (merge == MergeAugment)
- {
- if (reportCollisions)
- {
- WARN1("Multiple names for keycode %d\n", kc);
- ACTION2("Using <%s>, ignoring <%s>\n", buf, name);
- }
- return True;
- }
- else
- {
- if (reportCollisions)
- {
- WARN1("Multiple names for keycode %d\n", kc);
- ACTION2("Using <%s>, ignoring <%s>\n", name, buf);
- }
- info->names[kc] = 0;
- info->files[kc] = 0;
- }
- }
- old = FindKeyByLong(info, lval);
- if ((old != 0) && (old != kc))
- {
- if (merge == MergeOverride)
- {
- info->names[old] = 0;
- info->files[old] = 0;
- info->has_alt_forms[old] = True;
- if (reportCollisions)
- {
- WARN1("Key name <%s> assigned to multiple keys\n", name);
- ACTION2("Using %d, ignoring %d\n", kc, old);
- }
- }
- else if (merge != MergeAltForm)
- {
- if ((reportCollisions) && (warningLevel > 3))
- {
- WARN1("Key name <%s> assigned to multiple keys\n", name);
- ACTION2("Using %d, ignoring %d\n", old, kc);
- ACTION
- ("Use 'alternate' keyword to assign the same name to multiple keys\n");
- }
- return True;
- }
- else
- {
- info->has_alt_forms[old] = True;
- }
- }
- info->names[kc] = lval;
- info->files[kc] = fileID;
- info->has_alt_forms[kc] = (merge == MergeAltForm);
- return True;
-}
-
-/***====================================================================***/
-
-static void
-MergeIncludedKeycodes(KeyNamesInfo * into, KeyNamesInfo * from,
- unsigned merge)
-{
- register int i;
- char buf[5];
-
- if (from->errorCount > 0)
- {
- into->errorCount += from->errorCount;
- return;
- }
- if (into->name == NULL)
- {
- into->name = from->name;
- from->name = NULL;
- }
- for (i = from->computedMin; i <= from->computedMax; i++)
- {
- unsigned thisMerge;
- if (from->names[i] == 0)
- continue;
- LongToKeyName(from->names[i], buf);
- buf[4] = '\0';
- if (from->has_alt_forms[i])
- thisMerge = MergeAltForm;
- else
- thisMerge = merge;
- if (!AddKeyName(into, i, buf, thisMerge, from->fileID, False))
- into->errorCount++;
- }
- if (from->leds)
- {
- IndicatorNameInfo *led, *next;
- for (led = from->leds; led != NULL; led = next)
- {
- if (merge != MergeDefault)
- led->defs.merge = merge;
- if (!AddIndicatorName(into, led))
- into->errorCount++;
- next = (IndicatorNameInfo *) led->defs.next;
- }
- }
- if (!MergeAliases(&into->aliases, &from->aliases, merge))
- into->errorCount++;
- if (from->explicitMin > 0)
- {
- if ((into->explicitMin < 0)
- || (into->explicitMin > from->explicitMin))
- into->effectiveMin = into->explicitMin = from->explicitMin;
- }
- if (from->explicitMax > 0)
- {
- if ((into->explicitMax < 0)
- || (into->explicitMax < from->explicitMax))
- into->effectiveMax = into->explicitMax = from->explicitMax;
- }
- return;
-}
-
-/**
- * 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)
-{
- unsigned newMerge;
- XkbFile *rtrn;
- KeyNamesInfo included = {NULL};
- Bool haveSelf;
-
- haveSelf = False;
- if ((stmt->file == NULL) && (stmt->map == NULL))
- {
- haveSelf = True;
- included = *info;
- bzero(info, sizeof(KeyNamesInfo));
- }
- else if (strcmp(stmt->file, "computed") == 0)
- {
- xkb->flags |= AutoKeyNames;
- 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);
- HandleKeycodesFile(rtrn, xkb, MergeOverride, &included);
- if (stmt->stmt != NULL)
- {
- if (included.name != NULL)
- uFree(included.name);
- included.name = stmt->stmt;
- stmt->stmt = NULL;
- }
- }
- else
- {
- 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;
- unsigned op;
- KeyNamesInfo next_incl;
-
- for (next = stmt->next; next != NULL; next = next->next)
- {
- if ((next->file == NULL) && (next->map == NULL))
- {
- haveSelf = True;
- MergeIncludedKeycodes(&included, info, next->merge);
- ClearKeyNamesInfo(info);
- }
- else if (ProcessIncludeFile(next, XkmKeyNamesIndex, &rtrn, &op))
- {
- InitKeyNamesInfo(&next_incl);
- HandleKeycodesFile(rtrn, xkb, MergeOverride, &next_incl);
- MergeIncludedKeycodes(&included, &next_incl, op);
- ClearKeyNamesInfo(&next_incl);
- }
- else
- {
- info->errorCount += 10; /* XXX: Why 10?? */
- return False;
- }
- }
- }
- if (haveSelf)
- *info = included;
- else
- {
- MergeIncludedKeycodes(info, &included, newMerge);
- ClearKeyNamesInfo(&included);
- }
- return (info->errorCount == 0);
-}
-
-/**
- * Parse the given statement and store the output in the info struct.
- * e.g. <ESC> = 9
- */
-static int
-HandleKeycodeDef(KeycodeDef * stmt, unsigned merge, KeyNamesInfo * info)
-{
- int code;
- ExprResult result;
-
- if (!ExprResolveInteger(stmt->value, &result, NULL, NULL))
- {
- ACTION1("No value keycode assigned to name <%s>\n", stmt->name);
- return 0;
- }
- code = result.ival;
- if ((code < info->effectiveMin) || (code > info->effectiveMax))
- {
- ERROR2("Illegal keycode %d for name <%s>\n", code, stmt->name);
- ACTION2("Must be in the range %d-%d inclusive\n",
- info->effectiveMin, info->effectiveMax);
- return 0;
- }
- if (stmt->merge != MergeDefault)
- {
- if (stmt->merge == MergeReplace)
- merge = MergeOverride;
- else
- merge = stmt->merge;
- }
- return AddKeyName(info, code, stmt->name, merge, info->fileID, True);
-}
-
-#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, KeyNamesInfo * info)
-{
- ExprResult tmp, field;
- ExprDef *arrayNdx;
- int which;
-
- if (ExprResolveLhs(stmt->name, &tmp, &field, &arrayNdx) == 0)
- return 0; /* internal error, already reported */
-
- if (tmp.str != NULL)
- {
- ERROR1("Unknown element %s encountered\n", tmp.str);
- ACTION1("Default for field %s ignored\n", field.str);
- return 0;
- }
- if (uStrCaseCmp(field.str, "minimum") == 0)
- which = MIN_KEYCODE_DEF;
- else if (uStrCaseCmp(field.str, "maximum") == 0)
- which = MAX_KEYCODE_DEF;
- else
- {
- ERROR("Unknown field encountered\n");
- ACTION1("Assigment to field %s ignored\n", field.str);
- return 0;
- }
- if (arrayNdx != NULL)
- {
- ERROR1("The %s setting is not an array\n", field.str);
- ACTION("Illegal array reference ignored\n");
- return 0;
- }
-
- if (ExprResolveInteger(stmt->value, &tmp, NULL, NULL) == 0)
- {
- ACTION1("Assignment to field %s ignored\n", field.str);
- return 0;
- }
- if ((tmp.ival < XkbMinLegalKeyCode) || (tmp.ival > XkbMaxLegalKeyCode))
- {
- ERROR3
- ("Illegal keycode %d (must be in the range %d-%d inclusive)\n",
- tmp.ival, XkbMinLegalKeyCode, XkbMaxLegalKeyCode);
- ACTION1("Value of \"%s\" not changed\n", field.str);
- return 0;
- }
- if (which == MIN_KEYCODE_DEF)
- {
- if ((info->explicitMax > 0) && (info->explicitMax < tmp.ival))
- {
- ERROR2
- ("Minimum key code (%d) must be <= maximum key code (%d)\n",
- tmp.ival, info->explicitMax);
- ACTION("Minimum key code value not changed\n");
- return 0;
- }
- if ((info->computedMax > 0) && (info->computedMin < tmp.ival))
- {
- ERROR2
- ("Minimum key code (%d) must be <= lowest defined key (%d)\n",
- tmp.ival, info->computedMin);
- ACTION("Minimum key code value not changed\n");
- return 0;
- }
- info->explicitMin = tmp.ival;
- info->effectiveMin = tmp.ival;
- }
- if (which == MAX_KEYCODE_DEF)
- {
- if ((info->explicitMin > 0) && (info->explicitMin > tmp.ival))
- {
- ERROR2("Maximum code (%d) must be >= minimum key code (%d)\n",
- tmp.ival, info->explicitMin);
- ACTION("Maximum code value not changed\n");
- return 0;
- }
- if ((info->computedMax > 0) && (info->computedMax > tmp.ival))
- {
- ERROR2
- ("Maximum code (%d) must be >= highest defined key (%d)\n",
- tmp.ival, info->computedMax);
- ACTION("Maximum code value not changed\n");
- return 0;
- }
- info->explicitMax = tmp.ival;
- info->effectiveMax = tmp.ival;
- }
- return 1;
-}
-
-static int
-HandleIndicatorNameDef(IndicatorNameDef * def,
- unsigned merge, KeyNamesInfo * info)
-{
- IndicatorNameInfo ii;
- ExprResult tmp;
-
- if ((def->ndx < 1) || (def->ndx > XkbNumIndicators))
- {
- info->errorCount++;
- ERROR1("Name specified for illegal indicator index %d\n", def->ndx);
- ACTION("Ignored\n");
- return False;
- }
- InitIndicatorNameInfo(&ii, info);
- ii.ndx = def->ndx;
- if (!ExprResolveString(def->name, &tmp, NULL, NULL))
- {
- char buf[20];
- snprintf(buf, sizeof(buf), "%d", def->ndx);
- info->errorCount++;
- return ReportBadType("indicator", "name", buf, "string");
- }
- ii.name = XkbInternAtom(NULL, tmp.str, False);
- ii.virtual = def->virtual;
- if (!AddIndicatorName(info, &ii))
- return False;
- 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)
-{
- ParseCommon *stmt;
-
- info->name = uStringDup(file->name);
- stmt = file->defs;
- while (stmt)
- {
- switch (stmt->stmtType)
- {
- case StmtInclude: /* e.g. include "evdev+aliases(qwerty)" */
- if (!HandleIncludeKeycodes((IncludeStmt *) stmt, xkb, info))
- info->errorCount++;
- break;
- case StmtKeycodeDef: /* e.g. <ESC> = 9; */
- if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info))
- info->errorCount++;
- break;
- case StmtKeyAliasDef: /* e.g. alias <MENU> = <COMP>; */
- if (!HandleAliasDef((KeyAliasDef *) stmt,
- merge, info->fileID, &info->aliases))
- info->errorCount++;
- break;
- case StmtVarDef: /* e.g. minimum, maximum */
- if (!HandleKeyNameVar((VarDef *) stmt, info))
- info->errorCount++;
- break;
- case StmtIndicatorNameDef: /* e.g. indicator 1 = "Caps Lock"; */
- if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt,
- merge, info))
- {
- info->errorCount++;
- }
- break;
- case StmtInterpDef:
- case StmtVModDef:
- ERROR("Keycode files may define key and indicator names only\n");
- ACTION1("Ignoring definition of %s\n",
- ((stmt->stmtType ==
- StmtInterpDef) ? "a symbol interpretation" :
- "virtual modifiers"));
- info->errorCount++;
- break;
- default:
- WSGO1("Unexpected statement type %d in HandleKeycodesFile\n",
- stmt->stmtType);
- break;
- }
- stmt = stmt->next;
- if (info->errorCount > 10)
- {
-#ifdef NOISY
- ERROR("Too many errors\n");
-#endif
- ACTION1("Abandoning keycodes file \"%s\"\n", file->topName);
- break;
- }
- }
- 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; /* 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 "minimum" statement was present */
- xkb->min_key_code = info.effectiveMin;
- else
- xkb->min_key_code = info.computedMin;
- if (info.explicitMax > 0) /* if "maximum" statement was present */
- xkb->max_key_code = info.effectiveMax;
- else
- xkb->max_key_code = info.computedMax;
- if (XkbAllocNames(xkb, XkbKeyNamesMask | XkbIndicatorNamesMask, 0, 0)
- == Success)
- {
- register int i;
- xkb->names->keycodes = XkbInternAtom(xkb->dpy, info.name, False);
- uDEBUG2(1, "key range: %d..%d\n", xkb->min_key_code,
- xkb->max_key_code);
- for (i = info.computedMin; i <= info.computedMax; i++)
- {
- LongToKeyName(info.names[i], xkb->names->keys[i].name);
- uDEBUG2(2, "key %d = %s\n", i,
- XkbKeyNameText(xkb->names->keys[i].name, XkbMessage));
- }
- }
- else
- {
- WSGO("Cannot create XkbNamesRec in CompileKeycodes\n");
- return False;
- }
- if (info.leds)
- {
- IndicatorNameInfo *ii;
- if (XkbAllocIndicatorMaps(xkb) != Success)
- {
- WSGO("Couldn't allocate IndicatorRec in CompileKeycodes\n");
- ACTION("Physical indicators not set\n");
- }
- for (ii = info.leds; ii != NULL;
- ii = (IndicatorNameInfo *) ii->defs.next)
- {
- xkb->names->indicators[ii->ndx - 1] =
- XkbInternAtom(xkb->dpy,
- XkbAtomGetString(NULL, ii->name), False);
- if (xkb->indicators != NULL)
- {
- register unsigned bit;
- bit = 1 << (ii->ndx - 1);
- if (ii->virtual)
- xkb->indicators->phys_indicators &= ~bit;
- else
- xkb->indicators->phys_indicators |= bit;
- }
- }
- }
- if (info.aliases)
- ApplyAliases(xkb, False, &info.aliases);
- return True;
- }
- ClearKeyNamesInfo(&info);
- return False;
-}
+/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + Permission to use, copy, modify, and distribute this + software and its documentation for any purpose and without + fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH + THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ********************************************************/ + +#include "xkbcomp.h" +#include "tokens.h" +#include "expr.h" +#include "keycodes.h" +#include "misc.h" +#include "alias.h" + +char * +longText(unsigned long val, unsigned format) +{ + char buf[4]; + + LongToKeyName(val, buf); + return XkbKeyNameText(buf, format); +} + +/***====================================================================***/ + +void +LongToKeyName(unsigned long val, char *name) +{ + name[0] = ((val >> 24) & 0xff); + name[1] = ((val >> 16) & 0xff); + name[2] = ((val >> 8) & 0xff); + name[3] = (val & 0xff); + return; +} + +/***====================================================================***/ + +typedef struct _IndicatorNameInfo +{ + CommonInfo defs; + int ndx; + Atom name; + Bool virtual; +} IndicatorNameInfo; + +typedef struct _KeyNamesInfo +{ + char *name; /* e.g. evdev+aliases(qwerty) */ + int errorCount; + unsigned fileID; + unsigned merge; + int computedMin; /* lowest keycode stored */ + int computedMax; /* highest keycode stored */ + int explicitMin; + int explicitMax; + int effectiveMin; + int effectiveMax; + 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; + AliasInfo *aliases; +} KeyNamesInfo; + +static void HandleKeycodesFile(XkbFile * file, + XkbDescPtr xkb, + unsigned merge, + KeyNamesInfo * info); + +static void +InitIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info) +{ + ii->defs.defined = 0; + ii->defs.merge = info->merge; + ii->defs.fileID = info->fileID; + ii->defs.next = NULL; + ii->ndx = 0; + ii->name = None; + ii->virtual = False; + return; +} + +static void +ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info) +{ + if (ii == info->leds) + { + ClearCommonInfo(&ii->defs); + info->leds = NULL; + } + return; +} + +static IndicatorNameInfo * +NextIndicatorName(KeyNamesInfo * info) +{ + IndicatorNameInfo *ii; + + ii = uTypedAlloc(IndicatorNameInfo); + if (ii) + { + InitIndicatorNameInfo(ii, info); + info->leds = (IndicatorNameInfo *) AddCommonInfo(&info->leds->defs, + (CommonInfo *) ii); + } + return ii; +} + +static IndicatorNameInfo * +FindIndicatorByIndex(KeyNamesInfo * info, int ndx) +{ + IndicatorNameInfo *old; + + for (old = info->leds; old != NULL; + old = (IndicatorNameInfo *) old->defs.next) + { + if (old->ndx == ndx) + return old; + } + return NULL; +} + +static IndicatorNameInfo * +FindIndicatorByName(KeyNamesInfo * info, Atom name) +{ + IndicatorNameInfo *old; + + for (old = info->leds; old != NULL; + old = (IndicatorNameInfo *) old->defs.next) + { + if (old->name == name) + return old; + } + return NULL; +} + +static Bool +AddIndicatorName(KeyNamesInfo * info, IndicatorNameInfo * new) +{ + IndicatorNameInfo *old; + Bool replace; + + replace = (new->defs.merge == MergeReplace) || + (new->defs.merge == MergeOverride); + old = FindIndicatorByName(info, new->name); + if (old) + { + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN1("Multiple indicators named %s\n", + XkbAtomText(NULL, new->name, XkbMessage)); + if (old->ndx == new->ndx) + { + if (old->virtual != new->virtual) + { + if (replace) + old->virtual = new->virtual; + ACTION2("Using %s instead of %s\n", + (old->virtual ? "virtual" : "real"), + (old->virtual ? "real" : "virtual")); + } + else + { + ACTION("Identical definitions ignored\n"); + } + return True; + } + else + { + if (replace) + ACTION2("Ignoring %d, using %d\n", old->ndx, new->ndx); + else + ACTION2("Using %d, ignoring %d\n", old->ndx, new->ndx); + } + if (replace) + { + if (info->leds == old) + info->leds = (IndicatorNameInfo *) old->defs.next; + else + { + IndicatorNameInfo *tmp; + tmp = info->leds; + for (; tmp != NULL; + tmp = (IndicatorNameInfo *) tmp->defs.next) + { + if (tmp->defs.next == (CommonInfo *) old) + { + tmp->defs.next = old->defs.next; + break; + } + } + } + uFree(old); + } + } + } + old = FindIndicatorByIndex(info, new->ndx); + if (old) + { + if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0)) + || (warningLevel > 9)) + { + WARN1("Multiple names for indicator %d\n", new->ndx); + if ((old->name == new->name) && (old->virtual == new->virtual)) + ACTION("Identical definitions ignored\n"); + else + { + const char *oldType, *newType; + Atom using, ignoring; + if (old->virtual) + oldType = "virtual indicator"; + else + oldType = "real indicator"; + if (new->virtual) + newType = "virtual indicator"; + else + newType = "real indicator"; + if (replace) + { + using = new->name; + ignoring = old->name; + } + else + { + using = old->name; + ignoring = new->name; + } + ACTION4("Using %s %s, ignoring %s %s\n", + oldType, XkbAtomText(NULL, using, XkbMessage), + newType, XkbAtomText(NULL, ignoring, XkbMessage)); + } + } + if (replace) + { + old->name = new->name; + old->virtual = new->virtual; + } + return True; + } + old = new; + new = NextIndicatorName(info); + if (!new) + { + WSGO1("Couldn't allocate name for indicator %d\n", new->ndx); + ACTION("Ignored\n"); + return False; + } + new->name = old->name; + new->ndx = old->ndx; + new->virtual = old->virtual; + return True; +} + +static void +ClearKeyNamesInfo(KeyNamesInfo * info) +{ + if (info->name != NULL) + uFree(info->name); + info->name = NULL; + info->computedMax = info->explicitMax = info->explicitMin = -1; + info->computedMin = 256; + info->effectiveMin = 8; + info->effectiveMax = 255; + bzero((char *) info->names, sizeof(info->names)); + bzero((char *) info->files, sizeof(info->files)); + bzero((char *) info->has_alt_forms, sizeof(info->has_alt_forms)); + if (info->leds) + ClearIndicatorNameInfo(info->leds, info); + if (info->aliases) + ClearAliases(&info->aliases); + return; +} + +static void +InitKeyNamesInfo(KeyNamesInfo * info) +{ + info->name = NULL; + info->leds = NULL; + info->aliases = NULL; + info->fileID=-1; + info->merge=0; + ClearKeyNamesInfo(info); + info->errorCount = 0; + return; +} + +static int +FindKeyByLong(KeyNamesInfo * info, unsigned long name) +{ + register int i; + + for (i = info->effectiveMin; i <= info->effectiveMax; i++) + { + if (info->names[i] == name) + return i; + } + return 0; +} + +/** + * 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, + int kc, + char *name, unsigned merge, unsigned fileID, Bool reportCollisions) +{ + int old; + unsigned long lval; + + if ((kc < info->effectiveMin) || (kc > info->effectiveMax)) + { + ERROR2("Illegal keycode %d for name <%s>\n", kc, name); + ACTION2("Must be in the range %d-%d inclusive\n", + info->effectiveMin, info->effectiveMax); + return False; + } + if (kc < info->computedMin) + info->computedMin = kc; + if (kc > info->computedMax) + info->computedMax = kc; + lval = KeyNameToLong(name); + + if (reportCollisions) + { + reportCollisions = ((warningLevel > 7) || + ((warningLevel > 0) + && (fileID == info->files[kc]))); + } + + if (info->names[kc] != 0) + { + char buf[6]; + + LongToKeyName(info->names[kc], buf); + buf[4] = '\0'; + if (info->names[kc] == lval) + { + if (info->has_alt_forms[kc] || (merge == MergeAltForm)) + { + info->has_alt_forms[kc] = True; + } + else if (reportCollisions) + { + WARN("Multiple identical key name definitions\n"); + ACTION2("Later occurences of \"<%s> = %d\" ignored\n", + buf, kc); + } + return True; + } + if (merge == MergeAugment) + { + if (reportCollisions) + { + WARN1("Multiple names for keycode %d\n", kc); + ACTION2("Using <%s>, ignoring <%s>\n", buf, name); + } + return True; + } + else + { + if (reportCollisions) + { + WARN1("Multiple names for keycode %d\n", kc); + ACTION2("Using <%s>, ignoring <%s>\n", name, buf); + } + info->names[kc] = 0; + info->files[kc] = 0; + } + } + old = FindKeyByLong(info, lval); + if ((old != 0) && (old != kc)) + { + if (merge == MergeOverride) + { + info->names[old] = 0; + info->files[old] = 0; + info->has_alt_forms[old] = True; + if (reportCollisions) + { + WARN1("Key name <%s> assigned to multiple keys\n", name); + ACTION2("Using %d, ignoring %d\n", kc, old); + } + } + else if (merge != MergeAltForm) + { + if ((reportCollisions) && (warningLevel > 3)) + { + WARN1("Key name <%s> assigned to multiple keys\n", name); + ACTION2("Using %d, ignoring %d\n", old, kc); + ACTION + ("Use 'alternate' keyword to assign the same name to multiple keys\n"); + } + return True; + } + else + { + info->has_alt_forms[old] = True; + } + } + info->names[kc] = lval; + info->files[kc] = fileID; + info->has_alt_forms[kc] = (merge == MergeAltForm); + return True; +} + +/***====================================================================***/ + +static void +MergeIncludedKeycodes(KeyNamesInfo * into, KeyNamesInfo * from, + unsigned merge) +{ + register int i; + char buf[5]; + + if (from->errorCount > 0) + { + into->errorCount += from->errorCount; + return; + } + if (into->name == NULL) + { + into->name = from->name; + from->name = NULL; + } + for (i = from->computedMin; i <= from->computedMax; i++) + { + unsigned thisMerge; + if (from->names[i] == 0) + continue; + LongToKeyName(from->names[i], buf); + buf[4] = '\0'; + if (from->has_alt_forms[i]) + thisMerge = MergeAltForm; + else + thisMerge = merge; + if (!AddKeyName(into, i, buf, thisMerge, from->fileID, False)) + into->errorCount++; + } + if (from->leds) + { + IndicatorNameInfo *led, *next; + for (led = from->leds; led != NULL; led = next) + { + if (merge != MergeDefault) + led->defs.merge = merge; + if (!AddIndicatorName(into, led)) + into->errorCount++; + next = (IndicatorNameInfo *) led->defs.next; + } + } + if (!MergeAliases(&into->aliases, &from->aliases, merge)) + into->errorCount++; + if (from->explicitMin > 0) + { + if ((into->explicitMin < 0) + || (into->explicitMin > from->explicitMin)) + into->effectiveMin = into->explicitMin = from->explicitMin; + } + if (from->explicitMax > 0) + { + if ((into->explicitMax < 0) + || (into->explicitMax < from->explicitMax)) + into->effectiveMax = into->explicitMax = from->explicitMax; + } + return; +} + +/** + * 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) +{ + unsigned newMerge; + XkbFile *rtrn; + KeyNamesInfo included = {NULL}; + Bool haveSelf; + + haveSelf = False; + if ((stmt->file == NULL) && (stmt->map == NULL)) + { + haveSelf = True; + included = *info; + bzero(info, sizeof(KeyNamesInfo)); + } + else if (strcmp(stmt->file, "computed") == 0) + { + xkb->flags |= AutoKeyNames; + 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); + HandleKeycodesFile(rtrn, xkb, MergeOverride, &included); + if (stmt->stmt != NULL) + { + if (included.name != NULL) + uFree(included.name); + included.name = stmt->stmt; + stmt->stmt = NULL; + } + } + else + { + 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; + unsigned op; + KeyNamesInfo next_incl; + + for (next = stmt->next; next != NULL; next = next->next) + { + if ((next->file == NULL) && (next->map == NULL)) + { + haveSelf = True; + MergeIncludedKeycodes(&included, info, next->merge); + ClearKeyNamesInfo(info); + } + else if (ProcessIncludeFile(next, XkmKeyNamesIndex, &rtrn, &op)) + { + InitKeyNamesInfo(&next_incl); + HandleKeycodesFile(rtrn, xkb, MergeOverride, &next_incl); + MergeIncludedKeycodes(&included, &next_incl, op); + ClearKeyNamesInfo(&next_incl); + } + else + { + info->errorCount += 10; /* XXX: Why 10?? */ + return False; + } + } + } + if (haveSelf) + *info = included; + else + { + MergeIncludedKeycodes(info, &included, newMerge); + ClearKeyNamesInfo(&included); + } + return (info->errorCount == 0); +} + +/** + * Parse the given statement and store the output in the info struct. + * e.g. <ESC> = 9 + */ +static int +HandleKeycodeDef(KeycodeDef * stmt, unsigned merge, KeyNamesInfo * info) +{ + int code; + ExprResult result; + + if (!ExprResolveInteger(stmt->value, &result, NULL, NULL)) + { + ACTION1("No value keycode assigned to name <%s>\n", stmt->name); + return 0; + } + code = result.ival; + if ((code < info->effectiveMin) || (code > info->effectiveMax)) + { + ERROR2("Illegal keycode %d for name <%s>\n", code, stmt->name); + ACTION2("Must be in the range %d-%d inclusive\n", + info->effectiveMin, info->effectiveMax); + return 0; + } + if (stmt->merge != MergeDefault) + { + if (stmt->merge == MergeReplace) + merge = MergeOverride; + else + merge = stmt->merge; + } + return AddKeyName(info, code, stmt->name, merge, info->fileID, True); +} + +#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, KeyNamesInfo * info) +{ + ExprResult tmp, field; + ExprDef *arrayNdx; + int which; + + if (ExprResolveLhs(stmt->name, &tmp, &field, &arrayNdx) == 0) + return 0; /* internal error, already reported */ + + if (tmp.str != NULL) + { + ERROR1("Unknown element %s encountered\n", tmp.str); + ACTION1("Default for field %s ignored\n", field.str); + return 0; + } + if (uStrCaseCmp(field.str, "minimum") == 0) + which = MIN_KEYCODE_DEF; + else if (uStrCaseCmp(field.str, "maximum") == 0) + which = MAX_KEYCODE_DEF; + else + { + ERROR("Unknown field encountered\n"); + ACTION1("Assigment to field %s ignored\n", field.str); + return 0; + } + if (arrayNdx != NULL) + { + ERROR1("The %s setting is not an array\n", field.str); + ACTION("Illegal array reference ignored\n"); + return 0; + } + + if (ExprResolveInteger(stmt->value, &tmp, NULL, NULL) == 0) + { + ACTION1("Assignment to field %s ignored\n", field.str); + return 0; + } + if ((tmp.ival < XkbMinLegalKeyCode) || (tmp.ival > XkbMaxLegalKeyCode)) + { + ERROR3 + ("Illegal keycode %d (must be in the range %d-%d inclusive)\n", + tmp.ival, XkbMinLegalKeyCode, XkbMaxLegalKeyCode); + ACTION1("Value of \"%s\" not changed\n", field.str); + return 0; + } + if (which == MIN_KEYCODE_DEF) + { + if ((info->explicitMax > 0) && (info->explicitMax < tmp.ival)) + { + ERROR2 + ("Minimum key code (%d) must be <= maximum key code (%d)\n", + tmp.ival, info->explicitMax); + ACTION("Minimum key code value not changed\n"); + return 0; + } + if ((info->computedMax > 0) && (info->computedMin < tmp.ival)) + { + ERROR2 + ("Minimum key code (%d) must be <= lowest defined key (%d)\n", + tmp.ival, info->computedMin); + ACTION("Minimum key code value not changed\n"); + return 0; + } + info->explicitMin = tmp.ival; + info->effectiveMin = tmp.ival; + } + if (which == MAX_KEYCODE_DEF) + { + if ((info->explicitMin > 0) && (info->explicitMin > tmp.ival)) + { + ERROR2("Maximum code (%d) must be >= minimum key code (%d)\n", + tmp.ival, info->explicitMin); + ACTION("Maximum code value not changed\n"); + return 0; + } + if ((info->computedMax > 0) && (info->computedMax > tmp.ival)) + { + ERROR2 + ("Maximum code (%d) must be >= highest defined key (%d)\n", + tmp.ival, info->computedMax); + ACTION("Maximum code value not changed\n"); + return 0; + } + info->explicitMax = tmp.ival; + info->effectiveMax = tmp.ival; + } + return 1; +} + +static int +HandleIndicatorNameDef(IndicatorNameDef * def, + unsigned merge, KeyNamesInfo * info) +{ + IndicatorNameInfo ii; + ExprResult tmp; + + if ((def->ndx < 1) || (def->ndx > XkbNumIndicators)) + { + info->errorCount++; + ERROR1("Name specified for illegal indicator index %d\n", def->ndx); + ACTION("Ignored\n"); + return False; + } + InitIndicatorNameInfo(&ii, info); + ii.ndx = def->ndx; + if (!ExprResolveString(def->name, &tmp, NULL, NULL)) + { + char buf[20]; + snprintf(buf, sizeof(buf), "%d", def->ndx); + info->errorCount++; + return ReportBadType("indicator", "name", buf, "string"); + } + ii.name = XkbInternAtom(NULL, tmp.str, False); + ii.virtual = def->virtual; + if (!AddIndicatorName(info, &ii)) + return False; + 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) +{ + ParseCommon *stmt; + + info->name = uStringDup(file->name); + stmt = file->defs; + while (stmt) + { + switch (stmt->stmtType) + { + case StmtInclude: /* e.g. include "evdev+aliases(qwerty)" */ + if (!HandleIncludeKeycodes((IncludeStmt *) stmt, xkb, info)) + info->errorCount++; + break; + case StmtKeycodeDef: /* e.g. <ESC> = 9; */ + if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info)) + info->errorCount++; + break; + case StmtKeyAliasDef: /* e.g. alias <MENU> = <COMP>; */ + if (!HandleAliasDef((KeyAliasDef *) stmt, + merge, info->fileID, &info->aliases)) + info->errorCount++; + break; + case StmtVarDef: /* e.g. minimum, maximum */ + if (!HandleKeyNameVar((VarDef *) stmt, info)) + info->errorCount++; + break; + case StmtIndicatorNameDef: /* e.g. indicator 1 = "Caps Lock"; */ + if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt, + merge, info)) + { + info->errorCount++; + } + break; + case StmtInterpDef: + case StmtVModDef: + ERROR("Keycode files may define key and indicator names only\n"); + ACTION1("Ignoring definition of %s\n", + ((stmt->stmtType == + StmtInterpDef) ? "a symbol interpretation" : + "virtual modifiers")); + info->errorCount++; + break; + default: + WSGO1("Unexpected statement type %d in HandleKeycodesFile\n", + stmt->stmtType); + break; + } + stmt = stmt->next; + if (info->errorCount > 10) + { +#ifdef NOISY + ERROR("Too many errors\n"); +#endif + ACTION1("Abandoning keycodes file \"%s\"\n", file->topName); + break; + } + } + 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; /* 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 "minimum" statement was present */ + xkb->min_key_code = info.effectiveMin; + else + xkb->min_key_code = info.computedMin; + if (info.explicitMax > 0) /* if "maximum" statement was present */ + xkb->max_key_code = info.effectiveMax; + else + xkb->max_key_code = info.computedMax; + if (XkbAllocNames(xkb, XkbKeyNamesMask | XkbIndicatorNamesMask, 0, 0) + == Success) + { + register int i; + xkb->names->keycodes = XkbInternAtom(xkb->dpy, info.name, False); + uDEBUG2(1, "key range: %d..%d\n", xkb->min_key_code, + xkb->max_key_code); + for (i = info.computedMin; i <= info.computedMax; i++) + { + LongToKeyName(info.names[i], xkb->names->keys[i].name); + uDEBUG2(2, "key %d = %s\n", i, + XkbKeyNameText(xkb->names->keys[i].name, XkbMessage)); + } + } + else + { + WSGO("Cannot create XkbNamesRec in CompileKeycodes\n"); + return False; + } + if (info.leds) + { + IndicatorNameInfo *ii; + if (XkbAllocIndicatorMaps(xkb) != Success) + { + WSGO("Couldn't allocate IndicatorRec in CompileKeycodes\n"); + ACTION("Physical indicators not set\n"); + } + for (ii = info.leds; ii != NULL; + ii = (IndicatorNameInfo *) ii->defs.next) + { + xkb->names->indicators[ii->ndx - 1] = + XkbInternAtom(xkb->dpy, + XkbAtomGetString(NULL, ii->name), False); + if (xkb->indicators != NULL) + { + register unsigned bit; + bit = 1 << (ii->ndx - 1); + if (ii->virtual) + xkb->indicators->phys_indicators &= ~bit; + else + xkb->indicators->phys_indicators |= bit; + } + } + } + if (info.aliases) + ApplyAliases(xkb, False, &info.aliases); + return True; + } + ClearKeyNamesInfo(&info); + return False; +} |