aboutsummaryrefslogtreecommitdiff
path: root/xkbcomp/keycodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'xkbcomp/keycodes.c')
-rw-r--r--xkbcomp/keycodes.c749
1 files changed, 749 insertions, 0 deletions
diff --git a/xkbcomp/keycodes.c b/xkbcomp/keycodes.c
new file mode 100644
index 000000000..a86592e4d
--- /dev/null
+++ b/xkbcomp/keycodes.c
@@ -0,0 +1,749 @@
+/* $Xorg: keycodes.c,v 1.4 2000/08/17 19:54:32 cpqbld Exp $ */
+/************************************************************
+ 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.
+
+ ********************************************************/
+/* $XFree86$ */
+
+#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;
+ int errorCount;
+ unsigned fileID;
+ unsigned merge;
+ int computedMin;
+ int computedMax;
+ int explicitMin;
+ int explicitMax;
+ int effectiveMin;
+ int effectiveMax;
+ unsigned long names[XkbMaxLegalKeyCode+1];
+ unsigned files[XkbMaxLegalKeyCode+1];
+ unsigned char has_alt_forms[XkbMaxLegalKeyCode+1];
+ IndicatorNameInfo * leds;
+ AliasInfo * aliases;
+} KeyNamesInfo;
+
+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;
+const char *action;
+
+ 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;
+ action= "Using %s instead of %s\n";
+ }
+ else {
+ action= "Identical definitions ignored\n";
+ }
+ ACTION2(action,(old->virtual?"virtual":"real"),
+ (old->virtual?"real":"virtual"));
+ return True;
+ }
+ else {
+ if (replace) action= "Ignoring %d, using %d\n";
+ else action= "Using %d, ignoring %d\n";
+ ACTION2(action,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;
+ 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;
+}
+
+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;
+}
+
+typedef void (*FileHandler)(
+ XkbFile * /* rtrn */,
+ XkbDescPtr /* xkb */,
+ unsigned /* merge */,
+ KeyNamesInfo * /* included */
+);
+
+static Bool
+HandleIncludeKeycodes( IncludeStmt * stmt,
+ XkbDescPtr xkb,
+ KeyNamesInfo * info,
+ FileHandler hndlr)
+{
+unsigned newMerge;
+XkbFile * rtrn;
+KeyNamesInfo included;
+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);
+ }
+ else if (ProcessIncludeFile(stmt,XkmKeyNamesIndex,&rtrn,&newMerge)) {
+ InitKeyNamesInfo(&included);
+ (*hndlr)(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;
+ return False;
+ }
+ 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);
+ (*hndlr)(rtrn,xkb,MergeOverride,&next_incl);
+ MergeIncludedKeycodes(&included,&next_incl,op);
+ ClearKeyNamesInfo(&next_incl);
+ }
+ else {
+ info->errorCount+= 10;
+ return False;
+ }
+ }
+ }
+ if (haveSelf)
+ *info= included;
+ else {
+ MergeIncludedKeycodes(info,&included,newMerge);
+ ClearKeyNamesInfo(&included);
+ }
+ return (info->errorCount==0);
+}
+
+static int
+HandleKeycodeDef( KeycodeDef * stmt,
+ XkbDescPtr xkb,
+ 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
+
+static int
+HandleKeyNameVar(VarDef *stmt,XkbDescPtr xkb,unsigned merge,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,
+ XkbDescPtr xkb,
+ 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];
+ sprintf(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;
+}
+
+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:
+ if (!HandleIncludeKeycodes((IncludeStmt *)stmt,xkb,info,
+ HandleKeycodesFile))
+ info->errorCount++;
+ break;
+ case StmtKeycodeDef:
+ if (!HandleKeycodeDef((KeycodeDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtKeyAliasDef:
+ if (!HandleAliasDef((KeyAliasDef *)stmt,
+ merge,info->fileID,&info->aliases))
+ info->errorCount++;
+ break;
+ case StmtVarDef:
+ if (!HandleKeyNameVar((VarDef *)stmt,xkb,merge,info))
+ info->errorCount++;
+ break;
+ case StmtIndicatorNameDef:
+ if (!HandleIndicatorNameDef((IndicatorNameDef *)stmt,xkb,
+ 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;
+}
+
+Bool
+CompileKeycodes(XkbFile *file,XkbFileInfo *result,unsigned merge)
+{
+KeyNamesInfo info;
+XkbDescPtr xkb;
+
+ xkb= result->xkb;
+ InitKeyNamesInfo(&info);
+ HandleKeycodesFile(file,xkb,merge,&info);
+
+ if (info.errorCount==0) {
+ if (info.explicitMin>0)
+ xkb->min_key_code= info.effectiveMin;
+ else xkb->min_key_code= info.computedMin;
+ if (info.explicitMax>0)
+ 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;
+}