1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
28 * Copyright © 2012 Intel Corporation
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of this software and associated documentation files (the "Software"),
32 * to deal in the Software without restriction, including without limitation
33 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 * and/or sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following conditions:
37 * The above copyright notice and this permission notice (including the next
38 * paragraph) shall be included in all copies or substantial portions of the
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47 * DEALINGS IN THE SOFTWARE.
49 * Author: Daniel Stone <daniel@fooishbar.org>
61 #define VMOD_HIDE_VALUE 0
62 #define VMOD_SHOW_VALUE 1
63 #define VMOD_COMMENT_VALUE 2
65 #define BUF_CHUNK_SIZE 4096
68 do_realloc(char **buf, size_t *size, size_t offset, size_t at_least)
72 *size += BUF_CHUNK_SIZE;
73 if (at_least >= BUF_CHUNK_SIZE)
76 new = realloc(*buf, *size);
81 memset(*buf + offset, 0, *size - offset);
86 /* This whole thing should be a function, but you can't call vsnprintf
88 #define check_write_buf(keymap, buf, size, offset, ...) \
93 /* Concatenate the strings, and check whether or not the output was \
95 while ((_printed = snprintf(*buf + *offset, *size - *offset, \
98 /* If it was truncated, embiggen the string and roll from the top. */ \
99 if (!do_realloc(buf, size, *offset, _printed)) { \
101 "xkbcommon: failed to allocate %zu bytes for keymap\n", \
110 *offset += _printed; \
113 #define write_buf(keymap, buf, size, offset, ...) \
115 check_write_buf(keymap, buf, size, offset, __VA_ARGS__); \
121 write_vmods(struct xkb_keymap *keymap, char **buf, size_t *size, size_t *offset)
126 for (i = 0; i < XkbNumVirtualMods; i++) {
127 if (!keymap->names->vmods[i])
130 write_buf(keymap, buf, size, offset, "\t\tvirtual_modifiers ");
132 write_buf(keymap, buf, size, offset, ",");
133 write_buf(keymap, buf, size, offset, "%s", keymap->names->vmods[i]);
138 write_buf(keymap, buf, size, offset, ";\n\n");
143 #define GET_TEXT_BUF_SIZE 512
145 #define append_get_text(...) do { \
146 int _size = snprintf(ret, GET_TEXT_BUF_SIZE, __VA_ARGS__); \
147 if (_size >= GET_TEXT_BUF_SIZE) \
151 /* FIXME: Merge with src/xkbcomp/expr.c::modIndexNames. */
152 static const char *core_mod_names[] = {
164 get_mod_index_text(uint8_t real_mod)
166 return core_mod_names[real_mod];
170 get_mod_mask_text(struct xkb_keymap *keymap, uint8_t real_mods, uint32_t vmods)
172 static char ret[GET_TEXT_BUF_SIZE], ret2[GET_TEXT_BUF_SIZE];
175 memset(ret, 0, GET_TEXT_BUF_SIZE);
177 if (real_mods == 0 && vmods == 0) {
182 /* This is so broken. If we have a real modmask of 0xff and a
183 * vmodmask, we'll get, e.g., all+RightControl. But, it's what xkbfile
185 if (real_mods == 0xff) {
188 else if (real_mods) {
189 for (i = 0; i < XkbNumModifiers; i++) {
190 if (!(real_mods & (1 << i)))
192 if (ret[0] != '\0') {
194 append_get_text("%s+%s", ret2, core_mod_names[i]);
197 append_get_text("%s", core_mod_names[i]);
205 for (i = 0; i < XkbNumVirtualMods; i++) {
206 if (!(vmods & (1 << i)))
208 if (ret[0] != '\0') {
210 append_get_text("%s+%s", ret2, keymap->names->vmods[i]);
213 append_get_text("%s", keymap->names->vmods[i]);
221 get_indicator_state_text(uint8_t which)
224 static char ret[GET_TEXT_BUF_SIZE];
225 /* FIXME: Merge with ... something ... in xkbcomp? */
226 static const char *state_names[] = {
234 memset(ret, 0, GET_TEXT_BUF_SIZE);
236 which &= XkbIM_UseAnyMods;
243 for (i = 0; which != 0; i++) {
244 if (!(which & (1 << i)))
249 append_get_text("%s+%s", ret, state_names[i]);
251 append_get_text("%s", state_names[i]);
258 get_control_mask_text(uint32_t control_mask)
261 static char ret[GET_TEXT_BUF_SIZE];
262 /* FIXME: Merge with ... something ... in xkbcomp. */
263 static const char *ctrl_names[] = {
279 memset(ret, 0, GET_TEXT_BUF_SIZE);
281 control_mask &= XkbAllBooleanCtrlsMask;
283 if (control_mask == 0) {
287 else if (control_mask == XkbAllBooleanCtrlsMask) {
292 for (i = 0; control_mask; i++) {
293 if (!(control_mask & (1 << i)))
295 control_mask &= ~(1 << i);
298 append_get_text("%s+%s", ret, ctrl_names[i]);
300 append_get_text("%s", ctrl_names[i]);
307 write_keycodes(struct xkb_keymap *keymap, char **buf, size_t *size,
311 struct xkb_key_alias *alias;
314 if (keymap->names->keycodes)
315 write_buf(keymap, buf, size, offset, "\txkb_keycodes \"%s\" {\n",
316 keymap->names->keycodes);
318 write_buf(keymap, buf, size, offset, "\txkb_keycodes {\n");
320 write_buf(keymap, buf, size, offset, "\t\tminimum = %d;\n",
321 keymap->min_key_code);
322 write_buf(keymap, buf, size, offset, "\t\tmaximum = %d;\n",
323 keymap->max_key_code);
325 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
326 const char *alternate = "";
328 if (darray_item(keymap->names->keys, key).name[0] == '\0')
330 if (XkbcFindKeycodeByName(keymap,
331 darray_item(keymap->names->keys, key).name,
333 alternate = "alternate ";
334 write_buf(keymap, buf, size, offset, "\t\t%s%6s = %d;\n", alternate,
335 XkbcKeyNameText(darray_item(keymap->names->keys, key).name),
339 for (i = 0; i < XkbNumIndicators; i++) {
340 if (!keymap->names->indicators[i])
342 write_buf(keymap, buf, size, offset, "\t\tindicator %d = \"%s\";\n",
343 i + 1, keymap->names->indicators[i]);
347 darray_foreach(alias, keymap->names->key_aliases)
348 write_buf(keymap, buf, size, offset, "\t\talias %6s = %6s;\n",
349 XkbcKeyNameText(alias->alias),
350 XkbcKeyNameText(alias->real));
352 write_buf(keymap, buf, size, offset, "\t};\n\n");
357 write_types(struct xkb_keymap *keymap, char **buf, size_t *size,
361 struct xkb_key_type *type;
363 if (keymap->names->keytypes)
364 write_buf(keymap, buf, size, offset, "\txkb_types \"%s\" {\n\n",
365 keymap->names->keytypes);
367 write_buf(keymap, buf, size, offset, "\txkb_types {\n\n");
369 write_vmods(keymap, buf, size, offset);
371 darray_foreach(type, keymap->map->types) {
372 write_buf(keymap, buf, size, offset, "\t\ttype \"%s\" {\n",
374 write_buf(keymap, buf, size, offset, "\t\t\tmodifiers= %s;\n",
375 get_mod_mask_text(keymap, type->mods.real_mods,
378 for (n = 0; n < darray_size(type->map); n++) {
379 struct xkb_kt_map_entry *entry = &darray_item(type->map, n);
382 str = get_mod_mask_text(keymap, entry->mods.real_mods,
384 write_buf(keymap, buf, size, offset, "\t\t\tmap[%s]= Level%d;\n",
385 str, entry->level + 1);
387 if (!type->preserve || (!type->preserve[n].real_mods &&
388 !type->preserve[n].vmods))
390 write_buf(keymap, buf, size, offset, "\t\t\tpreserve[%s]= ", str);
391 write_buf(keymap, buf, size, offset, "%s;\n",
392 get_mod_mask_text(keymap, type->preserve[n].real_mods,
393 type->preserve[n].vmods));
396 if (type->level_names) {
397 for (n = 0; n < type->num_levels; n++) {
398 if (!type->level_names[n])
400 write_buf(keymap, buf, size, offset,
401 "\t\t\tlevel_name[Level%d]= \"%s\";\n", n + 1,
402 type->level_names[n]);
405 write_buf(keymap, buf, size, offset, "\t\t};\n");
408 write_buf(keymap, buf, size, offset, "\t};\n\n");
413 write_indicator_map(struct xkb_keymap *keymap, char **buf, size_t *size,
414 size_t *offset, int num)
416 struct xkb_indicator_map *led = &keymap->indicators->maps[num];
418 write_buf(keymap, buf, size, offset, "\t\tindicator \"%s\" {\n",
419 keymap->names->indicators[num]);
421 if (led->which_groups) {
422 if (led->which_groups != XkbIM_UseEffective) {
423 write_buf(keymap, buf, size, offset, "\t\t\twhichGroupState= %s;\n",
424 get_indicator_state_text(led->which_groups));
426 write_buf(keymap, buf, size, offset, "\t\t\tgroups= 0x%02x;\n",
430 if (led->which_mods) {
431 if (led->which_mods != XkbIM_UseEffective) {
432 write_buf(keymap, buf, size, offset, "\t\t\twhichModState= %s;\n",
433 get_indicator_state_text(led->which_mods));
435 write_buf(keymap, buf, size, offset, "\t\t\tmodifiers= %s;\n",
436 get_mod_mask_text(keymap, led->mods.real_mods,
441 write_buf(keymap, buf, size, offset, "\t\t\tcontrols= %s;\n",
442 get_control_mask_text(led->ctrls));
445 write_buf(keymap, buf, size, offset, "\t\t};\n");
450 get_interp_match_text(uint8_t type)
454 switch (type & XkbSI_OpMask) {
456 sprintf(ret, "NoneOf");
458 case XkbSI_AnyOfOrNone:
459 sprintf(ret, "AnyOfOrNone");
462 sprintf(ret, "AnyOf");
465 sprintf(ret, "AllOf");
468 sprintf(ret, "Exactly");
471 sprintf(ret, "0x%x", type & XkbSI_OpMask);
479 write_action(struct xkb_keymap *keymap, char **buf, size_t *size,
480 size_t *offset, union xkb_action *action, const char *prefix,
483 const char *type = NULL;
484 const char *args = NULL;
491 switch (action->any.type) {
495 case XkbSA_LatchMods:
501 if (action->mods.flags & XkbSA_UseModMapMods)
504 args = get_mod_mask_text(keymap, action->mods.real_mods,
506 write_buf(keymap, buf, size, offset, "%s%s(modifiers=%s%s%s)%s",
508 (action->any.type != XkbSA_LockGroup &&
509 action->mods.flags & XkbSA_ClearLocks) ? ",clearLocks" : "",
510 (action->any.type != XkbSA_LockGroup &&
511 action->mods.flags & XkbSA_LatchToLock) ? ",latchToLock" : "",
517 case XkbSA_LatchGroup:
520 case XkbSA_LockGroup:
523 write_buf(keymap, buf, size, offset, "%s%s(group=%s%d%s%s)%s",
525 (!(action->group.flags & XkbSA_GroupAbsolute) &&
526 action->group.group > 0) ? "+" : "",
527 (action->group.flags & XkbSA_GroupAbsolute) ?
528 action->group.group + 1 : action->group.group,
529 (action->any.type != XkbSA_LockGroup &&
530 action->group.flags & XkbSA_ClearLocks) ? ",clearLocks" : "",
531 (action->any.type != XkbSA_LockGroup &&
532 action->group.flags & XkbSA_LatchToLock) ? ",latchToLock" : "",
535 case XkbSA_Terminate:
536 write_buf(keymap, buf, size, offset, "%sTerminate()%s", prefix, suffix);
539 write_buf(keymap, buf, size, offset, "%sMovePtr(x=%s%d,y=%s%d%s)%s",
541 (!(action->ptr.flags & XkbSA_MoveAbsoluteX) &&
542 action->ptr.x >= 0) ? "+" : "",
544 (!(action->ptr.flags & XkbSA_MoveAbsoluteY) &&
545 action->ptr.y >= 0) ? "+" : "",
547 (action->ptr.flags & XkbSA_NoAcceleration) ? ",!accel" : "",
553 case XkbSA_LockPtrBtn:
556 switch (action->btn.flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
557 case XkbSA_LockNoUnlock:
558 args = ",affect=lock";
560 case XkbSA_LockNoLock:
561 args = ",affect=unlock";
563 case XkbSA_LockNoLock | XkbSA_LockNoUnlock:
564 args = ",affect=neither";
567 args = ",affect=both";
574 write_buf(keymap, buf, size, offset, "%s%s(button=", prefix, type);
575 if (action->btn.button > 0 && action->btn.button <= 5)
576 write_buf(keymap, buf, size, offset, "%d", action->btn.button);
578 write_buf(keymap, buf, size, offset, "default");
579 if (action->btn.count)
580 write_buf(keymap, buf, size, offset, ",count=%d",
583 write_buf(keymap, buf, size, offset, "%s", args);
584 write_buf(keymap, buf, size, offset, ")%s", suffix);
586 case XkbSA_SetPtrDflt:
587 write_buf(keymap, buf, size, offset, "%sSetPtrDflt(", prefix);
588 if (action->dflt.affect == XkbSA_AffectDfltBtn)
589 write_buf(keymap, buf, size, offset, "affect=button,button=%s%d",
590 (!(action->dflt.flags & XkbSA_DfltBtnAbsolute) &&
591 action->dflt.value >= 0) ? "+" : "",
593 write_buf(keymap, buf, size, offset, ")%s", suffix);
595 case XkbSA_SwitchScreen:
596 write_buf(keymap, buf, size, offset,
597 "%sSwitchScreen(screen=%s%d,%ssame)%s", prefix,
598 (!(action->screen.flags & XkbSA_SwitchAbsolute) &&
599 action->screen.screen >= 0) ? "+" : "",
600 action->screen.screen,
601 (action->screen.flags & XkbSA_SwitchApplication) ? "!" : "",
604 /* Deprecated actions below here */
605 case XkbSA_SetControls:
607 type = "SetControls";
608 case XkbSA_LockControls:
610 type = "LockControls";
611 write_buf(keymap, buf, size, offset, "%s%s(controls=%s)%s",
612 prefix, type, get_control_mask_text(action->ctrls.ctrls),
616 case XkbSA_ActionMessage:
617 case XkbSA_RedirectKey:
618 case XkbSA_DeviceBtn:
619 case XkbSA_LockDeviceBtn:
622 write_buf(keymap, buf, size, offset, "%sNoAction()%s", prefix, suffix);
624 case XkbSA_XFree86Private:
626 write_buf(keymap, buf, size, offset,
627 "%sPrivate(type=0x%02x,data[0]=0x%02x,data[1]=0x%02x,data[2]=0x%02x,data[3]=0x%02x,data[4]=0x%02x,data[5]=0x%02x,data[6]=0x%02x)%s",
628 prefix, action->any.type, action->any.data[0],
629 action->any.data[1], action->any.data[2],
630 action->any.data[3], action->any.data[4],
631 action->any.data[5], action->any.data[6], suffix);
639 write_compat(struct xkb_keymap *keymap, char **buf, size_t *size,
643 struct xkb_sym_interpret *interp;
645 if (keymap->names->compat)
646 write_buf(keymap, buf, size, offset, "\txkb_compatibility \"%s\" {\n\n",
647 keymap->names->compat);
649 write_buf(keymap, buf, size, offset, "\txkb_compatibility {\n\n");
651 write_vmods(keymap, buf, size, offset);
653 write_buf(keymap, buf, size, offset, "\t\tinterpret.useModMapMods= AnyLevel;\n");
654 write_buf(keymap, buf, size, offset, "\t\tinterpret.repeat= False;\n");
655 write_buf(keymap, buf, size, offset, "\t\tinterpret.locking= False;\n");
657 darray_foreach(interp, keymap->compat->sym_interpret) {
658 char keysym_name[64];
660 if (interp->sym == XKB_KEY_NoSymbol)
661 sprintf(keysym_name, "Any");
663 xkb_keysym_get_name(interp->sym, keysym_name, sizeof(keysym_name));
665 write_buf(keymap, buf, size, offset, "\t\tinterpret %s+%s(%s) {\n",
667 get_interp_match_text(interp->match),
668 get_mod_mask_text(keymap, interp->mods, 0));
670 if (interp->virtual_mod != XkbNoModifier) {
671 write_buf(keymap, buf, size, offset, "\t\t\tvirtualModifier= %s;\n",
672 keymap->names->vmods[interp->virtual_mod]);
675 if (interp->match & XkbSI_LevelOneOnly)
676 write_buf(keymap, buf, size, offset, "\t\t\tuseModMapMods=level1;\n");
677 if (interp->flags & XkbSI_LockingKey)
678 write_buf(keymap, buf, size, offset, "\t\t\tlocking= True;\n");
679 if (interp->flags & XkbSI_AutoRepeat)
680 write_buf(keymap, buf, size, offset, "\t\t\trepeat= True;\n");
682 write_action(keymap, buf, size, offset, &interp->act,
683 "\t\t\taction= ", ";\n");
684 write_buf(keymap, buf, size, offset, "\t\t};\n");
687 for (i = 0; i < XkbNumKbdGroups; i++) {
690 gc = &keymap->compat->groups[i];
691 if (gc->real_mods == 0 && gc->vmods ==0)
693 write_buf(keymap, buf, size, offset,
694 "\t\tgroup %d = %s;\n", i + 1,
695 get_mod_mask_text(keymap, gc->real_mods, gc->vmods));
698 for (i = 0; i < XkbNumIndicators; i++) {
699 struct xkb_indicator_map *map = &keymap->indicators->maps[i];
700 if (map->flags == 0 && map->which_groups == 0 &&
701 map->groups == 0 && map->which_mods == 0 &&
702 map->mods.real_mods == 0 && map->mods.vmods == 0 &&
705 write_indicator_map(keymap, buf, size, offset, i);
708 write_buf(keymap, buf, size, offset, "\t};\n\n");
714 write_keysyms(struct xkb_keymap *keymap, char **buf, size_t *size,
715 size_t *offset, xkb_keycode_t key, unsigned int group)
717 const xkb_keysym_t *syms;
719 #define OUT_BUF_LEN 128
720 char out_buf[OUT_BUF_LEN];
722 for (level = 0; level < XkbKeyGroupWidth(keymap, key, group); level++) {
724 write_buf(keymap, buf, size, offset, ", ");
725 num_syms = xkb_key_get_syms_by_level(keymap, key, group, level,
728 write_buf(keymap, buf, size, offset, "%15s", "NoSymbol");
730 else if (num_syms == 1) {
731 xkb_keysym_get_name(syms[0], out_buf, OUT_BUF_LEN);
732 write_buf(keymap, buf, size, offset, "%15s", out_buf);
736 write_buf(keymap, buf, size, offset, "{ ");
737 for (s = 0; s < num_syms; s++) {
739 write_buf(keymap, buf, size, offset, ", ");
740 xkb_keysym_get_name(syms[s], out_buf, OUT_BUF_LEN);
741 write_buf(keymap, buf, size, offset, "%15s", out_buf);
743 write_buf(keymap, buf, size, offset, " }");
752 write_symbols(struct xkb_keymap *keymap, char **buf, size_t *size,
755 struct xkb_client_map *map = keymap->map;
756 struct xkb_server_map *srv = keymap->server;
761 if (keymap->names->symbols)
762 write_buf(keymap, buf, size, offset, "\txkb_symbols \"%s\" {\n\n",
763 keymap->names->symbols);
765 write_buf(keymap, buf, size, offset, "\txkb_symbols {\n\n");
767 for (tmp = group = 0; group < XkbNumKbdGroups; group++) {
768 if (!keymap->names->groups[group])
770 write_buf(keymap, buf, size, offset,
771 "\t\tname[group%d]=\"%s\";\n", group + 1,
772 keymap->names->groups[group]);
776 write_buf(keymap, buf, size, offset, "\n");
778 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
781 if (xkb_key_num_groups(keymap, key) == 0)
783 if (XkbcFindKeycodeByName(keymap,
784 darray_item(keymap->names->keys, key).name,
788 write_buf(keymap, buf, size, offset, "\t\tkey %6s {",
789 XkbcKeyNameText(darray_item(keymap->names->keys, key).name));
791 if ((srv->explicit[key] & XkbExplicitKeyTypesMask)) {
792 bool multi_type = false;
793 int type = XkbKeyTypeIndex(keymap, key, 0);
797 for (group = 0; group < xkb_key_num_groups(keymap, key); group++) {
798 if (XkbKeyTypeIndex(keymap, key, group) != type) {
805 group < xkb_key_num_groups(keymap, key);
807 if (!(srv->explicit[key] & (1 << group)))
809 type = XkbKeyTypeIndex(keymap, key, group);
810 write_buf(keymap, buf, size, offset,
811 "\n\t\t\ttype[group%d]= \"%s\",",
813 darray_item(map->types, type).name);
817 write_buf(keymap, buf, size, offset,
818 "\n\t\t\ttype= \"%s\",",
819 darray_item(map->types, type).name);
822 if (keymap->ctrls && (srv->explicit[key] & XkbExplicitAutoRepeatMask)) {
823 if (keymap->ctrls->per_key_repeat[key / 8] & (1 << (key % 8)))
824 write_buf(keymap, buf, size, offset,
825 "\n\t\t\trepeat= Yes,");
827 write_buf(keymap, buf, size, offset,
828 "\n\t\t\trepeat= No,");
831 if (keymap->server->vmodmap[key] &&
832 (srv->explicit[key] & XkbExplicitVModMapMask)) {
833 write_buf(keymap, buf, size, offset, "\n\t\t\tvirtualMods= %s,",
834 get_mod_mask_text(keymap, 0, keymap->server->vmodmap[key]));
838 switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(keymap, key))) {
839 case XkbClampIntoRange:
840 write_buf(keymap, buf, size, offset, "\n\t\t\tgroupsClamp,");
842 case XkbRedirectIntoRange:
843 write_buf(keymap, buf, size, offset,
844 "\n\t\t\tgroupsRedirect= Group%d,",
845 XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(keymap, key)) + 1);
849 if (srv->explicit == NULL ||
850 (srv->explicit[key] & XkbExplicitInterpretMask))
851 showActions = XkbKeyHasActions(keymap, key);
855 if (xkb_key_num_groups(keymap, key) > 1 || showActions)
859 write_buf(keymap, buf, size, offset, "\t[ ");
860 if (!write_keysyms(keymap, buf, size, offset, key, 0))
862 write_buf(keymap, buf, size, offset, " ] };\n");
865 union xkb_action *acts;
868 acts = XkbKeyActionsPtr(keymap, key);
869 for (group = 0; group < xkb_key_num_groups(keymap, key); group++) {
871 write_buf(keymap, buf, size, offset, ",");
872 write_buf(keymap, buf, size, offset,
873 "\n\t\t\tsymbols[Group%d]= [ ", group + 1);
874 if (!write_keysyms(keymap, buf, size, offset, key, group))
876 write_buf(keymap, buf, size, offset, " ]");
878 write_buf(keymap, buf, size, offset,
879 ",\n\t\t\tactions[Group%d]= [ ", group + 1);
881 level < XkbKeyGroupWidth(keymap, key, group);
884 write_buf(keymap, buf, size, offset, ", ");
885 write_action(keymap, buf, size, offset, &acts[level],
888 write_buf(keymap, buf, size, offset, " ]");
889 acts += XkbKeyGroupsWidth(keymap, key);
892 write_buf(keymap, buf, size, offset, "\n\t\t};\n");
895 if (map && map->modmap) {
896 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
899 if (map->modmap[key] == 0)
902 for (mod = 0; mod < XkbNumModifiers; mod++) {
903 if (!(map->modmap[key] & (1 << mod)))
906 write_buf(keymap, buf, size, offset,
907 "\t\tmodifier_map %s { %s };\n",
908 get_mod_index_text(mod),
909 XkbcKeyNameText(darray_item(keymap->names->keys,
915 write_buf(keymap, buf, size, offset, "\t};\n\n");
920 xkb_map_get_as_string(struct xkb_keymap *keymap)
926 check_write_buf(keymap, &ret, &size, &offset, "xkb_keymap {\n");
929 if (!write_keycodes(keymap, &ret, &size, &offset))
931 if (!write_types(keymap, &ret, &size, &offset))
933 if (!write_compat(keymap, &ret, &size, &offset))
935 if (!write_symbols(keymap, &ret, &size, &offset))
937 check_write_buf(keymap, &ret, &size, &offset, "};\n");