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