297da592c33e94b8bae1821348d5f51b02b148c5
[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 bool
30 LookupString(const LookupEntry tab[], const char *string,
31               unsigned int *value_rtrn)
32 {
33     const LookupEntry *entry;
34
35     if (!string)
36         return false;
37
38     for (entry = tab; entry->name; entry++) {
39         if (istreq(entry->name, string)) {
40             *value_rtrn = entry->value;
41             return true;
42         }
43     }
44
45     return false;
46 }
47
48 const char *
49 LookupValue(const LookupEntry tab[], unsigned int value)
50 {
51     const LookupEntry *entry;
52
53     for (entry = tab; entry->name; entry++)
54         if (entry->value == value)
55             return entry->name;
56
57     return NULL;
58 }
59
60 const LookupEntry ctrlMaskNames[] = {
61     { "RepeatKeys", XkbRepeatKeysMask },
62     { "Repeat", XkbRepeatKeysMask },
63     { "AutoRepeat", XkbRepeatKeysMask },
64     { "SlowKeys", XkbSlowKeysMask },
65     { "BounceKeys", XkbBounceKeysMask },
66     { "StickyKeys", XkbStickyKeysMask },
67     { "MouseKeys", XkbMouseKeysMask },
68     { "MouseKeysAccel", XkbMouseKeysAccelMask },
69     { "AccessXKeys", XkbAccessXKeysMask },
70     { "AccessXTimeout", XkbAccessXTimeoutMask },
71     { "AccessXFeedback", XkbAccessXFeedbackMask },
72     { "AudibleBell", XkbAudibleBellMask },
73     { "IgnoreGroupLock", XkbIgnoreGroupLockMask },
74     { "all", XkbAllBooleanCtrlsMask },
75     { "none", 0 },
76     { "Overlay1", 0 },
77     { "Overlay2", 0 },
78     { NULL, 0 }
79 };
80
81 const LookupEntry modComponentMaskNames[] = {
82     {"base", XkbIM_UseBase},
83     {"latched", XkbIM_UseLatched},
84     {"locked", XkbIM_UseLocked},
85     {"effective", XkbIM_UseEffective},
86     {"compat", XkbIM_UseCompat},
87     {"any", XkbIM_UseAnyMods},
88     {"none", 0},
89     {NULL, 0}
90 };
91
92 const LookupEntry groupComponentMaskNames[] = {
93     {"base", XkbIM_UseBase},
94     {"latched", XkbIM_UseLatched},
95     {"locked", XkbIM_UseLocked},
96     {"effective", XkbIM_UseEffective},
97     {"any", XkbIM_UseAnyGroup},
98     {"none", 0},
99     {NULL, 0}
100 };
101
102 const LookupEntry groupMaskNames[] = {
103     {"group1", 0x01},
104     {"group2", 0x02},
105     {"group3", 0x04},
106     {"group4", 0x08},
107     {"group5", 0x10},
108     {"group6", 0x20},
109     {"group7", 0x40},
110     {"group8", 0x80},
111     {"none", 0x00},
112     {"all", 0xff},
113     {NULL, 0}
114 };
115
116 const LookupEntry groupNames[] = {
117     {"group1", 1},
118     {"group2", 2},
119     {"group3", 3},
120     {"group4", 4},
121     {"group5", 5},
122     {"group6", 6},
123     {"group7", 7},
124     {"group8", 8},
125     {NULL, 0}
126 };
127
128 const LookupEntry levelNames[] = {
129     { "level1", 1 },
130     { "level2", 2 },
131     { "level3", 3 },
132     { "level4", 4 },
133     { "level5", 5 },
134     { "level6", 6 },
135     { "level7", 7 },
136     { "level8", 8 },
137     { NULL, 0 }
138 };
139
140 const LookupEntry buttonNames[] = {
141     { "button1", 1 },
142     { "button2", 2 },
143     { "button3", 3 },
144     { "button4", 4 },
145     { "button5", 5 },
146     { "default", 0 },
147     { NULL, 0 }
148 };
149
150 const LookupEntry useModMapValueNames[] = {
151     { "levelone", 1 },
152     { "level1", 1 },
153     { "anylevel", 0 },
154     { "any", 0 },
155     { NULL, 0 }
156 };
157
158 const LookupEntry actionTypeNames[] = {
159     { "NoAction", XkbSA_NoAction },
160     { "SetMods", XkbSA_SetMods },
161     { "LatchMods", XkbSA_LatchMods },
162     { "LockMods", XkbSA_LockMods },
163     { "SetGroup", XkbSA_SetGroup },
164     { "LatchGroup", XkbSA_LatchGroup },
165     { "LockGroup", XkbSA_LockGroup },
166     { "MovePtr", XkbSA_MovePtr },
167     { "MovePointer", XkbSA_MovePtr },
168     { "PtrBtn", XkbSA_PtrBtn },
169     { "PointerButton", XkbSA_PtrBtn },
170     { "LockPtrBtn", XkbSA_LockPtrBtn },
171     { "LockPtrButton", XkbSA_LockPtrBtn },
172     { "LockPointerButton", XkbSA_LockPtrBtn },
173     { "LockPointerBtn", XkbSA_LockPtrBtn },
174     { "SetPtrDflt", XkbSA_SetPtrDflt },
175     { "SetPointerDefault", XkbSA_SetPtrDflt },
176     { "ISOLock", XkbSA_ISOLock },
177     { "Terminate", XkbSA_Terminate },
178     { "TerminateServer", XkbSA_Terminate },
179     { "SwitchScreen", XkbSA_SwitchScreen },
180     { "SetControls", XkbSA_SetControls },
181     { "LockControls", XkbSA_LockControls },
182     { "ActionMessage", XkbSA_ActionMessage },
183     { "MessageAction", XkbSA_ActionMessage },
184     { "Message", XkbSA_ActionMessage },
185     { "RedirectKey", XkbSA_RedirectKey },
186     { "Redirect", XkbSA_RedirectKey },
187     { "DeviceBtn", XkbSA_DeviceBtn },
188     { "DevBtn", XkbSA_DeviceBtn },
189     { "DevButton", XkbSA_DeviceBtn },
190     { "DeviceButton", XkbSA_DeviceBtn },
191     { "LockDeviceBtn", XkbSA_LockDeviceBtn },
192     { "LockDevBtn", XkbSA_LockDeviceBtn },
193     { "LockDevButton", XkbSA_LockDeviceBtn },
194     { "LockDeviceButton", XkbSA_LockDeviceBtn },
195     { "DeviceValuator", XkbSA_DeviceValuator },
196     { "DevVal", XkbSA_DeviceValuator },
197     { "DeviceVal", XkbSA_DeviceValuator },
198     { "DevValuator", XkbSA_DeviceValuator },
199     { "Private", PrivateAction },
200     { NULL, 0 },
201 };
202
203 const LookupEntry symInterpretMatchMaskNames[] = {
204     { "NoneOf", XkbSI_NoneOf },
205     { "AnyOfOrNone", XkbSI_AnyOfOrNone },
206     { "AnyOf", XkbSI_AnyOf },
207     { "AllOf", XkbSI_AllOf },
208     { "Exactly", XkbSI_Exactly },
209 };
210
211 #define BUFFER_SIZE 1024
212
213 static char *
214 GetBuffer(size_t size)
215 {
216     static char buffer[BUFFER_SIZE];
217     static size_t next;
218     char *rtrn;
219
220     if (size >= BUFFER_SIZE)
221         return NULL;
222
223     if (BUFFER_SIZE - next <= size)
224         next = 0;
225
226     rtrn = &buffer[next];
227     next += size;
228
229     return rtrn;
230 }
231
232 /*
233  * Get a vmod name's text, where the vmod index is zero based
234  * (0..XkbNumVirtualMods-1).
235  */
236 static const char *
237 VModIndexText(struct xkb_keymap *keymap, xkb_mod_index_t ndx)
238 {
239     int len;
240     char *rtrn;
241     const char *tmp = NULL;
242     char buf[20];
243
244     if (ndx >= XkbNumVirtualMods)
245          tmp = "illegal";
246     else
247          tmp = xkb_atom_text(keymap->ctx, keymap->vmod_names[ndx]);
248
249     if (!tmp) {
250         snprintf(buf, sizeof(buf) - 1, "%d", ndx);
251         tmp = buf;
252     }
253
254     len = strlen(tmp) + 1;
255     if (len >= BUFFER_SIZE)
256         len = BUFFER_SIZE - 1;
257
258     rtrn = GetBuffer(len);
259     strncpy(rtrn, tmp, len);
260
261     return rtrn;
262 }
263
264 /* Get a mod mask's text, where the mask is in rmods+vmods format. */
265 const char *
266 VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t cmask)
267 {
268     xkb_mod_index_t i;
269     xkb_mod_mask_t bit;
270     xkb_mod_mask_t rmask, vmask;
271     int len, rem;
272     const char *mm = NULL;
273     char *rtrn, *str;
274     char buf[BUFFER_SIZE];
275
276     rmask = cmask & 0xff;
277     vmask = cmask >> XkbNumModifiers;
278
279     if (rmask == 0 && vmask == 0)
280         return "none";
281
282     if (rmask != 0)
283         mm = ModMaskText(rmask);
284
285     str = buf;
286     buf[0] = '\0';
287     rem = BUFFER_SIZE;
288
289     if (vmask != 0) {
290         for (i = 0, bit = 1; i < XkbNumVirtualMods && rem > 1; i++, bit <<=
291                  1) {
292             if (!(vmask & bit))
293                 continue;
294
295             len = snprintf(str, rem, "%s%s",
296                            (str != buf) ? "+" : "",
297                            VModIndexText(keymap, i));
298             rem -= len;
299             str += len;
300         }
301
302         str = buf;
303     }
304     else
305         str = NULL;
306
307     len = (str ? strlen(str) : 0) + (mm ? strlen(mm) : 0) +
308           (str && mm ? 1 : 0);
309     if (len >= BUFFER_SIZE)
310         len = BUFFER_SIZE - 1;
311
312     rtrn = GetBuffer(len + 1);
313     rtrn[0] = '\0';
314
315     snprintf(rtrn, len + 1, "%s%s%s", (mm ? mm : ""),
316              (mm && str ? "+" : ""), (str ? str : ""));
317
318     return rtrn;
319 }
320
321 /*
322  * IMPORTATNT
323  * The indices used for the legacy core modifiers is derived from
324  * the order of the names in this table. It matches the values
325  * ShiftMapIndex, LockMapIndex, etc. from X11/X.h. Take note before
326  * changing.
327  */
328 static const char *modNames[XkbNumModifiers] = {
329     "Shift",
330     "Lock",
331     "Control",
332     "Mod1",
333     "Mod2",
334     "Mod3",
335     "Mod4",
336     "Mod5",
337 };
338
339 xkb_mod_index_t
340 ModNameToIndex(const char *name)
341 {
342     xkb_mod_index_t i;
343
344     for (i = 0; i < XkbNumModifiers; i++)
345         if (istreq(name, modNames[i]))
346             return i;
347
348     return XKB_MOD_INVALID;
349 }
350
351 const char *
352 ModIndexToName(xkb_mod_index_t ndx)
353 {
354     if (ndx < XkbNumModifiers)
355         return modNames[ndx];
356     return NULL;
357 }
358
359 const char *
360 ModIndexText(xkb_mod_index_t ndx)
361 {
362     const char *name;
363     char *buf;
364
365     name = ModIndexToName(ndx);
366     if (name)
367         return name;
368
369     if (ndx == XKB_MOD_INVALID)
370         return "none";
371
372     buf = GetBuffer(32);
373     snprintf(buf, 32, "ILLEGAL_%02x", ndx);
374
375     return buf;
376 }
377
378 /* Gets the text for the real modifiers only. */
379 const char *
380 ModMaskText(xkb_mod_mask_t mask)
381 {
382     int i, rem;
383     xkb_mod_index_t bit;
384     char *str, *buf;
385
386     if ((mask & 0xff) == 0xff)
387         return "all";
388
389     if ((mask & 0xff) == 0)
390         return "none";
391
392     rem = 64;
393     buf = GetBuffer(rem);
394     str = buf;
395     buf[0] = '\0';
396     for (i = 0, bit = 1; i < XkbNumModifiers && rem > 1; i++, bit <<= 1) {
397         int len;
398
399         if (!(mask & bit))
400             continue;
401
402         len = snprintf(str, rem, "%s%s",
403                        (str != buf ?  "+" : ""), modNames[i]);
404         rem -= len;
405         str += len;
406     }
407
408     return buf;
409 }
410
411 const char *
412 ActionTypeText(unsigned type)
413 {
414     const char *name = LookupValue(actionTypeNames, type);
415     return name ? name : "Private";
416 }
417
418 const char *
419 KeysymText(xkb_keysym_t sym)
420 {
421     static char buffer[64];
422
423     xkb_keysym_get_name(sym, buffer, sizeof buffer);
424
425     return buffer;
426 }
427
428 const char *
429 KeyNameText(const char name[XkbKeyNameLength])
430 {
431     char *buf;
432     int len;
433
434     buf = GetBuffer(7);
435     buf[0] = '<';
436     strncpy(&buf[1], name, 4);
437     buf[5] = '\0';
438     len = strlen(buf);
439     buf[len++] = '>';
440     buf[len] = '\0';
441
442     return buf;
443 }
444
445 const char *
446 SIMatchText(unsigned type)
447 {
448     const char *name;
449     char *buf;
450
451     type &= XkbSI_OpMask;
452
453     name = LookupValue(symInterpretMatchMaskNames, type);
454     if (name)
455         return name;
456
457     buf = GetBuffer(40);
458     snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
459     return buf;
460 }