kbproto unentanglement: control actions
[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", CONTROL_REPEAT },
62     { "Repeat", CONTROL_REPEAT },
63     { "AutoRepeat", CONTROL_REPEAT },
64     { "SlowKeys", CONTROL_SLOW },
65     { "BounceKeys", CONTROL_DEBOUNCE },
66     { "StickyKeys", CONTROL_STICKY },
67     { "MouseKeys", CONTROL_MOUSEKEYS },
68     { "MouseKeysAccel", CONTROL_MOUSEKEYS_ACCEL },
69     { "AccessXKeys", CONTROL_AX },
70     { "AccessXTimeout", CONTROL_AX_TIMEOUT },
71     { "AccessXFeedback", CONTROL_AX_FEEDBACK },
72     { "AudibleBell", CONTROL_BELL },
73     { "IgnoreGroupLock", CONTROL_IGNORE_GROUP_LOCK },
74     { "all", CONTROL_ALL },
75     { "none", 0 },
76     { "Overlay1", 0 },
77     { "Overlay2", 0 },
78     { NULL, 0 }
79 };
80
81 const LookupEntry modComponentMaskNames[] = {
82     {"base", XKB_STATE_DEPRESSED},
83     {"latched", XKB_STATE_LATCHED},
84     {"locked", XKB_STATE_LOCKED},
85     {"effective", XKB_STATE_EFFECTIVE},
86     {"compat", XKB_STATE_EFFECTIVE},
87     {"any", XKB_STATE_EFFECTIVE},
88     {"none", 0},
89     {NULL, 0}
90 };
91
92 const LookupEntry groupComponentMaskNames[] = {
93     {"base", XKB_STATE_DEPRESSED},
94     {"latched", XKB_STATE_LATCHED},
95     {"locked", XKB_STATE_LOCKED},
96     {"effective", XKB_STATE_EFFECTIVE},
97     {"any", XKB_STATE_EFFECTIVE},
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", ACTION_TYPE_NONE },
160     { "SetMods", ACTION_TYPE_MOD_SET },
161     { "LatchMods", ACTION_TYPE_MOD_LATCH },
162     { "LockMods", ACTION_TYPE_MOD_LOCK },
163     { "SetGroup", ACTION_TYPE_GROUP_SET },
164     { "LatchGroup", ACTION_TYPE_GROUP_LATCH },
165     { "LockGroup", ACTION_TYPE_GROUP_LOCK },
166     { "MovePtr", ACTION_TYPE_PTR_MOVE },
167     { "MovePointer", ACTION_TYPE_PTR_MOVE },
168     { "PtrBtn", ACTION_TYPE_PTR_BUTTON },
169     { "PointerButton", ACTION_TYPE_PTR_BUTTON },
170     { "LockPtrBtn", ACTION_TYPE_PTR_LOCK },
171     { "LockPtrButton", ACTION_TYPE_PTR_LOCK },
172     { "LockPointerButton", ACTION_TYPE_PTR_LOCK },
173     { "LockPointerBtn", ACTION_TYPE_PTR_LOCK },
174     { "SetPtrDflt", ACTION_TYPE_PTR_DEFAULT },
175     { "SetPointerDefault", ACTION_TYPE_PTR_DEFAULT },
176     { "Terminate", ACTION_TYPE_TERMINATE },
177     { "TerminateServer", ACTION_TYPE_TERMINATE },
178     { "SwitchScreen", ACTION_TYPE_SWITCH_VT },
179     { "SetControls", ACTION_TYPE_CTRL_SET },
180     { "LockControls", ACTION_TYPE_CTRL_LOCK },
181     { "RedirectKey", ACTION_TYPE_KEY_REDIRECT },
182     { "Redirect", ACTION_TYPE_KEY_REDIRECT },
183     { "Private", ACTION_TYPE_PRIVATE },
184     /* deprecated actions below here - unused */
185     { "ISOLock", ACTION_TYPE_NONE },
186     { "ActionMessage", ACTION_TYPE_NONE },
187     { "MessageAction", ACTION_TYPE_NONE },
188     { "Message", ACTION_TYPE_NONE },
189     { "DeviceBtn", ACTION_TYPE_NONE },
190     { "DevBtn", ACTION_TYPE_NONE },
191     { "DevButton", ACTION_TYPE_NONE },
192     { "DeviceButton", ACTION_TYPE_NONE },
193     { "LockDeviceBtn", ACTION_TYPE_NONE },
194     { "LockDevBtn", ACTION_TYPE_NONE },
195     { "LockDevButton", ACTION_TYPE_NONE },
196     { "LockDeviceButton", ACTION_TYPE_NONE },
197     { "DeviceValuator", ACTION_TYPE_NONE },
198     { "DevVal", ACTION_TYPE_NONE },
199     { "DeviceVal", ACTION_TYPE_NONE },
200     { "DevValuator", ACTION_TYPE_NONE },
201     { NULL, 0 },
202 };
203
204 const LookupEntry symInterpretMatchMaskNames[] = {
205     { "NoneOf", XkbSI_NoneOf },
206     { "AnyOfOrNone", XkbSI_AnyOfOrNone },
207     { "AnyOf", XkbSI_AnyOf },
208     { "AllOf", XkbSI_AllOf },
209     { "Exactly", XkbSI_Exactly },
210 };
211
212 #define BUFFER_SIZE 1024
213
214 static char *
215 GetBuffer(size_t size)
216 {
217     static char buffer[BUFFER_SIZE];
218     static size_t next;
219     char *rtrn;
220
221     if (size >= BUFFER_SIZE)
222         return NULL;
223
224     if (BUFFER_SIZE - next <= size)
225         next = 0;
226
227     rtrn = &buffer[next];
228     next += size;
229
230     return rtrn;
231 }
232
233 /*
234  * Get a vmod name's text, where the vmod index is zero based
235  * (0..XKB_NUM_VIRTUAL_MODS-1).
236  */
237 static const char *
238 VModIndexText(struct xkb_keymap *keymap, xkb_mod_index_t ndx)
239 {
240     int len;
241     char *rtrn;
242     const char *tmp = NULL;
243     char buf[20];
244
245     if (ndx >= XKB_NUM_VIRTUAL_MODS)
246          tmp = "illegal";
247     else
248          tmp = xkb_atom_text(keymap->ctx, keymap->vmod_names[ndx]);
249
250     if (!tmp) {
251         snprintf(buf, sizeof(buf) - 1, "%d", ndx);
252         tmp = buf;
253     }
254
255     len = strlen(tmp) + 1;
256     if (len >= BUFFER_SIZE)
257         len = BUFFER_SIZE - 1;
258
259     rtrn = GetBuffer(len);
260     strncpy(rtrn, tmp, len);
261
262     return rtrn;
263 }
264
265 /* Get a mod mask's text, where the mask is in rmods+vmods format. */
266 const char *
267 VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t cmask)
268 {
269     xkb_mod_index_t i;
270     xkb_mod_mask_t bit;
271     xkb_mod_mask_t rmask, vmask;
272     int len, rem;
273     const char *mm = NULL;
274     char *rtrn, *str;
275     char buf[BUFFER_SIZE];
276
277     rmask = cmask & 0xff;
278     vmask = cmask >> XKB_NUM_CORE_MODS;
279
280     if (rmask == 0 && vmask == 0)
281         return "none";
282
283     if (rmask != 0)
284         mm = ModMaskText(rmask);
285
286     str = buf;
287     buf[0] = '\0';
288     rem = BUFFER_SIZE;
289
290     if (vmask != 0) {
291         for (i = 0, bit = 1; i < XKB_NUM_VIRTUAL_MODS && rem > 1; i++, bit <<=
292                  1) {
293             if (!(vmask & bit))
294                 continue;
295
296             len = snprintf(str, rem, "%s%s",
297                            (str != buf) ? "+" : "",
298                            VModIndexText(keymap, i));
299             rem -= len;
300             str += len;
301         }
302
303         str = buf;
304     }
305     else
306         str = NULL;
307
308     len = (str ? strlen(str) : 0) + (mm ? strlen(mm) : 0) +
309           (str && mm ? 1 : 0);
310     if (len >= BUFFER_SIZE)
311         len = BUFFER_SIZE - 1;
312
313     rtrn = GetBuffer(len + 1);
314     rtrn[0] = '\0';
315
316     snprintf(rtrn, len + 1, "%s%s%s", (mm ? mm : ""),
317              (mm && str ? "+" : ""), (str ? str : ""));
318
319     return rtrn;
320 }
321
322 /*
323  * IMPORTATNT
324  * The indices used for the legacy core modifiers is derived from
325  * the order of the names in this table. It matches the values
326  * ShiftMapIndex, LockMapIndex, etc. from X11/X.h. Take note before
327  * changing.
328  */
329 static const char *modNames[XKB_NUM_CORE_MODS] = {
330     "Shift",
331     "Lock",
332     "Control",
333     "Mod1",
334     "Mod2",
335     "Mod3",
336     "Mod4",
337     "Mod5",
338 };
339
340 xkb_mod_index_t
341 ModNameToIndex(const char *name)
342 {
343     xkb_mod_index_t i;
344
345     for (i = 0; i < XKB_NUM_CORE_MODS; i++)
346         if (istreq(name, modNames[i]))
347             return i;
348
349     return XKB_MOD_INVALID;
350 }
351
352 const char *
353 ModIndexToName(xkb_mod_index_t ndx)
354 {
355     if (ndx < XKB_NUM_CORE_MODS)
356         return modNames[ndx];
357     return NULL;
358 }
359
360 const char *
361 ModIndexText(xkb_mod_index_t ndx)
362 {
363     const char *name;
364     char *buf;
365
366     name = ModIndexToName(ndx);
367     if (name)
368         return name;
369
370     if (ndx == XKB_MOD_INVALID)
371         return "none";
372
373     buf = GetBuffer(32);
374     snprintf(buf, 32, "ILLEGAL_%02x", ndx);
375
376     return buf;
377 }
378
379 /* Gets the text for the real modifiers only. */
380 const char *
381 ModMaskText(xkb_mod_mask_t mask)
382 {
383     int i, rem;
384     xkb_mod_index_t bit;
385     char *str, *buf;
386
387     if ((mask & 0xff) == 0xff)
388         return "all";
389
390     if ((mask & 0xff) == 0)
391         return "none";
392
393     rem = 64;
394     buf = GetBuffer(rem);
395     str = buf;
396     buf[0] = '\0';
397     for (i = 0, bit = 1; i < XKB_NUM_CORE_MODS && rem > 1; i++, bit <<= 1) {
398         int len;
399
400         if (!(mask & bit))
401             continue;
402
403         len = snprintf(str, rem, "%s%s",
404                        (str != buf ?  "+" : ""), modNames[i]);
405         rem -= len;
406         str += len;
407     }
408
409     return buf;
410 }
411
412 const char *
413 ActionTypeText(unsigned type)
414 {
415     const char *name = LookupValue(actionTypeNames, type);
416     return name ? name : "Private";
417 }
418
419 const char *
420 KeysymText(xkb_keysym_t sym)
421 {
422     static char buffer[64];
423
424     xkb_keysym_get_name(sym, buffer, sizeof buffer);
425
426     return buffer;
427 }
428
429 const char *
430 KeyNameText(const char name[XKB_KEY_NAME_LENGTH])
431 {
432     char *buf;
433     int len;
434
435     buf = GetBuffer(7);
436     buf[0] = '<';
437     strncpy(&buf[1], name, 4);
438     buf[5] = '\0';
439     len = strlen(buf);
440     buf[len++] = '>';
441     buf[len] = '\0';
442
443     return buf;
444 }
445
446 const char *
447 SIMatchText(unsigned type)
448 {
449     const char *name;
450     char *buf;
451
452     type &= XkbSI_OpMask;
453
454     name = LookupValue(symInterpretMatchMaskNames, type);
455     if (name)
456         return name;
457
458     buf = GetBuffer(40);
459     snprintf(buf, 40, "0x%x", type & XkbSI_OpMask);
460     return buf;
461 }