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#include <ctype.h> 33#include <stdlib.h> 34 35#include <X11/Xos.h> 36 37#include <X11/X.h> 38#include <X11/Xproto.h> 39#include <X11/extensions/XKMformat.h> 40#include "misc.h" 41#include "inputstr.h" 42#include "dix.h" 43#include "xkbstr.h" 44#define XKBSRV_NEED_FILE_FUNCS 1 45#include <xkbsrv.h> 46#include "xkbgeom.h" 47 48/***====================================================================***/ 49 50#define BUFFER_SIZE 512 51 52static char textBuffer[BUFFER_SIZE]; 53static int tbNext= 0; 54 55static char * 56tbGetBuffer(unsigned size) 57{ 58char *rtrn; 59 60 if (size>=BUFFER_SIZE) 61 return NULL; 62 if ((BUFFER_SIZE-tbNext)<=size) 63 tbNext= 0; 64 rtrn= &textBuffer[tbNext]; 65 tbNext+= size; 66 return rtrn; 67} 68 69/***====================================================================***/ 70 71char * 72XkbAtomText(Atom atm,unsigned format) 73{ 74const char *atmstr; 75char *rtrn,*tmp; 76 77 atmstr = NameForAtom(atm); 78 if (atmstr != NULL) { 79 int len; 80 len= strlen(atmstr)+1; 81 if (len>BUFFER_SIZE) 82 len= BUFFER_SIZE-2; 83 rtrn= tbGetBuffer(len); 84 strncpy(rtrn,atmstr,len); 85 rtrn[len]= '\0'; 86 } 87 else { 88 rtrn= tbGetBuffer(1); 89 rtrn[0]= '\0'; 90 } 91 if (format==XkbCFile) { 92 for (tmp=rtrn;*tmp!='\0';tmp++) { 93 if ((tmp==rtrn)&&(!isalpha(*tmp))) 94 *tmp= '_'; 95 else if (!isalnum(*tmp)) 96 *tmp= '_'; 97 } 98 } 99 return XkbStringText(rtrn,format); 100} 101 102/***====================================================================***/ 103 104char * 105XkbVModIndexText(XkbDescPtr xkb,unsigned ndx,unsigned format) 106{ 107register int len; 108register Atom *vmodNames; 109char *rtrn; 110const char *tmp; 111char numBuf[20]; 112 113 if (xkb && xkb->names) 114 vmodNames= xkb->names->vmods; 115 else vmodNames= NULL; 116 117 tmp= NULL; 118 if (ndx>=XkbNumVirtualMods) 119 tmp= "illegal"; 120 else if (vmodNames&&(vmodNames[ndx]!=None)) 121 tmp= NameForAtom(vmodNames[ndx]); 122 if (tmp==NULL) { 123 sprintf(numBuf,"%d",ndx); 124 tmp = numBuf; 125 } 126 127 len= strlen(tmp)+1; 128 if (format==XkbCFile) 129 len+= 4; 130 if (len>=BUFFER_SIZE) 131 len= BUFFER_SIZE-1; 132 rtrn= tbGetBuffer(len); 133 if (format==XkbCFile) { 134 strcpy(rtrn,"vmod_"); 135 strncpy(&rtrn[5],tmp,len-4); 136 } 137 else strncpy(rtrn,tmp,len); 138 return rtrn; 139} 140 141char * 142XkbVModMaskText( XkbDescPtr xkb, 143 unsigned modMask, 144 unsigned mask, 145 unsigned format) 146{ 147register int i,bit; 148int len; 149char *mm,*rtrn; 150char *str,buf[BUFFER_SIZE]; 151 152 if ((modMask==0)&&(mask==0)) { 153 rtrn= tbGetBuffer(5); 154 if (format==XkbCFile) 155 sprintf(rtrn,"0"); 156 else sprintf(rtrn,"none"); 157 return rtrn; 158 } 159 if (modMask!=0) 160 mm= XkbModMaskText(modMask,format); 161 else mm= NULL; 162 163 str= buf; 164 buf[0]= '\0'; 165 if (mask) { 166 char *tmp; 167 for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { 168 if (mask&bit) { 169 tmp= XkbVModIndexText(xkb,i,format); 170 len= strlen(tmp)+1+(str==buf?0:1); 171 if (format==XkbCFile) 172 len+= 4; 173 if ((str-(buf+len))<=BUFFER_SIZE) { 174 if (str!=buf) { 175 if (format==XkbCFile) *str++= '|'; 176 else *str++= '+'; 177 len--; 178 } 179 } 180 if (format==XkbCFile) 181 sprintf(str,"%sMask",tmp); 182 else strcpy(str,tmp); 183 str= &str[len-1]; 184 } 185 } 186 str= buf; 187 } 188 else str= NULL; 189 if (mm) 190 len= strlen(mm); 191 else len= 0; 192 if (str) 193 len+= strlen(str)+(mm==NULL?0:1); 194 if (len>=BUFFER_SIZE) 195 len= BUFFER_SIZE-1; 196 rtrn= tbGetBuffer(len+1); 197 rtrn[0]= '\0'; 198 199 if (mm!=NULL) { 200 i= strlen(mm); 201 if (i>len) 202 i= len; 203 strcpy(rtrn,mm); 204 } 205 else { 206 i=0; 207 } 208 if (str!=NULL) { 209 if (mm!=NULL) { 210 if (format==XkbCFile) strcat(rtrn,"|"); 211 else strcat(rtrn,"+"); 212 } 213 strncat(rtrn,str,len-i); 214 } 215 rtrn[len]= '\0'; 216 return rtrn; 217} 218 219static char *modNames[XkbNumModifiers] = { 220 "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" 221}; 222 223char * 224XkbModIndexText(unsigned ndx,unsigned format) 225{ 226char * rtrn; 227char buf[100]; 228 229 if (format==XkbCFile) { 230 if (ndx<XkbNumModifiers) 231 sprintf(buf,"%sMapIndex",modNames[ndx]); 232 else if (ndx==XkbNoModifier) 233 sprintf(buf,"XkbNoModifier"); 234 else sprintf(buf,"0x%02x",ndx); 235 } 236 else { 237 if (ndx<XkbNumModifiers) 238 strcpy(buf,modNames[ndx]); 239 else if (ndx==XkbNoModifier) 240 strcpy(buf,"none"); 241 else sprintf(buf,"ILLEGAL_%02x",ndx); 242 } 243 rtrn= tbGetBuffer(strlen(buf)+1); 244 strcpy(rtrn,buf); 245 return rtrn; 246} 247 248char * 249XkbModMaskText(unsigned mask,unsigned format) 250{ 251register int i,bit; 252char buf[64],*rtrn; 253 254 if ((mask&0xff)==0xff) { 255 if (format==XkbCFile) strcpy(buf,"0xff"); 256 else strcpy(buf,"all"); 257 } 258 else if ((mask&0xff)==0) { 259 if (format==XkbCFile) strcpy(buf,"0"); 260 else strcpy(buf,"none"); 261 } 262 else { 263 char *str= buf; 264 buf[0]= '\0'; 265 for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { 266 if (mask&bit) { 267 if (str!=buf) { 268 if (format==XkbCFile) *str++= '|'; 269 else *str++= '+'; 270 } 271 strcpy(str,modNames[i]); 272 str= &str[strlen(str)]; 273 if (format==XkbCFile) { 274 strcpy(str,"Mask"); 275 str+= 4; 276 } 277 } 278 } 279 } 280 rtrn= tbGetBuffer(strlen(buf)+1); 281 strcpy(rtrn,buf); 282 return rtrn; 283} 284 285/***====================================================================***/ 286 287/*ARGSUSED*/ 288char * 289XkbConfigText(unsigned config,unsigned format) 290{ 291static char *buf; 292 293 buf= tbGetBuffer(32); 294 switch (config) { 295 case XkmSemanticsFile: 296 strcpy(buf,"Semantics"); 297 break; 298 case XkmLayoutFile: 299 strcpy(buf,"Layout"); 300 break; 301 case XkmKeymapFile: 302 strcpy(buf,"Keymap"); 303 break; 304 case XkmGeometryFile: 305 case XkmGeometryIndex: 306 strcpy(buf,"Geometry"); 307 break; 308 case XkmTypesIndex: 309 strcpy(buf,"Types"); 310 break; 311 case XkmCompatMapIndex: 312 strcpy(buf,"CompatMap"); 313 break; 314 case XkmSymbolsIndex: 315 strcpy(buf,"Symbols"); 316 break; 317 case XkmIndicatorsIndex: 318 strcpy(buf,"Indicators"); 319 break; 320 case XkmKeyNamesIndex: 321 strcpy(buf,"KeyNames"); 322 break; 323 case XkmVirtualModsIndex: 324 strcpy(buf,"VirtualMods"); 325 break; 326 default: 327 sprintf(buf,"unknown(%d)",config); 328 break; 329 } 330 return buf; 331} 332 333/***====================================================================***/ 334 335char * 336XkbKeysymText(KeySym sym,unsigned format) 337{ 338static char buf[32],*rtrn; 339 340 if (sym==NoSymbol) 341 strcpy(rtrn=buf,"NoSymbol"); 342 else sprintf(rtrn=buf, "0x%lx", (long)sym); 343 return rtrn; 344} 345 346char * 347XkbKeyNameText(char *name,unsigned format) 348{ 349char *buf; 350 351 if (format==XkbCFile) { 352 buf= tbGetBuffer(5); 353 memcpy(buf,name,4); 354 buf[4]= '\0'; 355 } 356 else { 357 int len; 358 buf= tbGetBuffer(7); 359 buf[0]= '<'; 360 memcpy(&buf[1],name,4); 361 buf[5]= '\0'; 362 len= strlen(buf); 363 buf[len++]= '>'; 364 buf[len]= '\0'; 365 } 366 return buf; 367} 368 369/***====================================================================***/ 370 371static char *siMatchText[5] = { 372 "NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly" 373}; 374 375char * 376XkbSIMatchText(unsigned type,unsigned format) 377{ 378static char buf[40]; 379char *rtrn; 380 381 switch (type&XkbSI_OpMask) { 382 case XkbSI_NoneOf: rtrn= siMatchText[0]; break; 383 case XkbSI_AnyOfOrNone: rtrn= siMatchText[1]; break; 384 case XkbSI_AnyOf: rtrn= siMatchText[2]; break; 385 case XkbSI_AllOf: rtrn= siMatchText[3]; break; 386 case XkbSI_Exactly: rtrn= siMatchText[4]; break; 387 default: sprintf(buf,"0x%x",type&XkbSI_OpMask); 388 return buf; 389 } 390 if (format==XkbCFile) { 391 if (type&XkbSI_LevelOneOnly) 392 sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn); 393 else sprintf(buf,"XkbSI_%s",rtrn); 394 rtrn= buf; 395 } 396 return rtrn; 397} 398 399/***====================================================================***/ 400 401static char *imWhichNames[]= { 402 "base", 403 "latched", 404 "locked", 405 "effective", 406 "compat" 407}; 408 409char * 410XkbIMWhichStateMaskText(unsigned use_which,unsigned format) 411{ 412int len; 413unsigned i,bit,tmp; 414char * buf; 415 416 if (use_which==0) { 417 buf= tbGetBuffer(2); 418 strcpy(buf,"0"); 419 return buf; 420 } 421 tmp= use_which&XkbIM_UseAnyMods; 422 for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { 423 if (tmp&bit) { 424 tmp&= ~bit; 425 len+= strlen(imWhichNames[i])+1; 426 if (format==XkbCFile) 427 len+= 9; 428 } 429 } 430 buf= tbGetBuffer(len+1); 431 tmp= use_which&XkbIM_UseAnyMods; 432 for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { 433 if (tmp&bit) { 434 tmp&= ~bit; 435 if (format==XkbCFile) { 436 if (len!=0) 437 buf[len++]= '|'; 438 sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]); 439 buf[len+9]= toupper(buf[len+9]); 440 } 441 else { 442 if (len!=0) 443 buf[len++]= '+'; 444 sprintf(&buf[len],"%s",imWhichNames[i]); 445 } 446 len+= strlen(&buf[len]); 447 } 448 } 449 return buf; 450} 451 452static char *ctrlNames[] = { 453 "repeatKeys", 454 "slowKeys", 455 "bounceKeys", 456 "stickyKeys", 457 "mouseKeys", 458 "mouseKeysAccel", 459 "accessXKeys", 460 "accessXTimeout", 461 "accessXFeedback", 462 "audibleBell", 463 "overlay1", 464 "overlay2", 465 "ignoreGroupLock" 466}; 467 468char * 469XkbControlsMaskText(unsigned ctrls,unsigned format) 470{ 471int len; 472unsigned i,bit,tmp; 473char * buf; 474 475 if (ctrls==0) { 476 buf= tbGetBuffer(5); 477 if (format==XkbCFile) 478 strcpy(buf,"0"); 479 else strcpy(buf,"none"); 480 return buf; 481 } 482 tmp= ctrls&XkbAllBooleanCtrlsMask; 483 for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { 484 if (tmp&bit) { 485 tmp&= ~bit; 486 len+= strlen(ctrlNames[i])+1; 487 if (format==XkbCFile) 488 len+= 7; 489 } 490 } 491 buf= tbGetBuffer(len+1); 492 tmp= ctrls&XkbAllBooleanCtrlsMask; 493 for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) { 494 if (tmp&bit) { 495 tmp&= ~bit; 496 if (format==XkbCFile) { 497 if (len!=0) 498 buf[len++]= '|'; 499 sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]); 500 buf[len+3]= toupper(buf[len+3]); 501 } 502 else { 503 if (len!=0) 504 buf[len++]= '+'; 505 sprintf(&buf[len],"%s",ctrlNames[i]); 506 } 507 len+= strlen(&buf[len]); 508 } 509 } 510 return buf; 511} 512 513/***====================================================================***/ 514 515char * 516XkbStringText(char *str,unsigned format) 517{ 518char * buf; 519register char *in,*out; 520int len; 521Bool ok; 522 523 if (str==NULL) { 524 buf= tbGetBuffer(2); 525 buf[0]='\0'; 526 return buf; 527 } 528 else if (format==XkbXKMFile) 529 return str; 530 for (ok= TRUE,len=0,in=str;*in!='\0';in++,len++) { 531 if (!isprint(*in)) { 532 ok= FALSE; 533 switch (*in) { 534 case '\n': case '\t': case '\v': 535 case '\b': case '\r': case '\f': 536 len++; 537 break; 538 default: 539 len+= 4; 540 break; 541 } 542 } 543 } 544 if (ok) 545 return str; 546 buf= tbGetBuffer(len+1); 547 for (in=str,out=buf;*in!='\0';in++) { 548 if (isprint(*in)) 549 *out++= *in; 550 else { 551 *out++= '\\'; 552 if (*in=='\n') *out++= 'n'; 553 else if (*in=='\t') *out++= 't'; 554 else if (*in=='\v') *out++= 'v'; 555 else if (*in=='\b') *out++= 'b'; 556 else if (*in=='\r') *out++= 'r'; 557 else if (*in=='\f') *out++= 'f'; 558 else if ((*in=='\033')&&(format==XkbXKMFile)) { 559 *out++= 'e'; 560 } 561 else { 562 *out++= '0'; 563 sprintf(out,"%o",*in); 564 while (*out!='\0') 565 out++; 566 } 567 } 568 } 569 *out++= '\0'; 570 return buf; 571} 572 573/***====================================================================***/ 574 575char * 576XkbGeomFPText(int val,unsigned format) 577{ 578int whole,frac; 579char * buf; 580 581 buf= tbGetBuffer(12); 582 if (format==XkbCFile) { 583 sprintf(buf,"%d",val); 584 } 585 else { 586 whole= val/XkbGeomPtsPerMM; 587 frac= val%XkbGeomPtsPerMM; 588 if (frac!=0) 589 sprintf(buf,"%d.%d",whole,frac); 590 else sprintf(buf,"%d",whole); 591 } 592 return buf; 593} 594 595char * 596XkbDoodadTypeText(unsigned type,unsigned format) 597{ 598char * buf; 599 if (format==XkbCFile) { 600 buf= tbGetBuffer(24); 601 if (type==XkbOutlineDoodad) strcpy(buf,"XkbOutlineDoodad"); 602 else if (type==XkbSolidDoodad) strcpy(buf,"XkbSolidDoodad"); 603 else if (type==XkbTextDoodad) strcpy(buf,"XkbTextDoodad"); 604 else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad"); 605 else if (type==XkbLogoDoodad) strcpy(buf,"XkbLogoDoodad"); 606 else sprintf(buf,"UnknownDoodad%d",type); 607 } 608 else { 609 buf= tbGetBuffer(12); 610 if (type==XkbOutlineDoodad) strcpy(buf,"outline"); 611 else if (type==XkbSolidDoodad) strcpy(buf,"solid"); 612 else if (type==XkbTextDoodad) strcpy(buf,"text"); 613 else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator"); 614 else if (type==XkbLogoDoodad) strcpy(buf,"logo"); 615 else sprintf(buf,"unknown%d",type); 616 } 617 return buf; 618} 619 620static char *actionTypeNames[XkbSA_NumActions]= { 621 "NoAction", 622 "SetMods", "LatchMods", "LockMods", 623 "SetGroup", "LatchGroup", "LockGroup", 624 "MovePtr", 625 "PtrBtn", "LockPtrBtn", 626 "SetPtrDflt", 627 "ISOLock", 628 "Terminate", "SwitchScreen", 629 "SetControls", "LockControls", 630 "ActionMessage", 631 "RedirectKey", 632 "DeviceBtn", "LockDeviceBtn" 633}; 634 635char * 636XkbActionTypeText(unsigned type,unsigned format) 637{ 638static char buf[32]; 639char *rtrn; 640 641 if (type<=XkbSA_LastAction) { 642 rtrn= actionTypeNames[type]; 643 if (format==XkbCFile) { 644 sprintf(buf,"XkbSA_%s",rtrn); 645 return buf; 646 } 647 return rtrn; 648 } 649 sprintf(buf,"Private"); 650 return buf; 651} 652 653/***====================================================================***/ 654 655static int 656TryCopyStr(char *to,char *from,int *pLeft) 657{ 658register int len; 659 if (*pLeft>0) { 660 len= strlen(from); 661 if (len<((*pLeft)-3)) { 662 strcat(to,from); 663 *pLeft-= len; 664 return TRUE; 665 } 666 } 667 *pLeft= -1; 668 return FALSE; 669} 670 671/*ARGSUSED*/ 672static Bool 673CopyNoActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int*sz) 674{ 675 return TRUE; 676} 677 678static Bool 679CopyModActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 680 int* sz) 681{ 682XkbModAction * act; 683unsigned tmp; 684 685 act= &action->mods; 686 tmp= XkbModActionVMods(act); 687 TryCopyStr(buf,"modifiers=",sz); 688 if (act->flags&XkbSA_UseModMapMods) 689 TryCopyStr(buf,"modMapMods",sz); 690 else if (act->real_mods || tmp) { 691 TryCopyStr(buf, 692 XkbVModMaskText(xkb,act->real_mods,tmp,XkbXKBFile), 693 sz); 694 } 695 else TryCopyStr(buf,"none",sz); 696 if (act->type==XkbSA_LockMods) 697 return TRUE; 698 if (act->flags&XkbSA_ClearLocks) 699 TryCopyStr(buf,",clearLocks",sz); 700 if (act->flags&XkbSA_LatchToLock) 701 TryCopyStr(buf,",latchToLock",sz); 702 return TRUE; 703} 704 705/*ARGSUSED*/ 706static Bool 707CopyGroupActionArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 708 int *sz) 709{ 710XkbGroupAction * act; 711char tbuf[32]; 712 713 act= &action->group; 714 TryCopyStr(buf,"group=",sz); 715 if (act->flags&XkbSA_GroupAbsolute) 716 sprintf(tbuf,"%d",XkbSAGroup(act)+1); 717 else if (XkbSAGroup(act)<0) 718 sprintf(tbuf,"%d",XkbSAGroup(act)); 719 else sprintf(tbuf,"+%d",XkbSAGroup(act)); 720 TryCopyStr(buf,tbuf,sz); 721 if (act->type==XkbSA_LockGroup) 722 return TRUE; 723 if (act->flags&XkbSA_ClearLocks) 724 TryCopyStr(buf,",clearLocks",sz); 725 if (act->flags&XkbSA_LatchToLock) 726 TryCopyStr(buf,",latchToLock",sz); 727 return TRUE; 728} 729 730/*ARGSUSED*/ 731static Bool 732CopyMovePtrArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) 733{ 734XkbPtrAction * act; 735int x,y; 736char tbuf[32]; 737 738 act= &action->ptr; 739 x= XkbPtrActionX(act); 740 y= XkbPtrActionY(act); 741 if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0)) 742 sprintf(tbuf,"x=%d",x); 743 else sprintf(tbuf,"x=+%d",x); 744 TryCopyStr(buf,tbuf,sz); 745 746 if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0)) 747 sprintf(tbuf,",y=%d",y); 748 else sprintf(tbuf,",y=+%d",y); 749 TryCopyStr(buf,tbuf,sz); 750 if (act->flags&XkbSA_NoAcceleration) 751 TryCopyStr(buf,",!accel",sz); 752 return TRUE; 753} 754 755/*ARGSUSED*/ 756static Bool 757CopyPtrBtnArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) 758{ 759XkbPtrBtnAction * act; 760char tbuf[32]; 761 762 act= &action->btn; 763 TryCopyStr(buf,"button=",sz); 764 if ((act->button>0)&&(act->button<6)) { 765 sprintf(tbuf,"%d",act->button); 766 TryCopyStr(buf,tbuf,sz); 767 } 768 else TryCopyStr(buf,"default",sz); 769 if (act->count>0) { 770 sprintf(tbuf,",count=%d",act->count); 771 TryCopyStr(buf,tbuf,sz); 772 } 773 if (action->type==XkbSA_LockPtrBtn) { 774 switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { 775 case XkbSA_LockNoLock: 776 sprintf(tbuf,",affect=unlock"); break; 777 case XkbSA_LockNoUnlock: 778 sprintf(tbuf,",affect=lock"); break; 779 case XkbSA_LockNoUnlock|XkbSA_LockNoLock: 780 sprintf(tbuf,",affect=neither"); break; 781 default: 782 sprintf(tbuf,",affect=both"); break; 783 } 784 TryCopyStr(buf,tbuf,sz); 785 } 786 return TRUE; 787} 788 789/*ARGSUSED*/ 790static Bool 791CopySetPtrDfltArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 792 int *sz) 793{ 794XkbPtrDfltAction * act; 795char tbuf[32]; 796 797 act= &action->dflt; 798 if (act->affect==XkbSA_AffectDfltBtn) { 799 TryCopyStr(buf,"affect=button,button=",sz); 800 if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0)) 801 sprintf(tbuf,"%d",XkbSAPtrDfltValue(act)); 802 else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act)); 803 TryCopyStr(buf,tbuf,sz); 804 } 805 return TRUE; 806} 807 808static Bool 809CopyISOLockArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) 810{ 811XkbISOAction * act; 812char tbuf[64]; 813 814 act= &action->iso; 815 if (act->flags&XkbSA_ISODfltIsGroup) { 816 TryCopyStr(tbuf,"group=",sz); 817 if (act->flags&XkbSA_GroupAbsolute) 818 sprintf(tbuf,"%d",XkbSAGroup(act)+1); 819 else if (XkbSAGroup(act)<0) 820 sprintf(tbuf,"%d",XkbSAGroup(act)); 821 else sprintf(tbuf,"+%d",XkbSAGroup(act)); 822 TryCopyStr(buf,tbuf,sz); 823 } 824 else { 825 unsigned tmp; 826 tmp= XkbModActionVMods(act); 827 TryCopyStr(buf,"modifiers=",sz); 828 if (act->flags&XkbSA_UseModMapMods) 829 TryCopyStr(buf,"modMapMods",sz); 830 else if (act->real_mods || tmp) { 831 if (act->real_mods) { 832 TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz); 833 if (tmp) 834 TryCopyStr(buf,"+",sz); 835 } 836 if (tmp) 837 TryCopyStr(buf,XkbVModMaskText(xkb,0,tmp,XkbXKBFile),sz); 838 } 839 else TryCopyStr(buf,"none",sz); 840 } 841 TryCopyStr(buf,",affect=",sz); 842 if ((act->affect&XkbSA_ISOAffectMask)==0) 843 TryCopyStr(buf,"all",sz); 844 else { 845 int nOut= 0; 846 if ((act->affect&XkbSA_ISONoAffectMods)==0) { 847 TryCopyStr(buf,"mods",sz); 848 nOut++; 849 } 850 if ((act->affect&XkbSA_ISONoAffectGroup)==0) { 851 sprintf(tbuf,"%sgroups",(nOut>0?"+":"")); 852 TryCopyStr(buf,tbuf,sz); 853 nOut++; 854 } 855 if ((act->affect&XkbSA_ISONoAffectPtr)==0) { 856 sprintf(tbuf,"%spointer",(nOut>0?"+":"")); 857 TryCopyStr(buf,tbuf,sz); 858 nOut++; 859 } 860 if ((act->affect&XkbSA_ISONoAffectCtrls)==0) { 861 sprintf(tbuf,"%scontrols",(nOut>0?"+":"")); 862 TryCopyStr(buf,tbuf,sz); 863 nOut++; 864 } 865 } 866 return TRUE; 867} 868 869/*ARGSUSED*/ 870static Bool 871CopySwitchScreenArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 872 int *sz) 873{ 874XkbSwitchScreenAction * act; 875char tbuf[32]; 876 877 act= &action->screen; 878 if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0)) 879 sprintf(tbuf,"screen=%d",XkbSAScreen(act)); 880 else sprintf(tbuf,"screen=+%d",XkbSAScreen(act)); 881 TryCopyStr(buf,tbuf,sz); 882 if (act->flags&XkbSA_SwitchApplication) 883 TryCopyStr(buf,",!same",sz); 884 else TryCopyStr(buf,",same",sz); 885 return TRUE; 886} 887 888/*ARGSUSED*/ 889static Bool 890CopySetLockControlsArgs(XkbDescPtr xkb,XkbAction *action, 891 char *buf,int *sz) 892{ 893XkbCtrlsAction * act; 894unsigned tmp; 895char tbuf[32]; 896 897 act= &action->ctrls; 898 tmp= XkbActionCtrls(act); 899 TryCopyStr(buf,"controls=",sz); 900 if (tmp==0) 901 TryCopyStr(buf,"none",sz); 902 else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask) 903 TryCopyStr(buf,"all",sz); 904 else { 905 int nOut= 0; 906 if (tmp&XkbRepeatKeysMask) { 907 sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":"")); 908 TryCopyStr(buf,tbuf,sz); 909 nOut++; 910 } 911 if (tmp&XkbSlowKeysMask) { 912 sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":"")); 913 TryCopyStr(buf,tbuf,sz); 914 nOut++; 915 } 916 if (tmp&XkbBounceKeysMask) { 917 sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":"")); 918 TryCopyStr(buf,tbuf,sz); 919 nOut++; 920 } 921 if (tmp&XkbStickyKeysMask) { 922 sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":"")); 923 TryCopyStr(buf,tbuf,sz); 924 nOut++; 925 } 926 if (tmp&XkbMouseKeysMask) { 927 sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":"")); 928 TryCopyStr(buf,tbuf,sz); 929 nOut++; 930 } 931 if (tmp&XkbMouseKeysAccelMask) { 932 sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":"")); 933 TryCopyStr(buf,tbuf,sz); 934 nOut++; 935 } 936 if (tmp&XkbAccessXKeysMask) { 937 sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":"")); 938 TryCopyStr(buf,tbuf,sz); 939 nOut++; 940 } 941 if (tmp&XkbAccessXTimeoutMask) { 942 sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":"")); 943 TryCopyStr(buf,tbuf,sz); 944 nOut++; 945 } 946 if (tmp&XkbAccessXFeedbackMask) { 947 sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":"")); 948 TryCopyStr(buf,tbuf,sz); 949 nOut++; 950 } 951 if (tmp&XkbAudibleBellMask) { 952 sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":"")); 953 TryCopyStr(buf,tbuf,sz); 954 nOut++; 955 } 956 if (tmp&XkbOverlay1Mask) { 957 sprintf(tbuf,"%sOverlay1",(nOut>0?"+":"")); 958 TryCopyStr(buf,tbuf,sz); 959 nOut++; 960 } 961 if (tmp&XkbOverlay2Mask) { 962 sprintf(tbuf,"%sOverlay2",(nOut>0?"+":"")); 963 TryCopyStr(buf,tbuf,sz); 964 nOut++; 965 } 966 if (tmp&XkbIgnoreGroupLockMask) { 967 sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":"")); 968 TryCopyStr(buf,tbuf,sz); 969 nOut++; 970 } 971 } 972 return TRUE; 973} 974 975/*ARGSUSED*/ 976static Bool 977CopyActionMessageArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 978 int *sz) 979{ 980XkbMessageAction * act; 981unsigned all; 982char tbuf[32]; 983 984 act= &action->msg; 985 all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease; 986 TryCopyStr(buf,"report=",sz); 987 if ((act->flags&all)==0) 988 TryCopyStr(buf,"none",sz); 989 else if ((act->flags&all)==all) 990 TryCopyStr(buf,"all",sz); 991 else if (act->flags&XkbSA_MessageOnPress) 992 TryCopyStr(buf,"KeyPress",sz); 993 else TryCopyStr(buf,"KeyRelease",sz); 994 sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz); 995 sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz); 996 sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz); 997 sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz); 998 sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz); 999 sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz); 1000 return TRUE; 1001} 1002 1003static Bool 1004CopyRedirectKeyArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 1005 int *sz) 1006{ 1007XkbRedirectKeyAction * act; 1008char tbuf[32],*tmp; 1009unsigned kc; 1010unsigned vmods,vmods_mask; 1011 1012 act= &action->redirect; 1013 kc= act->new_key; 1014 vmods= XkbSARedirectVMods(act); 1015 vmods_mask= XkbSARedirectVModsMask(act); 1016 if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) && 1017 (xkb->names->keys[kc].name[0]!='\0')) { 1018 char *kn; 1019 kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); 1020 sprintf(tbuf,"key=%s",kn); 1021 } 1022 else sprintf(tbuf,"key=%d",kc); 1023 TryCopyStr(buf,tbuf,sz); 1024 if ((act->mods_mask==0)&&(vmods_mask==0)) 1025 return TRUE; 1026 if ((act->mods_mask==XkbAllModifiersMask)&& 1027 (vmods_mask==XkbAllVirtualModsMask)) { 1028 tmp= XkbVModMaskText(xkb,act->mods,vmods,XkbXKBFile); 1029 TryCopyStr(buf,",mods=",sz); 1030 TryCopyStr(buf,tmp,sz); 1031 } 1032 else { 1033 if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) { 1034 tmp= XkbVModMaskText(xkb,act->mods_mask&act->mods, 1035 vmods_mask&vmods,XkbXKBFile); 1036 TryCopyStr(buf,",mods= ",sz); 1037 TryCopyStr(buf,tmp,sz); 1038 } 1039 if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) { 1040 tmp= XkbVModMaskText(xkb,act->mods_mask&(~act->mods), 1041 vmods_mask&(~vmods),XkbXKBFile); 1042 TryCopyStr(buf,",clearMods= ",sz); 1043 TryCopyStr(buf,tmp,sz); 1044 } 1045 } 1046 return TRUE; 1047} 1048 1049/*ARGSUSED*/ 1050static Bool 1051CopyDeviceBtnArgs(XkbDescPtr xkb,XkbAction *action,char *buf, 1052 int *sz) 1053{ 1054XkbDeviceBtnAction * act; 1055char tbuf[32]; 1056 1057 act= &action->devbtn; 1058 sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz); 1059 TryCopyStr(buf,",button=",sz); 1060 sprintf(tbuf,"%d",act->button); 1061 TryCopyStr(buf,tbuf,sz); 1062 if (act->count>0) { 1063 sprintf(tbuf,",count=%d",act->count); 1064 TryCopyStr(buf,tbuf,sz); 1065 } 1066 if (action->type==XkbSA_LockDeviceBtn) { 1067 switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) { 1068 case XkbSA_LockNoLock: 1069 sprintf(tbuf,",affect=unlock"); break; 1070 case XkbSA_LockNoUnlock: 1071 sprintf(tbuf,",affect=lock"); break; 1072 case XkbSA_LockNoUnlock|XkbSA_LockNoLock: 1073 sprintf(tbuf,",affect=neither"); break; 1074 default: 1075 sprintf(tbuf,",affect=both"); break; 1076 } 1077 TryCopyStr(buf,tbuf,sz); 1078 } 1079 return TRUE; 1080} 1081 1082/*ARGSUSED*/ 1083static Bool 1084CopyOtherArgs(XkbDescPtr xkb,XkbAction *action,char *buf,int *sz) 1085{ 1086XkbAnyAction * act; 1087char tbuf[32]; 1088 1089 act= &action->any; 1090 sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz); 1091 sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz); 1092 sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz); 1093 sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz); 1094 sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz); 1095 sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz); 1096 sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz); 1097 sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz); 1098 return TRUE; 1099} 1100 1101typedef Bool (*actionCopy)( 1102 XkbDescPtr /* xkb */, 1103 XkbAction * /* action */, 1104 char * /* buf */, 1105 int* /* sz */ 1106); 1107static actionCopy copyActionArgs[XkbSA_NumActions] = { 1108 CopyNoActionArgs /* NoAction */, 1109 CopyModActionArgs /* SetMods */, 1110 CopyModActionArgs /* LatchMods */, 1111 CopyModActionArgs /* LockMods */, 1112 CopyGroupActionArgs /* SetGroup */, 1113 CopyGroupActionArgs /* LatchGroup */, 1114 CopyGroupActionArgs /* LockGroup */, 1115 CopyMovePtrArgs /* MovePtr */, 1116 CopyPtrBtnArgs /* PtrBtn */, 1117 CopyPtrBtnArgs /* LockPtrBtn */, 1118 CopySetPtrDfltArgs /* SetPtrDflt */, 1119 CopyISOLockArgs /* ISOLock */, 1120 CopyNoActionArgs /* Terminate */, 1121 CopySwitchScreenArgs /* SwitchScreen */, 1122 CopySetLockControlsArgs /* SetControls */, 1123 CopySetLockControlsArgs /* LockControls */, 1124 CopyActionMessageArgs /* ActionMessage*/, 1125 CopyRedirectKeyArgs /* RedirectKey */, 1126 CopyDeviceBtnArgs /* DeviceBtn */, 1127 CopyDeviceBtnArgs /* LockDeviceBtn*/ 1128}; 1129 1130#define ACTION_SZ 256 1131 1132char * 1133XkbActionText(XkbDescPtr xkb,XkbAction *action,unsigned format) 1134{ 1135char buf[ACTION_SZ],*tmp; 1136int sz; 1137 1138 if (format==XkbCFile) { 1139 sprintf(buf, 1140 "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }", 1141 XkbActionTypeText(action->type,XkbCFile), 1142 action->any.data[0],action->any.data[1],action->any.data[2], 1143 action->any.data[3],action->any.data[4],action->any.data[5], 1144 action->any.data[6]); 1145 } 1146 else { 1147 sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile)); 1148 sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */ 1149 if (action->type<(unsigned)XkbSA_NumActions) 1150 (*copyActionArgs[action->type])(xkb,action,buf,&sz); 1151 else CopyOtherArgs(xkb,action,buf,&sz); 1152 TryCopyStr(buf,")",&sz); 1153 } 1154 tmp= tbGetBuffer(strlen(buf)+1); 1155 if (tmp!=NULL) 1156 strcpy(tmp,buf); 1157 return tmp; 1158} 1159 1160char * 1161XkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format) 1162{ 1163char buf[256],*tmp; 1164 1165 if (format==XkbCFile) { 1166 if (behavior->type==XkbKB_Default) 1167 sprintf(buf,"{ 0, 0 }"); 1168 else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data); 1169 } 1170 else { 1171 unsigned type,permanent; 1172 type= behavior->type&XkbKB_OpMask; 1173 permanent=((behavior->type&XkbKB_Permanent)!=0); 1174 1175 if (type==XkbKB_Lock) { 1176 sprintf(buf,"lock= %s",(permanent?"Permanent":"TRUE")); 1177 } 1178 else if (type==XkbKB_RadioGroup) { 1179 int g; 1180 char *tmp; 1181 g= ((behavior->data)&(~XkbKB_RGAllowNone))+1; 1182 if (XkbKB_RGAllowNone&behavior->data) { 1183 sprintf(buf,"allowNone,"); 1184 tmp= &buf[strlen(buf)]; 1185 } 1186 else tmp= buf; 1187 if (permanent) 1188 sprintf(tmp,"permanentRadioGroup= %d",g); 1189 else sprintf(tmp,"radioGroup= %d",g); 1190 } 1191 else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) { 1192 int ndx,kc; 1193 char *kn; 1194 1195 ndx= ((type==XkbKB_Overlay1)?1:2); 1196 kc= behavior->data; 1197 if ((xkb)&&(xkb->names)&&(xkb->names->keys)) 1198 kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile); 1199 else { 1200 static char tbuf[8]; 1201 sprintf(tbuf,"%d",kc); 1202 kn= tbuf; 1203 } 1204 if (permanent) 1205 sprintf(buf,"permanentOverlay%d= %s",ndx,kn); 1206 else sprintf(buf,"overlay%d= %s",ndx,kn); 1207 } 1208 } 1209 tmp= tbGetBuffer(strlen(buf)+1); 1210 if (tmp!=NULL) 1211 strcpy(tmp,buf); 1212 return tmp; 1213} 1214 1215/***====================================================================***/ 1216 1217char * 1218XkbIndentText(unsigned size) 1219{ 1220static char buf[32]; 1221register int i; 1222 1223 if (size>31) 1224 size= 31; 1225 1226 for (i=0;i<size;i++) { 1227 buf[i]= ' '; 1228 } 1229 buf[size]= '\0'; 1230 return buf; 1231} 1232