f3a09e843da1997acf28763c7d13b6c2ad6f3549
[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     if (!string)
35         return false;
36
37     for (const LookupEntry *entry = tab; entry->name; entry++) {
38         if (istreq(entry->name, string)) {
39             *value_rtrn = entry->value;
40             return true;
41         }
42     }
43
44     return false;
45 }
46
47 const char *
48 LookupValue(const LookupEntry tab[], unsigned int value)
49 {
50     for (const LookupEntry *entry = tab; entry->name; entry++)
51         if (entry->value == value)
52             return entry->name;
53
54     return NULL;
55 }
56
57 const LookupEntry ctrlMaskNames[] = {
58     { "RepeatKeys", CONTROL_REPEAT },
59     { "Repeat", CONTROL_REPEAT },
60     { "AutoRepeat", CONTROL_REPEAT },
61     { "SlowKeys", CONTROL_SLOW },
62     { "BounceKeys", CONTROL_DEBOUNCE },
63     { "StickyKeys", CONTROL_STICKY },
64     { "MouseKeys", CONTROL_MOUSEKEYS },
65     { "MouseKeysAccel", CONTROL_MOUSEKEYS_ACCEL },
66     { "AccessXKeys", CONTROL_AX },
67     { "AccessXTimeout", CONTROL_AX_TIMEOUT },
68     { "AccessXFeedback", CONTROL_AX_FEEDBACK },
69     { "AudibleBell", CONTROL_BELL },
70     { "IgnoreGroupLock", CONTROL_IGNORE_GROUP_LOCK },
71     { "all", CONTROL_ALL },
72     { "none", 0 },
73     { "Overlay1", 0 },
74     { "Overlay2", 0 },
75     { NULL, 0 }
76 };
77
78 const LookupEntry modComponentMaskNames[] = {
79     { "base", XKB_STATE_MODS_DEPRESSED },
80     { "latched", XKB_STATE_MODS_LATCHED },
81     { "locked", XKB_STATE_MODS_LOCKED },
82     { "effective", XKB_STATE_MODS_EFFECTIVE },
83     { "compat", XKB_STATE_MODS_EFFECTIVE },
84     { "any", XKB_STATE_MODS_EFFECTIVE },
85     { "none", 0 },
86     { NULL, 0 }
87 };
88
89 const LookupEntry groupComponentMaskNames[] = {
90     { "base", XKB_STATE_LAYOUT_DEPRESSED },
91     { "latched", XKB_STATE_LAYOUT_LATCHED },
92     { "locked", XKB_STATE_LAYOUT_LOCKED },
93     { "effective", XKB_STATE_LAYOUT_EFFECTIVE },
94     { "any", XKB_STATE_LAYOUT_EFFECTIVE },
95     { "none", 0 },
96     { NULL, 0 }
97 };
98
99 const LookupEntry groupMaskNames[] = {
100     { "Group1", 0x01 },
101     { "Group2", 0x02 },
102     { "Group3", 0x04 },
103     { "Group4", 0x08 },
104     { "Group5", 0x10 },
105     { "Group6", 0x20 },
106     { "Group7", 0x40 },
107     { "Group8", 0x80 },
108     { "none", 0x00 },
109     { "all", 0xff },
110     { NULL, 0 }
111 };
112
113 const LookupEntry groupNames[] = {
114     { "Group1", 1 },
115     { "Group2", 2 },
116     { "Group3", 3 },
117     { "Group4", 4 },
118     { "Group5", 5 },
119     { "Group6", 6 },
120     { "Group7", 7 },
121     { "Group8", 8 },
122     { NULL, 0 }
123 };
124
125 const LookupEntry levelNames[] = {
126     { "Level1", 1 },
127     { "Level2", 2 },
128     { "Level3", 3 },
129     { "Level4", 4 },
130     { "Level5", 5 },
131     { "Level6", 6 },
132     { "Level7", 7 },
133     { "Level8", 8 },
134     { NULL, 0 }
135 };
136
137 const LookupEntry buttonNames[] = {
138     { "Button1", 1 },
139     { "Button2", 2 },
140     { "Button3", 3 },
141     { "Button4", 4 },
142     { "Button5", 5 },
143     { "default", 0 },
144     { NULL, 0 }
145 };
146
147 const LookupEntry useModMapValueNames[] = {
148     { "LevelOne", 1 },
149     { "Level1", 1 },
150     { "AnyLevel", 0 },
151     { "any", 0 },
152     { NULL, 0 }
153 };
154
155 const LookupEntry actionTypeNames[] = {
156     { "NoAction", ACTION_TYPE_NONE },
157     { "SetMods", ACTION_TYPE_MOD_SET },
158     { "LatchMods", ACTION_TYPE_MOD_LATCH },
159     { "LockMods", ACTION_TYPE_MOD_LOCK },
160     { "SetGroup", ACTION_TYPE_GROUP_SET },
161     { "LatchGroup", ACTION_TYPE_GROUP_LATCH },
162     { "LockGroup", ACTION_TYPE_GROUP_LOCK },
163     { "MovePtr", ACTION_TYPE_PTR_MOVE },
164     { "MovePointer", ACTION_TYPE_PTR_MOVE },
165     { "PtrBtn", ACTION_TYPE_PTR_BUTTON },
166     { "PointerButton", ACTION_TYPE_PTR_BUTTON },
167     { "LockPtrBtn", ACTION_TYPE_PTR_LOCK },
168     { "LockPtrButton", ACTION_TYPE_PTR_LOCK },
169     { "LockPointerButton", ACTION_TYPE_PTR_LOCK },
170     { "LockPointerBtn", ACTION_TYPE_PTR_LOCK },
171     { "SetPtrDflt", ACTION_TYPE_PTR_DEFAULT },
172     { "SetPointerDefault", ACTION_TYPE_PTR_DEFAULT },
173     { "Terminate", ACTION_TYPE_TERMINATE },
174     { "TerminateServer", ACTION_TYPE_TERMINATE },
175     { "SwitchScreen", ACTION_TYPE_SWITCH_VT },
176     { "SetControls", ACTION_TYPE_CTRL_SET },
177     { "LockControls", ACTION_TYPE_CTRL_LOCK },
178     { "Private", ACTION_TYPE_PRIVATE },
179     /* deprecated actions below here - unused */
180     { "RedirectKey", ACTION_TYPE_NONE },
181     { "Redirect", ACTION_TYPE_NONE },
182     { "ISOLock", ACTION_TYPE_NONE },
183     { "ActionMessage", ACTION_TYPE_NONE },
184     { "MessageAction", ACTION_TYPE_NONE },
185     { "Message", ACTION_TYPE_NONE },
186     { "DeviceBtn", ACTION_TYPE_NONE },
187     { "DevBtn", ACTION_TYPE_NONE },
188     { "DevButton", ACTION_TYPE_NONE },
189     { "DeviceButton", ACTION_TYPE_NONE },
190     { "LockDeviceBtn", ACTION_TYPE_NONE },
191     { "LockDevBtn", ACTION_TYPE_NONE },
192     { "LockDevButton", ACTION_TYPE_NONE },
193     { "LockDeviceButton", ACTION_TYPE_NONE },
194     { "DeviceValuator", ACTION_TYPE_NONE },
195     { "DevVal", ACTION_TYPE_NONE },
196     { "DeviceVal", ACTION_TYPE_NONE },
197     { "DevValuator", ACTION_TYPE_NONE },
198     { NULL, 0 },
199 };
200
201 const LookupEntry symInterpretMatchMaskNames[] = {
202     { "NoneOf", MATCH_NONE },
203     { "AnyOfOrNone", MATCH_ANY_OR_NONE },
204     { "AnyOf", MATCH_ANY },
205     { "AllOf", MATCH_ALL },
206     { "Exactly", MATCH_EXACTLY },
207 };
208
209 const char *
210 ModIndexText(const struct xkb_keymap *keymap, xkb_mod_index_t ndx)
211 {
212     if (ndx == XKB_MOD_INVALID)
213         return "none";
214
215     if (ndx >= darray_size(keymap->mods))
216         return NULL;
217
218     return xkb_atom_text(keymap->ctx, darray_item(keymap->mods, ndx).name);
219 }
220
221 xkb_mod_index_t
222 ModNameToIndex(const struct xkb_keymap *keymap, xkb_atom_t name,
223                enum mod_type type)
224 {
225     xkb_mod_index_t i;
226     const struct xkb_mod *mod;
227
228     darray_enumerate(i, mod, keymap->mods)
229         if ((mod->type & type) && name == mod->name)
230             return i;
231
232     return XKB_MOD_INVALID;
233 }
234
235 const char *
236 ActionTypeText(enum xkb_action_type type)
237 {
238     const char *name = LookupValue(actionTypeNames, type);
239     return name ? name : "Private";
240 }
241
242 const char *
243 KeysymText(struct xkb_context *ctx, xkb_keysym_t sym)
244 {
245     char *buffer = xkb_context_get_buffer(ctx, 64);
246     xkb_keysym_get_name(sym, buffer, 64);
247     return buffer;
248 }
249
250 const char *
251 KeyNameText(struct xkb_context *ctx, xkb_atom_t name)
252 {
253     const char *sname = xkb_atom_text(ctx, name);
254     size_t len = strlen_safe(sname) + 3;
255     char *buf = xkb_context_get_buffer(ctx, len);
256     snprintf(buf, len, "<%s>", strempty(sname));
257     return buf;
258 }
259
260 const char *
261 SIMatchText(enum xkb_match_operation type)
262 {
263     return LookupValue(symInterpretMatchMaskNames, type);
264 }
265
266 const char *
267 ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask)
268 {
269     char buf[1024];
270     size_t pos = 0;
271     xkb_mod_index_t i;
272     const struct xkb_mod *mod;
273
274     if (mask == 0)
275         return "none";
276
277     if (mask == MOD_REAL_MASK_ALL)
278         return "all";
279
280     darray_enumerate(i, mod, keymap->mods) {
281         int ret;
282
283         if (!(mask & (1u << i)))
284             continue;
285
286         ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
287                        pos == 0 ? "" : "+",
288                        xkb_atom_text(keymap->ctx, mod->name));
289         if (ret <= 0 || pos + ret >= sizeof(buf))
290             break;
291         else
292             pos += ret;
293     }
294
295     return strcpy(xkb_context_get_buffer(keymap->ctx, pos + 1), buf);
296 }
297
298 const char *
299 LedStateMaskText(struct xkb_context *ctx, enum xkb_state_component mask)
300 {
301     char buf[1024];
302     size_t pos = 0;
303
304     if (mask == 0)
305         return "0";
306
307     for (unsigned i = 0; mask; i++) {
308         int ret;
309
310         if (!(mask & (1u << i)))
311             continue;
312
313         mask &= ~(1u << i);
314
315         ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
316                        pos == 0 ? "" : "+",
317                        LookupValue(modComponentMaskNames, 1u << i));
318         if (ret <= 0 || pos + ret >= sizeof(buf))
319             break;
320         else
321             pos += ret;
322     }
323
324     return strcpy(xkb_context_get_buffer(ctx, pos + 1), buf);
325 }
326
327 const char *
328 ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask)
329 {
330     char buf[1024];
331     size_t pos = 0;
332
333     if (mask == 0)
334         return "none";
335
336     if (mask == CONTROL_ALL)
337         return "all";
338
339     for (unsigned i = 0; mask; i++) {
340         int ret;
341
342         if (!(mask & (1u << i)))
343             continue;
344
345         mask &= ~(1u << i);
346
347         ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
348                        pos == 0 ? "" : "+",
349                        LookupValue(ctrlMaskNames, 1u << i));
350         if (ret <= 0 || pos + ret >= sizeof(buf))
351             break;
352         else
353             pos += ret;
354     }
355
356     return strcpy(xkb_context_get_buffer(ctx, pos + 1), buf);
357 }