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