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