compat.c revision f46a6179
1/* $Xorg: compat.c,v 1.3 2000/08/17 19:54:30 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 4 5 Permission to use, copy, modify, and distribute this 6 software and its documentation for any purpose and without 7 fee is hereby granted, provided that the above copyright 8 notice appear in all copies and that both that copyright 9 notice and this permission notice appear in supporting 10 documentation, and that the name of Silicon Graphics not be 11 used in advertising or publicity pertaining to distribution 12 of the software without specific prior written permission. 13 Silicon Graphics makes no representation about the suitability 14 of this software for any purpose. It is provided "as is" 15 without any express or implied warranty. 16 17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 24 THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 26 ********************************************************/ 27/* $XFree86: xc/programs/xkbcomp/compat.c,v 3.3 2001/01/17 23:45:43 dawes Exp $ */ 28 29#include <X11/Xos.h> 30#include "xkbcomp.h" 31#include "tokens.h" 32#include "expr.h" 33#include "vmod.h" 34#include "misc.h" 35#include "indicators.h" 36#include "action.h" 37 38typedef struct _SymInterpInfo { 39 CommonInfo defs; 40 XkbSymInterpretRec interp; 41} SymInterpInfo; 42 43#define _SI_VirtualMod (1<<0) 44#define _SI_Action (1<<1) 45#define _SI_AutoRepeat (1<<2) 46#define _SI_LockingKey (1<<3) 47#define _SI_LevelOneOnly (1<<4) 48 49typedef struct _GroupCompatInfo { 50 unsigned char fileID; 51 unsigned char merge; 52 unsigned char real_mods; 53 unsigned short vmods; 54} GroupCompatInfo; 55 56typedef struct _CompatInfo { 57 char * name; 58 unsigned fileID; 59 int errorCount; 60 int nInterps; 61 SymInterpInfo * interps; 62 SymInterpInfo dflt; 63 LEDInfo ledDflt; 64 GroupCompatInfo groupCompat[XkbNumKbdGroups]; 65 LEDInfo * leds; 66 VModInfo vmods; 67 ActionInfo * act; 68 XkbDescPtr xkb; 69} CompatInfo; 70 71/***====================================================================***/ 72 73#define ReportSINotArray(si,f,i) \ 74 ReportNotArray("symbol interpretation",(f),siText((si),(i))) 75#define ReportSIBadType(si,f,w,i) \ 76 ReportBadType("symbol interpretation",(f),siText((si),(i)),(w)) 77 78/***====================================================================***/ 79 80static char * 81siText(SymInterpInfo * si,CompatInfo * info) 82{ 83static char buf[128]; 84 85 if (si==&info->dflt) { 86 sprintf(buf,"default"); 87 } 88 else { 89 sprintf(buf,"%s+%s(%s)",XkbKeysymText(si->interp.sym,XkbMessage), 90 XkbSIMatchText(si->interp.match,XkbMessage), 91 XkbModMaskText(si->interp.mods,XkbMessage)); 92 } 93 return buf; 94} 95 96static void 97InitCompatInfo(CompatInfo *info,XkbDescPtr xkb) 98{ 99register int i; 100 101 info->xkb= xkb; 102 info->name= NULL; 103 info->fileID= 0; 104 info->errorCount= 0; 105 info->nInterps= 0; 106 info->interps= NULL; 107 info->act= NULL; 108 info->dflt.defs.fileID= info->fileID; 109 info->dflt.defs.defined= 0; 110 info->dflt.defs.merge= MergeOverride; 111 info->dflt.interp.flags= 0; 112 info->dflt.interp.virtual_mod= XkbNoModifier; 113 info->dflt.interp.act.type= XkbSA_NoAction; 114 for (i=0;i<XkbAnyActionDataSize;i++) { 115 info->dflt.interp.act.data[i]= 0; 116 } 117 ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt); 118 info->ledDflt.defs.fileID= info->fileID; 119 info->ledDflt.defs.defined= 0; 120 info->ledDflt.defs.merge= MergeOverride; 121 bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo)); 122 info->leds= NULL; 123 InitVModInfo(&info->vmods,xkb); 124 return; 125} 126 127static void 128ClearCompatInfo(CompatInfo *info,XkbDescPtr xkb) 129{ 130register int i; 131 132 if (info->name!=NULL) 133 uFree(info->name); 134 info->name= NULL; 135 info->dflt.defs.defined= 0; 136 info->dflt.defs.merge= MergeAugment; 137 info->dflt.interp.flags= 0; 138 info->dflt.interp.virtual_mod= XkbNoModifier; 139 info->dflt.interp.act.type= XkbSA_NoAction; 140 for (i=0;i<XkbAnyActionDataSize;i++) { 141 info->dflt.interp.act.data[i]= 0; 142 } 143 ClearIndicatorMapInfo(xkb->dpy,&info->ledDflt); 144 info->nInterps= 0; 145 info->interps= (SymInterpInfo *)ClearCommonInfo(&info->interps->defs); 146 bzero((char *)&info->groupCompat[0],XkbNumKbdGroups*sizeof(GroupCompatInfo)); 147 info->leds= (LEDInfo *)ClearCommonInfo(&info->leds->defs); 148 /* 3/30/94 (ef) -- XXX! Should free action info here */ 149 ClearVModInfo(&info->vmods,xkb); 150 return; 151} 152 153static SymInterpInfo * 154NextInterp(CompatInfo *info) 155{ 156SymInterpInfo * si; 157 158 si= uTypedAlloc(SymInterpInfo); 159 if (si) { 160 bzero((char *)si,sizeof(SymInterpInfo)); 161 info->interps= (SymInterpInfo *)AddCommonInfo(&info->interps->defs, 162 (CommonInfo *)si); 163 info->nInterps++; 164 } 165 return si; 166} 167 168static SymInterpInfo * 169FindMatchingInterp(CompatInfo *info,SymInterpInfo *new) 170{ 171SymInterpInfo * old; 172 173 for (old= info->interps;old!=NULL;old=(SymInterpInfo *)old->defs.next) { 174 if ((old->interp.sym==new->interp.sym)&& 175 (old->interp.mods==new->interp.mods)&& 176 (old->interp.match==new->interp.match)) { 177 return old; 178 } 179 } 180 return NULL; 181} 182 183static Bool 184AddInterp(CompatInfo *info,SymInterpInfo *new) 185{ 186unsigned collide; 187SymInterpInfo * old; 188 189 collide= 0; 190 old= FindMatchingInterp(info,new); 191 if (old!=NULL) { 192 if (new->defs.merge==MergeReplace) { 193 SymInterpInfo *next= (SymInterpInfo *)old->defs.next; 194 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 195 (warningLevel>9)) { 196 WARN1("Multiple definitions for \"%s\"\n",siText(new,info)); 197 ACTION("Earlier interpretation ignored\n"); 198 } 199 *old= *new; 200 old->defs.next= &next->defs; 201 return True; 202 } 203 if (UseNewField(_SI_VirtualMod,&old->defs,&new->defs,&collide)) { 204 old->interp.virtual_mod= new->interp.virtual_mod; 205 old->defs.defined|= _SI_VirtualMod; 206 } 207 if (UseNewField(_SI_Action,&old->defs,&new->defs,&collide)) { 208 old->interp.act= new->interp.act; 209 old->defs.defined|= _SI_Action; 210 } 211 if (UseNewField(_SI_AutoRepeat,&old->defs,&new->defs,&collide)) { 212 old->interp.flags&= ~XkbSI_AutoRepeat; 213 old->interp.flags|= (new->interp.flags&XkbSI_AutoRepeat); 214 old->defs.defined|= _SI_AutoRepeat; 215 } 216 if (UseNewField(_SI_LockingKey,&old->defs,&new->defs,&collide)) { 217 old->interp.flags&= ~XkbSI_LockingKey; 218 old->interp.flags|= (new->interp.flags&XkbSI_LockingKey); 219 old->defs.defined|= _SI_LockingKey; 220 } 221 if (UseNewField(_SI_LevelOneOnly,&old->defs,&new->defs,&collide)) { 222 old->interp.match&= ~XkbSI_LevelOneOnly; 223 old->interp.match|= (new->interp.match&XkbSI_LevelOneOnly); 224 old->defs.defined|= _SI_LevelOneOnly; 225 } 226 if (collide) { 227 WARN1("Multiple interpretations of \"%s\"\n",siText(new,info)); 228 ACTION1("Using %s definition for duplicate fields\n", 229 (new->defs.merge!=MergeAugment?"last":"first")); 230 } 231 return True; 232 } 233 old= new; 234 if ((new= NextInterp(info))==NULL) 235 return False; 236 *new= *old; 237 new->defs.next= NULL; 238 return True; 239} 240 241static Bool 242AddGroupCompat(CompatInfo *info,unsigned group,GroupCompatInfo *newGC) 243{ 244GroupCompatInfo * gc; 245unsigned merge; 246 247 merge= newGC->merge; 248 gc= &info->groupCompat[group]; 249 if (((gc->real_mods==newGC->real_mods)&&(gc->vmods==newGC->vmods))) { 250 return True; 251 } 252 if (((gc->fileID==newGC->fileID)&&(warningLevel>0))||(warningLevel>9)) { 253 WARN1("Compat map for group %d redefined\n",group+1); 254 ACTION1("Using %s definition\n",(merge==MergeAugment?"old":"new")); 255 } 256 if (merge!=MergeAugment) 257 *gc= *newGC; 258 return True; 259} 260 261/***====================================================================***/ 262 263static Bool 264ResolveStateAndPredicate( ExprDef * expr, 265 unsigned * pred_rtrn, 266 unsigned * mods_rtrn, 267 CompatInfo * info) 268{ 269ExprResult result; 270 271 if (expr==NULL) { 272 *pred_rtrn= XkbSI_AnyOfOrNone; 273 *mods_rtrn= ~0; 274 return True; 275 } 276 277 *pred_rtrn= XkbSI_Exactly; 278 if (expr->op==ExprActionDecl) { 279 char *pred_txt= XkbAtomText(NULL,expr->value.action.name,XkbMessage); 280 if (uStrCaseCmp(pred_txt,"noneof")==0) 281 *pred_rtrn= XkbSI_NoneOf; 282 else if (uStrCaseCmp(pred_txt,"anyofornone")==0) 283 *pred_rtrn= XkbSI_AnyOfOrNone; 284 else if (uStrCaseCmp(pred_txt,"anyof")==0) 285 *pred_rtrn= XkbSI_AnyOf; 286 else if (uStrCaseCmp(pred_txt,"allof")==0) 287 *pred_rtrn= XkbSI_AllOf; 288 else if (uStrCaseCmp(pred_txt,"exactly")==0) 289 *pred_rtrn= XkbSI_Exactly; 290 else { 291 ERROR1("Illegal modifier predicate \"%s\"\n",pred_txt); 292 ACTION("Ignored\n"); 293 return False; 294 } 295 expr= expr->value.action.args; 296 } 297 else if (expr->op==ExprIdent) { 298 char *pred_txt= XkbAtomText(NULL,expr->value.str,XkbMessage); 299 if ((pred_txt)&&(uStrCaseCmp(pred_txt,"any")==0)) { 300 *pred_rtrn= XkbSI_AnyOf; 301 *mods_rtrn= 0xff; 302 return True; 303 } 304 } 305 306 if (ExprResolveModMask(expr,&result,NULL,NULL)) { 307 *mods_rtrn= result.uval; 308 return True; 309 } 310 return False; 311} 312 313/***====================================================================***/ 314 315static void 316MergeIncludedCompatMaps( CompatInfo * into, 317 CompatInfo * from, 318 unsigned merge) 319{ 320SymInterpInfo * si; 321LEDInfo * led,*rtrn,*next; 322GroupCompatInfo * gcm; 323register int i; 324 325 if (from->errorCount>0) { 326 into->errorCount+= from->errorCount; 327 return; 328 } 329 if (into->name==NULL) { 330 into->name= from->name; 331 from->name= NULL; 332 } 333 for (si=from->interps;si;si=(SymInterpInfo *)si->defs.next) { 334 if (merge!=MergeDefault) 335 si->defs.merge= merge; 336 if (!AddInterp(into,si)) 337 into->errorCount++; 338 } 339 for (i=0,gcm=&from->groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) { 340 if (merge!=MergeDefault) 341 gcm->merge= merge; 342 if (!AddGroupCompat(into,i,gcm)) 343 into->errorCount++; 344 } 345 for (led=from->leds;led!=NULL;led=next) { 346 next= (LEDInfo *)led->defs.next; 347 if (merge!=MergeDefault) 348 led->defs.merge= merge; 349 rtrn= AddIndicatorMap(into->leds,led); 350 if (rtrn!=NULL) 351 into->leds= rtrn; 352 else into->errorCount++; 353 } 354 return; 355} 356 357typedef void (*FileHandler)( 358 XkbFile * /* rtrn */, 359 XkbDescPtr /* xkb */, 360 unsigned /* merge */, 361 CompatInfo * /* info */ 362); 363 364static Bool 365HandleIncludeCompatMap( IncludeStmt * stmt, 366 XkbDescPtr xkb, 367 CompatInfo * info, 368 FileHandler hndlr) 369{ 370unsigned newMerge; 371XkbFile * rtrn; 372CompatInfo included; 373Bool haveSelf; 374 375 haveSelf= False; 376 if ((stmt->file==NULL)&&(stmt->map==NULL)) { 377 haveSelf= True; 378 included= *info; 379 bzero(info,sizeof(CompatInfo)); 380 } 381 else if (ProcessIncludeFile(stmt,XkmCompatMapIndex,&rtrn,&newMerge)) { 382 InitCompatInfo(&included,xkb); 383 included.fileID= rtrn->id; 384 included.dflt= info->dflt; 385 included.dflt.defs.fileID= rtrn->id; 386 included.dflt.defs.merge= newMerge; 387 included.ledDflt.defs.fileID= rtrn->id; 388 included.ledDflt.defs.merge= newMerge; 389 included.act= info->act; 390 (*hndlr)(rtrn,xkb,MergeOverride,&included); 391 if (stmt->stmt!=NULL) { 392 if (included.name!=NULL) 393 uFree(included.name); 394 included.name= stmt->stmt; 395 stmt->stmt= NULL; 396 } 397 } 398 else { 399 info->errorCount+= 10; 400 return False; 401 } 402 if ((stmt->next!=NULL)&&(included.errorCount<1)) { 403 IncludeStmt * next; 404 unsigned op; 405 CompatInfo next_incl; 406 407 for (next=stmt->next;next!=NULL;next=next->next) { 408 if ((next->file==NULL)&&(next->map==NULL)) { 409 haveSelf= True; 410 MergeIncludedCompatMaps(&included,info,next->merge); 411 ClearCompatInfo(info,xkb); 412 } 413 else if (ProcessIncludeFile(next,XkmCompatMapIndex,&rtrn,&op)) { 414 InitCompatInfo(&next_incl,xkb); 415 next_incl.fileID= rtrn->id; 416 next_incl.dflt= info->dflt; 417 next_incl.dflt.defs.fileID= rtrn->id; 418 next_incl.dflt.defs.merge= op; 419 next_incl.ledDflt.defs.fileID= rtrn->id; 420 next_incl.ledDflt.defs.merge= op; 421 next_incl.act= info->act; 422 (*hndlr)(rtrn,xkb,MergeOverride,&next_incl); 423 MergeIncludedCompatMaps(&included,&next_incl,op); 424 ClearCompatInfo(&next_incl,xkb); 425 } 426 else { 427 info->errorCount+= 10; 428 return False; 429 } 430 } 431 } 432 if (haveSelf) 433 *info= included; 434 else { 435 MergeIncludedCompatMaps(info,&included,newMerge); 436 ClearCompatInfo(&included,xkb); 437 } 438 return (info->errorCount==0); 439} 440 441static LookupEntry useModMapValues[] = { 442 { "levelone", 1 }, 443 { "level1", 1 }, 444 { "anylevel", 0 }, 445 { "any", 0 }, 446 { NULL, 0 } 447}; 448 449static int 450SetInterpField( SymInterpInfo * si, 451 XkbDescPtr xkb, 452 char * field, 453 ExprDef * arrayNdx, 454 ExprDef * value, 455 CompatInfo * info) 456{ 457int ok= 1; 458ExprResult tmp; 459 460 if (uStrCaseCmp(field,"action")==0) { 461 if (arrayNdx!=NULL) 462 return ReportSINotArray(si,field,info); 463 ok= HandleActionDef(value,xkb,&si->interp.act,si->defs.merge,info->act); 464 if (ok) 465 si->defs.defined|= _SI_Action; 466 } 467 else if ((uStrCaseCmp(field,"virtualmodifier")==0)|| 468 (uStrCaseCmp(field,"virtualmod")==0)) { 469 if (arrayNdx!=NULL) 470 return ReportSINotArray(si,field,info); 471 ok= ResolveVirtualModifier(value,&tmp,&info->vmods); 472 if (ok) { 473 si->interp.virtual_mod= tmp.uval; 474 si->defs.defined|= _SI_VirtualMod; 475 } 476 else return ReportSIBadType(si,field,"virtual modifier",info); 477 } 478 else if (uStrCaseCmp(field,"repeat")==0) { 479 if (arrayNdx!=NULL) 480 return ReportSINotArray(si,field,info); 481 ok= ExprResolveBoolean(value,&tmp,NULL,NULL); 482 if (ok) { 483 if (tmp.uval) si->interp.flags|= XkbSI_AutoRepeat; 484 else si->interp.flags&= ~XkbSI_AutoRepeat; 485 si->defs.defined|= _SI_AutoRepeat; 486 } 487 else return ReportSIBadType(si,field,"boolean",info); 488 } 489 else if (uStrCaseCmp(field,"locking")==0) { 490 if (arrayNdx!=NULL) 491 return ReportSINotArray(si,field,info); 492 ok= ExprResolveBoolean(value,&tmp,NULL,NULL); 493 if (ok) { 494 if (tmp.uval) si->interp.flags|= XkbSI_LockingKey; 495 else si->interp.flags&= ~XkbSI_LockingKey; 496 si->defs.defined|= _SI_LockingKey; 497 } 498 else return ReportSIBadType(si,field,"boolean",info); 499 } 500 else if ((uStrCaseCmp(field,"usemodmap")==0)|| 501 (uStrCaseCmp(field,"usemodmapmods")==0)) { 502 if (arrayNdx!=NULL) 503 return ReportSINotArray(si,field,info); 504 ok= ExprResolveEnum(value,&tmp,useModMapValues); 505 if (ok) { 506 if (tmp.uval) si->interp.match|= XkbSI_LevelOneOnly; 507 else si->interp.match&= ~XkbSI_LevelOneOnly; 508 si->defs.defined|= _SI_LevelOneOnly; 509 } 510 else return ReportSIBadType(si,field,"level specification",info); 511 } 512 else { 513 ok= ReportBadField("symbol interpretation",field,siText(si,info)); 514 } 515 return ok; 516} 517 518LookupEntry groupNames[]= { 519 { "group1", 0x01 }, 520 { "group2", 0x02 }, 521 { "group3", 0x04 }, 522 { "group4", 0x08 }, 523 { "group5", 0x10 }, 524 { "group6", 0x20 }, 525 { "group7", 0x40 }, 526 { "group8", 0x80 }, 527 { "none", 0x00 }, 528 { "all", 0xff }, 529 { NULL, 0 } 530}; 531 532static int 533HandleInterpVar(VarDef *stmt,XkbDescPtr xkb,CompatInfo *info) 534{ 535ExprResult elem,field; 536ExprDef * ndx; 537 538 if (ExprResolveLhs(stmt->name,&elem,&field,&ndx)==0) 539 return 0; /* internal error, already reported */ 540 if (elem.str&&(uStrCaseCmp(elem.str,"interpret")==0)) 541 return SetInterpField(&info->dflt,xkb,field.str,ndx,stmt->value,info); 542 if (elem.str&&(uStrCaseCmp(elem.str,"indicator")==0)) { 543 return SetIndicatorMapField(&info->ledDflt,xkb,field.str,ndx, 544 stmt->value); 545 } 546 return SetActionField(xkb,elem.str,field.str,ndx,stmt->value,&info->act); 547} 548 549static int 550HandleInterpBody(VarDef *def,XkbDescPtr xkb,SymInterpInfo *si,CompatInfo *info) 551{ 552int ok= 1; 553ExprResult tmp,field; 554ExprDef * arrayNdx; 555 556 for (;def!=NULL;def= (VarDef *)def->common.next) { 557 if ((def->name)&&(def->name->type==ExprFieldRef)) { 558 ok= HandleInterpVar(def,xkb,info); 559 continue; 560 } 561 ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx); 562 if (ok) 563 ok= SetInterpField(si,xkb,field.str,arrayNdx,def->value,info); 564 } 565 return ok; 566} 567 568static int 569HandleInterpDef(InterpDef *def,XkbDescPtr xkb,unsigned merge,CompatInfo *info) 570{ 571unsigned pred,mods; 572SymInterpInfo si; 573 574 if (!ResolveStateAndPredicate(def->match,&pred,&mods,info)) { 575 ERROR("Couldn't determine matching modifiers\n"); 576 ACTION("Symbol interpretation ignored\n"); 577 return False; 578 } 579 if (def->merge!=MergeDefault) 580 merge= def->merge; 581 582 si= info->dflt; 583 si.defs.merge= merge; 584 si.interp.sym= def->sym; 585 si.interp.match= pred & XkbSI_OpMask; 586 si.interp.mods= mods; 587 if (!HandleInterpBody(def->def,xkb,&si,info)) { 588 info->errorCount++; 589 return False; 590 } 591 592 if (!AddInterp(info,&si)) { 593 info->errorCount++; 594 return False; 595 } 596 return True; 597} 598 599static int 600HandleGroupCompatDef( GroupCompatDef * def, 601 XkbDescPtr xkb, 602 unsigned merge, 603 CompatInfo * info) 604{ 605ExprResult val; 606GroupCompatInfo tmp; 607 608 if (def->merge!=MergeDefault) 609 merge= def->merge; 610 if (!XkbIsLegalGroup(def->group-1)) { 611 ERROR1("Keyboard group must be in the range 1..%d\n",XkbNumKbdGroups+1); 612 ACTION1("Compatibility map for illegal group %d ignored\n",def->group); 613 return False; 614 } 615 tmp.fileID= info->fileID; 616 tmp.merge= merge; 617 if (!ExprResolveModMask(def->def,&val,LookupVModMask,(XPointer)xkb)) { 618 ERROR("Expected a modifier mask in group compatibility definition\n"); 619 ACTION1("Ignoring illegal compatibility map for group %d\n",def->group); 620 return False; 621 } 622 tmp.real_mods= val.uval&0xff; 623 tmp.vmods= (val.uval>>8)&0xffff; 624 return AddGroupCompat(info,def->group-1,&tmp); 625} 626 627static void 628HandleCompatMapFile( XkbFile * file, 629 XkbDescPtr xkb, 630 unsigned merge, 631 CompatInfo * info) 632{ 633ParseCommon *stmt; 634 635 if (merge==MergeDefault) 636 merge= MergeAugment; 637 info->name= uStringDup(file->name); 638 stmt= file->defs; 639 while (stmt) { 640 switch (stmt->stmtType) { 641 case StmtInclude: 642 if (!HandleIncludeCompatMap((IncludeStmt *)stmt,xkb,info, 643 HandleCompatMapFile)) 644 info->errorCount++; 645 break; 646 case StmtInterpDef: 647 if (!HandleInterpDef((InterpDef *)stmt,xkb,merge,info)) 648 info->errorCount++; 649 break; 650 case StmtGroupCompatDef: 651 if (!HandleGroupCompatDef((GroupCompatDef*)stmt,xkb,merge,info)) 652 info->errorCount++; 653 break; 654 case StmtIndicatorMapDef: 655 { 656 LEDInfo *rtrn; 657 rtrn= HandleIndicatorMapDef((IndicatorMapDef *)stmt,xkb, 658 &info->ledDflt,info->leds, 659 merge); 660 if (rtrn!=NULL) 661 info->leds= rtrn; 662 else info->errorCount++; 663 } 664 break; 665 case StmtVarDef: 666 if (!HandleInterpVar((VarDef *)stmt,xkb,info)) 667 info->errorCount++; 668 break; 669 case StmtVModDef: 670 if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods)) 671 info->errorCount++; 672 break; 673 case StmtKeycodeDef: 674 ERROR("Interpretation files may not include other types\n"); 675 ACTION("Ignoring definition of key name\n"); 676 info->errorCount++; 677 break; 678 default: 679 WSGO1("Unexpected statement type %d in HandleCompatMapFile\n", 680 stmt->stmtType); 681 break; 682 } 683 stmt= stmt->next; 684 if (info->errorCount>10) { 685#ifdef NOISY 686 ERROR("Too many errors\n"); 687#endif 688 ACTION1("Abandoning compatibility map \"%s\"\n",file->topName); 689 break; 690 } 691 } 692 return; 693} 694 695static void 696CopyInterps( CompatInfo * info, 697 XkbCompatMapPtr compat, 698 Bool needSymbol, 699 unsigned pred) 700{ 701SymInterpInfo * si; 702 703 for (si=info->interps;si;si=(SymInterpInfo *)si->defs.next) { 704 if (((si->interp.match&XkbSI_OpMask)!=pred)|| 705 (needSymbol&&(si->interp.sym==NoSymbol))|| 706 ((!needSymbol)&&(si->interp.sym!=NoSymbol))) 707 continue; 708 if (compat->num_si>=compat->size_si) { 709 WSGO("No room to merge symbol interpretations\n"); 710 ACTION("Symbol interpretations lost\n"); 711 return; 712 } 713 compat->sym_interpret[compat->num_si++]= si->interp; 714 } 715 return; 716} 717 718Bool 719CompileCompatMap( XkbFile * file, 720 XkbFileInfo * result, 721 unsigned merge, 722 LEDInfo ** unboundLEDs) 723{ 724int i; 725CompatInfo info; 726XkbDescPtr xkb; 727GroupCompatInfo * gcm; 728 729 xkb= result->xkb; 730 InitCompatInfo(&info,xkb); 731 info.dflt.defs.merge= merge; 732 info.ledDflt.defs.merge= merge; 733 HandleCompatMapFile(file,xkb,merge,&info); 734 735 if (info.errorCount==0) { 736 int size; 737 if (XkbAllocCompatMap(xkb,XkbAllCompatMask,info.nInterps)!=Success) { 738 WSGO("Couldn't allocate compatibility map\n"); 739 ACTION("Exiting\n"); 740 return False; 741 } 742 if (info.name!=NULL) { 743 if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)==Success) 744 xkb->names->compat= XkbInternAtom(xkb->dpy,info.name,False); 745 else { 746 WSGO("Couldn't allocate space for compat name\n"); 747 ACTION2("Name \"%s\" (from %s) NOT assigned\n",scanFile, 748 info.name); 749 } 750 } 751 size= info.nInterps*sizeof(XkbSymInterpretRec); 752 if (size>0) { 753 CopyInterps(&info,xkb->compat,True,XkbSI_Exactly); 754 CopyInterps(&info,xkb->compat,True,XkbSI_AllOf|XkbSI_NoneOf); 755 CopyInterps(&info,xkb->compat,True,XkbSI_AnyOf); 756 CopyInterps(&info,xkb->compat,True,XkbSI_AnyOfOrNone); 757 CopyInterps(&info,xkb->compat,False,XkbSI_Exactly); 758 CopyInterps(&info,xkb->compat,False,XkbSI_AllOf|XkbSI_NoneOf); 759 CopyInterps(&info,xkb->compat,False,XkbSI_AnyOf); 760 CopyInterps(&info,xkb->compat,False,XkbSI_AnyOfOrNone); 761 } 762 for (i=0,gcm=&info.groupCompat[0];i<XkbNumKbdGroups;i++,gcm++) { 763 if ((gcm->fileID!=0)||(gcm->real_mods!=0)||(gcm->vmods!=0)) { 764 xkb->compat->groups[i].mask= gcm->real_mods; 765 xkb->compat->groups[i].real_mods= gcm->real_mods; 766 xkb->compat->groups[i].vmods= gcm->vmods; 767 } 768 } 769 if (info.leds!=NULL) { 770 if (!CopyIndicatorMapDefs(result,info.leds,unboundLEDs)) 771 info.errorCount++; 772 info.leds= NULL; 773 } 774 ClearCompatInfo(&info,xkb); 775 return True; 776 } 777 if (info.interps!=NULL) 778 uFree(info.interps); 779 return False; 780} 781