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(keymap, l, f, w) \
34 ReportBadType("indicator map", (f), \
35 xkb_atom_text((keymap)->ctx, (l)->name), (w))
36 #define ReportIndicatorNotArray(keymap, l, f) \
37 ReportNotArray("indicator map", (f), \
38 xkb_atom_text((keymap)->ctx, (l)->name))
40 /***====================================================================***/
43 ClearIndicatorMapInfo(struct xkb_context *ctx, LEDInfo * info)
45 info->name = xkb_atom_intern(ctx, "default");
46 info->indicator = _LED_NotBound;
47 info->flags = info->which_mods = info->real_mods = 0;
49 info->which_groups = info->groups = 0;
54 AddIndicatorMap(struct xkb_keymap *keymap, LEDInfo *oldLEDs, LEDInfo *new)
60 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
62 if (old->name == new->name)
64 if ((old->real_mods == new->real_mods) &&
65 (old->vmods == new->vmods) &&
66 (old->groups == new->groups) &&
67 (old->ctrls == new->ctrls) &&
68 (old->which_mods == new->which_mods) &&
69 (old->which_groups == new->which_groups))
71 old->defs.defined |= new->defs.defined;
74 if (new->defs.merge == MergeReplace)
76 CommonInfo *next = old->defs.next;
77 if (((old->defs.fileID == new->defs.fileID)
78 && (warningLevel > 0)) || (warningLevel > 9))
80 WARN("Map for indicator %s redefined\n",
81 xkb_atom_text(keymap->ctx, old->name));
82 ACTION("Earlier definition ignored\n");
85 old->defs.next = next;
89 if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide))
91 old->indicator = new->indicator;
92 old->defs.defined |= _LED_Index;
94 if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide))
96 old->which_mods = new->which_mods;
97 old->real_mods = new->real_mods;
98 old->vmods = new->vmods;
99 old->defs.defined |= _LED_Mods;
101 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
103 old->which_groups = new->which_groups;
104 old->groups = new->groups;
105 old->defs.defined |= _LED_Groups;
107 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, &collide))
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, &collide))
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, &collide))
126 old->flags &= ~XkbIM_LEDDrivesKB;
127 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
128 old->defs.defined |= _LED_DrivesKbd;
132 WARN("Map for indicator %s redefined\n",
133 xkb_atom_text(keymap->ctx, old->name));
134 ACTION("Using %s definition for duplicate fields\n",
135 (new->defs.merge == MergeAugment ? "first" : "last"));
139 if (old->defs.next == NULL)
143 old = uTypedAlloc(LEDInfo);
146 WSGO("Couldn't allocate indicator map\n");
147 ACTION("Map for indicator %s not compiled\n",
148 xkb_atom_text(keymap->ctx, new->name));
152 old->defs.next = NULL;
155 last->defs.next = &old->defs;
161 static const LookupEntry modComponentNames[] = {
162 {"base", XkbIM_UseBase},
163 {"latched", XkbIM_UseLatched},
164 {"locked", XkbIM_UseLocked},
165 {"effective", XkbIM_UseEffective},
166 {"compat", XkbIM_UseCompat},
167 {"any", XkbIM_UseAnyMods},
171 static const LookupEntry groupComponentNames[] = {
172 {"base", XkbIM_UseBase},
173 {"latched", XkbIM_UseLatched},
174 {"locked", XkbIM_UseLocked},
175 {"effective", XkbIM_UseEffective},
176 {"any", XkbIM_UseAnyGroup},
181 static const LookupEntry groupNames[] = {
196 SetIndicatorMapField(LEDInfo *led, struct xkb_keymap *keymap,
197 char *field, ExprDef *arrayNdx, ExprDef *value)
203 if ((strcasecmp(field, "modifiers") == 0) ||
204 (strcasecmp(field, "mods") == 0))
206 if (arrayNdx != NULL)
207 return ReportIndicatorNotArray(keymap, led, field);
208 if (!ExprResolveVModMask(value, &rtrn, keymap))
209 return ReportIndicatorBadType(keymap, led, field, "modifier mask");
210 led->real_mods = rtrn.uval & 0xff;
211 led->vmods = (rtrn.uval >> 8) & 0xff;
212 led->defs.defined |= _LED_Mods;
214 else if (strcasecmp(field, "groups") == 0)
216 if (arrayNdx != NULL)
217 return ReportIndicatorNotArray(keymap, led, field);
218 if (!ExprResolveMask(keymap->ctx, value, &rtrn, groupNames))
219 return ReportIndicatorBadType(keymap, led, field, "group mask");
220 led->groups = rtrn.uval;
221 led->defs.defined |= _LED_Groups;
223 else if ((strcasecmp(field, "controls") == 0) ||
224 (strcasecmp(field, "ctrls") == 0))
226 if (arrayNdx != NULL)
227 return ReportIndicatorNotArray(keymap, led, field);
228 if (!ExprResolveMask(keymap->ctx, value, &rtrn, ctrlNames))
229 return ReportIndicatorBadType(keymap, led, field,
231 led->ctrls = rtrn.uval;
232 led->defs.defined |= _LED_Ctrls;
234 else if (strcasecmp(field, "allowexplicit") == 0)
236 if (arrayNdx != NULL)
237 return ReportIndicatorNotArray(keymap, led, field);
238 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
239 return ReportIndicatorBadType(keymap, led, field, "boolean");
241 led->flags &= ~XkbIM_NoExplicit;
243 led->flags |= XkbIM_NoExplicit;
244 led->defs.defined |= _LED_Explicit;
246 else if ((strcasecmp(field, "whichmodstate") == 0) ||
247 (strcasecmp(field, "whichmodifierstate") == 0))
249 if (arrayNdx != NULL)
250 return ReportIndicatorNotArray(keymap, led, field);
251 if (!ExprResolveMask(keymap->ctx, value, &rtrn, modComponentNames))
253 return ReportIndicatorBadType(keymap, led, field,
254 "mask of modifier state components");
256 led->which_mods = rtrn.uval;
258 else if (strcasecmp(field, "whichgroupstate") == 0)
260 if (arrayNdx != NULL)
261 return ReportIndicatorNotArray(keymap, led, field);
262 if (!ExprResolveMask(keymap->ctx, value, &rtrn, groupComponentNames))
264 return ReportIndicatorBadType(keymap, led, field,
265 "mask of group state components");
267 led->which_groups = rtrn.uval;
269 else if ((strcasecmp(field, "driveskbd") == 0) ||
270 (strcasecmp(field, "driveskeyboard") == 0) ||
271 (strcasecmp(field, "leddriveskbd") == 0) ||
272 (strcasecmp(field, "leddriveskeyboard") == 0) ||
273 (strcasecmp(field, "indicatordriveskbd") == 0) ||
274 (strcasecmp(field, "indicatordriveskeyboard") == 0))
276 if (arrayNdx != NULL)
277 return ReportIndicatorNotArray(keymap, led, field);
278 if (!ExprResolveBoolean(keymap->ctx, value, &rtrn))
279 return ReportIndicatorBadType(keymap, led, field, "boolean");
281 led->flags |= XkbIM_LEDDrivesKB;
283 led->flags &= ~XkbIM_LEDDrivesKB;
284 led->defs.defined |= _LED_DrivesKbd;
286 else if (strcasecmp(field, "index") == 0)
288 if (arrayNdx != NULL)
289 return ReportIndicatorNotArray(keymap, led, field);
290 if (!ExprResolveInteger(keymap->ctx, value, &rtrn))
291 return ReportIndicatorBadType(keymap, led, field,
293 if ((rtrn.uval < 1) || (rtrn.uval > 32))
295 ERROR("Illegal indicator index %d (range 1..%d)\n",
296 rtrn.uval, XkbNumIndicators);
297 ACTION("Index definition for %s indicator ignored\n",
298 xkb_atom_text(keymap->ctx, led->name));
301 led->indicator = rtrn.uval;
302 led->defs.defined |= _LED_Index;
306 ERROR("Unknown field %s in map for %s indicator\n", field,
307 xkb_atom_text(keymap->ctx, led->name));
308 ACTION("Definition ignored\n");
315 HandleIndicatorMapDef(IndicatorMapDef *def, struct xkb_keymap *keymap,
316 LEDInfo *dflt, LEDInfo *oldLEDs, unsigned merge)
322 if (def->merge != MergeDefault)
326 led.defs.merge = merge;
327 led.name = def->name;
330 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
332 ExprResult elem, field;
334 if (!ExprResolveLhs(keymap, var->name, &elem, &field, &arrayNdx))
339 if (elem.str != NULL)
342 ("Cannot set defaults for \"%s\" element in indicator map\n",
344 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
349 ok = SetIndicatorMapField(&led, keymap, field.str, arrayNdx,
357 rtrn = AddIndicatorMap(keymap, oldLEDs, &led);
364 CopyIndicatorMapDefs(struct xkb_keymap *keymap, LEDInfo *leds,
365 LEDInfo **unboundRtrn)
368 LEDInfo *unbound, *last;
370 if (XkbcAllocNames(keymap, XkbIndicatorNamesMask, 0) != Success)
372 WSGO("Couldn't allocate names\n");
373 ACTION("Indicator names may be incorrect\n");
375 if (XkbcAllocIndicatorMaps(keymap) != Success)
377 WSGO("Can't allocate indicator maps\n");
378 ACTION("Indicator map definitions may be lost\n");
381 last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
382 while ((last != NULL) && (last->defs.next != NULL))
384 last = (LEDInfo *) last->defs.next;
386 for (led = leds; led != NULL; led = next)
388 next = (LEDInfo *) led->defs.next;
389 if ((led->groups != 0) && (led->which_groups == 0))
390 led->which_groups = XkbIM_UseEffective;
391 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
392 led->which_mods = XkbIM_UseEffective;
393 if ((led->indicator == _LED_NotBound) || (!keymap->indicators))
395 if (unboundRtrn != NULL)
397 led->defs.next = NULL;
399 last->defs.next = (CommonInfo *) led;
409 struct xkb_indicator_map * im;
410 im = &keymap->indicators->maps[led->indicator - 1];
411 im->flags = led->flags;
412 im->which_groups = led->which_groups;
413 im->groups = led->groups;
414 im->which_mods = led->which_mods;
415 im->mods.mask = led->real_mods;
416 im->mods.real_mods = led->real_mods;
417 im->mods.vmods = led->vmods;
418 im->ctrls = led->ctrls;
419 if (keymap->names != NULL)
421 free(keymap->names->indicators[led->indicator - 1]);
422 keymap->names->indicators[led->indicator-1] =
423 xkb_atom_strdup(keymap->ctx, led->name);
428 if (unboundRtrn != NULL)
430 *unboundRtrn = unbound;
436 BindIndicators(struct xkb_keymap *keymap, bool force, LEDInfo *unbound,
437 LEDInfo **unboundRtrn)
440 LEDInfo *led, *next, *last;
442 if (keymap->names != NULL)
444 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
446 if (led->indicator == _LED_NotBound)
448 for (i = 0; i < XkbNumIndicators; i++)
450 if (keymap->names->indicators[i] &&
451 strcmp(keymap->names->indicators[i],
452 xkb_atom_text(keymap->ctx, led->name)) == 0)
454 led->indicator = i + 1;
462 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
464 if (led->indicator == _LED_NotBound)
466 for (i = 0; i < XkbNumIndicators; i++)
468 if (keymap->names->indicators[i] == NULL)
470 keymap->names->indicators[i] =
471 xkb_atom_strdup(keymap->ctx, led->name);
472 led->indicator = i + 1;
476 if (led->indicator == _LED_NotBound)
478 ERROR("No unnamed indicators found\n");
480 ("Virtual indicator map \"%s\" not bound\n",
481 xkb_atom_text(keymap->ctx, led->name));
488 for (last = NULL, led = unbound; led != NULL; led = next)
490 next = (LEDInfo *) led->defs.next;
491 if (led->indicator == _LED_NotBound)
501 last->defs.next = &led->defs;
509 if ((keymap->names != NULL) &&
510 (strcmp(keymap->names->indicators[led->indicator - 1],
511 xkb_atom_text(keymap->ctx, led->name)) != 0))
513 const char *old = keymap->names->indicators[led->indicator - 1];
514 ERROR("Multiple names bound to indicator %d\n",
515 (unsigned int) led->indicator);
516 ACTION("Using %s, ignoring %s\n", old,
517 xkb_atom_text(keymap->ctx, led->name));
518 led->indicator = _LED_NotBound;
527 last->defs.next = &led->defs;
535 struct xkb_indicator_map * map;
536 map = &keymap->indicators->maps[led->indicator - 1];
537 map->flags = led->flags;
538 map->which_groups = led->which_groups;
539 map->groups = led->groups;
540 map->which_mods = led->which_mods;
541 map->mods.mask = led->real_mods;
542 map->mods.real_mods = led->real_mods;
543 map->mods.vmods = led->vmods;
544 map->ctrls = led->ctrls;
546 last->defs.next = &next->defs;
549 led->defs.next = NULL;
556 *unboundRtrn = unbound;
560 for (led = unbound; led != NULL; led = next)
562 next = led ? (LEDInfo *) led->defs.next : NULL;