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