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