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