xkmread.c revision 4642e01f
1/************************************************************ 2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 4 Permission to use, copy, modify, and distribute this 5 software and its documentation for any purpose and without 6 fee is hereby granted, provided that the above copyright 7 notice appear in all copies and that both that copyright 8 notice and this permission notice appear in supporting 9 documentation, and that the name of Silicon Graphics not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific prior written permission. 12 Silicon Graphics makes no representation about the suitability 13 of this software for any purpose. It is provided "as is" 14 without any express or implied warranty. 15 16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25 ********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <stdio.h> 32 33#include <X11/Xos.h> 34#include <X11/Xfuncs.h> 35 36#include <X11/X.h> 37#define NEED_EVENTS 38#include <X11/Xproto.h> 39#include <X11/keysym.h> 40#include "misc.h" 41#include "inputstr.h" 42#include "xkbstr.h" 43#include "xkbsrv.h" 44#include "xkbgeom.h" 45 46Atom 47XkbInternAtom(char *str,Bool only_if_exists) 48{ 49 if (str==NULL) 50 return None; 51 return MakeAtom(str,strlen(str),!only_if_exists); 52} 53 54char * 55_XkbDupString(char *str) 56{ 57char *new; 58 59 if (str==NULL) 60 return NULL; 61 new= (char *)_XkbCalloc(strlen(str)+1,sizeof(char)); 62 if (new) 63 strcpy(new,str); 64 return new; 65} 66 67/***====================================================================***/ 68 69static void * 70XkmInsureSize(void *oldPtr,int oldCount,int *newCountRtrn,int elemSize) 71{ 72int newCount= *newCountRtrn; 73 74 if (oldPtr==NULL) { 75 if (newCount==0) 76 return NULL; 77 oldPtr= _XkbCalloc(newCount,elemSize); 78 } 79 else if (oldCount<newCount) { 80 oldPtr= _XkbRealloc(oldPtr,newCount*elemSize); 81 if (oldPtr!=NULL) { 82 char *tmp= (char *)oldPtr; 83 bzero(&tmp[oldCount*elemSize],(newCount-oldCount)*elemSize); 84 } 85 } 86 else if (newCount<oldCount) { 87 *newCountRtrn= oldCount; 88 } 89 return oldPtr; 90} 91 92#define XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t)))) 93 94static CARD8 95XkmGetCARD8(FILE *file,int *pNRead) 96{ 97int tmp; 98 tmp= getc(file); 99 if (pNRead&&(tmp!=EOF)) 100 (*pNRead)+= 1; 101 return tmp; 102} 103 104static CARD16 105XkmGetCARD16(FILE *file,int *pNRead) 106{ 107CARD16 val; 108 109 if ((fread(&val,2,1,file)==1)&&(pNRead)) 110 (*pNRead)+= 2; 111 return val; 112} 113 114static CARD32 115XkmGetCARD32(FILE *file,int *pNRead) 116{ 117CARD32 val; 118 119 if ((fread(&val,4,1,file)==1)&&(pNRead)) 120 (*pNRead)+= 4; 121 return val; 122} 123 124static int 125XkmSkipPadding(FILE *file,unsigned pad) 126{ 127register int i,nRead=0; 128 129 for (i=0;i<pad;i++) { 130 if (getc(file)!=EOF) 131 nRead++; 132 } 133 return nRead; 134} 135 136static int 137XkmGetCountedString(FILE *file,char *str,int max_len) 138{ 139int count,nRead=0; 140 141 count= XkmGetCARD16(file,&nRead); 142 if (count>0) { 143 int tmp; 144 if (count>max_len) { 145 tmp= fread(str,1,max_len,file); 146 while (tmp<count) { 147 if ((getc(file))!=EOF) 148 tmp++; 149 else break; 150 } 151 } 152 else { 153 tmp= fread(str,1,count,file); 154 } 155 nRead+= tmp; 156 } 157 if (count>=max_len) str[max_len-1]= '\0'; 158 else str[count]= '\0'; 159 count= XkbPaddedSize(nRead)-nRead; 160 if (count>0) 161 nRead+= XkmSkipPadding(file,count); 162 return nRead; 163} 164 165/***====================================================================***/ 166 167static int 168ReadXkmVirtualMods(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) 169{ 170register unsigned int i,bit; 171unsigned int bound,named,tmp; 172int nRead=0; 173 174 if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) { 175 _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); 176 return -1; 177 } 178 bound= XkmGetCARD16(file,&nRead); 179 named= XkmGetCARD16(file,&nRead); 180 for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 181 if (bound&bit) { 182 xkb->server->vmods[i]= XkmGetCARD8(file,&nRead); 183 if (changes) 184 changes->map.vmods|= bit; 185 tmp++; 186 } 187 } 188 if ((i= XkbPaddedSize(tmp)-tmp)>0) 189 nRead+= XkmSkipPadding(file,i); 190 if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) { 191 _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); 192 return -1; 193 } 194 for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 195 char name[100]; 196 if (named&bit) { 197 if (nRead+=XkmGetCountedString(file,name,100)) { 198 xkb->names->vmods[i]= XkbInternAtom(name,False); 199 if (changes) 200 changes->names.changed_vmods|= bit; 201 } 202 } 203 } 204 return nRead; 205} 206 207/***====================================================================***/ 208 209static int 210ReadXkmKeycodes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) 211{ 212register int i; 213unsigned minKC,maxKC,nAl; 214int nRead=0; 215char name[100]; 216XkbKeyNamePtr pN; 217 218 name[0]= '\0'; 219 nRead+= XkmGetCountedString(file,name,100); 220 minKC= XkmGetCARD8(file,&nRead); 221 maxKC= XkmGetCARD8(file,&nRead); 222 if (xkb->min_key_code==0) { 223 xkb->min_key_code= minKC; 224 xkb->max_key_code= maxKC; 225 } 226 else { 227 if (minKC<xkb->min_key_code) 228 xkb->min_key_code= minKC; 229 if (maxKC>xkb->max_key_code) { 230 _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC); 231 return -1; 232 } 233 } 234 nAl= XkmGetCARD8(file,&nRead); 235 nRead+= XkmSkipPadding(file,1); 236 237#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask) 238 if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) { 239 _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); 240 return -1; 241 } 242 if (name[0]!='\0') { 243 xkb->names->keycodes= XkbInternAtom(name,False); 244 } 245 246 for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) { 247 if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) { 248 _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); 249 return -1; 250 } 251 nRead+= XkbKeyNameLength; 252 } 253 if (nAl>0) { 254 XkbKeyAliasPtr pAl; 255 for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) { 256 int tmp; 257 tmp= fread(pAl,1,2*XkbKeyNameLength,file); 258 if (tmp!=2*XkbKeyNameLength) { 259 _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); 260 return -1; 261 } 262 nRead+= 2*XkbKeyNameLength; 263 } 264 if (changes) 265 changes->names.changed|= XkbKeyAliasesMask; 266 } 267 if (changes) 268 changes->names.changed|= XkbKeyNamesMask; 269 return nRead; 270} 271 272/***====================================================================***/ 273 274static int 275ReadXkmKeyTypes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) 276{ 277register unsigned i,n; 278unsigned num_types; 279int nRead=0; 280int tmp; 281XkbKeyTypePtr type; 282xkmKeyTypeDesc wire; 283XkbKTMapEntryPtr entry; 284xkmKTMapEntryDesc wire_entry; 285char buf[100]; 286 287 if ((tmp= XkmGetCountedString(file,buf,100))<1) { 288 _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); 289 return -1; 290 } 291 nRead+= tmp; 292 if (buf[0]!='\0') { 293 if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) { 294 _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); 295 return -1; 296 } 297 xkb->names->types= XkbInternAtom(buf,False); 298 } 299 num_types= XkmGetCARD16(file,&nRead); 300 nRead+= XkmSkipPadding(file,2); 301 if (num_types<1) 302 return nRead; 303 if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) { 304 _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); 305 return nRead; 306 } 307 xkb->map->num_types= num_types; 308 if (num_types<XkbNumRequiredTypes) { 309 _XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0); 310 return -1; 311 } 312 type= xkb->map->types; 313 for (i=0;i<num_types;i++,type++) { 314 if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) { 315 _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); 316 return -1; 317 } 318 nRead+= SIZEOF(xkmKeyTypeDesc); 319 if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))|| 320 (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)|| 321 ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) { 322 _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i); 323 return -1; 324 } 325 tmp= wire.nMapEntries; 326 XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec); 327 if ((wire.nMapEntries>0)&&(type->map==NULL)) { 328 _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries); 329 return -1; 330 } 331 for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) { 332 if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) { 333 _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); 334 return -1; 335 } 336 nRead+= SIZEOF(xkmKTMapEntryDesc); 337 entry->active= (wire_entry.virtualMods==0); 338 entry->level= wire_entry.level; 339 entry->mods.mask= wire_entry.realMods; 340 entry->mods.real_mods= wire_entry.realMods; 341 entry->mods.vmods= wire_entry.virtualMods; 342 } 343 nRead+= XkmGetCountedString(file,buf,100); 344 if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))|| 345 ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))|| 346 ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))|| 347 ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) { 348 _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0); 349 return -1; 350 } 351 if (buf[0]!='\0') { 352 type->name= XkbInternAtom(buf,False); 353 } 354 else type->name= None; 355 356 if (wire.preserve) { 357 xkmModsDesc p_entry; 358 XkbModsPtr pre; 359 XkmInsureTypedSize(type->preserve,type->map_count,&tmp, 360 XkbModsRec); 361 if (type->preserve==NULL) { 362 _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); 363 return -1; 364 } 365 for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) { 366 if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) { 367 _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); 368 return -1; 369 } 370 nRead+= SIZEOF(xkmModsDesc); 371 pre->mask= p_entry.realMods; 372 pre->real_mods= p_entry.realMods; 373 pre->vmods= p_entry.virtualMods; 374 } 375 } 376 if (wire.nLevelNames>0) { 377 int width= wire.numLevels; 378 if (wire.nLevelNames>(unsigned)width) { 379 _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); 380 return -1; 381 } 382 XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom); 383 if (type->level_names!=NULL) { 384 for (n=0;n<wire.nLevelNames;n++) { 385 if ((tmp=XkmGetCountedString(file,buf,100))<1) 386 return -1; 387 nRead+= tmp; 388 if (strlen(buf)==0) 389 type->level_names[n]= None; 390 else type->level_names[n]= XkbInternAtom(buf,0); 391 } 392 } 393 } 394 type->mods.mask= wire.realMods; 395 type->mods.real_mods= wire.realMods; 396 type->mods.vmods= wire.virtualMods; 397 type->num_levels= wire.numLevels; 398 type->map_count= wire.nMapEntries; 399 } 400 if (changes) { 401 changes->map.changed|= XkbKeyTypesMask; 402 changes->map.first_type= 0; 403 changes->map.num_types= xkb->map->num_types; 404 } 405 return nRead; 406} 407 408/***====================================================================***/ 409 410static int 411ReadXkmCompatMap(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) 412{ 413register int i; 414unsigned num_si,groups; 415char name[100]; 416XkbSymInterpretPtr interp; 417xkmSymInterpretDesc wire; 418unsigned tmp; 419int nRead=0; 420XkbCompatMapPtr compat; 421 422 if ((tmp= XkmGetCountedString(file,name,100))<1) { 423 _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0); 424 return -1; 425 } 426 nRead+= tmp; 427 if (name[0]!='\0') { 428 if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) { 429 _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0); 430 return -1; 431 } 432 xkb->names->compat= XkbInternAtom(name,False); 433 } 434 num_si= XkmGetCARD16(file,&nRead); 435 groups= XkmGetCARD8(file,&nRead); 436 nRead+= XkmSkipPadding(file,1); 437 if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success) 438 return -1; 439 compat= xkb->compat; 440 compat->num_si= num_si; 441 interp= compat->sym_interpret; 442 for (i=0;i<num_si;i++,interp++) { 443 tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file); 444 nRead+= tmp*SIZEOF(xkmSymInterpretDesc); 445 interp->sym= wire.sym; 446 interp->mods= wire.mods; 447 interp->match= wire.match; 448 interp->virtual_mod= wire.virtualMod; 449 interp->flags= wire.flags; 450 interp->act.type= wire.actionType; 451 interp->act.data[0]= wire.actionData[0]; 452 interp->act.data[1]= wire.actionData[1]; 453 interp->act.data[2]= wire.actionData[2]; 454 interp->act.data[3]= wire.actionData[3]; 455 interp->act.data[4]= wire.actionData[4]; 456 interp->act.data[5]= wire.actionData[5]; 457 interp->act.data[6]= wire.actionData[6]; 458 } 459 if ((num_si>0)&&(changes)) { 460 changes->compat.first_si= 0; 461 changes->compat.num_si= num_si; 462 } 463 if (groups) { 464 register unsigned bit; 465 for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { 466 xkmModsDesc md; 467 if (groups&bit) { 468 tmp= fread(&md,SIZEOF(xkmModsDesc),1,file); 469 nRead+= tmp*SIZEOF(xkmModsDesc); 470 xkb->compat->groups[i].real_mods= md.realMods; 471 xkb->compat->groups[i].vmods= md.virtualMods; 472 if (md.virtualMods != 0) { 473 unsigned mask; 474 if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask)) 475 xkb->compat->groups[i].mask= md.realMods|mask; 476 } 477 else xkb->compat->groups[i].mask= md.realMods; 478 } 479 } 480 if (changes) 481 changes->compat.changed_groups|= groups; 482 } 483 return nRead; 484} 485 486static int 487ReadXkmIndicators(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) 488{ 489register unsigned nLEDs; 490xkmIndicatorMapDesc wire; 491char buf[100]; 492unsigned tmp; 493int nRead=0; 494 495 if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) { 496 _XkbLibError(_XkbErrBadAlloc,"indicator rec",0); 497 return -1; 498 } 499 if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) { 500 _XkbLibError(_XkbErrBadAlloc,"indicator names",0); 501 return -1; 502 } 503 nLEDs= XkmGetCARD8(file,&nRead); 504 nRead+= XkmSkipPadding(file,3); 505 xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead); 506 while (nLEDs-->0) { 507 Atom name; 508 XkbIndicatorMapPtr map; 509 510 if ((tmp=XkmGetCountedString(file,buf,100))<1) { 511 _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); 512 return -1; 513 } 514 nRead+= tmp; 515 if (buf[0]!='\0') 516 name= XkbInternAtom(buf,False); 517 else name= None; 518 if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) { 519 _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); 520 return -1; 521 } 522 nRead+= tmp*SIZEOF(xkmIndicatorMapDesc); 523 if (xkb->names) { 524 xkb->names->indicators[wire.indicator-1]= name; 525 if (changes) 526 changes->names.changed_indicators|= (1<<(wire.indicator-1)); 527 } 528 map= &xkb->indicators->maps[wire.indicator-1]; 529 map->flags= wire.flags; 530 map->which_groups= wire.which_groups; 531 map->groups= wire.groups; 532 map->which_mods= wire.which_mods; 533 map->mods.mask= wire.real_mods; 534 map->mods.real_mods= wire.real_mods; 535 map->mods.vmods= wire.vmods; 536 map->ctrls= wire.ctrls; 537 } 538 return nRead; 539} 540 541static XkbKeyTypePtr 542FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms) 543{ 544 if ((!xkb)||(!xkb->map)) 545 return NULL; 546 if (name!=None) { 547 register unsigned i; 548 for (i=0;i<xkb->map->num_types;i++) { 549 if (xkb->map->types[i].name==name) { 550 if (xkb->map->types[i].num_levels!=width) 551 DebugF("Group width mismatch between key and type\n"); 552 return &xkb->map->types[i]; 553 } 554 } 555 } 556 if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol))) 557 return &xkb->map->types[XkbOneLevelIndex]; 558 if (syms!=NULL) { 559 if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1])) 560 return &xkb->map->types[XkbAlphabeticIndex]; 561 else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) 562 return &xkb->map->types[XkbKeypadIndex]; 563 } 564 return &xkb->map->types[XkbTwoLevelIndex]; 565} 566 567static int 568ReadXkmSymbols(FILE *file,XkbDescPtr xkb) 569{ 570register int i,g,s,totalVModMaps; 571xkmKeySymMapDesc wireMap; 572char buf[100]; 573unsigned minKC,maxKC,groupNames,tmp; 574int nRead=0; 575 576 if ((tmp=XkmGetCountedString(file,buf,100))<1) 577 return -1; 578 nRead+= tmp; 579 minKC= XkmGetCARD8(file,&nRead); 580 maxKC= XkmGetCARD8(file,&nRead); 581 groupNames= XkmGetCARD8(file,&nRead); 582 totalVModMaps= XkmGetCARD8(file,&nRead); 583 if (XkbAllocNames(xkb, 584 XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask, 585 0,0)!=Success) { 586 _XkbLibError(_XkbErrBadAlloc,"physical names",0); 587 return -1; 588 } 589 if ((buf[0]!='\0')&&(xkb->names)) { 590 Atom name; 591 name= XkbInternAtom(buf,0); 592 xkb->names->symbols= name; 593 xkb->names->phys_symbols= name; 594 } 595 for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) { 596 if (groupNames&g) { 597 if ((tmp=XkmGetCountedString(file,buf,100))<1) 598 return -1; 599 nRead+= tmp; 600 if ((buf[0]!='\0')&&(xkb->names)) { 601 Atom name; 602 name= XkbInternAtom(buf,0); 603 xkb->names->groups[i]= name; 604 } 605 else xkb->names->groups[i]= None; 606 } 607 } 608 if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) { 609 _XkbLibError(_XkbErrBadAlloc,"server map",0); 610 return -1; 611 } 612 if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) { 613 _XkbLibError(_XkbErrBadAlloc,"client map",0); 614 return -1; 615 } 616 if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) { 617 _XkbLibError(_XkbErrBadAlloc,"controls",0); 618 return -1; 619 } 620 if ((xkb->map==NULL)||(xkb->server==NULL)) 621 return -1; 622 if (xkb->min_key_code<8) xkb->min_key_code= minKC; 623 if (xkb->max_key_code<8) xkb->max_key_code= maxKC; 624 if ((minKC>=8)&&(minKC<xkb->min_key_code)) 625 xkb->min_key_code= minKC; 626 if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) { 627 _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC); 628 return -1; 629 } 630 for (i=minKC;i<=(int)maxKC;i++) { 631 Atom typeName[XkbNumKbdGroups]; 632 XkbKeyTypePtr type[XkbNumKbdGroups]; 633 if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) { 634 _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0); 635 return -1; 636 } 637 nRead+= tmp*SIZEOF(xkmKeySymMapDesc); 638 bzero((char *)typeName,XkbNumKbdGroups*sizeof(Atom)); 639 bzero((char *)type,XkbNumKbdGroups*sizeof(XkbKeyTypePtr)); 640 if (wireMap.flags&XkmKeyHasTypes) { 641 register int g; 642 for (g=0;g<XkbNumKbdGroups;g++) { 643 if ((wireMap.flags&(1<<g))&& 644 ((tmp=XkmGetCountedString(file,buf,100))>0)) { 645 typeName[g]= XkbInternAtom(buf,1); 646 nRead+= tmp; 647 } 648 type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL); 649 if (type[g]==NULL) { 650 _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0); 651 return -1; 652 } 653 if (typeName[g]==type[g]->name) 654 xkb->server->explicit[i]|= (1<<g); 655 } 656 } 657 if (wireMap.flags&XkmRepeatingKey) { 658 xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8)); 659 xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; 660 } 661 else if (wireMap.flags&XkmNonRepeatingKey) { 662 xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8)); 663 xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; 664 } 665 xkb->map->modmap[i]= wireMap.modifier_map; 666 if (XkbNumGroups(wireMap.num_groups)>0) { 667 KeySym *sym; 668 int nSyms; 669 670 if (XkbNumGroups(wireMap.num_groups)>xkb->ctrls->num_groups) 671 xkb->ctrls->num_groups= wireMap.num_groups; 672 nSyms= XkbNumGroups(wireMap.num_groups)*wireMap.width; 673 sym= XkbResizeKeySyms(xkb,i,nSyms); 674 if (!sym) 675 return -1; 676 for (s=0;s<nSyms;s++) { 677 *sym++= XkmGetCARD32(file,&nRead); 678 } 679 if (wireMap.flags&XkmKeyHasActions) { 680 XkbAction * act; 681 act= XkbResizeKeyActions(xkb,i,nSyms); 682 for (s=0;s<nSyms;s++,act++) { 683 tmp=fread(act,SIZEOF(xkmActionDesc),1,file); 684 nRead+= tmp*SIZEOF(xkmActionDesc); 685 } 686 xkb->server->explicit[i]|= XkbExplicitInterpretMask; 687 } 688 } 689 for (g=0;g<XkbNumGroups(wireMap.num_groups);g++) { 690 if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) { 691 KeySym *tmpSyms; 692 tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g); 693 type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms); 694 } 695 xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]); 696 } 697 xkb->map->key_sym_map[i].group_info= wireMap.num_groups; 698 xkb->map->key_sym_map[i].width= wireMap.width; 699 if (wireMap.flags&XkmKeyHasBehavior) { 700 xkmBehaviorDesc b; 701 tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file); 702 nRead+= tmp*SIZEOF(xkmBehaviorDesc); 703 xkb->server->behaviors[i].type= b.type; 704 xkb->server->behaviors[i].data= b.data; 705 xkb->server->explicit[i]|= XkbExplicitBehaviorMask; 706 } 707 } 708 if (totalVModMaps>0) { 709 xkmVModMapDesc v; 710 for (i=0;i<totalVModMaps;i++) { 711 tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file); 712 nRead+= tmp*SIZEOF(xkmVModMapDesc); 713 if (tmp>0) 714 xkb->server->vmodmap[v.key]= v.vmods; 715 } 716 } 717 return nRead; 718} 719 720static int 721ReadXkmGeomDoodad( 722 FILE * file, 723 XkbGeometryPtr geom, 724 XkbSectionPtr section) 725{ 726XkbDoodadPtr doodad; 727xkmDoodadDesc doodadWire; 728char buf[100]; 729unsigned tmp; 730int nRead=0; 731 732 nRead+= XkmGetCountedString(file,buf,100); 733 tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file); 734 nRead+= SIZEOF(xkmDoodadDesc)*tmp; 735 doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(buf,False)); 736 if (!doodad) 737 return nRead; 738 doodad->any.type= doodadWire.any.type; 739 doodad->any.priority= doodadWire.any.priority; 740 doodad->any.top= doodadWire.any.top; 741 doodad->any.left= doodadWire.any.left; 742 switch (doodadWire.any.type) { 743 case XkbOutlineDoodad: 744 case XkbSolidDoodad: 745 doodad->shape.angle= doodadWire.shape.angle; 746 doodad->shape.color_ndx= doodadWire.shape.color_ndx; 747 doodad->shape.shape_ndx= doodadWire.shape.shape_ndx; 748 break; 749 case XkbTextDoodad: 750 doodad->text.angle= doodadWire.text.angle; 751 doodad->text.width= doodadWire.text.width; 752 doodad->text.height= doodadWire.text.height; 753 doodad->text.color_ndx= doodadWire.text.color_ndx; 754 nRead+= XkmGetCountedString(file,buf,100); 755 doodad->text.text= _XkbDupString(buf); 756 nRead+= XkmGetCountedString(file,buf,100); 757 doodad->text.font= _XkbDupString(buf); 758 break; 759 case XkbIndicatorDoodad: 760 doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx; 761 doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx; 762 doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx; 763 break; 764 case XkbLogoDoodad: 765 doodad->logo.angle= doodadWire.logo.angle; 766 doodad->logo.color_ndx= doodadWire.logo.color_ndx; 767 doodad->logo.shape_ndx= doodadWire.logo.shape_ndx; 768 nRead+= XkmGetCountedString(file,buf,100); 769 doodad->logo.logo_name= _XkbDupString(buf); 770 break; 771 default: 772 /* report error? */ 773 return nRead; 774 } 775 return nRead; 776} 777 778static int 779ReadXkmGeomOverlay( FILE * file, 780 XkbGeometryPtr geom, 781 XkbSectionPtr section) 782{ 783char buf[100]; 784unsigned tmp; 785int nRead=0; 786XkbOverlayPtr ol; 787XkbOverlayRowPtr row; 788xkmOverlayDesc olWire; 789xkmOverlayRowDesc rowWire; 790register int r; 791 792 nRead+= XkmGetCountedString(file,buf,100); 793 tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file); 794 nRead+= tmp*SIZEOF(xkmOverlayDesc); 795 ol= XkbAddGeomOverlay(section,XkbInternAtom(buf,False), 796 olWire.num_rows); 797 if (!ol) 798 return nRead; 799 for (r=0;r<olWire.num_rows;r++) { 800 int k; 801 xkmOverlayKeyDesc keyWire; 802 tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file); 803 nRead+= tmp*SIZEOF(xkmOverlayRowDesc); 804 row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys); 805 if (!row) { 806 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0); 807 return nRead; 808 } 809 for (k=0;k<rowWire.num_keys;k++) { 810 tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file); 811 nRead+= tmp*SIZEOF(xkmOverlayKeyDesc); 812 memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength); 813 memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength); 814 } 815 row->num_keys= rowWire.num_keys; 816 } 817 return nRead; 818} 819 820static int 821ReadXkmGeomSection( FILE * file, 822 XkbGeometryPtr geom) 823{ 824register int i; 825XkbSectionPtr section; 826xkmSectionDesc sectionWire; 827unsigned tmp; 828int nRead= 0; 829char buf[100]; 830Atom nameAtom; 831 832 nRead+= XkmGetCountedString(file,buf,100); 833 nameAtom= XkbInternAtom(buf,False); 834 tmp= fread(§ionWire,SIZEOF(xkmSectionDesc),1,file); 835 nRead+= SIZEOF(xkmSectionDesc)*tmp; 836 section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows, 837 sectionWire.num_doodads, 838 sectionWire.num_overlays); 839 if (!section) { 840 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); 841 return nRead; 842 } 843 section->top= sectionWire.top; 844 section->left= sectionWire.left; 845 section->width= sectionWire.width; 846 section->height= sectionWire.height; 847 section->angle= sectionWire.angle; 848 section->priority= sectionWire.priority; 849 if (sectionWire.num_rows>0) { 850 register int k; 851 XkbRowPtr row; 852 xkmRowDesc rowWire; 853 XkbKeyPtr key; 854 xkmKeyDesc keyWire; 855 856 for (i=0;i<sectionWire.num_rows;i++) { 857 tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file); 858 nRead+= SIZEOF(xkmRowDesc)*tmp; 859 row= XkbAddGeomRow(section,rowWire.num_keys); 860 if (!row) { 861 _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); 862 return nRead; 863 } 864 row->top= rowWire.top; 865 row->left= rowWire.left; 866 row->vertical= rowWire.vertical; 867 for (k=0;k<rowWire.num_keys;k++) { 868 tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file); 869 nRead+= SIZEOF(xkmKeyDesc)*tmp; 870 key= XkbAddGeomKey(row); 871 if (!key) { 872 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); 873 return nRead; 874 } 875 memcpy(key->name.name,keyWire.name,XkbKeyNameLength); 876 key->gap= keyWire.gap; 877 key->shape_ndx= keyWire.shape_ndx; 878 key->color_ndx= keyWire.color_ndx; 879 } 880 } 881 } 882 if (sectionWire.num_doodads>0) { 883 for (i=0;i<sectionWire.num_doodads;i++) { 884 tmp= ReadXkmGeomDoodad(file,geom,section); 885 nRead+= tmp; 886 if (tmp<1) 887 return nRead; 888 } 889 } 890 if (sectionWire.num_overlays>0) { 891 for (i=0;i<sectionWire.num_overlays;i++) { 892 tmp= ReadXkmGeomOverlay(file,geom,section); 893 nRead+= tmp; 894 if (tmp<1) 895 return nRead; 896 } 897 } 898 return nRead; 899} 900 901static int 902ReadXkmGeometry(FILE *file,XkbDescPtr xkb) 903{ 904register int i; 905char buf[100]; 906unsigned tmp; 907int nRead= 0; 908xkmGeometryDesc wireGeom; 909XkbGeometryPtr geom; 910XkbGeometrySizesRec sizes; 911 912 nRead+= XkmGetCountedString(file,buf,100); 913 tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file); 914 nRead+= tmp*SIZEOF(xkmGeometryDesc); 915 sizes.which= XkbGeomAllMask; 916 sizes.num_properties= wireGeom.num_properties; 917 sizes.num_colors= wireGeom.num_colors; 918 sizes.num_shapes= wireGeom.num_shapes; 919 sizes.num_sections= wireGeom.num_sections; 920 sizes.num_doodads= wireGeom.num_doodads; 921 sizes.num_key_aliases= wireGeom.num_key_aliases; 922 if (XkbAllocGeometry(xkb,&sizes)!=Success) { 923 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); 924 return nRead; 925 } 926 geom= xkb->geom; 927 geom->name= XkbInternAtom(buf,False); 928 geom->width_mm= wireGeom.width_mm; 929 geom->height_mm= wireGeom.height_mm; 930 nRead+= XkmGetCountedString(file,buf,100); 931 geom->label_font= _XkbDupString(buf); 932 if (wireGeom.num_properties>0) { 933 char val[1024]; 934 for (i=0;i<wireGeom.num_properties;i++) { 935 nRead+= XkmGetCountedString(file,buf,100); 936 nRead+= XkmGetCountedString(file,val,1024); 937 if (XkbAddGeomProperty(geom,buf,val)==NULL) { 938 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); 939 return nRead; 940 } 941 } 942 } 943 if (wireGeom.num_colors>0) { 944 for (i=0;i<wireGeom.num_colors;i++) { 945 nRead+= XkmGetCountedString(file,buf,100); 946 if (XkbAddGeomColor(geom,buf,i)==NULL) { 947 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); 948 return nRead; 949 } 950 } 951 } 952 geom->base_color= &geom->colors[wireGeom.base_color_ndx]; 953 geom->label_color= &geom->colors[wireGeom.label_color_ndx]; 954 if (wireGeom.num_shapes>0) { 955 XkbShapePtr shape; 956 xkmShapeDesc shapeWire; 957 Atom nameAtom; 958 for (i=0;i<wireGeom.num_shapes;i++) { 959 register int n; 960 XkbOutlinePtr ol; 961 xkmOutlineDesc olWire; 962 nRead+= XkmGetCountedString(file,buf,100); 963 nameAtom= XkbInternAtom(buf,False); 964 tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file); 965 nRead+= tmp*SIZEOF(xkmShapeDesc); 966 shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines); 967 if (!shape) { 968 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); 969 return nRead; 970 } 971 for (n=0;n<shapeWire.num_outlines;n++) { 972 register int p; 973 xkmPointDesc ptWire; 974 tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file); 975 nRead+= tmp*SIZEOF(xkmOutlineDesc); 976 ol= XkbAddGeomOutline(shape,olWire.num_points); 977 if (!ol) { 978 _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); 979 return nRead; 980 } 981 ol->num_points= olWire.num_points; 982 ol->corner_radius= olWire.corner_radius; 983 for (p=0;p<olWire.num_points;p++) { 984 tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file); 985 nRead+= tmp*SIZEOF(xkmPointDesc); 986 ol->points[p].x= ptWire.x; 987 ol->points[p].y= ptWire.y; 988 if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x; 989 if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x; 990 if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y; 991 if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y; 992 } 993 } 994 if (shapeWire.primary_ndx!=XkbNoShape) 995 shape->primary= &shape->outlines[shapeWire.primary_ndx]; 996 if (shapeWire.approx_ndx!=XkbNoShape) 997 shape->approx= &shape->outlines[shapeWire.approx_ndx]; 998 } 999 } 1000 if (wireGeom.num_sections>0) { 1001 for (i=0;i<wireGeom.num_sections;i++) { 1002 tmp= ReadXkmGeomSection(file,geom); 1003 nRead+= tmp; 1004 if (tmp==0) 1005 return nRead; 1006 } 1007 } 1008 if (wireGeom.num_doodads>0) { 1009 for (i=0;i<wireGeom.num_doodads;i++) { 1010 tmp= ReadXkmGeomDoodad(file,geom,NULL); 1011 nRead+= tmp; 1012 if (tmp==0) 1013 return nRead; 1014 } 1015 } 1016 if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) { 1017 int sz= XkbKeyNameLength*2; 1018 int num= wireGeom.num_key_aliases; 1019 if (fread(geom->key_aliases,sz,num,file)!=num) { 1020 _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0); 1021 return -1; 1022 } 1023 nRead+= (num*sz); 1024 geom->num_key_aliases= num; 1025 } 1026 return nRead; 1027} 1028 1029Bool 1030XkmProbe(FILE *file) 1031{ 1032unsigned hdr,tmp; 1033int nRead=0; 1034 1035 hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); 1036 tmp= XkmGetCARD32(file,&nRead); 1037 if (tmp!=hdr) { 1038 if ((tmp&(~0xff))==(hdr&(~0xff))) { 1039 _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff); 1040 } 1041 return 0; 1042 } 1043 return 1; 1044} 1045 1046static Bool 1047XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc) 1048{ 1049unsigned hdr,tmp; 1050int nRead=0; 1051unsigned i,size_toc; 1052 1053 hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); 1054 tmp= XkmGetCARD32(file,&nRead); 1055 if (tmp!=hdr) { 1056 if ((tmp&(~0xff))==(hdr&(~0xff))) { 1057 _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff); 1058 } 1059 else { 1060 _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp); 1061 } 1062 return 0; 1063 } 1064 fread(file_info,SIZEOF(xkmFileInfo),1,file); 1065 size_toc= file_info->num_toc; 1066 if (size_toc>max_toc) { 1067 DebugF("Warning! Too many TOC entries; last %d ignored\n", 1068 size_toc-max_toc); 1069 size_toc= max_toc; 1070 } 1071 for (i=0;i<size_toc;i++) { 1072 fread(&toc[i],SIZEOF(xkmSectionInfo),1,file); 1073 } 1074 return 1; 1075} 1076 1077/***====================================================================***/ 1078 1079#define MAX_TOC 16 1080unsigned 1081XkmReadFile(FILE *file,unsigned need,unsigned want,XkbDescPtr *xkb) 1082{ 1083register unsigned i; 1084xkmSectionInfo toc[MAX_TOC],tmpTOC; 1085xkmFileInfo fileInfo; 1086unsigned tmp,nRead=0; 1087unsigned which= need|want; 1088 1089 if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc)) 1090 return which; 1091 if ((fileInfo.present&need)!=need) { 1092 _XkbLibError(_XkbErrIllegalContents,"XkmReadFile", 1093 need&(~fileInfo.present)); 1094 return which; 1095 } 1096 if (*xkb==NULL) 1097 *xkb= XkbAllocKeyboard(); 1098 for (i=0;i<fileInfo.num_toc;i++) { 1099 fseek(file,toc[i].offset,SEEK_SET); 1100 tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); 1101 nRead= tmp*SIZEOF(xkmSectionInfo); 1102 if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)|| 1103 (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) { 1104 return which; 1105 } 1106 if ((which&(1<<tmpTOC.type))==0) { 1107 continue; 1108 } 1109 switch (tmpTOC.type) { 1110 case XkmVirtualModsIndex: 1111 tmp= ReadXkmVirtualMods(file,*xkb,NULL); 1112 break; 1113 case XkmTypesIndex: 1114 tmp= ReadXkmKeyTypes(file,*xkb,NULL); 1115 break; 1116 case XkmCompatMapIndex: 1117 tmp= ReadXkmCompatMap(file,*xkb,NULL); 1118 break; 1119 case XkmKeyNamesIndex: 1120 tmp= ReadXkmKeycodes(file,*xkb,NULL); 1121 break; 1122 case XkmIndicatorsIndex: 1123 tmp= ReadXkmIndicators(file,*xkb,NULL); 1124 break; 1125 case XkmSymbolsIndex: 1126 tmp= ReadXkmSymbols(file,*xkb); 1127 break; 1128 case XkmGeometryIndex: 1129 tmp= ReadXkmGeometry(file,*xkb); 1130 break; 1131 default: 1132 _XkbLibError(_XkbErrBadImplementation, 1133 XkbConfigText(tmpTOC.type,XkbMessage),0); 1134 tmp= 0; 1135 break; 1136 } 1137 if (tmp>0) { 1138 nRead+= tmp; 1139 which&= ~(1<<toc[i].type); 1140 (*xkb)->defined|= (1<<toc[i].type); 1141 } 1142 if (nRead!=tmpTOC.size) { 1143 _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage), 1144 nRead-tmpTOC.size); 1145 } 1146 } 1147 return which; 1148} 1149