Use CARD32 instead of Atom, move geom headers in
[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 #define DEBUG_VAR debugFlags
28 #include <stdio.h>
29 #include "xkbcomp.h"
30 #include "xkballoc.h"
31 #include "xkbmisc.h"
32 #include "tokens.h"
33 #include "expr.h"
34 #include "misc.h"
35
36 #include <X11/extensions/XKB.h>
37 #include <X11/extensions/XKBstrcommon.h>
38
39 #include "vmod.h"
40
41 void
42 InitVModInfo(VModInfo * info, XkbcDescPtr xkb)
43 {
44     ClearVModInfo(info, xkb);
45     info->errorCount = 0;
46     return;
47 }
48
49 void
50 ClearVModInfo(VModInfo * info, XkbcDescPtr xkb)
51 {
52     register int i;
53
54     if (XkbcAllocNames(xkb, XkbVirtualModNamesMask, 0, 0) != Success)
55         return;
56     if (XkbcAllocServerMap(xkb, XkbVirtualModsMask, 0) != Success)
57         return;
58     info->xkb = xkb;
59     info->newlyDefined = info->defined = info->available = 0;
60     if (xkb && xkb->names)
61     {
62         register int bit;
63         for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1)
64         {
65             if (xkb->names->vmods[i] != None)
66                 info->defined |= bit;
67         }
68     }
69     return;
70 }
71
72 /***====================================================================***/
73
74 /**
75  * Handle one entry in the virtualModifiers line (e.g. NumLock).
76  * If the entry is e.g. NumLock=Mod1, stmt->value is not NULL, and the
77  * XkbServerMap's vmod is set to the given modifier. Otherwise, the vmod is 0.
78  *
79  * @param stmt The statement specifying the name and (if any the value).
80  * @param mergeMode Merge strategy (e.g. MergeOverride)
81  */
82 Bool
83 HandleVModDef(VModDef * stmt, unsigned mergeMode, VModInfo * info)
84 {
85     register int i, bit, nextFree;
86     ExprResult mod;
87     XkbcServerMapPtr srv;
88     XkbcNamesPtr names;
89
90     srv = info->xkb->server;
91     names = info->xkb->names;
92     for (i = 0, bit = 1, nextFree = -1; i < XkbNumVirtualMods; i++, bit <<= 1)
93     {
94         if (info->defined & bit)
95         {
96             if (names->vmods[i] == stmt->name)
97             {                   /* already defined */
98                 info->available |= bit;
99                 if (stmt->value == NULL)
100                     return True;
101                 else
102                 {
103                     char *str1;
104                     const char *str2 = "";
105                     if (!ExprResolveModMask(stmt->value, &mod, NULL, NULL))
106                     {
107                         str1 = XkbcAtomText(stmt->name);
108                         ACTION("Declaration of %s ignored\n", str1);
109                         return False;
110                     }
111                     if (mod.uval == srv->vmods[i])
112                         return True;
113
114                     str1 = XkbcAtomText(stmt->name);
115                     WARN("Virtual modifier %s multiply defined\n", str1);
116                     str1 = XkbcModMaskText(srv->vmods[i], True);
117                     if (mergeMode == MergeOverride)
118                     {
119                         str2 = str1;
120                         str1 = XkbcModMaskText(mod.uval, True);
121                     }
122                     ACTION("Using %s, ignoring %s\n", str1, str2);
123                     if (mergeMode == MergeOverride)
124                         srv->vmods[i] = mod.uval;
125                     return True;
126                 }
127             }
128         }
129         else if (nextFree < 0)
130             nextFree = i;
131     }
132     if (nextFree < 0)
133     {
134         ERROR("Too many virtual modifiers defined (maximum %d)\n",
135                XkbNumVirtualMods);
136         return False;
137     }
138     info->defined |= (1 << nextFree);
139     info->newlyDefined |= (1 << nextFree);
140     info->available |= (1 << nextFree);
141     names->vmods[nextFree] = stmt->name;
142     if (stmt->value == NULL)
143         return True;
144     if (ExprResolveModMask(stmt->value, &mod, NULL, NULL))
145     {
146         srv->vmods[nextFree] = mod.uval;
147         return True;
148     }
149     ACTION("Declaration of %s ignored\n", XkbcAtomText(stmt->name));
150     return False;
151 }
152
153 /**
154  * Returns the index of the given modifier in the xkb->names->vmods array.
155  *
156  * @param priv Pointer to the xkb data structure.
157  * @param elem Must be None, otherwise return False.
158  * @param field The Atom of the modifier's name (e.g. Atom for LAlt)
159  * @param type Must be TypeInt, otherwise return False.
160  * @param val_rtrn Set to the index of the modifier that matches.
161  *
162  * @return True on success, False otherwise. If False is returned, val_rtrn is
163  * undefined.
164  */
165 int
166 LookupVModIndex(char * priv,
167                 CARD32 elem, CARD32 field, unsigned type, ExprResult * val_rtrn)
168 {
169     int i;
170     XkbcDescPtr xkb;
171
172     xkb = (XkbcDescPtr) priv;
173     if ((xkb == NULL) || (xkb->names == NULL) || (elem != None)
174         || (type != TypeInt))
175     {
176         return False;
177     }
178     /* For each named modifier, get the name and compare it to the one passed
179      * in. If we get a match, return the index of the modifier.
180      * The order of modifiers is the same as in the virtual_modifiers line in
181      * the xkb_types section.
182      */
183     for (i = 0; i < XkbNumVirtualMods; i++)
184     {
185         if (xkb->names->vmods[i] == field)
186         {
187             val_rtrn->uval = i;
188             return True;
189         }
190     }
191     return False;
192 }
193
194 /**
195  * Get the mask for the given modifier and set val_rtrn.uval to the mask.
196  * Note that the mask returned is always > 512.
197  *
198  * @param priv Pointer to xkb data structure.
199  * @param val_rtrn Set to the mask returned.
200  *
201  * @return True on success, False otherwise. If False is returned, val_rtrn is
202  * undefined.
203  */
204 int
205 LookupVModMask(char * priv,
206                CARD32 elem, CARD32 field, unsigned type, ExprResult * val_rtrn)
207 {
208     if (LookupVModIndex(priv, elem, field, type, val_rtrn))
209     {
210         register unsigned ndx = val_rtrn->uval;
211         val_rtrn->uval = (1 << (XkbNumModifiers + ndx));
212         return True;
213     }
214     return False;
215 }
216
217 int
218 FindKeypadVMod(XkbcDescPtr xkb)
219 {
220     CARD32 name;
221     ExprResult rtrn;
222
223     name = XkbcInternAtom("NumLock", False);
224     if ((xkb) && LookupVModIndex((char *) xkb, None, name, TypeInt, &rtrn))
225     {
226         return rtrn.ival;
227     }
228     return -1;
229 }
230
231 Bool
232 ResolveVirtualModifier(ExprDef * def, ExprResult * val_rtrn, VModInfo * info)
233 {
234     XkbcNamesPtr names;
235
236     names = info->xkb->names;
237     if (def->op == ExprIdent)
238     {
239         int i, bit;
240         for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1)
241         {
242             if ((info->available & bit) && names->vmods[i] == def->value.str)
243             {
244                 val_rtrn->uval = i;
245                 return True;
246             }
247         }
248     }
249     if (ExprResolveInteger(def, val_rtrn, NULL, NULL))
250     {
251         if (val_rtrn->uval < XkbNumVirtualMods)
252             return True;
253         ERROR("Illegal virtual modifier %d (must be 0..%d inclusive)\n",
254                val_rtrn->uval, XkbNumVirtualMods - 1);
255     }
256     return False;
257 }