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 /***====================================================================***/
33 #define ReportIndicatorBadType(l, f, w) \
34 ReportBadType("indicator map", (f), XkbcAtomText((l)->name), (w))
35 #define ReportIndicatorNotArray(l, f) \
36 ReportNotArray("indicator map", (f), XkbcAtomText((l)->name))
38 /***====================================================================***/
41 ClearIndicatorMapInfo(struct xkb_context *context, LEDInfo * info)
43 info->name = xkb_atom_intern(context, "default");
44 info->indicator = _LED_NotBound;
45 info->flags = info->which_mods = info->real_mods = 0;
47 info->which_groups = info->groups = 0;
52 AddIndicatorMap(LEDInfo * oldLEDs, LEDInfo * new)
58 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
60 if (old->name == new->name)
62 if ((old->real_mods == new->real_mods) &&
63 (old->vmods == new->vmods) &&
64 (old->groups == new->groups) &&
65 (old->ctrls == new->ctrls) &&
66 (old->which_mods == new->which_mods) &&
67 (old->which_groups == new->which_groups))
69 old->defs.defined |= new->defs.defined;
72 if (new->defs.merge == MergeReplace)
74 CommonInfo *next = old->defs.next;
75 if (((old->defs.fileID == new->defs.fileID)
76 && (warningLevel > 0)) || (warningLevel > 9))
78 WARN("Map for indicator %s redefined\n",
79 XkbcAtomText(old->name));
80 ACTION("Earlier definition ignored\n");
83 old->defs.next = next;
87 if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide))
89 old->indicator = new->indicator;
90 old->defs.defined |= _LED_Index;
92 if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide))
94 old->which_mods = new->which_mods;
95 old->real_mods = new->real_mods;
96 old->vmods = new->vmods;
97 old->defs.defined |= _LED_Mods;
99 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
101 old->which_groups = new->which_groups;
102 old->groups = new->groups;
103 old->defs.defined |= _LED_Groups;
105 if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide))
107 old->ctrls = new->ctrls;
108 old->defs.defined |= _LED_Ctrls;
110 if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide))
112 old->flags &= ~XkbIM_NoExplicit;
113 old->flags |= (new->flags & XkbIM_NoExplicit);
114 old->defs.defined |= _LED_Explicit;
116 if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide))
118 old->flags &= ~XkbIM_NoAutomatic;
119 old->flags |= (new->flags & XkbIM_NoAutomatic);
120 old->defs.defined |= _LED_Automatic;
122 if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide))
124 old->flags &= ~XkbIM_LEDDrivesKB;
125 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
126 old->defs.defined |= _LED_DrivesKbd;
130 WARN("Map for indicator %s redefined\n",
131 XkbcAtomText(old->name));
132 ACTION("Using %s definition for duplicate fields\n",
133 (new->defs.merge == MergeAugment ? "first" : "last"));
137 if (old->defs.next == NULL)
141 old = uTypedAlloc(LEDInfo);
144 WSGO("Couldn't allocate indicator map\n");
145 ACTION("Map for indicator %s not compiled\n",
146 XkbcAtomText(new->name));
150 old->defs.next = NULL;
153 last->defs.next = &old->defs;
159 static const LookupEntry modComponentNames[] = {
160 {"base", XkbIM_UseBase},
161 {"latched", XkbIM_UseLatched},
162 {"locked", XkbIM_UseLocked},
163 {"effective", XkbIM_UseEffective},
164 {"compat", XkbIM_UseCompat},
165 {"any", XkbIM_UseAnyMods},
169 static const LookupEntry groupComponentNames[] = {
170 {"base", XkbIM_UseBase},
171 {"latched", XkbIM_UseLatched},
172 {"locked", XkbIM_UseLocked},
173 {"effective", XkbIM_UseEffective},
174 {"any", XkbIM_UseAnyGroup},
179 static const LookupEntry groupNames[] = {
194 SetIndicatorMapField(LEDInfo *led, struct xkb_keymap *keymap,
195 char *field, ExprDef *arrayNdx, ExprDef *value)
201 if ((strcasecmp(field, "modifiers") == 0) ||
202 (strcasecmp(field, "mods") == 0))
204 if (arrayNdx != NULL)
205 return ReportIndicatorNotArray(led, field);
206 if (!ExprResolveVModMask(value, &rtrn, keymap))
207 return ReportIndicatorBadType(led, field, "modifier mask");
208 led->real_mods = rtrn.uval & 0xff;
209 led->vmods = (rtrn.uval >> 8) & 0xff;
210 led->defs.defined |= _LED_Mods;
212 else if (strcasecmp(field, "groups") == 0)
214 if (arrayNdx != NULL)
215 return ReportIndicatorNotArray(led, field);
216 if (!ExprResolveMask(value, &rtrn, groupNames))
217 return ReportIndicatorBadType(led, field, "group mask");
218 led->groups = rtrn.uval;
219 led->defs.defined |= _LED_Groups;
221 else if ((strcasecmp(field, "controls") == 0) ||
222 (strcasecmp(field, "ctrls") == 0))
224 if (arrayNdx != NULL)
225 return ReportIndicatorNotArray(led, field);
226 if (!ExprResolveMask(value, &rtrn, ctrlNames))
227 return ReportIndicatorBadType(led, field,
229 led->ctrls = rtrn.uval;
230 led->defs.defined |= _LED_Ctrls;
232 else if (strcasecmp(field, "allowexplicit") == 0)
234 if (arrayNdx != NULL)
235 return ReportIndicatorNotArray(led, field);
236 if (!ExprResolveBoolean(value, &rtrn))
237 return ReportIndicatorBadType(led, field, "boolean");
239 led->flags &= ~XkbIM_NoExplicit;
241 led->flags |= XkbIM_NoExplicit;
242 led->defs.defined |= _LED_Explicit;
244 else if ((strcasecmp(field, "whichmodstate") == 0) ||
245 (strcasecmp(field, "whichmodifierstate") == 0))
247 if (arrayNdx != NULL)
248 return ReportIndicatorNotArray(led, field);
249 if (!ExprResolveMask(value, &rtrn, modComponentNames))
251 return ReportIndicatorBadType(led, field,
252 "mask of modifier state components");
254 led->which_mods = rtrn.uval;
256 else if (strcasecmp(field, "whichgroupstate") == 0)
258 if (arrayNdx != NULL)
259 return ReportIndicatorNotArray(led, field);
260 if (!ExprResolveMask(value, &rtrn, groupComponentNames))
262 return ReportIndicatorBadType(led, field,
263 "mask of group state components");
265 led->which_groups = rtrn.uval;
267 else if ((strcasecmp(field, "driveskbd") == 0) ||
268 (strcasecmp(field, "driveskeyboard") == 0) ||
269 (strcasecmp(field, "leddriveskbd") == 0) ||
270 (strcasecmp(field, "leddriveskeyboard") == 0) ||
271 (strcasecmp(field, "indicatordriveskbd") == 0) ||
272 (strcasecmp(field, "indicatordriveskeyboard") == 0))
274 if (arrayNdx != NULL)
275 return ReportIndicatorNotArray(led, field);
276 if (!ExprResolveBoolean(value, &rtrn))
277 return ReportIndicatorBadType(led, field, "boolean");
279 led->flags |= XkbIM_LEDDrivesKB;
281 led->flags &= ~XkbIM_LEDDrivesKB;
282 led->defs.defined |= _LED_DrivesKbd;
284 else if (strcasecmp(field, "index") == 0)
286 if (arrayNdx != NULL)
287 return ReportIndicatorNotArray(led, field);
288 if (!ExprResolveInteger(value, &rtrn))
289 return ReportIndicatorBadType(led, field,
291 if ((rtrn.uval < 1) || (rtrn.uval > 32))
293 ERROR("Illegal indicator index %d (range 1..%d)\n",
294 rtrn.uval, XkbNumIndicators);
295 ACTION("Index definition for %s indicator ignored\n",
296 XkbcAtomText(led->name));
299 led->indicator = rtrn.uval;
300 led->defs.defined |= _LED_Index;
304 ERROR("Unknown field %s in map for %s indicator\n", field,
305 XkbcAtomText(led->name));
306 ACTION("Definition ignored\n");
313 HandleIndicatorMapDef(IndicatorMapDef *def, struct xkb_keymap *keymap,
314 LEDInfo *dflt, LEDInfo *oldLEDs, unsigned merge)
320 if (def->merge != MergeDefault)
324 led.defs.merge = merge;
325 led.name = def->name;
328 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
330 ExprResult elem, field;
332 if (!ExprResolveLhs(keymap, var->name, &elem, &field, &arrayNdx))
337 if (elem.str != NULL)
340 ("Cannot set defaults for \"%s\" element in indicator map\n",
342 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
347 ok = SetIndicatorMapField(&led, keymap, field.str, arrayNdx,
355 rtrn = AddIndicatorMap(oldLEDs, &led);
362 CopyIndicatorMapDefs(struct xkb_keymap *keymap, LEDInfo *leds,
363 LEDInfo **unboundRtrn)
366 LEDInfo *unbound, *last;
368 if (XkbcAllocNames(keymap, XkbIndicatorNamesMask, 0) != Success)
370 WSGO("Couldn't allocate names\n");
371 ACTION("Indicator names may be incorrect\n");
373 if (XkbcAllocIndicatorMaps(keymap) != Success)
375 WSGO("Can't allocate indicator maps\n");
376 ACTION("Indicator map definitions may be lost\n");
379 last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
380 while ((last != NULL) && (last->defs.next != NULL))
382 last = (LEDInfo *) last->defs.next;
384 for (led = leds; led != NULL; led = next)
386 next = (LEDInfo *) led->defs.next;
387 if ((led->groups != 0) && (led->which_groups == 0))
388 led->which_groups = XkbIM_UseEffective;
389 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
390 led->which_mods = XkbIM_UseEffective;
391 if ((led->indicator == _LED_NotBound) || (!keymap->indicators))
393 if (unboundRtrn != NULL)
395 led->defs.next = NULL;
397 last->defs.next = (CommonInfo *) led;
407 struct xkb_indicator_map * im;
408 im = &keymap->indicators->maps[led->indicator - 1];
409 im->flags = led->flags;
410 im->which_groups = led->which_groups;
411 im->groups = led->groups;
412 im->which_mods = led->which_mods;
413 im->mods.mask = led->real_mods;
414 im->mods.real_mods = led->real_mods;
415 im->mods.vmods = led->vmods;
416 im->ctrls = led->ctrls;
417 if (keymap->names != NULL)
419 free(UNCONSTIFY(keymap->names->indicators[led->indicator - 1]));
420 keymap->names->indicators[led->indicator-1] =
421 xkb_atom_strdup(keymap->context, led->name);
426 if (unboundRtrn != NULL)
428 *unboundRtrn = unbound;
434 BindIndicators(struct xkb_keymap *keymap, bool force, LEDInfo *unbound,
435 LEDInfo **unboundRtrn)
438 LEDInfo *led, *next, *last;
440 if (keymap->names != NULL)
442 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
444 if (led->indicator == _LED_NotBound)
446 for (i = 0; i < XkbNumIndicators; i++)
448 if (keymap->names->indicators[i] &&
449 strcmp(keymap->names->indicators[i],
450 XkbcAtomText(led->name)) == 0)
452 led->indicator = i + 1;
460 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
462 if (led->indicator == _LED_NotBound)
464 for (i = 0; i < XkbNumIndicators; i++)
466 if (keymap->names->indicators[i] == NULL)
468 keymap->names->indicators[i] =
469 xkb_atom_strdup(keymap->context, led->name);
470 led->indicator = i + 1;
474 if (led->indicator == _LED_NotBound)
476 ERROR("No unnamed indicators found\n");
478 ("Virtual indicator map \"%s\" not bound\n",
479 XkbcAtomText(led->name));
486 for (last = NULL, led = unbound; led != NULL; led = next)
488 next = (LEDInfo *) led->defs.next;
489 if (led->indicator == _LED_NotBound)
499 last->defs.next = &led->defs;
507 if ((keymap->names != NULL) &&
508 (strcmp(keymap->names->indicators[led->indicator - 1],
509 XkbcAtomText(led->name)) != 0))
511 const char *old = keymap->names->indicators[led->indicator - 1];
512 ERROR("Multiple names bound to indicator %d\n",
513 (unsigned int) led->indicator);
514 ACTION("Using %s, ignoring %s\n", old, XkbcAtomText(led->name));
515 led->indicator = _LED_NotBound;
524 last->defs.next = &led->defs;
532 struct xkb_indicator_map * map;
533 map = &keymap->indicators->maps[led->indicator - 1];
534 map->flags = led->flags;
535 map->which_groups = led->which_groups;
536 map->groups = led->groups;
537 map->which_mods = led->which_mods;
538 map->mods.mask = led->real_mods;
539 map->mods.real_mods = led->real_mods;
540 map->mods.vmods = led->vmods;
541 map->ctrls = led->ctrls;
543 last->defs.next = &next->defs;
546 led->defs.next = NULL;
553 *unboundRtrn = unbound;
557 for (led = unbound; led != NULL; led = next)
559 next = led ? (LEDInfo *) led->defs.next : NULL;