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