kbproto unentanglement: XkbNumVirtualMods
[platform/upstream/libxkbcommon.git] / src / xkbcomp / vmod.c
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 #include "xkbcomp-priv.h"
28 #include "text.h"
29 #include "expr.h"
30 #include "vmod.h"
31
32 void
33 InitVModInfo(VModInfo *info, struct xkb_keymap *keymap)
34 {
35     xkb_group_index_t i;
36
37     info->defined = info->available = 0;
38
39     for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++)
40         if (keymap->vmod_names[i])
41             info->defined |= (1 << i);
42 }
43
44 void
45 ClearVModInfo(VModInfo *info)
46 {
47     info->defined = info->available = 0;
48 }
49
50 bool
51 HandleVModDef(VModDef *stmt, struct xkb_keymap *keymap,
52               enum merge_mode mergeMode, VModInfo *info)
53 {
54     xkb_mod_index_t i;
55     int nextFree;
56     xkb_mod_mask_t bit;
57
58     if (stmt->value)
59         log_err(keymap->ctx,
60                 "Support for setting a value in a virtual_modifiers statement has been removed; "
61                 "Value ignored\n");
62
63     nextFree = -1;
64     for (i = 0, bit = 1; i < XKB_NUM_VIRTUAL_MODS; i++, bit <<= 1) {
65         if (!(info->defined & bit)) {
66             if (nextFree < 0)
67                 nextFree = i;
68             continue;
69         }
70
71         /* Already defined. */
72         if (!keymap->vmod_names[i])
73             continue;
74
75         if (keymap->vmod_names[i] != stmt->name)
76             continue;
77
78         info->available |= bit;
79         return true;
80     }
81
82     if (nextFree < 0) {
83         log_err(keymap->ctx,
84                 "Too many virtual modifiers defined (maximum %d)\n",
85                 XKB_NUM_VIRTUAL_MODS);
86         return false;
87     }
88
89     info->defined |= (1 << nextFree);
90     info->available |= (1 << nextFree);
91
92     keymap->vmod_names[nextFree] = stmt->name;
93     return true;
94 }
95
96 static bool
97 LookupVModIndex(const struct xkb_keymap *keymap, xkb_atom_t field,
98                 enum expr_value_type type, xkb_mod_index_t *val_rtrn)
99 {
100     xkb_mod_index_t i;
101
102     if (type != EXPR_TYPE_INT)
103         return false;
104
105     for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
106         if (keymap->vmod_names[i] == field) {
107             *val_rtrn = i;
108             return true;
109         }
110     }
111
112     return false;
113 }
114
115 bool
116 LookupVModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
117                enum expr_value_type type, xkb_mod_mask_t *val_rtrn)
118 {
119     xkb_mod_index_t ndx;
120
121     if (LookupModMask(ctx, NULL, field, type, val_rtrn)) {
122         return true;
123     }
124     else if (LookupVModIndex(priv, field, type, &ndx)) {
125         *val_rtrn = (1 << (XKB_NUM_CORE_MODS + ndx));
126         return true;
127     }
128
129     return false;
130 }
131
132 bool
133 ResolveVirtualModifier(ExprDef *def, struct xkb_keymap *keymap,
134                        xkb_mod_index_t *ndx_rtrn, VModInfo *info)
135 {
136     xkb_mod_index_t i;
137     xkb_atom_t name = def->value.str;
138
139     if (def->op != EXPR_IDENT) {
140         log_err(keymap->ctx,
141                 "Cannot resolve virtual modifier: "
142                 "found %s where a virtual modifier name was expected\n",
143                 expr_op_type_to_string(def->op));
144         return false;
145     }
146
147     for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
148         if ((info->available & (1 << i)) && keymap->vmod_names[i] == name) {
149             *ndx_rtrn = i;
150             return true;
151         }
152     }
153
154     log_err(keymap->ctx,
155             "Cannot resolve virtual modifier: "
156             "\"%s\" was not previously declared\n",
157             xkb_atom_text(keymap->ctx, name));
158     return false;
159 }