xkbcomp: clean up compile_keymap function
[platform/upstream/libxkbcommon.git] / src / text.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 "text.h"
28
29 #define BUFFER_SIZE 1024
30
31 static char *
32 GetBuffer(size_t size)
33 {
34     static char buffer[BUFFER_SIZE];
35     static size_t next;
36     char *rtrn;
37
38     if (size >= BUFFER_SIZE)
39         return NULL;
40
41     if (BUFFER_SIZE - next <= size)
42         next = 0;
43
44     rtrn = &buffer[next];
45     next += size;
46
47     return rtrn;
48 }
49
50 /*
51  * Get a vmod name's text, where the vmod index is zero based
52  * (0..XkbNumVirtualMods-1).
53  */
54 static const char *
55 VModIndexText(struct xkb_keymap *keymap, xkb_mod_index_t ndx)
56 {
57     int len;
58     char *rtrn;
59     const char *tmp = NULL;
60     char buf[20];
61
62     if (ndx >= XkbNumVirtualMods)
63          tmp = "illegal";
64     else
65          tmp = keymap->vmod_names[ndx];
66
67     if (!tmp) {
68         snprintf(buf, sizeof(buf) - 1, "%d", ndx);
69         tmp = buf;
70     }
71
72     len = strlen(tmp) + 1;
73     if (len >= BUFFER_SIZE)
74         len = BUFFER_SIZE - 1;
75
76     rtrn = GetBuffer(len);
77     strncpy(rtrn, tmp, len);
78
79     return rtrn;
80 }
81
82 /* Get a mod mask's text, where the mask is in rmods+vmods format. */
83 const char *
84 VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t cmask)
85 {
86     xkb_mod_index_t i;
87     xkb_mod_mask_t bit;
88     xkb_mod_mask_t rmask, vmask;
89     int len, rem;
90     const char *mm = NULL;
91     char *rtrn, *str;
92     char buf[BUFFER_SIZE];
93
94     rmask = cmask & 0xff;
95     vmask = cmask >> XkbNumModifiers;
96
97     if (rmask == 0 && vmask == 0)
98         return "none";
99
100     if (rmask != 0)
101         mm = ModMaskText(rmask);
102
103     str = buf;
104     buf[0] = '\0';
105     rem = BUFFER_SIZE;
106
107     if (vmask != 0) {
108         for (i = 0, bit = 1; i < XkbNumVirtualMods && rem > 1; i++, bit <<=
109                  1) {
110             if (!(vmask & bit))
111                 continue;
112
113             len = snprintf(str, rem, "%s%s",
114                            (str != buf) ? "+" : "",
115                            VModIndexText(keymap, i));
116             rem -= len;
117             str += len;
118         }
119
120         str = buf;
121     }
122     else
123         str = NULL;
124
125     len = (str ? strlen(str) : 0) + (mm ? strlen(mm) : 0) +
126           (str && mm ? 1 : 0);
127     if (len >= BUFFER_SIZE)
128         len = BUFFER_SIZE - 1;
129
130     rtrn = GetBuffer(len + 1);
131     rtrn[0] = '\0';
132
133     snprintf(rtrn, len + 1, "%s%s%s", (mm ? mm : ""),
134              (mm && str ? "+" : ""), (str ? str : ""));
135
136     return rtrn;
137 }
138
139 /*
140  * IMPORTATNT
141  * The indices used for the legacy core modifiers is derived from
142  * the order of the names in this table. It matches the values
143  * ShiftMapIndex, LockMapIndex, etc. from X11/X.h. Take note before
144  * changing.
145  */
146 static const char *modNames[XkbNumModifiers] = {
147     "Shift",
148     "Lock",
149     "Control",
150     "Mod1",
151     "Mod2",
152     "Mod3",
153     "Mod4",
154     "Mod5",
155 };
156
157 xkb_mod_index_t
158 ModNameToIndex(const char *name)
159 {
160     xkb_mod_index_t i;
161
162     for (i = 0; i < XkbNumModifiers; i++)
163         if (istreq(name, modNames[i]))
164             return i;
165
166     return XKB_MOD_INVALID;
167 }
168
169 const char *
170 ModIndexToName(xkb_mod_index_t ndx)
171 {
172     if (ndx < XkbNumModifiers)
173         return modNames[ndx];
174     return NULL;
175 }
176
177 const char *
178 ModIndexText(xkb_mod_index_t ndx)
179 {
180     const char *name;
181     char *buf;
182
183     name = ModIndexToName(ndx);
184     if (name)
185         return name;
186
187     if (ndx == XkbNoModifier)
188         return "none";
189
190     buf = GetBuffer(32);
191     snprintf(buf, 32, "ILLEGAL_%02x", ndx);
192
193     return buf;
194 }
195
196 /* Gets the text for the real modifiers only. */
197 const char *
198 ModMaskText(xkb_mod_mask_t mask)
199 {
200     int i, rem;
201     xkb_mod_index_t bit;
202     char *str, *buf;
203
204     if ((mask & 0xff) == 0xff)
205         return "all";
206
207     if ((mask & 0xff) == 0)
208         return "none";
209
210     rem = 64;
211     buf = GetBuffer(rem);
212     str = buf;
213     buf[0] = '\0';
214     for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
215         int len;
216
217         if (!(mask & bit))
218             continue;
219
220         len = snprintf(str, rem, "%s%s",
221                        (str != buf ?  "+" : ""), modNames[i]);
222         rem -= len;
223         str += len;
224     }
225
226     return buf;
227 }
228
229 static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = {
230     [FILE_TYPE_KEYMAP]   = "xkb_keymap",
231     [FILE_TYPE_TYPES]    = "xkb_types",
232     [FILE_TYPE_COMPAT]   = "xkb_compatibility",
233     [FILE_TYPE_SYMBOLS]  = "xkb_symbols",
234     [FILE_TYPE_KEYCODES] = "xkb_keycodes",
235     [FILE_TYPE_RULES]    = "rules",
236 };
237
238 const char *
239 FileTypeText(enum xkb_file_type type)
240 {
241     if (type > _FILE_TYPE_NUM_ENTRIES)
242         return "unknown";
243     return xkb_file_type_strings[type];
244 }
245
246 static const char *actionTypeNames[XkbSA_NumActions] = {
247     [XkbSA_NoAction]       = "NoAction",
248     [XkbSA_SetMods]        = "SetMods",
249     [XkbSA_LatchMods]      = "LatchMods",
250     [XkbSA_LockMods]       = "LockMods",
251     [XkbSA_SetGroup]       = "SetGroup",
252     [XkbSA_LatchGroup]     = "LatchGroup",
253     [XkbSA_LockGroup]      = "LockGroup",
254     [XkbSA_MovePtr]        = "MovePtr",
255     [XkbSA_PtrBtn]         = "PtrBtn",
256     [XkbSA_LockPtrBtn]     = "LockPtrBtn",
257     [XkbSA_SetPtrDflt]     = "SetPtrDflt",
258     [XkbSA_ISOLock]        = "ISOLock",
259     [XkbSA_Terminate]      = "Terminate",
260     [XkbSA_SwitchScreen]   = "SwitchScreen",
261     [XkbSA_SetControls]    = "SetControls",
262     [XkbSA_LockControls]   = "LockControls",
263     [XkbSA_ActionMessage]  = "ActionMessage",
264     [XkbSA_RedirectKey]    = "RedirectKey",
265     [XkbSA_DeviceBtn]      = "DeviceBtn",
266     [XkbSA_LockDeviceBtn]  = "LockDeviceBtn",
267     [XkbSA_DeviceValuator] = "DeviceValuator"
268 };
269
270 const char *
271 ActionTypeText(unsigned type)
272 {
273     if (type <= XkbSA_LastAction)
274         return actionTypeNames[type];
275     return "Private";
276 }
277
278 const char *
279 KeysymText(xkb_keysym_t sym)
280 {
281     static char buffer[64];
282
283     xkb_keysym_get_name(sym, buffer, sizeof buffer);
284
285     return buffer;
286 }
287
288 const char *
289 KeyNameText(const char name[XkbKeyNameLength])
290 {
291     char *buf;
292     int len;
293
294     buf = GetBuffer(7);
295     buf[0] = '<';
296     strncpy(&buf[1], name, 4);
297     buf[5] = '\0';
298     len = strlen(buf);
299     buf[len++] = '>';
300     buf[len] = '\0';
301
302     return buf;
303 }
304
305 static const char *siMatchText[5] = {
306     "NoneOf",       /* XkbSI_NoneOf */
307     "AnyOfOrNone",  /* XkbSI_AnyOfOrNone */
308     "AnyOf",        /* XkbSI_AnyOf */
309     "AllOf",        /* XkbSI_AllOf */
310     "Exactly"       /* XkbSI_Exactly */
311 };
312
313 const char *
314 SIMatchText(unsigned type)
315 {
316     char *buf;
317
318     switch (type & XkbSI_OpMask) {
319     case XkbSI_NoneOf:
320         return siMatchText[0];
321     case XkbSI_AnyOfOrNone:
322         return siMatchText[1];
323     case XkbSI_AnyOf:
324         return siMatchText[2];
325     case XkbSI_AllOf:
326         return siMatchText[3];
327     case XkbSI_Exactly:
328         return siMatchText[4];
329     default:
330         buf = GetBuffer(40);
331         snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
332         return buf;
333     }
334 }