symbols.c revision f46a6179
1/* $Xorg: symbols.c,v 1.3 2000/08/17 19:54:33 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/symbols.c,v 3.15 2003/04/19 12:25:31 pascal Exp $ */ 28 29#include "xkbcomp.h" 30#include "tokens.h" 31#include "expr.h" 32 33#include <X11/keysym.h> 34#include <X11/Xutil.h> 35#include <stdlib.h> 36 37#include "expr.h" 38#include "vmod.h" 39#include "action.h" 40#include "keycodes.h" 41#include "misc.h" 42#include "alias.h" 43 44extern Atom tok_ONE_LEVEL; 45extern Atom tok_TWO_LEVEL; 46extern Atom tok_KEYPAD; 47 48/***====================================================================***/ 49 50#define RepeatYes 1 51#define RepeatNo 0 52#define RepeatUndefined ~((unsigned)0) 53 54#define _Key_Syms (1<<0) 55#define _Key_Acts (1<<1) 56#define _Key_Repeat (1<<2) 57#define _Key_Behavior (1<<3) 58#define _Key_Type_Dflt (1<<4) 59#define _Key_Types (1<<5) 60#define _Key_GroupInfo (1<<6) 61#define _Key_VModMap (1<<7) 62 63typedef struct _KeyInfo { 64 CommonInfo defs; 65 unsigned long name; 66 unsigned char groupInfo; 67 unsigned char typesDefined; 68 unsigned char symsDefined; 69 unsigned char actsDefined; 70 short numLevels[XkbNumKbdGroups]; 71 KeySym * syms[XkbNumKbdGroups]; 72 XkbAction * acts[XkbNumKbdGroups]; 73 Atom types[XkbNumKbdGroups]; 74 unsigned repeat; 75 XkbBehavior behavior; 76 unsigned short vmodmap; 77 unsigned long nameForOverlayKey; 78 unsigned long allowNone; 79 Atom dfltType; 80} KeyInfo; 81 82static void 83InitKeyInfo(KeyInfo *info) 84{ 85register int i; 86static char dflt[4]= "*"; 87 88 info->defs.defined= 0; 89 info->defs.fileID= 0; 90 info->defs.merge= MergeOverride; 91 info->defs.next= NULL; 92 info->name= KeyNameToLong(dflt); 93 info->groupInfo= 0; 94 info->typesDefined= info->symsDefined= info->actsDefined= 0; 95 for (i=0;i<XkbNumKbdGroups;i++) { 96 info->numLevels[i]= 0; 97 info->types[i]= None; 98 info->syms[i]= NULL; 99 info->acts[i]= NULL; 100 } 101 info->dfltType= None; 102 info->behavior.type= XkbKB_Default; 103 info->behavior.data= 0; 104 info->vmodmap= 0; 105 info->nameForOverlayKey= 0; 106 info->repeat= RepeatUndefined; 107 info->allowNone= 0; 108 return; 109} 110 111static void 112FreeKeyInfo(KeyInfo *info) 113{ 114register int i; 115 116 info->defs.defined= 0; 117 info->defs.fileID= 0; 118 info->defs.merge= MergeOverride; 119 info->defs.next= NULL; 120 info->groupInfo= 0; 121 info->typesDefined= info->symsDefined= info->actsDefined= 0; 122 for (i=0;i<XkbNumKbdGroups;i++) { 123 info->numLevels[i]= 0; 124 info->types[i]= None; 125 if (info->syms[i]!=NULL) 126 uFree(info->syms[i]); 127 info->syms[i]= NULL; 128 if (info->acts[i]!=NULL) 129 uFree(info->acts[i]); 130 info->acts[i]= NULL; 131 } 132 info->dfltType= None; 133 info->behavior.type= XkbKB_Default; 134 info->behavior.data= 0; 135 info->vmodmap= 0; 136 info->nameForOverlayKey= 0; 137 info->repeat= RepeatUndefined; 138 return; 139} 140 141static Bool 142CopyKeyInfo(KeyInfo *old,KeyInfo *new,Bool clearOld) 143{ 144register int i; 145 146 *new= *old; 147 new->defs.next= NULL; 148 if (clearOld) { 149 for (i=0;i<XkbNumKbdGroups;i++) { 150 old->numLevels[i]= 0; 151 old->syms[i]= NULL; 152 old->acts[i]= NULL; 153 } 154 } 155 else { 156 int width; 157 for (i=0;i<XkbNumKbdGroups;i++) { 158 width= new->numLevels[i]; 159 if (old->syms[i]!=NULL) { 160 new->syms[i]= uTypedCalloc(width,KeySym); 161 if (!new->syms[i]) { 162 new->syms[i]= NULL; 163 new->numLevels[i]= 0; 164 return False; 165 } 166 memcpy((char *)new->syms[i],(char *)old->syms[i], 167 width*sizeof(KeySym)); 168 } 169 if (old->acts[i]!=NULL) { 170 new->acts[i]= uTypedCalloc(width,XkbAction); 171 if (!new->acts[i]) { 172 new->acts[i]= NULL; 173 return False; 174 } 175 memcpy((char *)new->acts[i],(char *)old->acts[i], 176 width*sizeof(XkbAction)); 177 } 178 } 179 } 180 return True; 181} 182 183/***====================================================================***/ 184 185typedef struct _ModMapEntry { 186 CommonInfo defs; 187 Bool haveSymbol; 188 int modifier; 189 union { 190 unsigned long keyName; 191 KeySym keySym; 192 } u; 193} ModMapEntry; 194 195#define SYMBOLS_INIT_SIZE 110 196#define SYMBOLS_CHUNK 20 197typedef struct _SymbolsInfo { 198 char * name; 199 int errorCount; 200 unsigned fileID; 201 unsigned merge; 202 unsigned explicit_group; 203 unsigned groupInfo; 204 unsigned szKeys; 205 unsigned nKeys; 206 KeyInfo * keys; 207 KeyInfo dflt; 208 VModInfo vmods; 209 ActionInfo * action; 210 Atom groupNames[XkbNumKbdGroups]; 211 212 ModMapEntry * modMap; 213 AliasInfo * aliases; 214} SymbolsInfo; 215 216static void 217InitSymbolsInfo(SymbolsInfo *info,XkbDescPtr xkb) 218{ 219register int i; 220 221 tok_ONE_LEVEL= XkbInternAtom(NULL,"ONE_LEVEL",False); 222 tok_TWO_LEVEL= XkbInternAtom(NULL,"TWO_LEVEL",False); 223 tok_KEYPAD= XkbInternAtom(NULL,"KEYPAD",False); 224 info->name= NULL; 225 info->explicit_group= 0; 226 info->errorCount= 0; 227 info->fileID= 0; 228 info->merge= MergeOverride; 229 info->groupInfo= 0; 230 info->szKeys= SYMBOLS_INIT_SIZE; 231 info->nKeys= 0; 232 info->keys= uTypedCalloc(SYMBOLS_INIT_SIZE,KeyInfo); 233 info->modMap= NULL; 234 for (i=0;i<XkbNumKbdGroups;i++) 235 info->groupNames[i]= None; 236 InitKeyInfo(&info->dflt); 237 InitVModInfo(&info->vmods,xkb); 238 info->action= NULL; 239 info->aliases= NULL; 240 return; 241} 242 243static void 244FreeSymbolsInfo(SymbolsInfo *info) 245{ 246register int i; 247 248 if (info->name) 249 uFree(info->name); 250 info->name= NULL; 251 if (info->keys) { 252 for (i=0;i<info->nKeys;i++) { 253 FreeKeyInfo(&info->keys[i]); 254 } 255 uFree(info->keys); 256 info->keys= NULL; 257 } 258 if (info->modMap) { 259 ClearCommonInfo(&info->modMap->defs); 260 info->modMap= NULL; 261 } 262 if (info->aliases) { 263 ClearAliases(&info->aliases); 264 info->aliases= NULL; 265 } 266 bzero((char *)info,sizeof(SymbolsInfo)); 267 return; 268} 269 270static Bool 271ResizeKeyGroup( KeyInfo * key, 272 unsigned group, 273 unsigned atLeastSize, 274 Bool forceActions) 275{ 276Bool tooSmall; 277unsigned newWidth; 278 279 tooSmall= (key->numLevels[group]<atLeastSize); 280 if (tooSmall) newWidth= atLeastSize; 281 else newWidth= key->numLevels[group]; 282 283 if ((key->syms[group]==NULL)||tooSmall) { 284 key->syms[group]= uTypedRecalloc(key->syms[group], 285 key->numLevels[group],newWidth, 286 KeySym); 287 if (!key->syms[group]) 288 return False; 289 } 290 if (((forceActions)&&(tooSmall||(key->acts[group]==NULL)))|| 291 (tooSmall&&(key->acts[group]!=NULL))) { 292 key->acts[group]= uTypedRecalloc(key->acts[group], 293 key->numLevels[group],newWidth, 294 XkbAction); 295 if (!key->acts[group]) 296 return False; 297 } 298 key->numLevels[group]= newWidth; 299 return True; 300} 301 302static Bool 303MergeKeyGroups( SymbolsInfo * info, 304 KeyInfo * into, 305 KeyInfo * from, 306 unsigned group) 307{ 308KeySym * resultSyms; 309XkbAction * resultActs; 310int resultWidth; 311register int i; 312Bool report,clobber; 313 314 clobber= (from->defs.merge!=MergeAugment); 315 report= (warningLevel>9)|| 316 ((into->defs.fileID==from->defs.fileID)&&(warningLevel>0)); 317 if (into->numLevels[group]>=from->numLevels[group]) { 318 resultSyms= into->syms[group]; 319 resultActs= into->acts[group]; 320 resultWidth= into->numLevels[group]; 321 } 322 else { 323 resultSyms= from->syms[group]; 324 resultActs= from->acts[group]; 325 resultWidth= from->numLevels[group]; 326 } 327 if (resultSyms==NULL) { 328 resultSyms= uTypedCalloc(resultWidth,KeySym); 329 if (!resultSyms) { 330 WSGO("Could not allocate symbols for group merge\n"); 331 ACTION2("Group %d of key %s not merged\n",group, 332 longText(into->name,XkbMessage)); 333 return False; 334 } 335 } 336 if ((resultActs==NULL)&&(into->acts[group]||from->acts[group])) { 337 resultActs= uTypedCalloc(resultWidth,XkbAction); 338 if (!resultActs) { 339 WSGO("Could not allocate actions for group merge\n"); 340 ACTION2("Group %d of key %s not merged\n",group, 341 longText(into->name,XkbMessage)); 342 return False; 343 } 344 } 345 for (i=0;i<resultWidth;i++) { 346 KeySym fromSym,toSym; 347 if (from->syms[group] && (i<from->numLevels[group])) 348 fromSym= from->syms[group][i]; 349 else fromSym= NoSymbol; 350 if (into->syms[group] && (i<into->numLevels[group])) 351 toSym= into->syms[group][i]; 352 else toSym= NoSymbol; 353 if ((fromSym==NoSymbol)||(fromSym==toSym)) 354 resultSyms[i]= toSym; 355 else if (toSym==NoSymbol) 356 resultSyms[i]= fromSym; 357 else { 358 KeySym use,ignore; 359 if (clobber) { use= fromSym; ignore= toSym; } 360 else { use= toSym; ignore= fromSym; } 361 if (report) { 362 WARN3("Multiple symbols for level %d/group %d on key %s\n", 363 i+1,group+1,longText(into->name,XkbMessage)); 364 ACTION2("Using %s, ignoring %s\n",XkbKeysymText(use,XkbMessage), 365 XkbKeysymText(ignore,XkbMessage)); 366 } 367 resultSyms[i]= use; 368 } 369 if (resultActs!=NULL) { 370 XkbAction *fromAct,*toAct; 371 fromAct= (from->acts[group]?&from->acts[group][i]:NULL); 372 toAct= (into->acts[group]?&into->acts[group][i]:NULL); 373 if (((fromAct==NULL)||(fromAct->type==XkbSA_NoAction))&& 374 (toAct!=NULL)) { 375 resultActs[i]= *toAct; 376 } 377 else if (((toAct==NULL)||(toAct->type==XkbSA_NoAction))&& 378 (fromAct!=NULL)) { 379 resultActs[i]= *fromAct; 380 } 381 else { 382 XkbAction *use,*ignore; 383 if (clobber) { use= fromAct; ignore= toAct; } 384 else { use= toAct; ignore= fromAct; } 385 if (report) { 386 WARN3("Multiple actions for level %d/group %d on key %s\n", 387 i+1,group+1,longText(into->name,XkbMessage)); 388 ACTION2("Using %s, ignoring %s\n", 389 XkbActionTypeText(use->type,XkbMessage), 390 XkbActionTypeText(ignore->type,XkbMessage)); 391 } 392 resultActs[i]= *use; 393 } 394 } 395 } 396 if ((into->syms[group]!=NULL)&&(resultSyms!=into->syms[group])) 397 uFree(into->syms[group]); 398 if ((from->syms[group]!=NULL)&&(resultSyms!=from->syms[group])) 399 uFree(from->syms[group]); 400 if ((into->acts[group]!=NULL)&&(resultActs!=into->acts[group])) 401 uFree(into->acts[group]); 402 if ((from->acts[group]!=NULL)&&(resultActs!=from->acts[group])) 403 uFree(from->acts[group]); 404 into->numLevels[group]= resultWidth; 405 into->syms[group]= resultSyms; 406 from->syms[group]= NULL; 407 into->acts[group]= resultActs; 408 from->acts[group]= NULL; 409 into->symsDefined|= (1<<group); 410 from->symsDefined&= ~(1<<group); 411 into->actsDefined|= (1<<group); 412 from->actsDefined&= ~(1<<group); 413 return True; 414} 415 416static Bool 417MergeKeys(SymbolsInfo *info,KeyInfo *into,KeyInfo *from) 418{ 419register int i; 420unsigned collide= 0; 421Bool report; 422 423 if (from->defs.merge==MergeReplace) { 424 for (i=0;i<XkbNumKbdGroups;i++) { 425 if (into->numLevels[i]!=0) { 426 if (into->syms[i]) 427 uFree(into->syms[i]); 428 if (into->acts[i]) 429 uFree(into->acts[i]); 430 } 431 } 432 *into= *from; 433 bzero(from,sizeof(KeyInfo)); 434 return True; 435 } 436 report= ((warningLevel>9)|| 437 ((into->defs.fileID==from->defs.fileID)&&(warningLevel>0))); 438 for (i=0;i<XkbNumKbdGroups;i++) { 439 if (from->numLevels[i]>0) { 440 if (into->numLevels[i]==0) { 441 into->numLevels[i]= from->numLevels[i]; 442 into->syms[i]= from->syms[i]; 443 into->acts[i]= from->acts[i]; 444 into->symsDefined|= (1<<i); 445 from->syms[i]= NULL; 446 from->acts[i]= NULL; 447 from->numLevels[i]= 0; 448 from->symsDefined&= ~(1<<i); 449 if (into->syms[i]) into->defs.defined|= _Key_Syms; 450 if (into->acts[i]) into->defs.defined|= _Key_Acts; 451 } 452 else { 453 if (report) { 454 if (into->syms[i]) collide|= _Key_Syms; 455 if (into->acts[i]) collide|= _Key_Acts; 456 } 457 MergeKeyGroups(info,into,from,(unsigned)i); 458 } 459 } 460 if (from->types[i]!=None) { 461 if ((into->types[i]!=None)&&(report)&& 462 (into->types[i]!=from->types[i])) { 463 Atom use,ignore; 464 collide|= _Key_Types; 465 if (from->defs.merge!=MergeAugment) { 466 use= from->types[i]; 467 ignore= into->types[i]; 468 } 469 else { 470 use= into->types[i]; 471 ignore= from->types[i]; 472 } 473 WARN2("Multiple definitions for group %d type of key %s\n", 474 i,longText(into->name,XkbMessage)); 475 ACTION2("Using %s, ignoring %s\n", 476 XkbAtomText(NULL,use,XkbMessage), 477 XkbAtomText(NULL,ignore,XkbMessage)); 478 } 479 if ((from->defs.merge!=MergeAugment)||(into->types[i]==None)) { 480 into->types[i]= from->types[i]; 481 } 482 } 483 } 484 if (UseNewField(_Key_Behavior,&into->defs,&from->defs,&collide)) { 485 into->behavior= from->behavior; 486 into->nameForOverlayKey= from->nameForOverlayKey; 487 into->defs.defined|= _Key_Behavior; 488 } 489 if (UseNewField(_Key_VModMap,&into->defs,&from->defs,&collide)) { 490 into->vmodmap= from->vmodmap; 491 into->defs.defined|= _Key_VModMap; 492 } 493 if (UseNewField(_Key_Repeat,&into->defs,&from->defs,&collide)) { 494 into->repeat= from->repeat; 495 into->defs.defined|= _Key_Repeat; 496 } 497 if (UseNewField(_Key_Type_Dflt,&into->defs,&from->defs,&collide)) { 498 into->dfltType= from->dfltType; 499 into->defs.defined|= _Key_Type_Dflt; 500 } 501 if (UseNewField(_Key_GroupInfo,&into->defs,&from->defs,&collide)) { 502 into->groupInfo= from->groupInfo; 503 into->defs.defined|= _Key_GroupInfo; 504 } 505 if ( collide ) { 506 WARN1("Symbol map for key %s redefined\n", 507 longText(into->name,XkbMessage)); 508 ACTION1("Using %s definition for conflicting fields\n", 509 (from->defs.merge==MergeAugment?"first":"last")); 510 } 511 return True; 512} 513 514static Bool 515AddKeySymbols(SymbolsInfo *info,KeyInfo *key,XkbDescPtr xkb) 516{ 517register int i; 518unsigned long real_name; 519 520 for (i=0;i<info->nKeys;i++) { 521 if (info->keys[i].name==key->name) 522 return MergeKeys(info,&info->keys[i],key); 523 } 524 if(FindKeyNameForAlias(xkb, key->name, &real_name)) { 525 for (i=0;i<info->nKeys;i++) { 526 if (info->keys[i].name==real_name) 527 return MergeKeys(info,&info->keys[i],key); 528 } 529 } 530 if (info->nKeys>=info->szKeys) { 531 info->szKeys+= SYMBOLS_CHUNK; 532 info->keys= uTypedRecalloc(info->keys,info->nKeys,info->szKeys,KeyInfo); 533 if (!info->keys) { 534 WSGO("Could not allocate key symbols descriptions\n"); 535 ACTION("Some key symbols definitions may be lost\n"); 536 return False; 537 } 538 } 539 return CopyKeyInfo(key,&info->keys[info->nKeys++],True); 540} 541 542static Bool 543AddModMapEntry(SymbolsInfo *info,ModMapEntry *new) 544{ 545ModMapEntry * mm; 546Bool clobber; 547 548 clobber= (new->defs.merge!=MergeAugment); 549 for (mm=info->modMap;mm!=NULL;mm= (ModMapEntry *)mm->defs.next) { 550 if (new->haveSymbol&&mm->haveSymbol&&(new->u.keySym==mm->u.keySym)) { 551 unsigned use,ignore; 552 if (mm->modifier!=new->modifier) { 553 if (clobber) { 554 use= new->modifier; 555 ignore= mm->modifier; 556 } 557 else { 558 use= mm->modifier; 559 ignore= new->modifier; 560 } 561 ERROR1("%s added to symbol map for multiple modifiers\n", 562 XkbKeysymText(new->u.keySym,XkbMessage)); 563 ACTION2("Using %s, ignoring %s.\n", 564 XkbModIndexText(use,XkbMessage), 565 XkbModIndexText(ignore,XkbMessage)); 566 mm->modifier= use; 567 } 568 return True; 569 } 570 if ((!new->haveSymbol)&&(!mm->haveSymbol)&& 571 (new->u.keyName==mm->u.keyName)) { 572 unsigned use,ignore; 573 if (mm->modifier!=new->modifier) { 574 if (clobber) { 575 use= new->modifier; 576 ignore= mm->modifier; 577 } 578 else { 579 use= mm->modifier; 580 ignore= new->modifier; 581 } 582 ERROR1("Key %s added to map for multiple modifiers\n", 583 longText(new->u.keyName,XkbMessage)); 584 ACTION2("Using %s, ignoring %s.\n", 585 XkbModIndexText(use,XkbMessage), 586 XkbModIndexText(ignore,XkbMessage)); 587 mm->modifier= use; 588 } 589 return True; 590 } 591 } 592 mm= uTypedAlloc(ModMapEntry); 593 if (mm==NULL) { 594 WSGO("Could not allocate modifier map entry\n"); 595 ACTION1("Modifier map for %s will be incomplete\n", 596 XkbModIndexText(new->modifier,XkbMessage)); 597 return False; 598 } 599 *mm= *new; 600 mm->defs.next= &info->modMap->defs; 601 info->modMap= mm; 602 return True; 603} 604 605/***====================================================================***/ 606 607static void 608MergeIncludedSymbols(SymbolsInfo *into,SymbolsInfo *from, 609 unsigned merge,XkbDescPtr xkb) 610{ 611register int i; 612KeyInfo * key; 613 614 if (from->errorCount>0) { 615 into->errorCount+= from->errorCount; 616 return; 617 } 618 if (into->name==NULL) { 619 into->name= from->name; 620 from->name= NULL; 621 } 622 for (i=0;i<XkbNumKbdGroups;i++) { 623 if (from->groupNames[i]!=None) { 624 if ((merge!=MergeAugment)||(into->groupNames[i]==None)) 625 into->groupNames[i]= from->groupNames[i]; 626 } 627 } 628 for (i=0,key=from->keys;i<from->nKeys;i++,key++) { 629 if (merge!=MergeDefault) 630 key->defs.merge= merge; 631 if (!AddKeySymbols(into,key,xkb)) 632 into->errorCount++; 633 } 634 if (from->modMap!=NULL) { 635 ModMapEntry *mm,*next; 636 for (mm=from->modMap;mm!=NULL;mm=next) { 637 if (merge!=MergeDefault) 638 mm->defs.merge= merge; 639 if (!AddModMapEntry(into,mm)) 640 into->errorCount++; 641 next= (ModMapEntry *)mm->defs.next; 642 uFree(mm); 643 } 644 from->modMap= NULL; 645 } 646 if (!MergeAliases(&into->aliases,&from->aliases,merge)) 647 into->errorCount++; 648 return; 649} 650 651typedef void (*FileHandler)( 652 XkbFile * /* rtrn */, 653 XkbDescPtr /* xkb */, 654 unsigned /* merge */, 655 SymbolsInfo * /* included */ 656); 657 658static Bool 659HandleIncludeSymbols( IncludeStmt * stmt, 660 XkbDescPtr xkb, 661 SymbolsInfo * info, 662 FileHandler hndlr) 663{ 664unsigned newMerge; 665XkbFile * rtrn; 666SymbolsInfo included; 667Bool haveSelf; 668 669 haveSelf= False; 670 if ((stmt->file==NULL)&&(stmt->map==NULL)) { 671 haveSelf= True; 672 included= *info; 673 bzero(info,sizeof(SymbolsInfo)); 674 } 675 else if (ProcessIncludeFile(stmt,XkmSymbolsIndex,&rtrn,&newMerge)) { 676 InitSymbolsInfo(&included,xkb); 677 included.fileID= included.dflt.defs.fileID= rtrn->id; 678 included.merge= included.dflt.defs.merge= MergeOverride; 679 if (stmt->modifier) { 680 included.explicit_group= atoi(stmt->modifier) - 1; 681 } else { 682 included.explicit_group= info->explicit_group; 683 } 684 (*hndlr)(rtrn,xkb,MergeOverride,&included); 685 if (stmt->stmt!=NULL) { 686 if (included.name!=NULL) 687 uFree(included.name); 688 included.name= stmt->stmt; 689 stmt->stmt= NULL; 690 } 691 } 692 else { 693 info->errorCount+= 10; 694 return False; 695 } 696 if ((stmt->next!=NULL)&&(included.errorCount<1)) { 697 IncludeStmt * next; 698 unsigned op; 699 SymbolsInfo next_incl; 700 701 for (next=stmt->next;next!=NULL;next=next->next) { 702 if ((next->file==NULL)&&(next->map==NULL)) { 703 haveSelf= True; 704 MergeIncludedSymbols(&included,info,next->merge,xkb); 705 FreeSymbolsInfo(info); 706 } 707 else if (ProcessIncludeFile(next,XkmSymbolsIndex,&rtrn,&op)) { 708 InitSymbolsInfo(&next_incl,xkb); 709 next_incl.fileID= next_incl.dflt.defs.fileID= rtrn->id; 710 next_incl.merge= next_incl.dflt.defs.merge= MergeOverride; 711 if (next->modifier) { 712 next_incl.explicit_group= atoi(next->modifier) - 1; 713 } else { 714 next_incl.explicit_group= info->explicit_group; 715 } 716 (*hndlr)(rtrn,xkb,MergeOverride,&next_incl); 717 MergeIncludedSymbols(&included,&next_incl,op,xkb); 718 FreeSymbolsInfo(&next_incl); 719 } 720 else { 721 info->errorCount+= 10; 722 return False; 723 } 724 } 725 } 726 if (haveSelf) 727 *info= included; 728 else { 729 MergeIncludedSymbols(info,&included,newMerge,xkb); 730 FreeSymbolsInfo(&included); 731 } 732 return (info->errorCount==0); 733} 734 735static LookupEntry groupNames[]= { 736 { "group1", 1 }, 737 { "group2", 2 }, 738 { "group3", 3 }, 739 { "group4", 4 }, 740 { "group5", 5 }, 741 { "group6", 6 }, 742 { "group7", 7 }, 743 { "group8", 8 }, 744 { NULL, 0 } 745}; 746 747 748#define SYMBOLS 1 749#define ACTIONS 2 750 751static Bool 752GetGroupIndex( KeyInfo * key, 753 ExprDef * arrayNdx, 754 unsigned what, 755 unsigned * ndx_rtrn) 756{ 757const char *name; 758ExprResult tmp; 759 760 if (what==SYMBOLS) name= "symbols"; 761 else name= "actions"; 762 763 if (arrayNdx==NULL) { 764 register int i; 765 unsigned defined; 766 if (what==SYMBOLS) defined= key->symsDefined; 767 else defined= key->actsDefined; 768 769 for (i=0;i<XkbNumKbdGroups;i++) { 770 if ((defined&(1<<i))==0) { 771 *ndx_rtrn= i; 772 return True; 773 } 774 } 775 ERROR3("Too many groups of %s for key %s (max %d)\n",name, 776 longText(key->name,XkbMessage), 777 XkbNumKbdGroups+1); 778 ACTION1("Ignoring %s defined for extra groups\n",name); 779 return False; 780 } 781 if (!ExprResolveInteger(arrayNdx,&tmp,SimpleLookup,(XPointer)groupNames)) { 782 ERROR2("Illegal group index for %s of key %s\n",name, 783 longText(key->name,XkbMessage)); 784 ACTION("Definition with non-integer array index ignored\n"); 785 return False; 786 } 787 if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) { 788 ERROR3("Group index for %s of key %s is out of range (1..%d)\n",name, 789 longText(key->name,XkbMessage), 790 XkbNumKbdGroups+1); 791 ACTION2("Ignoring %s for group %d\n",name,tmp.uval); 792 return False; 793 } 794 *ndx_rtrn= tmp.uval-1; 795 return True; 796} 797 798static Bool 799AddSymbolsToKey( KeyInfo * key, 800 XkbDescPtr xkb, 801 char * field, 802 ExprDef * arrayNdx, 803 ExprDef * value, 804 SymbolsInfo * info) 805{ 806unsigned ndx,nSyms; 807int i; 808 809 if (!GetGroupIndex(key,arrayNdx,SYMBOLS,&ndx)) 810 return False; 811 if (value==NULL) { 812 key->symsDefined|= (1<<ndx); 813 return True; 814 } 815 if (value->op!=ExprKeysymList) { 816 ERROR1("Expected a list of symbols, found %s\n",exprOpText(value->op)); 817 ACTION2("Ignoring symbols for group %d of %s\n",ndx, 818 longText(key->name,XkbMessage)); 819 return False; 820 } 821 if (key->syms[ndx]!=NULL) { 822 WSGO2("Symbols for key %s, group %d already defined\n", 823 longText(key->name,XkbMessage), 824 ndx); 825 return False; 826 } 827 nSyms= value->value.list.nSyms; 828 if (((key->numLevels[ndx]<nSyms)||(key->syms[ndx]==NULL))&& 829 (!ResizeKeyGroup(key,ndx,nSyms,False))) { 830 WSGO2("Could not resize group %d of key %s\n",ndx, 831 longText(key->name,XkbMessage)); 832 ACTION("Symbols lost\n"); 833 return False; 834 } 835 key->symsDefined|= (1<<ndx); 836 memcpy((char *)key->syms[ndx],(char *)value->value.list.syms, 837 nSyms*sizeof(KeySym)); 838 for (i=key->numLevels[ndx]-1;(i>=0)&&(key->syms[ndx][i]==NoSymbol);i--) { 839 key->numLevels[ndx]--; 840 } 841 return True; 842} 843 844static Bool 845AddActionsToKey( KeyInfo * key, 846 XkbDescPtr xkb, 847 char * field, 848 ExprDef * arrayNdx, 849 ExprDef * value, 850 SymbolsInfo * info) 851{ 852register int i; 853unsigned ndx,nActs; 854ExprDef * act; 855XkbAnyAction * toAct; 856 857 if (!GetGroupIndex(key,arrayNdx,ACTIONS,&ndx)) 858 return False; 859 860 if (value==NULL) { 861 key->actsDefined|= (1<<ndx); 862 return True; 863 } 864 if (value->op!=ExprActionList) { 865 WSGO1("Bad expression type (%d) for action list value\n",value->op); 866 ACTION2("Ignoring actions for group %d of %s\n",ndx, 867 longText(key->name,XkbMessage)); 868 return False; 869 } 870 if (key->acts[ndx]!=NULL) { 871 WSGO2("Actions for key %s, group %d already defined\n", 872 longText(key->name,XkbMessage), 873 ndx); 874 return False; 875 } 876 for (nActs=0,act= value->value.child;act!=NULL;nActs++) { 877 act= (ExprDef *)act->common.next; 878 } 879 if (nActs<1) { 880 WSGO("Action list but not actions in AddActionsToKey\n"); 881 return False; 882 } 883 if (((key->numLevels[ndx]<nActs)||(key->acts[ndx]==NULL))&& 884 (!ResizeKeyGroup(key,ndx,nActs,True))) { 885 WSGO2("Could not resize group %d of key %s\n",ndx, 886 longText(key->name,XkbMessage)); 887 ACTION("Actions lost\n"); 888 return False; 889 } 890 key->actsDefined|= (1<<ndx); 891 892 toAct= (XkbAnyAction *)key->acts[ndx]; 893 act= value->value.child; 894 for (i=0;i<nActs;i++,toAct++) { 895 if (!HandleActionDef(act,xkb,toAct,MergeOverride,info->action)) { 896 ERROR1("Illegal action definition for %s\n", 897 longText(key->name,XkbMessage)); 898 ACTION2("Action for group %d/level %d ignored\n",ndx+1,i+1); 899 } 900 act= (ExprDef *)act->common.next; 901 } 902 return True; 903} 904 905static int 906SetAllowNone(KeyInfo *key,ExprDef *arrayNdx,ExprDef *value) 907{ 908ExprResult tmp; 909unsigned radio_groups= 0; 910 911 if (arrayNdx==NULL) { 912 radio_groups= XkbAllRadioGroupsMask; 913 } 914 else { 915 if (!ExprResolveInteger(arrayNdx,&tmp,RadioLookup,NULL)){ 916 ERROR("Illegal index in group name definition\n"); 917 ACTION("Definition with non-integer array index ignored\n"); 918 return False; 919 } 920 if ((tmp.uval<1)||(tmp.uval>XkbMaxRadioGroups)) { 921 ERROR1("Illegal radio group specified (must be 1..%d)\n", 922 XkbMaxRadioGroups+1); 923 ACTION1("Value of \"allow none\" for group %d ignored\n",tmp.uval); 924 return False; 925 } 926 radio_groups|= (1<<(tmp.uval-1)); 927 } 928 if (!ExprResolveBoolean(value,&tmp,NULL,NULL)) { 929 ERROR1("Illegal \"allow none\" value for %s\n", 930 longText(key->name,XkbMessage)); 931 ACTION("Non-boolean value ignored\n"); 932 return False; 933 } 934 if (tmp.uval) key->allowNone|= radio_groups; 935 else key->allowNone&= ~radio_groups; 936 return True; 937} 938 939 940static LookupEntry lockingEntries[] = { 941 { "true", XkbKB_Lock }, 942 { "yes", XkbKB_Lock }, 943 { "on", XkbKB_Lock }, 944 { "false", XkbKB_Default }, 945 { "no", XkbKB_Default }, 946 { "off", XkbKB_Default }, 947 { "permanent", XkbKB_Lock|XkbKB_Permanent }, 948 { NULL, 0 } 949}; 950 951static LookupEntry repeatEntries[]= { 952 { "true", RepeatYes }, 953 { "yes", RepeatYes }, 954 { "on", RepeatYes }, 955 { "false", RepeatNo }, 956 { "no", RepeatNo }, 957 { "off", RepeatNo }, 958 { "default", RepeatUndefined }, 959 { NULL, 0 } 960}; 961 962static LookupEntry rgEntries[]= { 963 { "none", 0 }, 964 { NULL, 0 } 965}; 966 967static Bool 968SetSymbolsField( KeyInfo * key, 969 XkbDescPtr xkb, 970 char * field, 971 ExprDef * arrayNdx, 972 ExprDef * value, 973 SymbolsInfo * info) 974{ 975Bool ok= True; 976ExprResult tmp; 977 978 if (uStrCaseCmp(field,"type")==0) { 979 ExprResult ndx; 980 if ((!ExprResolveString(value,&tmp,NULL,NULL))&&(warningLevel>0)) { 981 WARN("The type field of a key symbol map must be a string\n"); 982 ACTION("Ignoring illegal type definition\n"); 983 } 984 if (arrayNdx==NULL) { 985 key->dfltType= XkbInternAtom(NULL,tmp.str,False); 986 key->defs.defined|= _Key_Type_Dflt; 987 } 988 else if (!ExprResolveInteger(arrayNdx,&ndx,SimpleLookup, 989 (XPointer)groupNames)) { 990 ERROR1("Illegal group index for type of key %s\n", 991 longText(key->name,XkbMessage)); 992 ACTION("Definition with non-integer array index ignored\n"); 993 return False; 994 } 995 else if ((ndx.uval<1)||(ndx.uval>XkbNumKbdGroups)) { 996 ERROR2("Group index for type of key %s is out of range (1..%d)\n", 997 longText(key->name,XkbMessage), 998 XkbNumKbdGroups+1); 999 ACTION1("Ignoring type for group %d\n",ndx.uval); 1000 return False; 1001 } 1002 else { 1003 key->types[ndx.uval-1]= XkbInternAtom(NULL,tmp.str,False); 1004 key->typesDefined|= (1<<(ndx.uval-1)); 1005 } 1006 } 1007 else if (uStrCaseCmp(field,"symbols")==0) 1008 return AddSymbolsToKey(key,xkb,field,arrayNdx,value,info); 1009 else if (uStrCaseCmp(field,"actions")==0) 1010 return AddActionsToKey(key,xkb,field,arrayNdx,value,info); 1011 else if ((uStrCaseCmp(field,"vmods")==0)|| 1012 (uStrCaseCmp(field,"virtualmods")==0)|| 1013 (uStrCaseCmp(field,"virtualmodifiers")==0)) { 1014 ok= ExprResolveModMask(value,&tmp,LookupVModMask,(XPointer)xkb); 1015 if (ok) { 1016 key->vmodmap= (tmp.uval>>8); 1017 key->defs.defined|= _Key_VModMap; 1018 } 1019 else { 1020 ERROR1("Expected a virtual modifier mask, found %s\n", 1021 exprOpText(value->op)); 1022 ACTION1("Ignoring virtual modifiers definition for key %s\n", 1023 longText(key->name,XkbMessage)); 1024 } 1025 } 1026 else if ((uStrCaseCmp(field,"locking")==0)||(uStrCaseCmp(field,"lock")==0)|| 1027 (uStrCaseCmp(field,"locks")==0)) { 1028 ok= ExprResolveEnum(value,&tmp,lockingEntries); 1029 if (ok) 1030 key->behavior.type= tmp.uval; 1031 key->defs.defined|= _Key_Behavior; 1032 } 1033 else if ((uStrCaseCmp(field,"radiogroup")==0)|| 1034 (uStrCaseCmp(field,"permanentradiogroup")==0)) { 1035 Bool permanent= False; 1036 if (uStrCaseCmp(field,"permanentradiogroup")==0) 1037 permanent= True; 1038 ok= ExprResolveInteger(value,&tmp,SimpleLookup,(XPointer)rgEntries); 1039 if (!ok) { 1040 ERROR1("Illegal radio group specification for %s\n", 1041 longText(key->name,XkbMessage)); 1042 ACTION("Non-integer radio group ignored\n"); 1043 return False; 1044 } 1045 if (tmp.uval==0) { 1046 key->behavior.type= XkbKB_Default; 1047 key->behavior.data= 0; 1048 return ok; 1049 } 1050 if ((tmp.uval<1)||(tmp.uval>XkbMaxRadioGroups)) { 1051 ERROR1("Radio group specification for %s out of range (1..32)\n", 1052 longText(key->name,XkbMessage)); 1053 ACTION1("Illegal radio group %d ignored\n",tmp.uval); 1054 return False; 1055 } 1056 key->behavior.type= XkbKB_RadioGroup|(permanent?XkbKB_Permanent:0); 1057 key->behavior.data= tmp.uval-1; 1058 if (key->allowNone&(1<<(tmp.uval-1))) 1059 key->behavior.data|= XkbKB_RGAllowNone; 1060 key->defs.defined|= _Key_Behavior; 1061 } 1062 else if (uStrCaseEqual(field,"allownone")) { 1063 ok= SetAllowNone(key,arrayNdx,value); 1064 } 1065 else if (uStrCasePrefix("overlay",field)|| 1066 uStrCasePrefix("permanentoverlay",field)) { 1067 Bool permanent= False; 1068 char *which; 1069 int overlayNdx; 1070 if (uStrCasePrefix("permanent",field)) { 1071 permanent= True; 1072 which= &field[sizeof("permanentoverlay")-1]; 1073 } 1074 else { 1075 which= &field[sizeof("overlay")-1]; 1076 } 1077 if (sscanf(which,"%d",&overlayNdx)==1) { 1078 if (((overlayNdx<1)||(overlayNdx>2))&&(warningLevel>0)) { 1079 ERROR2("Illegal overlay %d specified for %s\n", 1080 overlayNdx, 1081 longText(key->name,XkbMessage)); 1082 ACTION("Ignored\n"); 1083 return False; 1084 } 1085 } 1086 else if (*which=='\0') 1087 overlayNdx=1; 1088 else if (warningLevel>0) { 1089 ERROR2("Illegal overlay \"%s\" specified for %s\n", 1090 which, 1091 longText(key->name,XkbMessage)); 1092 ACTION("Ignored\n"); 1093 return False; 1094 } 1095 ok= ExprResolveKeyName(value,&tmp,NULL,NULL); 1096 if (!ok) { 1097 ERROR1("Illegal overlay key specification for %s\n", 1098 longText(key->name,XkbMessage)); 1099 ACTION("Overlay key must be specified by name\n"); 1100 return False; 1101 } 1102 if (overlayNdx==1) key->behavior.type= XkbKB_Overlay1; 1103 else key->behavior.type= XkbKB_Overlay2; 1104 if (permanent) 1105 key->behavior.type|= XkbKB_Permanent; 1106 1107 key->behavior.data= 0; 1108 key->nameForOverlayKey= KeyNameToLong(tmp.keyName.name); 1109 key->defs.defined|= _Key_Behavior; 1110 } 1111 else if ((uStrCaseCmp(field,"repeating")==0)|| 1112 (uStrCaseCmp(field,"repeats")==0)|| 1113 (uStrCaseCmp(field,"repeat")==0)){ 1114 ok= ExprResolveEnum(value,&tmp,repeatEntries); 1115 if (!ok) { 1116 ERROR1("Illegal repeat setting for %s\n", 1117 longText(key->name,XkbMessage)); 1118 ACTION("Non-boolean repeat setting ignored\n"); 1119 return False; 1120 } 1121 key->repeat= tmp.uval; 1122 key->defs.defined|= _Key_Repeat; 1123 } 1124 else if ((uStrCaseCmp(field,"groupswrap")==0)|| 1125 (uStrCaseCmp(field,"wrapgroups")==0)) { 1126 ok= ExprResolveBoolean(value,&tmp,NULL,NULL); 1127 if (!ok) { 1128 ERROR1("Illegal groupsWrap setting for %s\n", 1129 longText(key->name,XkbMessage)); 1130 ACTION("Non-boolean value ignored\n"); 1131 return False; 1132 } 1133 if (tmp.uval) key->groupInfo= XkbWrapIntoRange; 1134 else key->groupInfo= XkbClampIntoRange; 1135 key->defs.defined|= _Key_GroupInfo; 1136 } 1137 else if ((uStrCaseCmp(field,"groupsclamp")==0)|| 1138 (uStrCaseCmp(field,"clampgroups")==0)) { 1139 ok= ExprResolveBoolean(value,&tmp,NULL,NULL); 1140 if (!ok) { 1141 ERROR1("Illegal groupsClamp setting for %s\n", 1142 longText(key->name,XkbMessage)); 1143 ACTION("Non-boolean value ignored\n"); 1144 return False; 1145 } 1146 if (tmp.uval) key->groupInfo= XkbClampIntoRange; 1147 else key->groupInfo= XkbWrapIntoRange; 1148 key->defs.defined|= _Key_GroupInfo; 1149 } 1150 else if ((uStrCaseCmp(field,"groupsredirect")==0)|| 1151 (uStrCaseCmp(field,"redirectgroups")==0)) { 1152 if (!ExprResolveInteger(value,&tmp,SimpleLookup,(XPointer)groupNames)) { 1153 ERROR1("Illegal group index for redirect of key %s\n", 1154 longText(key->name,XkbMessage)); 1155 ACTION("Definition with non-integer group ignored\n"); 1156 return False; 1157 } 1158 if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) { 1159 ERROR2("Out-of-range (1..%d) group for redirect of key %s\n", 1160 XkbNumKbdGroups, 1161 longText(key->name,XkbMessage)); 1162 ERROR1("Ignoring illegal group %d\n",tmp.uval); 1163 return False; 1164 } 1165 key->groupInfo= XkbSetGroupInfo(0,XkbRedirectIntoRange,tmp.uval-1); 1166 key->defs.defined|= _Key_GroupInfo; 1167 } 1168 else { 1169 ERROR1("Unknown field %s in a symbol interpretation\n",field); 1170 ACTION("Definition ignored\n"); 1171 ok= False; 1172 } 1173 return ok; 1174} 1175 1176static int 1177SetGroupName(SymbolsInfo *info,ExprDef *arrayNdx,ExprDef *value) 1178{ 1179ExprResult tmp,name; 1180 1181 if ((arrayNdx==NULL)&&(warningLevel>0)) { 1182 WARN("You must specify an index when specifying a group name\n"); 1183 ACTION("Group name definition without array subscript ignored\n"); 1184 return False; 1185 } 1186 if (!ExprResolveInteger(arrayNdx,&tmp,SimpleLookup,(XPointer)groupNames)) { 1187 ERROR("Illegal index in group name definition\n"); 1188 ACTION("Definition with non-integer array index ignored\n"); 1189 return False; 1190 } 1191 if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) { 1192 ERROR1("Attempt to specify name for illegal group (must be 1..%d)\n", 1193 XkbNumKbdGroups+1); 1194 ACTION1("Name for group %d ignored\n",tmp.uval); 1195 return False; 1196 } 1197 if (!ExprResolveString(value,&name,NULL,NULL)) { 1198 ERROR("Group name must be a string\n"); 1199 ACTION1("Illegal name for group %d ignored\n",tmp.uval); 1200 return False; 1201 } 1202 info->groupNames[tmp.uval-1+info->explicit_group]= 1203 XkbInternAtom(NULL,name.str,False); 1204 1205 return True; 1206} 1207 1208static int 1209HandleSymbolsVar(VarDef *stmt,XkbDescPtr xkb,SymbolsInfo *info) 1210{ 1211ExprResult elem,field,tmp; 1212ExprDef * arrayNdx; 1213 1214 if (ExprResolveLhs(stmt->name,&elem,&field,&arrayNdx)==0) 1215 return 0; /* internal error, already reported */ 1216 if (elem.str&&(uStrCaseCmp(elem.str,"key")==0)) { 1217 return SetSymbolsField(&info->dflt,xkb,field.str,arrayNdx,stmt->value, 1218 info); 1219 } 1220 else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"name")==0)|| 1221 (uStrCaseCmp(field.str,"groupname")==0))) { 1222 return SetGroupName(info,arrayNdx,stmt->value); 1223 } 1224 else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"groupswrap")==0)|| 1225 (uStrCaseCmp(field.str,"wrapgroups")==0))) { 1226 if (!ExprResolveBoolean(stmt->value,&tmp,NULL,NULL)) { 1227 ERROR("Illegal setting for global groupsWrap\n"); 1228 ACTION("Non-boolean value ignored\n"); 1229 return False; 1230 } 1231 if (tmp.uval) info->groupInfo= XkbWrapIntoRange; 1232 else info->groupInfo= XkbClampIntoRange; 1233 return True; 1234 } 1235 else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"groupsclamp")==0)|| 1236 (uStrCaseCmp(field.str,"clampgroups")==0))) { 1237 if (!ExprResolveBoolean(stmt->value,&tmp,NULL,NULL)) { 1238 ERROR("Illegal setting for global groupsClamp\n"); 1239 ACTION("Non-boolean value ignored\n"); 1240 return False; 1241 } 1242 if (tmp.uval) info->groupInfo= XkbClampIntoRange; 1243 else info->groupInfo= XkbWrapIntoRange; 1244 return True; 1245 } 1246 else if ((elem.str==NULL)&&((uStrCaseCmp(field.str,"groupsredirect")==0)|| 1247 (uStrCaseCmp(field.str,"redirectgroups")==0))) { 1248 if (!ExprResolveInteger(stmt->value,&tmp, 1249 SimpleLookup,(XPointer)groupNames)) { 1250 ERROR("Illegal group index for global groupsRedirect\n"); 1251 ACTION("Definition with non-integer group ignored\n"); 1252 return False; 1253 } 1254 if ((tmp.uval<1)||(tmp.uval>XkbNumKbdGroups)) { 1255 ERROR1("Out-of-range (1..%d) group for global groupsRedirect\n", 1256 XkbNumKbdGroups); 1257 ACTION1("Ignoring illegal group %d\n",tmp.uval); 1258 return False; 1259 } 1260 info->groupInfo= XkbSetGroupInfo(0,XkbRedirectIntoRange,tmp.uval); 1261 return True; 1262 } 1263 else if ((elem.str==NULL)&&(uStrCaseCmp(field.str,"allownone")==0)) { 1264 return SetAllowNone(&info->dflt,arrayNdx,stmt->value); 1265 } 1266 return SetActionField(xkb,elem.str,field.str,arrayNdx,stmt->value, 1267 &info->action); 1268} 1269 1270static Bool 1271HandleSymbolsBody( VarDef * def, 1272 XkbDescPtr xkb, 1273 KeyInfo * key, 1274 SymbolsInfo * info) 1275{ 1276Bool ok= True; 1277ExprResult tmp,field; 1278ExprDef * arrayNdx; 1279 1280 for (;def!=NULL;def= (VarDef *)def->common.next) { 1281 if ((def->name)&&(def->name->type==ExprFieldRef)) { 1282 ok= HandleSymbolsVar(def,xkb,info); 1283 continue; 1284 } 1285 else { 1286 if (def->name==NULL) { 1287 if ((def->value==NULL)||(def->value->op==ExprKeysymList)) 1288 field.str= "symbols"; 1289 else field.str= "actions"; 1290 arrayNdx= NULL; 1291 } 1292 else { 1293 ok= ExprResolveLhs(def->name,&tmp,&field,&arrayNdx); 1294 } 1295 if (ok) 1296 ok= SetSymbolsField(key,xkb,field.str,arrayNdx,def->value,info); 1297 } 1298 } 1299 return ok; 1300} 1301 1302static Bool 1303SetExplicitGroup( SymbolsInfo * info, 1304 KeyInfo * key) 1305{ 1306 unsigned group = info->explicit_group; 1307 1308 if (group == 0) 1309 return True; 1310 1311 if ((key->typesDefined|key->symsDefined|key->actsDefined) & ~1) { 1312 int i; 1313 WARN1("For the map %s an explicit group specified\n", info->name); 1314 WARN1("but key %s has more than one group defined\n", 1315 longText(key->name,XkbMessage)); 1316 ACTION("All groups except first one will be ignored\n"); 1317 for (i = 1; i < XkbNumKbdGroups ; i++) { 1318 key->numLevels[i]= 0; 1319 if (key->syms[i]!=NULL) 1320 uFree(key->syms[i]); 1321 key->syms[i]= (KeySym*) NULL; 1322 if (key->acts[i]!=NULL) 1323 uFree(key->acts[i]); 1324 key->acts[i]= (XkbAction*) NULL; 1325 key->types[i]= (Atom) 0; 1326 } 1327 } 1328 key->typesDefined = key->symsDefined = key->actsDefined = 1 << group; 1329 1330 key->numLevels[group]= key->numLevels[0]; 1331 key->numLevels[0]= 0; 1332 key->syms[group]= key->syms[0]; 1333 key->syms[0]= (KeySym*) NULL; 1334 key->acts[group]= key->acts[0]; 1335 key->acts[0]= (XkbAction*) NULL; 1336 key->types[group]= key->types[0]; 1337 key->types[0]= (Atom) 0; 1338 return True; 1339} 1340 1341static int 1342HandleSymbolsDef( SymbolsDef * stmt, 1343 XkbDescPtr xkb, 1344 unsigned merge, 1345 SymbolsInfo * info) 1346{ 1347KeyInfo key; 1348 1349 InitKeyInfo(&key); 1350 CopyKeyInfo(&info->dflt,&key,False); 1351 key.defs.merge= stmt->merge; 1352 key.name= KeyNameToLong(stmt->keyName); 1353 if (!HandleSymbolsBody((VarDef *)stmt->symbols,xkb,&key,info)) { 1354 info->errorCount++; 1355 return False; 1356 } 1357 1358 if (!SetExplicitGroup(info,&key)) { 1359 info->errorCount++; 1360 return False; 1361 } 1362 1363 if (!AddKeySymbols(info,&key,xkb)) { 1364 info->errorCount++; 1365 return False; 1366 } 1367 return True; 1368} 1369 1370static Bool 1371HandleModMapDef( ModMapDef * def, 1372 XkbDescPtr xkb, 1373 unsigned merge, 1374 SymbolsInfo * info) 1375{ 1376ExprDef * key; 1377ModMapEntry tmp; 1378ExprResult rtrn; 1379Bool ok; 1380 1381 if (!LookupModIndex(NULL,None,def->modifier,TypeInt,&rtrn)) { 1382 ERROR("Illegal modifier map definition\n"); 1383 ACTION1("Ignoring map for non-modifier \"%s\"\n", 1384 XkbAtomText(NULL,def->modifier,XkbMessage)); 1385 return False; 1386 } 1387 ok= True; 1388 tmp.modifier= rtrn.uval; 1389 for (key=def->keys;key!=NULL;key=(ExprDef *)key->common.next) { 1390 if ((key->op==ExprValue)&&(key->type==TypeKeyName)) { 1391 tmp.haveSymbol= False; 1392 tmp.u.keyName= KeyNameToLong(key->value.keyName); 1393 } 1394 else if (ExprResolveKeySym(key,&rtrn,NULL,NULL)) { 1395 tmp.haveSymbol= True; 1396 tmp.u.keySym= rtrn.uval; 1397 } 1398 else { 1399 ERROR("Modmap entries may contain only key names or keysyms\n"); 1400 ACTION1("Illegal definition for %s modifier ignored\n", 1401 XkbModIndexText(tmp.modifier,XkbMessage)); 1402 continue; 1403 } 1404 1405 ok= AddModMapEntry(info,&tmp)&&ok; 1406 } 1407 return ok; 1408} 1409 1410static void 1411HandleSymbolsFile( XkbFile * file, 1412 XkbDescPtr xkb, 1413 unsigned merge, 1414 SymbolsInfo * info) 1415{ 1416ParseCommon *stmt; 1417 1418 info->name= uStringDup(file->name); 1419 stmt= file->defs; 1420 while (stmt) { 1421 switch (stmt->stmtType) { 1422 case StmtInclude: 1423 if (!HandleIncludeSymbols((IncludeStmt *)stmt,xkb,info, 1424 HandleSymbolsFile)) 1425 info->errorCount++; 1426 break; 1427 case StmtSymbolsDef: 1428 if (!HandleSymbolsDef((SymbolsDef *)stmt,xkb,merge,info)) 1429 info->errorCount++; 1430 break; 1431 case StmtVarDef: 1432 if (!HandleSymbolsVar((VarDef *)stmt,xkb,info)) 1433 info->errorCount++; 1434 break; 1435 case StmtVModDef: 1436 if (!HandleVModDef((VModDef *)stmt,merge,&info->vmods)) 1437 info->errorCount++; 1438 break; 1439 case StmtInterpDef: 1440 ERROR("Interpretation files may not include other types\n"); 1441 ACTION("Ignoring definition of symbol interpretation\n"); 1442 info->errorCount++; 1443 break; 1444 case StmtKeycodeDef: 1445 ERROR("Interpretation files may not include other types\n"); 1446 ACTION("Ignoring definition of key name\n"); 1447 info->errorCount++; 1448 break; 1449 case StmtModMapDef: 1450 if (!HandleModMapDef((ModMapDef *)stmt,xkb,merge,info)) 1451 info->errorCount++; 1452 break; 1453 default: 1454 WSGO1("Unexpected statement type %d in HandleSymbolsFile\n", 1455 stmt->stmtType); 1456 break; 1457 } 1458 stmt= stmt->next; 1459 if (info->errorCount>10) { 1460#ifdef NOISY 1461 ERROR("Too many errors\n"); 1462#endif 1463 ACTION1("Abandoning symbols file \"%s\"\n",file->topName); 1464 break; 1465 } 1466 } 1467 return; 1468} 1469 1470static Bool 1471FindKeyForSymbol(XkbDescPtr xkb,KeySym sym,unsigned int *kc_rtrn) 1472{ 1473register int i, j; 1474register Bool gotOne; 1475 1476 j= 0; 1477 do { 1478 gotOne= False; 1479 for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) { 1480 if ( j<(int)XkbKeyNumSyms(xkb,i) ) { 1481 gotOne = True; 1482 if ((XkbKeySym(xkb,i,j)==sym)) { 1483 *kc_rtrn= i; 1484 return True; 1485 } 1486 } 1487 } 1488 j++; 1489 } while (gotOne); 1490 return False; 1491} 1492 1493static Bool 1494FindNamedType(XkbDescPtr xkb,Atom name,unsigned *type_rtrn) 1495{ 1496register unsigned n; 1497 1498 if (xkb&&xkb->map&&xkb->map->types) { 1499 for (n=0;n<xkb->map->num_types;n++) { 1500 if (xkb->map->types[n].name==(Atom)name) { 1501 *type_rtrn= n; 1502 return True; 1503 } 1504 } 1505 } 1506 return False; 1507} 1508 1509static Bool 1510KSIsLower (KeySym ks) 1511{ 1512 KeySym lower, upper; 1513 XConvertCase(ks, &lower, &upper); 1514 1515 if (lower == upper) 1516 return False; 1517 return (ks == lower ? True : False); 1518} 1519 1520static Bool 1521KSIsUpper (KeySym ks) 1522{ 1523 KeySym lower, upper; 1524 XConvertCase(ks, &lower, &upper); 1525 1526 if (lower == upper) 1527 return False; 1528 return (ks == upper ? True : False); 1529} 1530 1531static Bool 1532FindAutomaticType(int width,KeySym *syms,Atom *typeNameRtrn, Bool *autoType) 1533{ 1534 *autoType = False; 1535 if ((width==1)||(width==0)) { 1536 *typeNameRtrn= XkbInternAtom(NULL,"ONE_LEVEL",False); 1537 *autoType = True; 1538 } else if (width == 2) { 1539 if ( syms && KSIsLower(syms[0]) && KSIsUpper(syms[1]) ) { 1540 *typeNameRtrn= XkbInternAtom(NULL,"ALPHABETIC",False); 1541 } else if ( syms && 1542 (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])) ) { 1543 *typeNameRtrn= XkbInternAtom(NULL,"KEYPAD",False); 1544 *autoType = True; 1545 } else { 1546 *typeNameRtrn= XkbInternAtom(NULL,"TWO_LEVEL",False); 1547 *autoType = True; 1548 } 1549 } else if (width <= 4 ) { 1550 if ( syms && KSIsLower(syms[0]) && KSIsUpper(syms[1]) ) 1551 if ( KSIsLower(syms[2]) && KSIsUpper(syms[3]) ) 1552 *typeNameRtrn= XkbInternAtom(NULL, 1553 "FOUR_LEVEL_ALPHABETIC",False); 1554 else 1555 *typeNameRtrn= XkbInternAtom(NULL, 1556 "FOUR_LEVEL_SEMIALPHABETIC",False); 1557 1558 else if ( syms && (XkbKSIsKeypad(syms[0]) || XkbKSIsKeypad(syms[1])) ) 1559 *typeNameRtrn= XkbInternAtom(NULL, 1560 "FOUR_LEVEL_KEYPAD",False); 1561 else *typeNameRtrn= XkbInternAtom(NULL,"FOUR_LEVEL",False); 1562 } 1563 return ((width>=0)&&(width<=4)); 1564} 1565 1566static void 1567PrepareKeyDef(KeyInfo *key) 1568{ 1569 int i, j, width, defined, lastGroup; 1570 Bool identical; 1571 1572 defined = key->symsDefined | key->actsDefined | key->typesDefined; 1573 for (i = XkbNumKbdGroups - 1; i >= 0; i--) { 1574 if (defined & (1<<i)) 1575 break; 1576 } 1577 lastGroup = i; 1578 1579 if (lastGroup == 0) 1580 return; 1581 1582 /* If there are empty groups between non-empty ones fill them with data */ 1583 /* from the first group. */ 1584 /* We can make a wrong assumption here. But leaving gaps is worse. */ 1585 for (i = lastGroup; i > 0; i--) { 1586 if (defined & (1<<i)) 1587 continue; 1588 width = key->numLevels[0]; 1589 if (key->typesDefined & 1) { 1590 for (j = 0; j < width; j++) { 1591 key->types[i] = key->types[0]; 1592 } 1593 key->typesDefined |= 1 << i; 1594 } 1595 if ((key->actsDefined & 1) && key->acts[0]) { 1596 key->acts[i]= uTypedCalloc(width, XkbAction); 1597 if (key->acts[i] == NULL) 1598 continue; 1599 memcpy((void *) key->acts[i], (void *) key->acts[0], 1600 width * sizeof(XkbAction)); 1601 key->actsDefined |= 1 << i; 1602 } 1603 if ((key->symsDefined & 1) && key->syms[0]) { 1604 key->syms[i]= uTypedCalloc(width, KeySym); 1605 if (key->syms[i] == NULL) 1606 continue; 1607 memcpy((void *) key->syms[i], (void *) key->syms[0], 1608 width * sizeof(KeySym)); 1609 key->symsDefined |= 1 << i; 1610 } 1611 if (defined & 1) { 1612 key->numLevels[i] = key->numLevels[0]; 1613 } 1614 } 1615 /* If all groups are completely identical remove them all */ 1616 /* exept the first one. */ 1617 identical = True; 1618 for (i = lastGroup; i > 0; i--) { 1619 if ((key->numLevels[i] != key->numLevels[0]) || 1620 (key->types[i] != key->types[0])) { 1621 identical = False; 1622 break; 1623 } 1624 if ((key->syms[i] != key->syms[0]) && 1625 (key->syms[i] == NULL || key->syms[0] == NULL || 1626 memcmp((void*) key->syms[i], (void*) key->syms[0], 1627 sizeof(KeySym) * key->numLevels[0])) ) { 1628 identical = False; 1629 break; 1630 } 1631 if ((key->acts[i] != key->acts[0]) && 1632 (key->acts[i] == NULL || key->acts[0] == NULL || 1633 memcmp((void*) key->acts[i], (void*) key->acts[0], 1634 sizeof(XkbAction) * key->numLevels[0]))) { 1635 identical = False; 1636 break; 1637 } 1638 } 1639 if (identical) { 1640 for (i = lastGroup; i > 0; i--) { 1641 key->numLevels[i]= 0; 1642 if (key->syms[i] != NULL) 1643 uFree(key->syms[i]); 1644 key->syms[i]= (KeySym*) NULL; 1645 if (key->acts[i] != NULL) 1646 uFree(key->acts[i]); 1647 key->acts[i]= (XkbAction*) NULL; 1648 key->types[i]= (Atom) 0; 1649 } 1650 key->symsDefined &= 1; 1651 key->actsDefined &= 1; 1652 key->typesDefined &= 1; 1653 } 1654 return; 1655} 1656 1657static Bool 1658CopySymbolsDef(XkbFileInfo *result,KeyInfo *key,int start_from) 1659{ 1660register int i; 1661unsigned okc,kc,width,tmp,nGroups; 1662XkbKeyTypePtr type; 1663Bool haveActions,autoType,useAlias; 1664KeySym * outSyms; 1665XkbAction * outActs; 1666XkbDescPtr xkb; 1667unsigned types[XkbNumKbdGroups]; 1668 1669 xkb= result->xkb; 1670 useAlias= (start_from==0); 1671 if (!FindNamedKey(xkb,key->name,&kc,useAlias,CreateKeyNames(xkb), 1672 start_from)) { 1673 if ((start_from==0)&&(warningLevel>=5)) { 1674 WARN2("Key %s not found in %s keycodes\n", 1675 longText(key->name,XkbMessage), 1676 XkbAtomText(NULL,xkb->names->keycodes,XkbMessage)); 1677 ACTION("Symbols ignored\n"); 1678 } 1679 return False; 1680 } 1681 1682 haveActions= False; 1683 for (i=width=nGroups=0;i<XkbNumKbdGroups;i++) { 1684 if (((i+1)>nGroups)&&(((key->symsDefined|key->actsDefined)&(1<<i))|| 1685 (key->typesDefined)&(1<<i))) 1686 nGroups= i+1; 1687 if (key->acts[i]) 1688 haveActions= True; 1689 autoType= False; 1690 if (key->types[i]==None) { 1691 if (key->dfltType!=None) 1692 key->types[i]= key->dfltType; 1693 else if (FindAutomaticType(key->numLevels[i],key->syms[i], 1694 &key->types[i], &autoType)) { 1695 } 1696 else { 1697 if (warningLevel>=5) { 1698 WARN1("No automatic type for %d symbols\n", 1699 (unsigned int)key->numLevels[i]); 1700 ACTION3("Using %s for the %s key (keycode %d)\n", 1701 XkbAtomText(NULL,key->types[i],XkbMessage), 1702 longText(key->name,XkbMessage),kc); 1703 } 1704 } 1705 } 1706 if (FindNamedType(xkb,key->types[i],&types[i])) { 1707 if (!autoType || key->numLevels[i] > 2) 1708 xkb->server->explicit[kc]|= (1<<i); 1709 } 1710 else { 1711 if (warningLevel>=3) { 1712 WARN1("Type \"%s\" is not defined\n", 1713 XkbAtomText(NULL,key->types[i],XkbMessage)); 1714 ACTION2("Using TWO_LEVEL for the %s key (keycode %d)\n", 1715 longText(key->name,XkbMessage),kc); 1716 } 1717 types[i]= XkbTwoLevelIndex; 1718 } 1719 type= &xkb->map->types[types[i]]; 1720 if (type->num_levels<key->numLevels[i]) { 1721 if (warningLevel>0) { 1722 WARN4("Type \"%s\" has %d levels, but %s has %d symbols\n", 1723 XkbAtomText(NULL,type->name,XkbMessage), 1724 (unsigned int)type->num_levels, 1725 longText(key->name,XkbMessage), 1726 (unsigned int)key->numLevels[i]); 1727 ACTION("Ignoring extra symbols\n"); 1728 } 1729 key->numLevels[i]= type->num_levels; 1730 } 1731 if (key->numLevels[i]>width) 1732 width= key->numLevels[i]; 1733 if (type->num_levels>width) 1734 width= type->num_levels; 1735 } 1736 1737 i= width*nGroups; 1738 outSyms= XkbResizeKeySyms(xkb,kc,i); 1739 if (outSyms==NULL) { 1740 WSGO2("Could not enlarge symbols for %s (keycode %d)\n", 1741 longText(key->name,XkbMessage),kc); 1742 return False; 1743 } 1744 if (haveActions) { 1745 outActs= XkbResizeKeyActions(xkb,kc,i); 1746 if (outActs==NULL) { 1747 WSGO2("Could not enlarge actions for %s (key %d)\n", 1748 longText(key->name,XkbMessage),kc); 1749 return False; 1750 } 1751 xkb->server->explicit[kc]|= XkbExplicitInterpretMask; 1752 } 1753 else outActs= NULL; 1754 if (key->defs.defined&_Key_GroupInfo) 1755 i= key->groupInfo; 1756 else i= xkb->map->key_sym_map[kc].group_info; 1757 xkb->map->key_sym_map[kc].group_info= XkbSetNumGroups(i,nGroups); 1758 xkb->map->key_sym_map[kc].width= width; 1759 for (i=0;i<nGroups;i++) { 1760 xkb->map->key_sym_map[kc].kt_index[i]= types[i]; 1761 if (key->syms[i]!=NULL) { 1762 for (tmp=0;tmp<width;tmp++) { 1763 if (tmp<key->numLevels[i]) 1764 outSyms[tmp]= key->syms[i][tmp]; 1765 else outSyms[tmp]= NoSymbol; 1766 if ((outActs!=NULL)&&(key->acts[i]!=NULL)) { 1767 if (tmp<key->numLevels[i]) 1768 outActs[tmp]= key->acts[i][tmp]; 1769 else outActs[tmp].type= XkbSA_NoAction; 1770 } 1771 } 1772 } 1773 outSyms+= width; 1774 if (outActs) 1775 outActs+= width; 1776 } 1777 switch (key->behavior.type&XkbKB_OpMask) { 1778 case XkbKB_Default: 1779 break; 1780 case XkbKB_Overlay1: 1781 case XkbKB_Overlay2: 1782 /* find key by name! */ 1783 if (!FindNamedKey(xkb,key->nameForOverlayKey,&okc,True, 1784 CreateKeyNames(xkb),0)) { 1785 if (warningLevel>=1) { 1786 WARN2("Key %s not found in %s keycodes\n", 1787 longText(key->nameForOverlayKey,XkbMessage), 1788 XkbAtomText(NULL,xkb->names->keycodes,XkbMessage)); 1789 ACTION1("Not treating %s as an overlay key \n", 1790 longText(key->name,XkbMessage)); 1791 } 1792 break; 1793 } 1794 key->behavior.data= okc; 1795 default: 1796 xkb->server->behaviors[kc]= key->behavior; 1797 xkb->server->explicit[kc]|= XkbExplicitBehaviorMask; 1798 break; 1799 } 1800 if (key->defs.defined&_Key_VModMap) { 1801 xkb->server->vmodmap[kc]= key->vmodmap; 1802 xkb->server->explicit[kc]|= XkbExplicitVModMapMask; 1803 } 1804 if (key->repeat!=RepeatUndefined) { 1805 if (key->repeat==RepeatYes) 1806 xkb->ctrls->per_key_repeat[kc/8]|= (1<<(kc%8)); 1807 else xkb->ctrls->per_key_repeat[kc/8]&= ~(1<<(kc%8)); 1808 xkb->server->explicit[kc]|= XkbExplicitAutoRepeatMask; 1809 } 1810 CopySymbolsDef(result,key,kc+1); 1811 return True; 1812} 1813 1814static Bool 1815CopyModMapDef(XkbFileInfo *result,ModMapEntry *entry) 1816{ 1817unsigned kc; 1818XkbDescPtr xkb; 1819 1820 xkb= result->xkb; 1821 if ((!entry->haveSymbol)&&(!FindNamedKey(xkb,entry->u.keyName,&kc,True, 1822 CreateKeyNames(xkb),0))) { 1823 if (warningLevel>=5) { 1824 WARN2("Key %s not found in %s keycodes\n", 1825 longText(entry->u.keyName,XkbMessage), 1826 XkbAtomText(NULL,xkb->names->keycodes,XkbMessage)); 1827 ACTION1("Modifier map entry for %s not updated\n", 1828 XkbModIndexText(entry->modifier,XkbMessage)); 1829 } 1830 return False; 1831 } 1832 else if (entry->haveSymbol&&(!FindKeyForSymbol(xkb,entry->u.keySym,&kc))) { 1833 if (warningLevel>5) { 1834 WARN2("Key \"%s\" not found in %s symbol map\n", 1835 XkbKeysymText(entry->u.keySym,XkbMessage), 1836 XkbAtomText(NULL,xkb->names->symbols,XkbMessage)); 1837 ACTION1("Modifier map entry for %s not updated\n", 1838 XkbModIndexText(entry->modifier,XkbMessage)); 1839 } 1840 return False; 1841 } 1842 xkb->map->modmap[kc]|= (1<<entry->modifier); 1843 return True; 1844} 1845 1846Bool 1847CompileSymbols(XkbFile *file,XkbFileInfo *result,unsigned merge) 1848{ 1849register int i; 1850SymbolsInfo info; 1851XkbDescPtr xkb; 1852 1853 xkb= result->xkb; 1854 InitSymbolsInfo(&info,xkb); 1855 info.dflt.defs.fileID= file->id; 1856 info.dflt.defs.merge= merge; 1857 HandleSymbolsFile(file,xkb,merge,&info); 1858 1859 if (info.nKeys == 0) 1860 return True; 1861 if (info.errorCount==0) { 1862 KeyInfo *key; 1863 if (XkbAllocNames(xkb,XkbSymbolsNameMask|XkbGroupNamesMask,0,0) 1864 !=Success) { 1865 WSGO("Can not allocate names in CompileSymbols\n"); 1866 ACTION("Symbols not added\n"); 1867 return False; 1868 } 1869 if(XkbAllocClientMap(xkb,XkbKeySymsMask|XkbModifierMapMask,0)!=Success){ 1870 WSGO("Could not allocate client map in CompileSymbols\n"); 1871 ACTION("Symbols not added\n"); 1872 return False; 1873 } 1874 if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,32)!=Success) { 1875 WSGO("Could not allocate server map in CompileSymbols\n"); 1876 ACTION("Symbols not added\n"); 1877 return False; 1878 } 1879 if (XkbAllocControls(xkb,XkbPerKeyRepeatMask)!=Success) { 1880 WSGO("Could not allocate controls in CompileSymbols\n"); 1881 ACTION("Symbols not added\n"); 1882 return False; 1883 } 1884 xkb->names->symbols= XkbInternAtom(xkb->dpy,info.name,False); 1885 if (info.aliases) 1886 ApplyAliases(xkb,False,&info.aliases); 1887 for (i=0;i<XkbNumKbdGroups;i++) { 1888 if (info.groupNames[i]!=None) 1889 xkb->names->groups[i]= info.groupNames[i]; 1890 } 1891 for (key=info.keys,i=0;i<info.nKeys;i++,key++) { 1892 PrepareKeyDef(key); 1893 } 1894 for (key=info.keys,i=0;i<info.nKeys;i++,key++) { 1895 if (!CopySymbolsDef(result,key,0)) 1896 info.errorCount++; 1897 } 1898 if (warningLevel>3) { 1899 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 1900 if (xkb->names->keys[i].name[0]=='\0') 1901 continue; 1902 if (XkbKeyNumGroups(xkb,i)<1) { 1903 char buf[5]; 1904 memcpy(buf,xkb->names->keys[i].name,4); 1905 buf[4]= '\0'; 1906 WARN2("No symbols defined for <%s> (keycode %d)\n",buf,i); 1907 } 1908 } 1909 } 1910 if (info.modMap) { 1911 ModMapEntry *mm,*next; 1912 for (mm=info.modMap;mm!=NULL;mm=next) { 1913 if (!CopyModMapDef(result,mm)) 1914 info.errorCount++; 1915 next= (ModMapEntry *)mm->defs.next; 1916 } 1917 } 1918 return True; 1919 } 1920 return False; 1921} 1922