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 write_buf(keymap, buf, size, offset, "\txkb_keycodes {\n");
315 write_buf(keymap, buf, size, offset, "\t\tminimum = %d;\n",
316 keymap->min_key_code);
317 write_buf(keymap, buf, size, offset, "\t\tmaximum = %d;\n",
318 keymap->max_key_code);
320 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
321 const char *alternate = "";
323 if (darray_item(keymap->names->keys, key).name[0] == '\0')
325 if (XkbcFindKeycodeByName(keymap,
326 darray_item(keymap->names->keys, key).name,
328 alternate = "alternate ";
329 write_buf(keymap, buf, size, offset, "\t\t%s%6s = %d;\n", alternate,
330 XkbcKeyNameText(darray_item(keymap->names->keys, key).name),
334 for (i = 0; i < XkbNumIndicators; i++) {
335 if (!keymap->names->indicators[i])
337 write_buf(keymap, buf, size, offset, "\t\tindicator %d = \"%s\";\n",
338 i + 1, keymap->names->indicators[i]);
342 darray_foreach(alias, keymap->names->key_aliases)
343 write_buf(keymap, buf, size, offset, "\t\talias %6s = %6s;\n",
344 XkbcKeyNameText(alias->alias),
345 XkbcKeyNameText(alias->real));
347 write_buf(keymap, buf, size, offset, "\t};\n\n");
352 write_types(struct xkb_keymap *keymap, char **buf, size_t *size,
356 struct xkb_key_type *type;
358 write_buf(keymap, buf, size, offset, "\txkb_types {\n\n");
359 write_vmods(keymap, buf, size, offset);
361 darray_foreach(type, keymap->map->types) {
362 write_buf(keymap, buf, size, offset, "\t\ttype \"%s\" {\n",
364 write_buf(keymap, buf, size, offset, "\t\t\tmodifiers= %s;\n",
365 get_mod_mask_text(keymap, type->mods.real_mods,
368 for (n = 0; n < darray_size(type->map); n++) {
369 struct xkb_kt_map_entry *entry = &darray_item(type->map, n);
372 str = get_mod_mask_text(keymap, entry->mods.real_mods,
374 write_buf(keymap, buf, size, offset, "\t\t\tmap[%s]= Level%d;\n",
375 str, entry->level + 1);
377 if (!type->preserve || (!type->preserve[n].real_mods &&
378 !type->preserve[n].vmods))
380 write_buf(keymap, buf, size, offset, "\t\t\tpreserve[%s]= ", str);
381 write_buf(keymap, buf, size, offset, "%s;\n",
382 get_mod_mask_text(keymap, type->preserve[n].real_mods,
383 type->preserve[n].vmods));
386 if (type->level_names) {
387 for (n = 0; n < type->num_levels; n++) {
388 if (!type->level_names[n])
390 write_buf(keymap, buf, size, offset,
391 "\t\t\tlevel_name[Level%d]= \"%s\";\n", n + 1,
392 type->level_names[n]);
395 write_buf(keymap, buf, size, offset, "\t\t};\n");
398 write_buf(keymap, buf, size, offset, "\t};\n\n");
403 write_indicator_map(struct xkb_keymap *keymap, char **buf, size_t *size,
404 size_t *offset, int num)
406 struct xkb_indicator_map *led = &keymap->indicators->maps[num];
408 write_buf(keymap, buf, size, offset, "\t\tindicator \"%s\" {\n",
409 keymap->names->indicators[num]);
411 if (led->which_groups) {
412 if (led->which_groups != XkbIM_UseEffective) {
413 write_buf(keymap, buf, size, offset, "\t\t\twhichGroupState= %s;\n",
414 get_indicator_state_text(led->which_groups));
416 write_buf(keymap, buf, size, offset, "\t\t\tgroups= 0x%02x;\n",
420 if (led->which_mods) {
421 if (led->which_mods != XkbIM_UseEffective) {
422 write_buf(keymap, buf, size, offset, "\t\t\twhichModState= %s;\n",
423 get_indicator_state_text(led->which_mods));
425 write_buf(keymap, buf, size, offset, "\t\t\tmodifiers= %s;\n",
426 get_mod_mask_text(keymap, led->mods.real_mods,
431 write_buf(keymap, buf, size, offset, "\t\t\tcontrols= %s;\n",
432 get_control_mask_text(led->ctrls));
435 write_buf(keymap, buf, size, offset, "\t\t};\n");
440 get_interp_match_text(uint8_t type)
444 switch (type & XkbSI_OpMask) {
446 sprintf(ret, "NoneOf");
448 case XkbSI_AnyOfOrNone:
449 sprintf(ret, "AnyOfOrNone");
452 sprintf(ret, "AnyOf");
455 sprintf(ret, "AllOf");
458 sprintf(ret, "Exactly");
461 sprintf(ret, "0x%x", type & XkbSI_OpMask);
469 write_action(struct xkb_keymap *keymap, char **buf, size_t *size,
470 size_t *offset, union xkb_action *action, const char *prefix,
473 const char *type = NULL;
474 const char *args = NULL;
481 switch (action->any.type) {
485 case XkbSA_LatchMods:
491 if (action->mods.flags & XkbSA_UseModMapMods)
494 args = get_mod_mask_text(keymap, action->mods.real_mods,
496 write_buf(keymap, buf, size, offset, "%s%s(modifiers=%s%s%s)%s",
498 (action->any.type != XkbSA_LockGroup &&
499 action->mods.flags & XkbSA_ClearLocks) ? ",clearLocks" : "",
500 (action->any.type != XkbSA_LockGroup &&
501 action->mods.flags & XkbSA_LatchToLock) ? ",latchToLock" : "",
507 case XkbSA_LatchGroup:
510 case XkbSA_LockGroup:
513 write_buf(keymap, buf, size, offset, "%s%s(group=%s%d%s%s)%s",
515 (!(action->group.flags & XkbSA_GroupAbsolute) &&
516 action->group.group > 0) ? "+" : "",
517 (action->group.flags & XkbSA_GroupAbsolute) ?
518 action->group.group + 1 : action->group.group,
519 (action->any.type != XkbSA_LockGroup &&
520 action->group.flags & XkbSA_ClearLocks) ? ",clearLocks" : "",
521 (action->any.type != XkbSA_LockGroup &&
522 action->group.flags & XkbSA_LatchToLock) ? ",latchToLock" : "",
525 case XkbSA_Terminate:
526 write_buf(keymap, buf, size, offset, "%sTerminate()%s", prefix, suffix);
529 write_buf(keymap, buf, size, offset, "%sMovePtr(x=%s%d,y=%s%d%s)%s",
531 (!(action->ptr.flags & XkbSA_MoveAbsoluteX) &&
532 action->ptr.x >= 0) ? "+" : "",
534 (!(action->ptr.flags & XkbSA_MoveAbsoluteY) &&
535 action->ptr.y >= 0) ? "+" : "",
537 (action->ptr.flags & XkbSA_NoAcceleration) ? ",!accel" : "",
543 case XkbSA_LockPtrBtn:
546 switch (action->btn.flags & (XkbSA_LockNoUnlock | XkbSA_LockNoLock)) {
547 case XkbSA_LockNoUnlock:
548 args = ",affect=lock";
550 case XkbSA_LockNoLock:
551 args = ",affect=unlock";
553 case XkbSA_LockNoLock | XkbSA_LockNoUnlock:
554 args = ",affect=neither";
557 args = ",affect=both";
564 write_buf(keymap, buf, size, offset, "%s%s(button=", prefix, type);
565 if (action->btn.button > 0 && action->btn.button <= 5)
566 write_buf(keymap, buf, size, offset, "%d", action->btn.button);
568 write_buf(keymap, buf, size, offset, "default");
569 if (action->btn.count)
570 write_buf(keymap, buf, size, offset, ",count=%d",
573 write_buf(keymap, buf, size, offset, "%s", args);
574 write_buf(keymap, buf, size, offset, ")%s", suffix);
576 case XkbSA_SetPtrDflt:
577 write_buf(keymap, buf, size, offset, "%sSetPtrDflt(", prefix);
578 if (action->dflt.affect == XkbSA_AffectDfltBtn)
579 write_buf(keymap, buf, size, offset, "affect=button,button=%s%d",
580 (!(action->dflt.flags & XkbSA_DfltBtnAbsolute) &&
581 action->dflt.value >= 0) ? "+" : "",
583 write_buf(keymap, buf, size, offset, ")%s", suffix);
585 case XkbSA_SwitchScreen:
586 write_buf(keymap, buf, size, offset,
587 "%sSwitchScreen(screen=%s%d,%ssame)%s", prefix,
588 (!(action->screen.flags & XkbSA_SwitchAbsolute) &&
589 action->screen.screen >= 0) ? "+" : "",
590 action->screen.screen,
591 (action->screen.flags & XkbSA_SwitchApplication) ? "!" : "",
594 /* Deprecated actions below here */
595 case XkbSA_SetControls:
597 type = "SetControls";
598 case XkbSA_LockControls:
600 type = "LockControls";
601 write_buf(keymap, buf, size, offset, "%s%s(controls=%s)%s",
602 prefix, type, get_control_mask_text(action->ctrls.ctrls),
606 case XkbSA_ActionMessage:
607 case XkbSA_RedirectKey:
608 case XkbSA_DeviceBtn:
609 case XkbSA_LockDeviceBtn:
612 write_buf(keymap, buf, size, offset, "%sNoAction()%s", prefix, suffix);
614 case XkbSA_XFree86Private:
616 write_buf(keymap, buf, size, offset,
617 "%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",
618 prefix, action->any.type, action->any.data[0],
619 action->any.data[1], action->any.data[2],
620 action->any.data[3], action->any.data[4],
621 action->any.data[5], action->any.data[6], suffix);
629 write_compat(struct xkb_keymap *keymap, char **buf, size_t *size,
633 struct xkb_sym_interpret *interp;
635 write_buf(keymap, buf, size, offset, "\txkb_compatibility {\n\n");
637 write_vmods(keymap, buf, size, offset);
639 write_buf(keymap, buf, size, offset, "\t\tinterpret.useModMapMods= AnyLevel;\n");
640 write_buf(keymap, buf, size, offset, "\t\tinterpret.repeat= false;\n");
641 write_buf(keymap, buf, size, offset, "\t\tinterpret.locking= false;\n");
643 darray_foreach(interp, keymap->compat->sym_interpret) {
644 char keysym_name[64];
646 if (interp->sym == XKB_KEY_NoSymbol)
647 sprintf(keysym_name, "Any");
649 xkb_keysym_get_name(interp->sym, keysym_name, 64);
651 write_buf(keymap, buf, size, offset, "\t\tinterpret %s+%s(%s) {\n",
653 get_interp_match_text(interp->match),
654 get_mod_mask_text(keymap, interp->mods, 0));
656 if (interp->virtual_mod != XkbNoModifier) {
657 write_buf(keymap, buf, size, offset, "\t\t\tvirtualModifier= %s;\n",
658 keymap->names->vmods[interp->virtual_mod]);
661 if (interp->match & XkbSI_LevelOneOnly)
662 write_buf(keymap, buf, size, offset, "\t\t\tuseModMapMods=level1;\n");
663 if (interp->flags & XkbSI_LockingKey)
664 write_buf(keymap, buf, size, offset, "\t\t\tlocking= true;\n");
665 if (interp->flags & XkbSI_AutoRepeat)
666 write_buf(keymap, buf, size, offset, "\t\t\trepeat= true;\n");
668 write_action(keymap, buf, size, offset, &interp->act,
669 "\t\t\taction= ", ";\n");
670 write_buf(keymap, buf, size, offset, "\t\t};\n");
673 for (i = 0; i < XkbNumKbdGroups; i++) {
676 gc = &keymap->compat->groups[i];
677 if (gc->real_mods == 0 && gc->vmods ==0)
679 write_buf(keymap, buf, size, offset,
680 "\t\tgroup %d = %s;\n", i + 1,
681 get_mod_mask_text(keymap, gc->real_mods, gc->vmods));
684 for (i = 0; i < XkbNumIndicators; i++) {
685 struct xkb_indicator_map *map = &keymap->indicators->maps[i];
686 if (map->flags == 0 && map->which_groups == 0 &&
687 map->groups == 0 && map->which_mods == 0 &&
688 map->mods.real_mods == 0 && map->mods.vmods == 0 &&
691 write_indicator_map(keymap, buf, size, offset, i);
694 write_buf(keymap, buf, size, offset, "\t};\n\n");
700 write_keysyms(struct xkb_keymap *keymap, char **buf, size_t *size,
701 size_t *offset, xkb_keycode_t key, unsigned int group)
703 const xkb_keysym_t *syms;
705 #define OUT_BUF_LEN 128
706 char out_buf[OUT_BUF_LEN];
708 for (level = 0; level < XkbKeyGroupWidth(keymap, key, group); level++) {
710 write_buf(keymap, buf, size, offset, ", ");
711 num_syms = xkb_key_get_syms_by_level(keymap, key, group, level,
714 write_buf(keymap, buf, size, offset, "%15s", "NoSymbol");
716 else if (num_syms == 1) {
717 xkb_keysym_get_name(syms[0], out_buf, OUT_BUF_LEN);
718 write_buf(keymap, buf, size, offset, "%15s", out_buf);
722 write_buf(keymap, buf, size, offset, "{ ");
723 for (s = 0; s < num_syms; s++) {
725 write_buf(keymap, buf, size, offset, ", ");
726 xkb_keysym_get_name(syms[s], out_buf, OUT_BUF_LEN);
727 write_buf(keymap, buf, size, offset, "%15s", out_buf);
729 write_buf(keymap, buf, size, offset, " }");
738 write_symbols(struct xkb_keymap *keymap, char **buf, size_t *size,
741 struct xkb_client_map *map = keymap->map;
742 struct xkb_server_map *srv = keymap->server;
747 write_buf(keymap, buf, size, offset, "\txkb_symbols {\n\n");
749 for (tmp = group = 0; group < XkbNumKbdGroups; group++) {
750 if (!keymap->names->groups[group])
752 write_buf(keymap, buf, size, offset,
753 "\t\tname[group%d]=\"%s\";\n", group + 1,
754 keymap->names->groups[group]);
758 write_buf(keymap, buf, size, offset, "\n");
760 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
763 if (xkb_key_num_groups(keymap, key) == 0)
765 if (XkbcFindKeycodeByName(keymap,
766 darray_item(keymap->names->keys, key).name,
770 write_buf(keymap, buf, size, offset, "\t\tkey %6s {",
771 XkbcKeyNameText(darray_item(keymap->names->keys, key).name));
773 if ((srv->explicit[key] & XkbExplicitKeyTypesMask)) {
774 bool multi_type = false;
775 int type = XkbKeyTypeIndex(keymap, key, 0);
779 for (group = 0; group < xkb_key_num_groups(keymap, key); group++) {
780 if (XkbKeyTypeIndex(keymap, key, group) != type) {
787 group < xkb_key_num_groups(keymap, key);
789 if (!(srv->explicit[key] & (1 << group)))
791 type = XkbKeyTypeIndex(keymap, key, group);
792 write_buf(keymap, buf, size, offset,
793 "\n\t\t\ttype[Group%d]= \"%s\",",
795 darray_item(map->types, type).name);
799 write_buf(keymap, buf, size, offset,
800 "\n\t\t\ttype= \"%s\",",
801 darray_item(map->types, type).name);
804 if (keymap->ctrls && (srv->explicit[key] & XkbExplicitAutoRepeatMask)) {
805 if (keymap->ctrls->per_key_repeat[key / 8] & (1 << (key % 8)))
806 write_buf(keymap, buf, size, offset,
807 "\n\t\t\trepeat= Yes,");
809 write_buf(keymap, buf, size, offset,
810 "\n\t\t\trepeat= No,");
813 if (keymap->server->vmodmap[key] &&
814 (srv->explicit[key] & XkbExplicitVModMapMask)) {
815 write_buf(keymap, buf, size, offset, "\n\t\t\tvirtualMods= %s,",
816 get_mod_mask_text(keymap, 0, keymap->server->vmodmap[key]));
820 switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(keymap, key))) {
821 case XkbClampIntoRange:
822 write_buf(keymap, buf, size, offset, "\n\t\t\tgroupsClamp,");
824 case XkbRedirectIntoRange:
825 write_buf(keymap, buf, size, offset,
826 "\n\t\t\tgroupsRedirect= Group%d,",
827 XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(keymap, key)) + 1);
831 if (srv->explicit == NULL ||
832 (srv->explicit[key] & XkbExplicitInterpretMask))
833 showActions = XkbKeyHasActions(keymap, key);
837 if (xkb_key_num_groups(keymap, key) > 1 || showActions)
841 write_buf(keymap, buf, size, offset, "\t[ ");
842 if (!write_keysyms(keymap, buf, size, offset, key, 0))
844 write_buf(keymap, buf, size, offset, " ] };\n");
847 union xkb_action *acts;
850 acts = XkbKeyActionsPtr(keymap, key);
851 for (group = 0; group < xkb_key_num_groups(keymap, key); group++) {
853 write_buf(keymap, buf, size, offset, ",");
854 write_buf(keymap, buf, size, offset,
855 "\n\t\t\tsymbols[Group%d]= [ ", group + 1);
856 if (!write_keysyms(keymap, buf, size, offset, key, group))
858 write_buf(keymap, buf, size, offset, " ]");
860 write_buf(keymap, buf, size, offset,
861 ",\n\t\t\tactions[Group%d]= [ ", group + 1);
863 level < XkbKeyGroupWidth(keymap, key, group);
866 write_buf(keymap, buf, size, offset, ", ");
867 write_action(keymap, buf, size, offset, &acts[level],
870 write_buf(keymap, buf, size, offset, " ]");
871 acts += XkbKeyGroupsWidth(keymap, key);
874 write_buf(keymap, buf, size, offset, "\n\t\t};\n");
877 if (map && map->modmap) {
878 for (key = keymap->min_key_code; key <= keymap->max_key_code; key++) {
882 if (map->modmap[key] == 0)
885 for (mod = 0; mod < XkbNumModifiers; mod++) {
886 if (!(map->modmap[key] & (1 << mod)))
889 memcpy(name, darray_item(keymap->names->keys, key).name, 4);
892 write_buf(keymap, buf, size, offset,
893 "\t\tmodifier_map %s { <%s> };\n",
894 get_mod_index_text(mod), name);
899 write_buf(keymap, buf, size, offset, "\t};\n\n");
904 xkb_map_get_as_string(struct xkb_keymap *keymap)
910 check_write_buf(keymap, &ret, &size, &offset, "xkb_keymap {\n");
913 if (!write_keycodes(keymap, &ret, &size, &offset))
915 if (!write_types(keymap, &ret, &size, &offset))
917 if (!write_compat(keymap, &ret, &size, &offset))
919 if (!write_symbols(keymap, &ret, &size, &offset))
921 check_write_buf(keymap, &ret, &size, &offset, "};\n");