1 /************************************************************
2 * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
27 #include "indicators.h"
31 /***====================================================================***/
34 ReportIndicatorBadType(struct xkb_keymap *keymap, LEDInfo *led,
35 const char *field, const char *wanted)
37 return ReportBadType("indicator map", field,
38 xkb_atom_text(keymap->ctx, led->name), wanted);
42 ReportIndicatorNotArray(struct xkb_keymap *keymap, LEDInfo *led,
45 return ReportNotArray("indicator map", field,
46 xkb_atom_text(keymap->ctx, led->name));
49 /***====================================================================***/
52 ClearIndicatorMapInfo(struct xkb_context *ctx, LEDInfo * info)
54 info->name = xkb_atom_intern(ctx, "default");
55 info->indicator = _LED_NotBound;
56 info->flags = info->which_mods = info->real_mods = 0;
58 info->which_groups = info->groups = 0;
63 AddIndicatorMap(struct xkb_keymap *keymap, LEDInfo *oldLEDs, LEDInfo *new)
69 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next) {
70 if (old->name == new->name) {
71 if ((old->real_mods == new->real_mods) &&
72 (old->vmods == new->vmods) &&
73 (old->groups == new->groups) &&
74 (old->ctrls == new->ctrls) &&
75 (old->which_mods == new->which_mods) &&
76 (old->which_groups == new->which_groups)) {
77 old->defs.defined |= new->defs.defined;
80 if (new->defs.merge == MERGE_REPLACE) {
81 CommonInfo *next = old->defs.next;
82 if (((old->defs.file_id == new->defs.file_id)
83 && (warningLevel > 0)) || (warningLevel > 9)) {
84 WARN("Map for indicator %s redefined\n",
85 xkb_atom_text(keymap->ctx, old->name));
86 ACTION("Earlier definition ignored\n");
89 old->defs.next = next;
93 if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide)) {
94 old->indicator = new->indicator;
95 old->defs.defined |= _LED_Index;
97 if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide)) {
98 old->which_mods = new->which_mods;
99 old->real_mods = new->real_mods;
100 old->vmods = new->vmods;
101 old->defs.defined |= _LED_Mods;
103 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide)) {
104 old->which_groups = new->which_groups;
105 old->groups = new->groups;
106 old->defs.defined |= _LED_Groups;
108 if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide)) {
109 old->ctrls = new->ctrls;
110 old->defs.defined |= _LED_Ctrls;
112 if (UseNewField(_LED_Explicit, &old->defs, &new->defs,
114 old->flags &= ~XkbIM_NoExplicit;
115 old->flags |= (new->flags & XkbIM_NoExplicit);
116 old->defs.defined |= _LED_Explicit;
118 if (UseNewField(_LED_Automatic, &old->defs, &new->defs,
120 old->flags &= ~XkbIM_NoAutomatic;
121 old->flags |= (new->flags & XkbIM_NoAutomatic);
122 old->defs.defined |= _LED_Automatic;
124 if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs,
126 old->flags &= ~XkbIM_LEDDrivesKB;
127 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
128 old->defs.defined |= _LED_DrivesKbd;
131 WARN("Map for indicator %s redefined\n",
132 xkb_atom_text(keymap->ctx, old->name));
133 ACTION("Using %s definition for duplicate fields\n",
134 (new->defs.merge == MERGE_AUGMENT ? "first" : "last"));
138 if (old->defs.next == NULL)
142 old = uTypedAlloc(LEDInfo);
144 WSGO("Couldn't allocate indicator map\n");
145 ACTION("Map for indicator %s not compiled\n",
146 xkb_atom_text(keymap->ctx, new->name));
150 old->defs.next = NULL;
152 last->defs.next = &old->defs;
158 static const LookupEntry modComponentNames[] = {
159 { "base", XkbIM_UseBase },
160 { "latched", XkbIM_UseLatched },
161 { "locked", XkbIM_UseLocked },
162 { "effective", XkbIM_UseEffective },
163 { "compat", XkbIM_UseCompat },
164 { "any", XkbIM_UseAnyMods },
168 static const LookupEntry groupComponentNames[] = {
169 { "base", XkbIM_UseBase },
170 { "latched", XkbIM_UseLatched },
171 { "locked", XkbIM_UseLocked },
172 { "effective", XkbIM_UseEffective },
173 { "any", XkbIM_UseAnyGroup },
178 static const LookupEntry groupNames[] = {
193 SetIndicatorMapField(LEDInfo *led, struct xkb_keymap *keymap,
194 char *field, ExprDef *arrayNdx, ExprDef *value)
200 if ((strcasecmp(field, "modifiers") == 0) ||
201 (strcasecmp(field, "mods") == 0)) {
202 if (arrayNdx != NULL)
203 return ReportIndicatorNotArray(keymap, led, field);
204 if (!ExprResolveVModMask(value, &rtrn, keymap))
205 return ReportIndicatorBadType(keymap, led, field, "modifier mask");
206 led->real_mods = rtrn.uval & 0xff;
207 led->vmods = (rtrn.uval >> 8) & 0xff;
208 led->defs.defined |= _LED_Mods;
210 else if (strcasecmp(field, "groups") == 0) {
211 if (arrayNdx != NULL)
212 return ReportIndicatorNotArray(keymap, led, field);
213 if (!ExprResolveMask(keymap->ctx, value, &rtrn, groupNames))
214 return ReportIndicatorBadType(keymap, led, field, "group mask");
215 led->groups = rtrn.uval;
216 led->defs.defined |= _LED_Groups;
218 else if ((strcasecmp(field, "controls") == 0) ||
219 (strcasecmp(field, "ctrls") == 0)) {
220 if (arrayNdx != NULL)
221 return ReportIndicatorNotArray(keymap, led, field);
222 if (!ExprResolveMask(keymap->ctx, value, &rtrn, ctrlNames))
223 return ReportIndicatorBadType(keymap, led, field,
225 led->ctrls = rtrn.uval;
226 led->defs.defined |= _LED_Ctrls;
228 else if (strcasecmp(field, "allowexplicit") == 0) {
229 if (arrayNdx != NULL)
230 return ReportIndicatorNotArray(keymap, led, field);
231 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
232 return ReportIndicatorBadType(keymap, led, field, "boolean");
234 led->flags &= ~XkbIM_NoExplicit;
236 led->flags |= XkbIM_NoExplicit;
237 led->defs.defined |= _LED_Explicit;
239 else if ((strcasecmp(field, "whichmodstate") == 0) ||
240 (strcasecmp(field, "whichmodifierstate") == 0)) {
241 if (arrayNdx != NULL)
242 return ReportIndicatorNotArray(keymap, led, field);
243 if (!ExprResolveMask(keymap->ctx, value, &rtrn, modComponentNames)) {
244 return ReportIndicatorBadType(keymap, led, field,
245 "mask of modifier state components");
247 led->which_mods = rtrn.uval;
249 else if (strcasecmp(field, "whichgroupstate") == 0) {
250 if (arrayNdx != NULL)
251 return ReportIndicatorNotArray(keymap, led, field);
252 if (!ExprResolveMask(keymap->ctx, value, &rtrn,
253 groupComponentNames)) {
254 return ReportIndicatorBadType(keymap, led, field,
255 "mask of group state components");
257 led->which_groups = rtrn.uval;
259 else if ((strcasecmp(field, "driveskbd") == 0) ||
260 (strcasecmp(field, "driveskeyboard") == 0) ||
261 (strcasecmp(field, "leddriveskbd") == 0) ||
262 (strcasecmp(field, "leddriveskeyboard") == 0) ||
263 (strcasecmp(field, "indicatordriveskbd") == 0) ||
264 (strcasecmp(field, "indicatordriveskeyboard") == 0)) {
265 if (arrayNdx != NULL)
266 return ReportIndicatorNotArray(keymap, led, field);
267 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
268 return ReportIndicatorBadType(keymap, led, field, "boolean");
270 led->flags |= XkbIM_LEDDrivesKB;
272 led->flags &= ~XkbIM_LEDDrivesKB;
273 led->defs.defined |= _LED_DrivesKbd;
275 else if (strcasecmp(field, "index") == 0) {
276 if (arrayNdx != NULL)
277 return ReportIndicatorNotArray(keymap, led, field);
278 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
279 return ReportIndicatorBadType(keymap, led, field,
281 if ((rtrn.uval < 1) || (rtrn.uval > 32)) {
282 ERROR("Illegal indicator index %d (range 1..%d)\n",
283 rtrn.uval, XkbNumIndicators);
284 ACTION("Index definition for %s indicator ignored\n",
285 xkb_atom_text(keymap->ctx, led->name));
288 led->indicator = rtrn.uval;
289 led->defs.defined |= _LED_Index;
292 ERROR("Unknown field %s in map for %s indicator\n", field,
293 xkb_atom_text(keymap->ctx, led->name));
294 ACTION("Definition ignored\n");
301 HandleIndicatorMapDef(IndicatorMapDef *def, struct xkb_keymap *keymap,
302 LEDInfo *dflt, LEDInfo *oldLEDs, enum merge_mode merge)
308 if (def->merge != MERGE_DEFAULT)
312 led.defs.merge = merge;
313 led.name = def->name;
316 for (var = def->body; var != NULL; var = (VarDef *) var->common.next) {
317 ExprResult elem, field;
319 if (!ExprResolveLhs(keymap, var->name, &elem, &field, &arrayNdx)) {
323 if (elem.str != NULL) {
325 ("Cannot set defaults for \"%s\" element in indicator map\n",
327 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
331 ok = SetIndicatorMapField(&led, keymap, field.str, arrayNdx,
338 rtrn = AddIndicatorMap(keymap, oldLEDs, &led);
345 BindIndicators(struct xkb_keymap *keymap, LEDInfo *unbound)
348 LEDInfo *led, *next, *last;
350 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next) {
351 if (led->indicator == _LED_NotBound) {
352 for (i = 0; i < XkbNumIndicators; i++) {
353 if (keymap->indicator_names[i] &&
354 strcmp(keymap->indicator_names[i],
355 xkb_atom_text(keymap->ctx, led->name)) == 0) {
356 led->indicator = i + 1;
363 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next) {
364 if (led->indicator == _LED_NotBound) {
365 for (i = 0; i < XkbNumIndicators; i++) {
366 if (keymap->indicator_names[i] == NULL) {
367 keymap->indicator_names[i] =
368 xkb_atom_strdup(keymap->ctx, led->name);
369 led->indicator = i + 1;
373 if (led->indicator == _LED_NotBound) {
374 ERROR("No unnamed indicators found\n");
375 ACTION("Virtual indicator map \"%s\" not bound\n",
376 xkb_atom_text(keymap->ctx, led->name));
381 for (last = NULL, led = unbound; led != NULL; led = next) {
382 next = (LEDInfo *) led->defs.next;
383 if (led->indicator == _LED_NotBound) {
388 if (strcmp(keymap->indicator_names[led->indicator - 1],
389 xkb_atom_text(keymap->ctx, led->name)) != 0) {
390 const char *old = keymap->indicator_names[led->indicator - 1];
391 ERROR("Multiple names bound to indicator %d\n",
392 (unsigned int) led->indicator);
393 ACTION("Using %s, ignoring %s\n", old,
394 xkb_atom_text(keymap->ctx, led->name));
395 led->indicator = _LED_NotBound;
400 struct xkb_indicator_map * map;
401 map = &keymap->indicators[led->indicator - 1];
402 map->flags = led->flags;
403 map->which_groups = led->which_groups;
404 map->groups = led->groups;
405 map->which_mods = led->which_mods;
406 map->mods.mask = led->real_mods;
407 map->mods.real_mods = led->real_mods;
408 map->mods.vmods = led->vmods;
409 map->ctrls = led->ctrls;
411 last->defs.next = &next->defs;
414 led->defs.next = NULL;
420 for (led = unbound; led != NULL; led = next) {
421 next = led ? (LEDInfo *) led->defs.next : NULL;
427 CopyIndicatorMapDefs(struct xkb_keymap *keymap, LEDInfo *leds)
430 LEDInfo *unbound = NULL, *last = NULL;
432 for (led = leds; led != NULL; led = next) {
433 next = (LEDInfo *) led->defs.next;
434 if ((led->groups != 0) && (led->which_groups == 0))
435 led->which_groups = XkbIM_UseEffective;
436 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
437 led->which_mods = XkbIM_UseEffective;
438 if ((led->indicator == _LED_NotBound) || (!keymap->indicators)) {
439 led->defs.next = NULL;
441 last->defs.next = (CommonInfo *) led;
447 struct xkb_indicator_map * im;
448 im = &keymap->indicators[led->indicator - 1];
449 im->flags = led->flags;
450 im->which_groups = led->which_groups;
451 im->groups = led->groups;
452 im->which_mods = led->which_mods;
453 im->mods.mask = led->real_mods;
454 im->mods.real_mods = led->real_mods;
455 im->mods.vmods = led->vmods;
456 im->ctrls = led->ctrls;
457 free(keymap->indicator_names[led->indicator - 1]);
458 keymap->indicator_names[led->indicator - 1] =
459 xkb_atom_strdup(keymap->ctx, led->name);
465 BindIndicators(keymap, unbound);