Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / xkbtext.c
CommitLineData
a09e091a
JB
1/************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <ctype.h>
33#include <stdlib.h>
34
35#include <X11/Xos.h>
36
37#include <X11/X.h>
38#include <X11/Xproto.h>
39#include <X11/extensions/XKMformat.h>
40#include "misc.h"
41#include "inputstr.h"
42#include "dix.h"
43#include "xkbstr.h"
44#define XKBSRV_NEED_FILE_FUNCS 1
45#include <xkbsrv.h>
46#include "xkbgeom.h"
47
48/***====================================================================***/
49
50#define BUFFER_SIZE 512
51
52static char textBuffer[BUFFER_SIZE];
53static int tbNext = 0;
54
55static char *
56tbGetBuffer(unsigned size)
57{
58 char *rtrn;
59
60 if (size >= BUFFER_SIZE)
61 return NULL;
62 if ((BUFFER_SIZE - tbNext) <= size)
63 tbNext = 0;
64 rtrn = &textBuffer[tbNext];
65 tbNext += size;
66 return rtrn;
67}
68
69/***====================================================================***/
70
71char *
72XkbAtomText(Atom atm, unsigned format)
73{
74 const char *atmstr;
75 char *rtrn, *tmp;
76
77 atmstr = NameForAtom(atm);
78 if (atmstr != NULL) {
79 int len;
80
81 len = strlen(atmstr) + 1;
82 if (len > BUFFER_SIZE)
83 len = BUFFER_SIZE - 2;
84 rtrn = tbGetBuffer(len);
85 strlcpy(rtrn, atmstr, len);
86 }
87 else {
88 rtrn = tbGetBuffer(1);
89 rtrn[0] = '\0';
90 }
91 if (format == XkbCFile) {
92 for (tmp = rtrn; *tmp != '\0'; tmp++) {
93 if ((tmp == rtrn) && (!isalpha(*tmp)))
94 *tmp = '_';
95 else if (!isalnum(*tmp))
96 *tmp = '_';
97 }
98 }
99 return XkbStringText(rtrn, format);
100}
101
102/***====================================================================***/
103
104char *
105XkbVModIndexText(XkbDescPtr xkb, unsigned ndx, unsigned format)
106{
107 register int len;
108 register Atom *vmodNames;
109 char *rtrn;
110 const char *tmp;
111 char numBuf[20];
112
113 if (xkb && xkb->names)
114 vmodNames = xkb->names->vmods;
115 else
116 vmodNames = NULL;
117
118 tmp = NULL;
119 if (ndx >= XkbNumVirtualMods)
120 tmp = "illegal";
121 else if (vmodNames && (vmodNames[ndx] != None))
122 tmp = NameForAtom(vmodNames[ndx]);
123 if (tmp == NULL) {
124 snprintf(numBuf, sizeof(numBuf), "%d", ndx);
125 tmp = numBuf;
126 }
127
128 len = strlen(tmp) + 1;
129 if (format == XkbCFile)
130 len += 4;
131 if (len >= BUFFER_SIZE)
132 len = BUFFER_SIZE - 1;
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
143char *
144XkbVModMaskText(XkbDescPtr xkb,
145 unsigned modMask, unsigned mask, unsigned format)
146{
147 register int i, bit;
148 int len;
149 char *mm, *rtrn;
150 char *str, buf[BUFFER_SIZE];
151
152 if ((modMask == 0) && (mask == 0)) {
153 rtrn = tbGetBuffer(5);
154 if (format == XkbCFile)
155 sprintf(rtrn, "0");
156 else
157 sprintf(rtrn, "none");
158 return rtrn;
159 }
160 if (modMask != 0)
161 mm = XkbModMaskText(modMask, format);
162 else
163 mm = NULL;
164
165 str = buf;
166 buf[0] = '\0';
167 if (mask) {
168 char *tmp;
169
170 for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
171 if (mask & bit) {
172 tmp = XkbVModIndexText(xkb, i, format);
173 len = strlen(tmp) + 1 + (str == buf ? 0 : 1);
174 if (format == XkbCFile)
175 len += 4;
176 if ((str - (buf + len)) <= BUFFER_SIZE) {
177 if (str != buf) {
178 if (format == XkbCFile)
179 *str++ = '|';
180 else
181 *str++ = '+';
182 len--;
183 }
184 }
185 if (format == XkbCFile)
186 sprintf(str, "%sMask", tmp);
187 else
188 strcpy(str, tmp);
189 str = &str[len - 1];
190 }
191 }
192 str = buf;
193 }
194 else
195 str = NULL;
196 if (mm)
197 len = strlen(mm);
198 else
199 len = 0;
200 if (str)
201 len += strlen(str) + (mm == NULL ? 0 : 1);
202 if (len >= BUFFER_SIZE)
203 len = BUFFER_SIZE - 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", *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 act = &action->iso;
874 if (act->flags & XkbSA_ISODfltIsGroup) {
875 TryCopyStr(tbuf, "group=", sz);
876 if (act->flags & XkbSA_GroupAbsolute)
877 snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act) + 1);
878 else if (XkbSAGroup(act) < 0)
879 snprintf(tbuf, sizeof(tbuf), "%d", XkbSAGroup(act));
880 else
881 snprintf(tbuf, sizeof(tbuf), "+%d", XkbSAGroup(act));
882 TryCopyStr(buf, tbuf, sz);
883 }
884 else {
885 unsigned tmp;
886
887 tmp = XkbModActionVMods(act);
888 TryCopyStr(buf, "modifiers=", sz);
889 if (act->flags & XkbSA_UseModMapMods)
890 TryCopyStr(buf, "modMapMods", sz);
891 else if (act->real_mods || tmp) {
892 if (act->real_mods) {
893 TryCopyStr(buf, XkbModMaskText(act->real_mods, XkbXKBFile), sz);
894 if (tmp)
895 TryCopyStr(buf, "+", sz);
896 }
897 if (tmp)
898 TryCopyStr(buf, XkbVModMaskText(xkb, 0, tmp, XkbXKBFile), sz);
899 }
900 else
901 TryCopyStr(buf, "none", sz);
902 }
903 TryCopyStr(buf, ",affect=", sz);
904 if ((act->affect & XkbSA_ISOAffectMask) == 0)
905 TryCopyStr(buf, "all", sz);
906 else {
907 int nOut = 0;
908
909 if ((act->affect & XkbSA_ISONoAffectMods) == 0) {
910 TryCopyStr(buf, "mods", sz);
911 nOut++;
912 }
913 if ((act->affect & XkbSA_ISONoAffectGroup) == 0) {
914 snprintf(tbuf, sizeof(tbuf), "%sgroups", (nOut > 0 ? "+" : ""));
915 TryCopyStr(buf, tbuf, sz);
916 nOut++;
917 }
918 if ((act->affect & XkbSA_ISONoAffectPtr) == 0) {
919 snprintf(tbuf, sizeof(tbuf), "%spointer", (nOut > 0 ? "+" : ""));
920 TryCopyStr(buf, tbuf, sz);
921 nOut++;
922 }
923 if ((act->affect & XkbSA_ISONoAffectCtrls) == 0) {
924 snprintf(tbuf, sizeof(tbuf), "%scontrols", (nOut > 0 ? "+" : ""));
925 TryCopyStr(buf, tbuf, sz);
926 nOut++;
927 }
928 }
929 return TRUE;
930}
931
932 /*ARGSUSED*/ static Bool
933CopySwitchScreenArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
934{
935 XkbSwitchScreenAction *act;
936 char tbuf[32];
937
938 act = &action->screen;
939 if ((act->flags & XkbSA_SwitchAbsolute) || (XkbSAScreen(act) < 0))
940 snprintf(tbuf, sizeof(tbuf), "screen=%d", XkbSAScreen(act));
941 else
942 snprintf(tbuf, sizeof(tbuf), "screen=+%d", XkbSAScreen(act));
943 TryCopyStr(buf, tbuf, sz);
944 if (act->flags & XkbSA_SwitchApplication)
945 TryCopyStr(buf, ",!same", sz);
946 else
947 TryCopyStr(buf, ",same", sz);
948 return TRUE;
949}
950
951 /*ARGSUSED*/ static Bool
952CopySetLockControlsArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
953{
954 XkbCtrlsAction *act;
955 unsigned tmp;
956 char tbuf[32];
957
958 act = &action->ctrls;
959 tmp = XkbActionCtrls(act);
960 TryCopyStr(buf, "controls=", sz);
961 if (tmp == 0)
962 TryCopyStr(buf, "none", sz);
963 else if ((tmp & XkbAllBooleanCtrlsMask) == XkbAllBooleanCtrlsMask)
964 TryCopyStr(buf, "all", sz);
965 else {
966 int nOut = 0;
967
968 if (tmp & XkbRepeatKeysMask) {
969 snprintf(tbuf, sizeof(tbuf), "%sRepeatKeys", (nOut > 0 ? "+" : ""));
970 TryCopyStr(buf, tbuf, sz);
971 nOut++;
972 }
973 if (tmp & XkbSlowKeysMask) {
974 snprintf(tbuf, sizeof(tbuf), "%sSlowKeys", (nOut > 0 ? "+" : ""));
975 TryCopyStr(buf, tbuf, sz);
976 nOut++;
977 }
978 if (tmp & XkbBounceKeysMask) {
979 snprintf(tbuf, sizeof(tbuf), "%sBounceKeys", (nOut > 0 ? "+" : ""));
980 TryCopyStr(buf, tbuf, sz);
981 nOut++;
982 }
983 if (tmp & XkbStickyKeysMask) {
984 snprintf(tbuf, sizeof(tbuf), "%sStickyKeys", (nOut > 0 ? "+" : ""));
985 TryCopyStr(buf, tbuf, sz);
986 nOut++;
987 }
988 if (tmp & XkbMouseKeysMask) {
989 snprintf(tbuf, sizeof(tbuf), "%sMouseKeys", (nOut > 0 ? "+" : ""));
990 TryCopyStr(buf, tbuf, sz);
991 nOut++;
992 }
993 if (tmp & XkbMouseKeysAccelMask) {
994 snprintf(tbuf, sizeof(tbuf), "%sMouseKeysAccel",
995 (nOut > 0 ? "+" : ""));
996 TryCopyStr(buf, tbuf, sz);
997 nOut++;
998 }
999 if (tmp & XkbAccessXKeysMask) {
1000 snprintf(tbuf, sizeof(tbuf), "%sAccessXKeys",
1001 (nOut > 0 ? "+" : ""));
1002 TryCopyStr(buf, tbuf, sz);
1003 nOut++;
1004 }
1005 if (tmp & XkbAccessXTimeoutMask) {
1006 snprintf(tbuf, sizeof(tbuf), "%sAccessXTimeout",
1007 (nOut > 0 ? "+" : ""));
1008 TryCopyStr(buf, tbuf, sz);
1009 nOut++;
1010 }
1011 if (tmp & XkbAccessXFeedbackMask) {
1012 snprintf(tbuf, sizeof(tbuf), "%sAccessXFeedback",
1013 (nOut > 0 ? "+" : ""));
1014 TryCopyStr(buf, tbuf, sz);
1015 nOut++;
1016 }
1017 if (tmp & XkbAudibleBellMask) {
1018 snprintf(tbuf, sizeof(tbuf), "%sAudibleBell",
1019 (nOut > 0 ? "+" : ""));
1020 TryCopyStr(buf, tbuf, sz);
1021 nOut++;
1022 }
1023 if (tmp & XkbOverlay1Mask) {
1024 snprintf(tbuf, sizeof(tbuf), "%sOverlay1", (nOut > 0 ? "+" : ""));
1025 TryCopyStr(buf, tbuf, sz);
1026 nOut++;
1027 }
1028 if (tmp & XkbOverlay2Mask) {
1029 snprintf(tbuf, sizeof(tbuf), "%sOverlay2", (nOut > 0 ? "+" : ""));
1030 TryCopyStr(buf, tbuf, sz);
1031 nOut++;
1032 }
1033 if (tmp & XkbIgnoreGroupLockMask) {
1034 snprintf(tbuf, sizeof(tbuf), "%sIgnoreGroupLock",
1035 (nOut > 0 ? "+" : ""));
1036 TryCopyStr(buf, tbuf, sz);
1037 nOut++;
1038 }
1039 }
1040 return TRUE;
1041}
1042
1043 /*ARGSUSED*/ static Bool
1044CopyActionMessageArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1045{
1046 XkbMessageAction *act;
1047 unsigned all;
1048 char tbuf[32];
1049
1050 act = &action->msg;
1051 all = XkbSA_MessageOnPress | XkbSA_MessageOnRelease;
1052 TryCopyStr(buf, "report=", sz);
1053 if ((act->flags & all) == 0)
1054 TryCopyStr(buf, "none", sz);
1055 else if ((act->flags & all) == all)
1056 TryCopyStr(buf, "all", sz);
1057 else if (act->flags & XkbSA_MessageOnPress)
1058 TryCopyStr(buf, "KeyPress", sz);
1059 else
1060 TryCopyStr(buf, "KeyRelease", sz);
1061 snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->message[0]);
1062 TryCopyStr(buf, tbuf, sz);
1063 snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->message[1]);
1064 TryCopyStr(buf, tbuf, sz);
1065 snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->message[2]);
1066 TryCopyStr(buf, tbuf, sz);
1067 snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->message[3]);
1068 TryCopyStr(buf, tbuf, sz);
1069 snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->message[4]);
1070 TryCopyStr(buf, tbuf, sz);
1071 snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->message[5]);
1072 TryCopyStr(buf, tbuf, sz);
1073 return TRUE;
1074}
1075
1076static Bool
1077CopyRedirectKeyArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1078{
1079 XkbRedirectKeyAction *act;
1080 char tbuf[32], *tmp;
1081 unsigned kc;
1082 unsigned vmods, vmods_mask;
1083
1084 act = &action->redirect;
1085 kc = act->new_key;
1086 vmods = XkbSARedirectVMods(act);
1087 vmods_mask = XkbSARedirectVModsMask(act);
1088 if (xkb && xkb->names && xkb->names->keys && (kc <= xkb->max_key_code) &&
1089 (xkb->names->keys[kc].name[0] != '\0')) {
1090 char *kn;
1091
1092 kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
1093 snprintf(tbuf, sizeof(tbuf), "key=%s", kn);
1094 }
1095 else
1096 snprintf(tbuf, sizeof(tbuf), "key=%d", kc);
1097 TryCopyStr(buf, tbuf, sz);
1098 if ((act->mods_mask == 0) && (vmods_mask == 0))
1099 return TRUE;
1100 if ((act->mods_mask == XkbAllModifiersMask) &&
1101 (vmods_mask == XkbAllVirtualModsMask)) {
1102 tmp = XkbVModMaskText(xkb, act->mods, vmods, XkbXKBFile);
1103 TryCopyStr(buf, ",mods=", sz);
1104 TryCopyStr(buf, tmp, sz);
1105 }
1106 else {
1107 if ((act->mods_mask & act->mods) || (vmods_mask & vmods)) {
1108 tmp = XkbVModMaskText(xkb, act->mods_mask & act->mods,
1109 vmods_mask & vmods, XkbXKBFile);
1110 TryCopyStr(buf, ",mods= ", sz);
1111 TryCopyStr(buf, tmp, sz);
1112 }
1113 if ((act->mods_mask & (~act->mods)) || (vmods_mask & (~vmods))) {
1114 tmp = XkbVModMaskText(xkb, act->mods_mask & (~act->mods),
1115 vmods_mask & (~vmods), XkbXKBFile);
1116 TryCopyStr(buf, ",clearMods= ", sz);
1117 TryCopyStr(buf, tmp, sz);
1118 }
1119 }
1120 return TRUE;
1121}
1122
1123 /*ARGSUSED*/ static Bool
1124CopyDeviceBtnArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1125{
1126 XkbDeviceBtnAction *act;
1127 char tbuf[32];
1128
1129 act = &action->devbtn;
1130 snprintf(tbuf, sizeof(tbuf), "device= %d", act->device);
1131 TryCopyStr(buf, tbuf, sz);
1132 TryCopyStr(buf, ",button=", sz);
1133 snprintf(tbuf, sizeof(tbuf), "%d", act->button);
1134 TryCopyStr(buf, tbuf, sz);
1135 if (act->count > 0) {
1136 snprintf(tbuf, sizeof(tbuf), ",count=%d", act->count);
1137 TryCopyStr(buf, tbuf, sz);
1138 }
1139 if (action->type == XkbSA_LockDeviceBtn) {
1140 switch (act->flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
1141 case XkbSA_LockNoLock:
1142 TryCopyStr(buf, ",affect=unlock", sz);
1143 break;
1144 case XkbSA_LockNoUnlock:
1145 TryCopyStr(buf, ",affect=lock", sz);
1146 break;
1147 case XkbSA_LockNoUnlock | XkbSA_LockNoLock:
1148 TryCopyStr(buf, ",affect=neither", sz);
1149 break;
1150 default:
1151 TryCopyStr(buf, ",affect=both", sz);
1152 break;
1153 }
1154 }
1155 return TRUE;
1156}
1157
1158 /*ARGSUSED*/ static Bool
1159CopyOtherArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
1160{
1161 XkbAnyAction *act;
1162 char tbuf[32];
1163
1164 act = &action->any;
1165 snprintf(tbuf, sizeof(tbuf), "type=0x%02x", act->type);
1166 TryCopyStr(buf, tbuf, sz);
1167 snprintf(tbuf, sizeof(tbuf), ",data[0]=0x%02x", act->data[0]);
1168 TryCopyStr(buf, tbuf, sz);
1169 snprintf(tbuf, sizeof(tbuf), ",data[1]=0x%02x", act->data[1]);
1170 TryCopyStr(buf, tbuf, sz);
1171 snprintf(tbuf, sizeof(tbuf), ",data[2]=0x%02x", act->data[2]);
1172 TryCopyStr(buf, tbuf, sz);
1173 snprintf(tbuf, sizeof(tbuf), ",data[3]=0x%02x", act->data[3]);
1174 TryCopyStr(buf, tbuf, sz);
1175 snprintf(tbuf, sizeof(tbuf), ",data[4]=0x%02x", act->data[4]);
1176 TryCopyStr(buf, tbuf, sz);
1177 snprintf(tbuf, sizeof(tbuf), ",data[5]=0x%02x", act->data[5]);
1178 TryCopyStr(buf, tbuf, sz);
1179 snprintf(tbuf, sizeof(tbuf), ",data[6]=0x%02x", act->data[6]);
1180 TryCopyStr(buf, tbuf, sz);
1181 return TRUE;
1182}
1183
1184typedef Bool (*actionCopy) (XkbDescPtr /* xkb */ ,
1185 XkbAction * /* action */ ,
1186 char * /* buf */ ,
1187 int * /* sz */
1188 );
1189
1190static actionCopy copyActionArgs[XkbSA_NumActions] = {
1191 CopyNoActionArgs /* NoAction */ ,
1192 CopyModActionArgs /* SetMods */ ,
1193 CopyModActionArgs /* LatchMods */ ,
1194 CopyModActionArgs /* LockMods */ ,
1195 CopyGroupActionArgs /* SetGroup */ ,
1196 CopyGroupActionArgs /* LatchGroup */ ,
1197 CopyGroupActionArgs /* LockGroup */ ,
1198 CopyMovePtrArgs /* MovePtr */ ,
1199 CopyPtrBtnArgs /* PtrBtn */ ,
1200 CopyPtrBtnArgs /* LockPtrBtn */ ,
1201 CopySetPtrDfltArgs /* SetPtrDflt */ ,
1202 CopyISOLockArgs /* ISOLock */ ,
1203 CopyNoActionArgs /* Terminate */ ,
1204 CopySwitchScreenArgs /* SwitchScreen */ ,
1205 CopySetLockControlsArgs /* SetControls */ ,
1206 CopySetLockControlsArgs /* LockControls */ ,
1207 CopyActionMessageArgs /* ActionMessage */ ,
1208 CopyRedirectKeyArgs /* RedirectKey */ ,
1209 CopyDeviceBtnArgs /* DeviceBtn */ ,
1210 CopyDeviceBtnArgs /* LockDeviceBtn */
1211};
1212
1213#define ACTION_SZ 256
1214
1215char *
1216XkbActionText(XkbDescPtr xkb, XkbAction *action, unsigned format)
1217{
1218 char buf[ACTION_SZ], *tmp;
1219 int sz;
1220
1221 if (format == XkbCFile) {
1222 snprintf(buf, sizeof(buf),
1223 "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
1224 XkbActionTypeText(action->type, XkbCFile),
1225 action->any.data[0], action->any.data[1], action->any.data[2],
1226 action->any.data[3], action->any.data[4], action->any.data[5],
1227 action->any.data[6]);
1228 }
1229 else {
1230 snprintf(buf, sizeof(buf), "%s(",
1231 XkbActionTypeText(action->type, XkbXKBFile));
1232 sz = ACTION_SZ - strlen(buf) + 2; /* room for close paren and NULL */
1233 if (action->type < (unsigned) XkbSA_NumActions)
1234 (*copyActionArgs[action->type]) (xkb, action, buf, &sz);
1235 else
1236 CopyOtherArgs(xkb, action, buf, &sz);
1237 TryCopyStr(buf, ")", &sz);
1238 }
1239 tmp = tbGetBuffer(strlen(buf) + 1);
1240 if (tmp != NULL)
1241 strcpy(tmp, buf);
1242 return tmp;
1243}
1244
1245char *
1246XkbBehaviorText(XkbDescPtr xkb, XkbBehavior * behavior, unsigned format)
1247{
1248 char buf[256], *tmp;
1249
1250 if (format == XkbCFile) {
1251 if (behavior->type == XkbKB_Default)
1252 snprintf(buf, sizeof(buf), "{ 0, 0 }");
1253 else
1254 snprintf(buf, sizeof(buf), "{ %3d, 0x%02x }", behavior->type,
1255 behavior->data);
1256 }
1257 else {
1258 unsigned type, permanent;
1259
1260 type = behavior->type & XkbKB_OpMask;
1261 permanent = ((behavior->type & XkbKB_Permanent) != 0);
1262
1263 if (type == XkbKB_Lock) {
1264 snprintf(buf, sizeof(buf), "lock= %s",
1265 (permanent ? "Permanent" : "TRUE"));
1266 }
1267 else if (type == XkbKB_RadioGroup) {
1268 int g;
1269
1270 g = ((behavior->data) & (~XkbKB_RGAllowNone)) + 1;
1271 if (XkbKB_RGAllowNone & behavior->data) {
1272 snprintf(buf, sizeof(buf), "allowNone,");
1273 tmp = &buf[strlen(buf)];
1274 }
1275 else
1276 tmp = buf;
1277 if (permanent)
1278 sprintf(tmp, "permanentRadioGroup= %d", g);
1279 else
1280 sprintf(tmp, "radioGroup= %d", g);
1281 }
1282 else if ((type == XkbKB_Overlay1) || (type == XkbKB_Overlay2)) {
1283 int ndx, kc;
1284 char *kn;
1285
1286 ndx = ((type == XkbKB_Overlay1) ? 1 : 2);
1287 kc = behavior->data;
1288 if ((xkb) && (xkb->names) && (xkb->names->keys))
1289 kn = XkbKeyNameText(xkb->names->keys[kc].name, XkbXKBFile);
1290 else {
1291 static char tbuf[8];
1292
1293 snprintf(tbuf, sizeof(tbuf), "%d", kc);
1294 kn = tbuf;
1295 }
1296 if (permanent)
1297 snprintf(buf, sizeof(buf), "permanentOverlay%d= %s", ndx, kn);
1298 else
1299 snprintf(buf, sizeof(buf), "overlay%d= %s", ndx, kn);
1300 }
1301 }
1302 tmp = tbGetBuffer(strlen(buf) + 1);
1303 if (tmp != NULL)
1304 strcpy(tmp, buf);
1305 return tmp;
1306}
1307
1308/***====================================================================***/
1309
1310char *
1311XkbIndentText(unsigned size)
1312{
1313 static char buf[32];
1314 register int i;
1315
1316 if (size > 31)
1317 size = 31;
1318
1319 for (i = 0; i < size; i++) {
1320 buf[i] = ' ';
1321 }
1322 buf[size] = '\0';
1323 return buf;
1324}