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