xkbout.c revision 4cd6a3ae
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#elif defined(HAVE_CONFIG_H) 30#include <config.h> 31#endif 32 33#include <stdio.h> 34#include <ctype.h> 35#include <stdlib.h> 36#include <X11/Xfuncs.h> 37 38#ifndef XKB_IN_SERVER 39 40#include <X11/Xlib.h> 41#include <X11/XKBlib.h> 42#include <X11/extensions/XKBgeom.h> 43 44#include "XKMformat.h" 45#include "XKBfileInt.h" 46 47#else 48 49#include <X11/X.h> 50#include <X11/keysym.h> 51#include <X11/Xproto.h> 52#include "misc.h" 53#include "inputstr.h" 54#include "dix.h" 55#include <X11/extensions/XKBstr.h> 56#define XKBSRV_NEED_FILE_FUNCS 1 57#include <X11/extensions/XKBsrv.h> 58 59#include <X11/extensions/XKBgeom.h> 60#include <X11/extensions/XKBfile.h> 61 62#endif 63 64#define VMOD_HIDE_VALUE 0 65#define VMOD_SHOW_VALUE 1 66#define VMOD_COMMENT_VALUE 2 67 68static Bool 69WriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue) 70{ 71register int i,nMods; 72Atom * vmodNames; 73 74 if (xkb==NULL) 75 return False; 76 if (xkb->names!=NULL) 77 vmodNames= xkb->names->vmods; 78 else vmodNames= NULL; 79 80 for (i=nMods=0;i<XkbNumVirtualMods;i++) { 81 if ((vmodNames!=NULL)&&(vmodNames[i]!=None)) { 82 if (nMods==0) fprintf(file," virtual_modifiers "); 83 else fprintf(file,","); 84 fprintf(file,"%s",XkbAtomText(dpy,vmodNames[i],XkbXKBFile)); 85 if ((showValue!=VMOD_HIDE_VALUE)&& 86 (xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) { 87 if (showValue==VMOD_COMMENT_VALUE) { 88 fprintf(file,"/* = %s */", 89 XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); 90 } 91 else { 92 fprintf(file,"= %s", 93 XkbModMaskText(xkb->server->vmods[i],XkbXKBFile)); 94 } 95 } 96 nMods++; 97 } 98 } 99 if (nMods>0) 100 fprintf(file,";\n\n"); 101 return True; 102} 103 104/***====================================================================***/ 105 106static Bool 107WriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action) 108{ 109XkbDescPtr xkb; 110Display * dpy; 111 112 xkb= result->xkb; 113 dpy= xkb->dpy; 114 fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile)); 115 return True; 116} 117 118/***====================================================================***/ 119 120Bool 121XkbWriteXKBKeycodes( FILE * file, 122 XkbFileInfo * result, 123 Bool topLevel, 124 Bool showImplicit, 125 XkbFileAddOnFunc addOn, 126 void * priv) 127{ 128Atom kcName; 129register unsigned i; 130XkbDescPtr xkb; 131Display * dpy; 132const char * alternate; 133 134 xkb= result->xkb; 135 if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) { 136 _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0); 137 return False; 138 } 139 dpy= xkb->dpy; 140 kcName= xkb->names->keycodes; 141 if (kcName!=None) 142 fprintf(file,"xkb_keycodes \"%s\" {\n", 143 XkbAtomText(dpy,kcName,XkbXKBFile)); 144 else fprintf(file,"xkb_keycodes {\n"); 145 fprintf(file," minimum = %d;\n",xkb->min_key_code); 146 fprintf(file," maximum = %d;\n",xkb->max_key_code); 147 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 148 if (xkb->names->keys[i].name[0]!='\0') { 149 if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) 150 alternate= "alternate "; 151 else alternate= ""; 152 fprintf(file," %s%6s = %d;\n",alternate, 153 XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile), 154 i); 155 } 156 } 157 if (xkb->indicators!=NULL) { 158 for (i=0;i<XkbNumIndicators;i++) { 159 const char *type; 160 if (xkb->indicators->phys_indicators&(1<<i)) 161 type= " "; 162 else type= " virtual "; 163 if (xkb->names->indicators[i]!=None) { 164 fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1, 165 XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile)); 166 } 167 } 168 } 169 if (xkb->names->key_aliases!=NULL) { 170 XkbKeyAliasPtr pAl; 171 pAl= xkb->names->key_aliases; 172 for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) { 173 fprintf(file," alias %6s = %6s;\n", 174 XkbKeyNameText(pAl->alias,XkbXKBFile), 175 XkbKeyNameText(pAl->real,XkbXKBFile)); 176 } 177 } 178 if (addOn) 179 (*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv); 180 fprintf(file,"};\n\n"); 181 return True; 182} 183 184Bool 185XkbWriteXKBKeyTypes( FILE * file, 186 XkbFileInfo * result, 187 Bool topLevel, 188 Bool showImplicit, 189 XkbFileAddOnFunc addOn, 190 void * priv) 191{ 192Display * dpy; 193register unsigned i,n; 194XkbKeyTypePtr type; 195XkbKTMapEntryPtr entry; 196XkbDescPtr xkb; 197 198 xkb= result->xkb; 199 if ((!xkb)||(!xkb->map)||(!xkb->map->types)) { 200 _XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0); 201 return False; 202 } 203 dpy= xkb->dpy; 204 if (xkb->map->num_types<XkbNumRequiredTypes) { 205 _XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",0); 206 return 0; 207 } 208 if ((xkb->names==NULL)||(xkb->names->types==None)) 209 fprintf(file,"xkb_types {\n\n"); 210 else fprintf(file,"xkb_types \"%s\" {\n\n", 211 XkbAtomText(dpy,xkb->names->types,XkbXKBFile)); 212 WriteXKBVModDecl(file,dpy,xkb, 213 (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); 214 215 type= xkb->map->types; 216 for (i=0;i<xkb->map->num_types;i++,type++) { 217 fprintf(file," type \"%s\" {\n", 218 XkbAtomText(dpy,type->name,XkbXKBFile)); 219 fprintf(file," modifiers= %s;\n", 220 XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods, 221 XkbXKBFile)); 222 entry= type->map; 223 for (n=0;n<type->map_count;n++,entry++) { 224 char *str; 225 str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods, 226 XkbXKBFile); 227 fprintf(file," map[%s]= Level%d;\n",str,entry->level+1); 228 if ((type->preserve)&&((type->preserve[n].real_mods)|| 229 (type->preserve[n].vmods))) { 230 fprintf(file," preserve[%s]= ",str); 231 fprintf(file,"%s;\n",XkbVModMaskText(dpy,xkb, 232 type->preserve[n].real_mods, 233 type->preserve[n].vmods, 234 XkbXKBFile)); 235 } 236 } 237 if (type->level_names!=NULL) { 238 Atom *name= type->level_names; 239 for (n=0;n<type->num_levels;n++,name++) { 240 if ((*name)==None) 241 continue; 242 fprintf(file," level_name[Level%d]= \"%s\";\n",n+1, 243 XkbAtomText(dpy,*name,XkbXKBFile)); 244 } 245 } 246 fprintf(file," };\n"); 247 } 248 if (addOn) 249 (*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv); 250 fprintf(file,"};\n\n"); 251 return True; 252} 253 254static Bool 255WriteXKBIndicatorMap( FILE * file, 256 XkbFileInfo * result, 257 Atom name, 258 XkbIndicatorMapPtr led, 259 XkbFileAddOnFunc addOn, 260 void * priv) 261{ 262XkbDescPtr xkb; 263char *tmp; 264 265 xkb= result->xkb; 266 tmp = XkbAtomGetString(xkb->dpy, name); 267 fprintf(file," indicator \"%s\" {\n",tmp); 268 _XkbFree(tmp); 269 if (led->flags&XkbIM_NoExplicit) 270 fprintf(file," !allowExplicit;\n"); 271 if (led->flags&XkbIM_LEDDrivesKB) 272 fprintf(file," indicatorDrivesKeyboard;\n"); 273 if (led->which_groups!=0) { 274 if (led->which_groups!=XkbIM_UseEffective) { 275 fprintf(file," whichGroupState= %s;\n", 276 XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile)); 277 } 278 fprintf(file," groups= 0x%02x;\n",led->groups); 279 } 280 if (led->which_mods!=0) { 281 if (led->which_mods!=XkbIM_UseEffective) { 282 fprintf(file," whichModState= %s;\n", 283 XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile)); 284 } 285 fprintf(file," modifiers= %s;\n", 286 XkbVModMaskText(xkb->dpy,xkb, 287 led->mods.real_mods,led->mods.vmods, 288 XkbXKBFile)); 289 } 290 if (led->ctrls!=0) { 291 fprintf(file," controls= %s;\n", 292 XkbControlsMaskText(led->ctrls,XkbXKBFile)); 293 } 294 if (addOn) 295 (*addOn)(file,result,False,True,XkmIndicatorsIndex,priv); 296 fprintf(file," };\n"); 297 return True; 298} 299 300Bool 301XkbWriteXKBCompatMap( FILE * file, 302 XkbFileInfo * result, 303 Bool topLevel, 304 Bool showImplicit, 305 XkbFileAddOnFunc addOn, 306 void * priv) 307{ 308Display * dpy; 309register unsigned i; 310XkbSymInterpretPtr interp; 311XkbDescPtr xkb; 312 313 xkb= result->xkb; 314 if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) { 315 _XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0); 316 return False; 317 } 318 dpy= xkb->dpy; 319 if ((xkb->names==NULL)||(xkb->names->compat==None)) 320 fprintf(file,"xkb_compatibility {\n\n"); 321 else fprintf(file,"xkb_compatibility \"%s\" {\n\n", 322 XkbAtomText(dpy,xkb->names->compat,XkbXKBFile)); 323 WriteXKBVModDecl(file,dpy,xkb, 324 (showImplicit?VMOD_COMMENT_VALUE:VMOD_HIDE_VALUE)); 325 326 fprintf(file," interpret.useModMapMods= AnyLevel;\n"); 327 fprintf(file," interpret.repeat= False;\n"); 328 fprintf(file," interpret.locking= False;\n"); 329 interp= xkb->compat->sym_interpret; 330 for (i=0;i<xkb->compat->num_si;i++,interp++) { 331 fprintf(file," interpret %s+%s(%s) {\n", 332 ((interp->sym==NoSymbol)?"Any": 333 XkbKeysymText(interp->sym,XkbXKBFile)), 334 XkbSIMatchText(interp->match,XkbXKBFile), 335 XkbModMaskText(interp->mods,XkbXKBFile)); 336 if (interp->virtual_mod!=XkbNoModifier) { 337 fprintf(file," virtualModifier= %s;\n", 338 XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile)); 339 } 340 if (interp->match&XkbSI_LevelOneOnly) 341 fprintf(file," useModMapMods=level1;\n"); 342 if (interp->flags&XkbSI_LockingKey) 343 fprintf(file," locking= True;\n"); 344 if (interp->flags&XkbSI_AutoRepeat) 345 fprintf(file," repeat= True;\n"); 346 fprintf(file," action= "); 347 WriteXKBAction(file,result,&interp->act); 348 fprintf(file,";\n"); 349 fprintf(file," };\n"); 350 } 351 for (i=0;i<XkbNumKbdGroups;i++) { 352 XkbModsPtr gc; 353 354 gc= &xkb->compat->groups[i]; 355 if ((gc->real_mods==0)&&(gc->vmods==0)) 356 continue; 357 fprintf(file," group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb, 358 gc->real_mods,gc->vmods, 359 XkbXKBFile)); 360 } 361 if (xkb->indicators) { 362 for (i=0;i<XkbNumIndicators;i++) { 363 XkbIndicatorMapPtr map= &xkb->indicators->maps[i]; 364 if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)|| 365 (map->which_mods!=0)|| 366 (map->mods.real_mods!=0)||(map->mods.vmods!=0)|| 367 (map->ctrls!=0)) { 368 WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map, 369 addOn,priv); 370 } 371 } 372 } 373 if (addOn) 374 (*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv); 375 fprintf(file,"};\n\n"); 376 return True; 377} 378 379Bool 380XkbWriteXKBSymbols( FILE * file, 381 XkbFileInfo * result, 382 Bool topLevel, 383 Bool showImplicit, 384 XkbFileAddOnFunc addOn, 385 void * priv) 386{ 387Display * dpy; 388register unsigned i,tmp; 389XkbDescPtr xkb; 390XkbClientMapPtr map; 391XkbServerMapPtr srv; 392Bool showActions; 393 394 xkb= result->xkb; 395 396 if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) { 397 _XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0); 398 return False; 399 } 400 if ((!xkb->names)||(!xkb->names->keys)) { 401 _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0); 402 return False; 403 } 404 405 map= xkb->map; 406 srv= xkb->server; 407 dpy= xkb->dpy; 408 409 if ((xkb->names==NULL)||(xkb->names->symbols==None)) 410 fprintf(file,"xkb_symbols {\n\n"); 411 else fprintf(file,"xkb_symbols \"%s\" {\n\n", 412 XkbAtomText(dpy,xkb->names->symbols,XkbXKBFile)); 413 for (tmp=i=0;i<XkbNumKbdGroups;i++) { 414 if (xkb->names->groups[i]!=None) { 415 fprintf(file," name[group%d]=\"%s\";\n",i+1, 416 XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile)); 417 tmp++; 418 } 419 } 420 if (tmp>0) 421 fprintf(file,"\n"); 422 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 423 Bool simple; 424 if ((int)XkbKeyNumSyms(xkb,i)<1) 425 continue; 426 if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i) 427 continue; 428 simple= True; 429 fprintf(file," key %6s {", 430 XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile)); 431 if (srv->explicit) { 432 if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)|| 433 (showImplicit)) { 434 int typeNdx,g; 435 Bool multi; 436 const char * comment=" "; 437 438 if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0) 439 comment= "//"; 440 multi= False; 441 typeNdx= XkbKeyKeyTypeIndex(xkb,i,0); 442 for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) { 443 if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx) 444 multi= True; 445 } 446 if (multi) { 447 for (g=0;g<XkbKeyNumGroups(xkb,i);g++) { 448 typeNdx= XkbKeyKeyTypeIndex(xkb,i,g); 449 if (srv->explicit[i]&(1<<g)) { 450 fprintf(file,"\n%s type[group%d]= \"%s\",", 451 comment,g+1, 452 XkbAtomText(dpy,map->types[typeNdx].name, 453 XkbXKBFile)); 454 } 455 else if (showImplicit) { 456 fprintf(file,"\n// type[group%d]= \"%s\",",g+1, 457 XkbAtomText(dpy,map->types[typeNdx].name, 458 XkbXKBFile)); 459 } 460 } 461 } 462 else { 463 fprintf(file,"\n%s type= \"%s\",",comment, 464 XkbAtomText(dpy,map->types[typeNdx].name, 465 XkbXKBFile)); 466 } 467 simple= False; 468 } 469 if (((srv->explicit[i]&XkbExplicitAutoRepeatMask)!=0)&& 470 (xkb->ctrls!=NULL)) { 471 if (xkb->ctrls->per_key_repeat[i/8]&(1<<(i%8))) 472 fprintf(file,"\n repeat= Yes,"); 473 else fprintf(file,"\n repeat= No,"); 474 simple= False; 475 } 476 if ((xkb->server!=NULL)&&(xkb->server->vmodmap!=NULL)&& 477 (xkb->server->vmodmap[i]!=0)) { 478 if ((srv->explicit[i]&XkbExplicitVModMapMask)!=0) { 479 fprintf(file,"\n virtualMods= %s,", 480 XkbVModMaskText(dpy,xkb,0, 481 xkb->server->vmodmap[i], 482 XkbXKBFile)); 483 } 484 else if (showImplicit) { 485 fprintf(file,"\n// virtualMods= %s,", 486 XkbVModMaskText(dpy,xkb,0, 487 xkb->server->vmodmap[i], 488 XkbXKBFile)); 489 } 490 } 491 } 492 switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) { 493 case XkbClampIntoRange: 494 fprintf(file,"\n groupsClamp,"); 495 break; 496 case XkbRedirectIntoRange: 497 fprintf(file,"\n groupsRedirect= Group%d,", 498 XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1); 499 break; 500 } 501 if (srv->behaviors!=NULL) { 502 unsigned type; 503 type= srv->behaviors[i].type&XkbKB_OpMask; 504 505 if (type!=XkbKB_Default) { 506 simple= False; 507 fprintf(file,"\n %s,", 508 XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile)); 509 } 510 } 511 if ((srv->explicit==NULL) || showImplicit || 512 ((srv->explicit[i]&XkbExplicitInterpretMask)!=0)) 513 showActions= XkbKeyHasActions(xkb,i); 514 else showActions= False; 515 516 if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions) 517 simple= False; 518 if (simple) { 519 KeySym *syms; 520 unsigned s; 521 522 syms= XkbKeySymsPtr(xkb,i); 523 fprintf(file," [ "); 524 for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) { 525 if (s!=0) 526 fprintf(file,", "); 527 fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile)); 528 } 529 fprintf(file," ] };\n"); 530 } 531 else { 532 unsigned g,s; 533 KeySym *syms; 534 XkbAction *acts; 535 syms= XkbKeySymsPtr(xkb,i); 536 acts= XkbKeyActionsPtr(xkb,i); 537 for (g=0;g<XkbKeyNumGroups(xkb,i);g++) { 538 if (g!=0) 539 fprintf(file,","); 540 fprintf(file,"\n symbols[Group%d]= [ ",g+1); 541 for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) { 542 if (s!=0) 543 fprintf(file,", "); 544 fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile)); 545 } 546 fprintf(file," ]"); 547 syms+= XkbKeyGroupsWidth(xkb,i); 548 if (showActions) { 549 fprintf(file,",\n actions[Group%d]= [ ",g+1); 550 for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) { 551 if (s!=0) 552 fprintf(file,", "); 553 WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]); 554 } 555 fprintf(file," ]"); 556 acts+= XkbKeyGroupsWidth(xkb,i); 557 } 558 } 559 fprintf(file,"\n };\n"); 560 } 561 } 562 if (map && map->modmap) { 563 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 564 if (map->modmap[i]!=0) { 565 register int n,bit; 566 for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) { 567 if (map->modmap[i]&bit) { 568 char buf[5]; 569 memcpy(buf,xkb->names->keys[i].name,4); 570 buf[4]= '\0'; 571 fprintf(file," modifier_map %s { <%s> };\n", 572 XkbModIndexText(n,XkbXKBFile),buf); 573 } 574 } 575 } 576 } 577 } 578 if (addOn) 579 (*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv); 580 fprintf(file,"};\n\n"); 581 return True; 582} 583 584static Bool 585WriteXKBOutline( FILE * file, 586 XkbShapePtr shape, 587 XkbOutlinePtr outline, 588 int lastRadius, 589 int first, 590 int indent) 591{ 592register int i; 593XkbPointPtr pt; 594char * iStr; 595 596 fprintf(file,"%s",iStr= XkbIndentText(first)); 597 if (first!=indent) 598 iStr= XkbIndentText(indent); 599 if (outline->corner_radius!=lastRadius) { 600 fprintf(file,"corner= %s,", 601 XkbGeomFPText(outline->corner_radius,XkbMessage)); 602 if (shape!=NULL) { 603 fprintf(file,"\n%s",iStr); 604 } 605 } 606 if (shape) { 607 if (outline==shape->approx) 608 fprintf(file,"approx= "); 609 else if (outline==shape->primary) 610 fprintf(file,"primary= "); 611 } 612 fprintf(file,"{"); 613 for (pt=outline->points,i=0;i<outline->num_points;i++,pt++) { 614 if (i==0) fprintf(file," "); 615 else if ((i%4)==0) fprintf(file,",\n%s ",iStr); 616 else fprintf(file,", "); 617 fprintf(file,"[ %3s, %3s ]",XkbGeomFPText(pt->x,XkbXKBFile), 618 XkbGeomFPText(pt->y,XkbXKBFile)); 619 } 620 fprintf(file," }"); 621 return True; 622} 623 624static Bool 625WriteXKBDoodad( FILE * file, 626 Display * dpy, 627 unsigned indent, 628 XkbGeometryPtr geom, 629 XkbDoodadPtr doodad) 630{ 631register char * i_str; 632XkbShapePtr shape; 633XkbColorPtr color; 634 635 i_str= XkbIndentText(indent); 636 fprintf(file,"%s%s \"%s\" {\n",i_str, 637 XkbDoodadTypeText(doodad->any.type,XkbMessage), 638 XkbAtomText(dpy,doodad->any.name,XkbMessage)); 639 fprintf(file,"%s top= %s;\n",i_str, 640 XkbGeomFPText(doodad->any.top,XkbXKBFile)); 641 fprintf(file,"%s left= %s;\n",i_str, 642 XkbGeomFPText(doodad->any.left,XkbXKBFile)); 643 fprintf(file,"%s priority= %d;\n",i_str,doodad->any.priority); 644 switch (doodad->any.type) { 645 case XkbOutlineDoodad: 646 case XkbSolidDoodad: 647 if (doodad->shape.angle!=0) { 648 fprintf(file,"%s angle= %s;\n",i_str, 649 XkbGeomFPText(doodad->shape.angle,XkbXKBFile)); 650 } 651 if (doodad->shape.color_ndx!=0) { 652 fprintf(file,"%s color= \"%s\";\n",i_str, 653 XkbShapeDoodadColor(geom,&doodad->shape)->spec); 654 } 655 shape= XkbShapeDoodadShape(geom,&doodad->shape); 656 fprintf(file,"%s shape= \"%s\";\n",i_str, 657 XkbAtomText(dpy,shape->name,XkbXKBFile)); 658 break; 659 case XkbTextDoodad: 660 if (doodad->text.angle!=0) { 661 fprintf(file,"%s angle= %s;\n",i_str, 662 XkbGeomFPText(doodad->text.angle,XkbXKBFile)); 663 } 664 if (doodad->text.width!=0) { 665 fprintf(file,"%s width= %s;\n",i_str, 666 XkbGeomFPText(doodad->text.width,XkbXKBFile)); 667 668 } 669 if (doodad->text.height!=0) { 670 fprintf(file,"%s height= %s;\n",i_str, 671 XkbGeomFPText(doodad->text.height,XkbXKBFile)); 672 673 } 674 if (doodad->text.color_ndx!=0) { 675 color= XkbTextDoodadColor(geom,&doodad->text); 676 fprintf(file,"%s color= \"%s\";\n",i_str, 677 XkbStringText(color->spec,XkbXKBFile)); 678 } 679 fprintf(file,"%s XFont= \"%s\";\n",i_str, 680 XkbStringText(doodad->text.font,XkbXKBFile)); 681 fprintf(file,"%s text= \"%s\";\n",i_str, 682 XkbStringText(doodad->text.text,XkbXKBFile)); 683 break; 684 case XkbIndicatorDoodad: 685 shape= XkbIndicatorDoodadShape(geom,&doodad->indicator); 686 color= XkbIndicatorDoodadOnColor(geom,&doodad->indicator); 687 fprintf(file,"%s onColor= \"%s\";\n",i_str, 688 XkbStringText(color->spec,XkbXKBFile)); 689 color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator); 690 fprintf(file,"%s offColor= \"%s\";\n",i_str, 691 XkbStringText(color->spec,XkbXKBFile)); 692 fprintf(file,"%s shape= \"%s\";\n",i_str, 693 XkbAtomText(dpy,shape->name,XkbXKBFile)); 694 break; 695 case XkbLogoDoodad: 696 fprintf(file,"%s logoName= \"%s\";\n",i_str, 697 XkbStringText(doodad->logo.logo_name,XkbXKBFile)); 698 if (doodad->shape.angle!=0) { 699 fprintf(file,"%s angle= %s;\n",i_str, 700 XkbGeomFPText(doodad->logo.angle,XkbXKBFile)); 701 } 702 if (doodad->shape.color_ndx!=0) { 703 fprintf(file,"%s color= \"%s\";\n",i_str, 704 XkbLogoDoodadColor(geom,&doodad->logo)->spec); 705 } 706 shape= XkbLogoDoodadShape(geom,&doodad->logo); 707 fprintf(file,"%s shape= \"%s\";\n",i_str, 708 XkbAtomText(dpy,shape->name,XkbXKBFile)); 709 break; 710 } 711 fprintf(file,"%s};\n",i_str); 712 return True; 713} 714 715/*ARGSUSED*/ 716static Bool 717WriteXKBOverlay( FILE * file, 718 Display * dpy, 719 unsigned indent, 720 XkbGeometryPtr geom, 721 XkbOverlayPtr ol) 722{ 723register char * i_str; 724int r,k,nOut; 725XkbOverlayRowPtr row; 726XkbOverlayKeyPtr key; 727 728 i_str= XkbIndentText(indent); 729 if (ol->name!=None) { 730 fprintf(file,"%soverlay \"%s\" {\n",i_str, 731 XkbAtomText(dpy,ol->name,XkbMessage)); 732 } 733 else fprintf(file,"%soverlay {\n",i_str); 734 for (nOut=r=0,row=ol->rows;r<ol->num_rows;r++,row++) { 735 for (k=0,key=row->keys;k<row->num_keys;k++,key++) { 736 char *over,*under; 737 over= XkbKeyNameText(key->over.name,XkbXKBFile); 738 under= XkbKeyNameText(key->under.name,XkbXKBFile); 739 if (nOut==0) 740 fprintf(file,"%s %6s=%6s",i_str,under,over); 741 else if ((nOut%4)==0) 742 fprintf(file,",\n%s %6s=%6s",i_str,under,over); 743 else fprintf(file,", %6s=%6s",under,over); 744 nOut++; 745 } 746 } 747 fprintf(file,"\n%s};\n",i_str); 748 return True; 749} 750 751static Bool 752WriteXKBSection( FILE * file, 753 Display * dpy, 754 XkbSectionPtr s, 755 XkbGeometryPtr geom) 756{ 757register int i; 758XkbRowPtr row; 759int dfltKeyColor = 0; 760 761 fprintf(file," section \"%s\" {\n", 762 XkbAtomText(dpy,s->name,XkbXKBFile)); 763 if (s->rows&&(s->rows->num_keys>0)) { 764 dfltKeyColor= s->rows->keys[0].color_ndx; 765 fprintf(file," key.color= \"%s\";\n", 766 XkbStringText(geom->colors[dfltKeyColor].spec,XkbXKBFile)); 767 } 768 fprintf(file," priority= %d;\n",s->priority); 769 fprintf(file," top= %s;\n",XkbGeomFPText(s->top,XkbXKBFile)); 770 fprintf(file," left= %s;\n",XkbGeomFPText(s->left,XkbXKBFile)); 771 fprintf(file," width= %s;\n",XkbGeomFPText(s->width,XkbXKBFile)); 772 fprintf(file," height= %s;\n", 773 XkbGeomFPText(s->height,XkbXKBFile)); 774 if (s->angle!=0) { 775 fprintf(file," angle= %s;\n", 776 XkbGeomFPText(s->angle,XkbXKBFile)); 777 } 778 for (i=0,row=s->rows;row&&i<s->num_rows;i++,row++) { 779 fprintf(file," row {\n"); 780 fprintf(file," top= %s;\n", 781 XkbGeomFPText(row->top,XkbXKBFile)); 782 fprintf(file," left= %s;\n", 783 XkbGeomFPText(row->left,XkbXKBFile)); 784 if (row->vertical) 785 fprintf(file," vertical;\n"); 786 if (row->num_keys>0) { 787 register int k; 788 register XkbKeyPtr key; 789 int forceNL=0; 790 int nThisLine= 0; 791 fprintf(file," keys {\n"); 792 for (k=0,key=row->keys;k<row->num_keys;k++,key++) { 793 XkbShapePtr shape; 794 if (key->color_ndx!=dfltKeyColor) 795 forceNL= 1; 796 if (k==0) { 797 fprintf(file," "); 798 nThisLine= 0; 799 } 800 else if (((nThisLine%2)==1)||(forceNL)) { 801 fprintf(file,",\n "); 802 forceNL= nThisLine= 0; 803 } 804 else { 805 fprintf(file,", "); 806 nThisLine++; 807 } 808 shape= XkbKeyShape(geom,key); 809 fprintf(file,"{ %6s, \"%s\", %3s", 810 XkbKeyNameText(key->name.name,XkbXKBFile), 811 XkbAtomText(dpy,shape->name,XkbXKBFile), 812 XkbGeomFPText(key->gap,XkbXKBFile)); 813 if (key->color_ndx!=dfltKeyColor) { 814 fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec); 815 forceNL= 1; 816 } 817 fprintf(file," }"); 818 } 819 fprintf(file,"\n };\n"); 820 } 821 fprintf(file," };\n"); 822 } 823 if (s->doodads!=NULL) { 824 XkbDoodadPtr doodad; 825 for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) { 826 WriteXKBDoodad(file,dpy,8,geom,doodad); 827 } 828 } 829 if (s->overlays!=NULL) { 830 XkbOverlayPtr ol; 831 for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) { 832 WriteXKBOverlay(file,dpy,8,geom,ol); 833 } 834 } 835 fprintf(file," }; // End of \"%s\" section\n\n", 836 XkbAtomText(dpy,s->name,XkbXKBFile)); 837 return True; 838} 839 840Bool 841XkbWriteXKBGeometry( FILE * file, 842 XkbFileInfo * result, 843 Bool topLevel, 844 Bool showImplicit, 845 XkbFileAddOnFunc addOn, 846 void * priv) 847{ 848Display * dpy; 849register unsigned i,n; 850XkbDescPtr xkb; 851XkbGeometryPtr geom; 852 853 xkb= result->xkb; 854 if ((!xkb)||(!xkb->geom)) { 855 _XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0); 856 return False; 857 } 858 dpy= xkb->dpy; 859 geom= xkb->geom; 860 if (geom->name==None) 861 fprintf(file,"xkb_geometry {\n\n"); 862 else fprintf(file,"xkb_geometry \"%s\" {\n\n", 863 XkbAtomText(dpy,geom->name,XkbXKBFile)); 864 fprintf(file," width= %s;\n", 865 XkbGeomFPText(geom->width_mm,XkbXKBFile)); 866 fprintf(file," height= %s;\n\n", 867 XkbGeomFPText(geom->height_mm,XkbXKBFile)); 868 869 if (geom->key_aliases!=NULL) { 870 XkbKeyAliasPtr pAl; 871 pAl= geom->key_aliases; 872 for (i=0;i<geom->num_key_aliases;i++,pAl++) { 873 fprintf(file," alias %6s = %6s;\n", 874 XkbKeyNameText(pAl->alias,XkbXKBFile), 875 XkbKeyNameText(pAl->real,XkbXKBFile)); 876 } 877 fprintf(file,"\n"); 878 } 879 880 if (geom->base_color!=NULL) 881 fprintf(file," baseColor= \"%s\";\n", 882 XkbStringText(geom->base_color->spec,XkbXKBFile)); 883 if (geom->label_color!=NULL) 884 fprintf(file," labelColor= \"%s\";\n", 885 XkbStringText(geom->label_color->spec,XkbXKBFile)); 886 if (geom->label_font!=NULL) 887 fprintf(file," xfont= \"%s\";\n", 888 XkbStringText(geom->label_font,XkbXKBFile)); 889 if ((geom->num_colors>0)&&(showImplicit)) { 890 XkbColorPtr color; 891 for (color=geom->colors,i=0;i<geom->num_colors;i++,color++) { 892 fprintf(file,"// color[%d]= \"%s\"\n",i, 893 XkbStringText(color->spec,XkbXKBFile)); 894 } 895 fprintf(file,"\n"); 896 } 897 if (geom->num_properties>0) { 898 XkbPropertyPtr prop; 899 for (prop=geom->properties,i=0;i<geom->num_properties;i++,prop++) { 900 fprintf(file," %s= \"%s\";\n",prop->name, 901 XkbStringText(prop->value,XkbXKBFile)); 902 } 903 fprintf(file,"\n"); 904 } 905 if (geom->num_shapes>0) { 906 XkbShapePtr shape; 907 XkbOutlinePtr outline; 908 int lastR; 909 for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { 910 lastR=0; 911 fprintf(file," shape \"%s\" {", 912 XkbAtomText(dpy,shape->name,XkbXKBFile)); 913 outline= shape->outlines; 914 if (shape->num_outlines>1) { 915 for (n=0;n<shape->num_outlines;n++,outline++) { 916 if (n==0) fprintf(file,"\n"); 917 else fprintf(file,",\n"); 918 WriteXKBOutline(file,shape,outline,lastR,8,8); 919 lastR= outline->corner_radius; 920 } 921 fprintf(file,"\n };\n"); 922 } 923 else { 924 WriteXKBOutline(file,NULL,outline,lastR,1,8); 925 fprintf(file," };\n"); 926 } 927 } 928 } 929 if (geom->num_sections>0) { 930 XkbSectionPtr section; 931 for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){ 932 WriteXKBSection(file,dpy,section,geom); 933 } 934 } 935 if (geom->num_doodads>0) { 936 XkbDoodadPtr doodad; 937 for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) { 938 WriteXKBDoodad(file,dpy,4,geom,doodad); 939 } 940 } 941 if (addOn) 942 (*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv); 943 fprintf(file,"};\n\n"); 944 return True; 945} 946 947/*ARGSUSED*/ 948Bool 949XkbWriteXKBSemantics( FILE * file, 950 XkbFileInfo * result, 951 Bool topLevel, 952 Bool showImplicit, 953 XkbFileAddOnFunc addOn, 954 void * priv) 955{ 956Bool ok; 957 958 fprintf(file,"xkb_semantics {\n"); 959 ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv); 960 ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv); 961 fprintf(file,"};\n"); 962 return ok; 963} 964 965/*ARGSUSED*/ 966Bool 967XkbWriteXKBLayout( FILE * file, 968 XkbFileInfo * result, 969 Bool topLevel, 970 Bool showImplicit, 971 XkbFileAddOnFunc addOn, 972 void * priv) 973{ 974Bool ok; 975XkbDescPtr xkb; 976 977 xkb= result->xkb; 978 fprintf(file,"xkb_layout {\n"); 979 ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv); 980 ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv); 981 ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv); 982 if (xkb->geom) 983 ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv); 984 fprintf(file,"};\n"); 985 return ok; 986} 987 988/*ARGSUSED*/ 989Bool 990XkbWriteXKBKeymap( FILE * file, 991 XkbFileInfo * result, 992 Bool topLevel, 993 Bool showImplicit, 994 XkbFileAddOnFunc addOn, 995 void * priv) 996{ 997Bool ok; 998XkbDescPtr xkb; 999 1000 xkb= result->xkb; 1001 fprintf(file,"xkb_keymap {\n"); 1002 ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv); 1003 ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv); 1004 ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv); 1005 ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv); 1006 if (xkb->geom) 1007 ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv); 1008 fprintf(file,"};\n"); 1009 return ok; 1010} 1011 1012Bool 1013XkbWriteXKBFile( FILE * out, 1014 XkbFileInfo * result, 1015 Bool showImplicit, 1016 XkbFileAddOnFunc addOn, 1017 void * priv) 1018{ 1019Bool ok = False; 1020Bool (*func)( 1021 FILE * /* file */, 1022 XkbFileInfo * /* result */, 1023 Bool /* topLevel */, 1024 Bool /* showImplicit */, 1025 XkbFileAddOnFunc /* addOn */, 1026 void * /* priv */ 1027) = NULL; 1028 1029 switch (result->type) { 1030 case XkmSemanticsFile: 1031 func= XkbWriteXKBSemantics; 1032 break; 1033 case XkmLayoutFile: 1034 func= XkbWriteXKBLayout; 1035 break; 1036 case XkmKeymapFile: 1037 func= XkbWriteXKBKeymap; 1038 break; 1039 case XkmTypesIndex: 1040 func= XkbWriteXKBKeyTypes; 1041 break; 1042 case XkmCompatMapIndex: 1043 func= XkbWriteXKBCompatMap; 1044 break; 1045 case XkmSymbolsIndex: 1046 func= XkbWriteXKBSymbols; 1047 break; 1048 case XkmKeyNamesIndex: 1049 func= XkbWriteXKBKeycodes; 1050 break; 1051 case XkmGeometryFile: 1052 case XkmGeometryIndex: 1053 func= XkbWriteXKBGeometry; 1054 break; 1055 case XkmVirtualModsIndex: 1056 case XkmIndicatorsIndex: 1057 _XkbLibError(_XkbErrBadImplementation, 1058 XkbConfigText(result->type,XkbMessage),0); 1059 return False; 1060 } 1061 if (out==NULL) { 1062 _XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0); 1063 ok= False; 1064 } 1065 else if (func) { 1066 ok= (*func)(out,result,True,showImplicit,addOn,priv); 1067 } 1068 return ok; 1069} 1070