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 ********************************************************/
33 #include "indicators.h"
37 /***====================================================================***/
39 #define ReportIndicatorBadType(l, f, w) \
40 ReportBadType("indicator map", (f), XkbcAtomText((l)->name), (w))
41 #define ReportIndicatorNotArray(l, f) \
42 ReportNotArray("indicator map", (f), XkbcAtomText((l)->name))
44 /***====================================================================***/
47 ClearIndicatorMapInfo(LEDInfo * info)
49 info->name = xkb_intern_atom("default");
50 info->indicator = _LED_NotBound;
51 info->flags = info->which_mods = info->real_mods = 0;
53 info->which_groups = info->groups = 0;
58 AddIndicatorMap(LEDInfo * oldLEDs, LEDInfo * new)
64 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
66 if (old->name == new->name)
68 if ((old->real_mods == new->real_mods) &&
69 (old->vmods == new->vmods) &&
70 (old->groups == new->groups) &&
71 (old->ctrls == new->ctrls) &&
72 (old->which_mods == new->which_mods) &&
73 (old->which_groups == new->which_groups))
75 old->defs.defined |= new->defs.defined;
78 if (new->defs.merge == MergeReplace)
80 CommonInfo *next = old->defs.next;
81 if (((old->defs.fileID == new->defs.fileID)
82 && (warningLevel > 0)) || (warningLevel > 9))
84 WARN("Map for indicator %s redefined\n",
85 XkbcAtomText(old->name));
86 ACTION("Earlier definition ignored\n");
89 old->defs.next = next;
93 if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide))
95 old->indicator = new->indicator;
96 old->defs.defined |= _LED_Index;
98 if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide))
100 old->which_mods = new->which_mods;
101 old->real_mods = new->real_mods;
102 old->vmods = new->vmods;
103 old->defs.defined |= _LED_Mods;
105 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
107 old->which_groups = new->which_groups;
108 old->groups = new->groups;
109 old->defs.defined |= _LED_Groups;
111 if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide))
113 old->ctrls = new->ctrls;
114 old->defs.defined |= _LED_Ctrls;
116 if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide))
118 old->flags &= ~XkbIM_NoExplicit;
119 old->flags |= (new->flags & XkbIM_NoExplicit);
120 old->defs.defined |= _LED_Explicit;
122 if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide))
124 old->flags &= ~XkbIM_NoAutomatic;
125 old->flags |= (new->flags & XkbIM_NoAutomatic);
126 old->defs.defined |= _LED_Automatic;
128 if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide))
130 old->flags &= ~XkbIM_LEDDrivesKB;
131 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
132 old->defs.defined |= _LED_DrivesKbd;
136 WARN("Map for indicator %s redefined\n",
137 XkbcAtomText(old->name));
138 ACTION("Using %s definition for duplicate fields\n",
139 (new->defs.merge == MergeAugment ? "first" : "last"));
143 if (old->defs.next == NULL)
147 old = uTypedAlloc(LEDInfo);
150 WSGO("Couldn't allocate indicator map\n");
151 ACTION("Map for indicator %s not compiled\n",
152 XkbcAtomText(new->name));
156 old->defs.next = NULL;
159 last->defs.next = &old->defs;
165 static const LookupEntry modComponentNames[] = {
166 {"base", XkbIM_UseBase},
167 {"latched", XkbIM_UseLatched},
168 {"locked", XkbIM_UseLocked},
169 {"effective", XkbIM_UseEffective},
170 {"compat", XkbIM_UseCompat},
171 {"any", XkbIM_UseAnyMods},
175 static const LookupEntry groupComponentNames[] = {
176 {"base", XkbIM_UseBase},
177 {"latched", XkbIM_UseLatched},
178 {"locked", XkbIM_UseLocked},
179 {"effective", XkbIM_UseEffective},
180 {"any", XkbIM_UseAnyGroup},
185 static const LookupEntry groupNames[] = {
200 SetIndicatorMapField(LEDInfo * led,
201 struct xkb_desc * xkb,
202 char *field, ExprDef * arrayNdx, ExprDef * value)
208 if ((strcasecmp(field, "modifiers") == 0) ||
209 (strcasecmp(field, "mods") == 0))
211 if (arrayNdx != NULL)
212 return ReportIndicatorNotArray(led, field);
213 if (!ExprResolveVModMask(value, &rtrn, xkb))
214 return ReportIndicatorBadType(led, field, "modifier mask");
215 led->real_mods = rtrn.uval & 0xff;
216 led->vmods = (rtrn.uval >> 8) & 0xff;
217 led->defs.defined |= _LED_Mods;
219 else if (strcasecmp(field, "groups") == 0)
221 if (arrayNdx != NULL)
222 return ReportIndicatorNotArray(led, field);
223 if (!ExprResolveMask(value, &rtrn, groupNames))
224 return ReportIndicatorBadType(led, field, "group mask");
225 led->groups = rtrn.uval;
226 led->defs.defined |= _LED_Groups;
228 else if ((strcasecmp(field, "controls") == 0) ||
229 (strcasecmp(field, "ctrls") == 0))
231 if (arrayNdx != NULL)
232 return ReportIndicatorNotArray(led, field);
233 if (!ExprResolveMask(value, &rtrn, ctrlNames))
234 return ReportIndicatorBadType(led, field,
236 led->ctrls = rtrn.uval;
237 led->defs.defined |= _LED_Ctrls;
239 else if (strcasecmp(field, "allowexplicit") == 0)
241 if (arrayNdx != NULL)
242 return ReportIndicatorNotArray(led, field);
243 if (!ExprResolveBoolean(value, &rtrn))
244 return ReportIndicatorBadType(led, field, "boolean");
246 led->flags &= ~XkbIM_NoExplicit;
248 led->flags |= XkbIM_NoExplicit;
249 led->defs.defined |= _LED_Explicit;
251 else if ((strcasecmp(field, "whichmodstate") == 0) ||
252 (strcasecmp(field, "whichmodifierstate") == 0))
254 if (arrayNdx != NULL)
255 return ReportIndicatorNotArray(led, field);
256 if (!ExprResolveMask(value, &rtrn, modComponentNames))
258 return ReportIndicatorBadType(led, field,
259 "mask of modifier state components");
261 led->which_mods = rtrn.uval;
263 else if (strcasecmp(field, "whichgroupstate") == 0)
265 if (arrayNdx != NULL)
266 return ReportIndicatorNotArray(led, field);
267 if (!ExprResolveMask(value, &rtrn, groupComponentNames))
269 return ReportIndicatorBadType(led, field,
270 "mask of group state components");
272 led->which_groups = rtrn.uval;
274 else if ((strcasecmp(field, "driveskbd") == 0) ||
275 (strcasecmp(field, "driveskeyboard") == 0) ||
276 (strcasecmp(field, "leddriveskbd") == 0) ||
277 (strcasecmp(field, "leddriveskeyboard") == 0) ||
278 (strcasecmp(field, "indicatordriveskbd") == 0) ||
279 (strcasecmp(field, "indicatordriveskeyboard") == 0))
281 if (arrayNdx != NULL)
282 return ReportIndicatorNotArray(led, field);
283 if (!ExprResolveBoolean(value, &rtrn))
284 return ReportIndicatorBadType(led, field, "boolean");
286 led->flags |= XkbIM_LEDDrivesKB;
288 led->flags &= ~XkbIM_LEDDrivesKB;
289 led->defs.defined |= _LED_DrivesKbd;
291 else if (strcasecmp(field, "index") == 0)
293 if (arrayNdx != NULL)
294 return ReportIndicatorNotArray(led, field);
295 if (!ExprResolveInteger(value, &rtrn))
296 return ReportIndicatorBadType(led, field,
298 if ((rtrn.uval < 1) || (rtrn.uval > 32))
300 ERROR("Illegal indicator index %d (range 1..%d)\n",
301 rtrn.uval, XkbNumIndicators);
302 ACTION("Index definition for %s indicator ignored\n",
303 XkbcAtomText(led->name));
306 led->indicator = rtrn.uval;
307 led->defs.defined |= _LED_Index;
311 ERROR("Unknown field %s in map for %s indicator\n", field,
312 XkbcAtomText(led->name));
313 ACTION("Definition ignored\n");
320 HandleIndicatorMapDef(IndicatorMapDef * def,
321 struct xkb_desc * xkb,
322 LEDInfo * dflt, LEDInfo * oldLEDs, unsigned merge)
328 if (def->merge != MergeDefault)
332 led.defs.merge = merge;
333 led.name = def->name;
336 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
338 ExprResult elem, field;
340 if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx))
345 if (elem.str != NULL)
348 ("Cannot set defaults for \"%s\" element in indicator map\n",
350 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
355 ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx,
363 rtrn = AddIndicatorMap(oldLEDs, &led);
370 CopyIndicatorMapDefs(struct xkb_desc * xkb, LEDInfo *leds, LEDInfo **unboundRtrn)
373 LEDInfo *unbound, *last;
375 if (XkbcAllocNames(xkb, XkbIndicatorNamesMask, 0) != Success)
377 WSGO("Couldn't allocate names\n");
378 ACTION("Indicator names may be incorrect\n");
380 if (XkbcAllocIndicatorMaps(xkb) != Success)
382 WSGO("Can't allocate indicator maps\n");
383 ACTION("Indicator map definitions may be lost\n");
386 last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
387 while ((last != NULL) && (last->defs.next != NULL))
389 last = (LEDInfo *) last->defs.next;
391 for (led = leds; led != NULL; led = next)
393 next = (LEDInfo *) led->defs.next;
394 if ((led->groups != 0) && (led->which_groups == 0))
395 led->which_groups = XkbIM_UseEffective;
396 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
397 led->which_mods = XkbIM_UseEffective;
398 if ((led->indicator == _LED_NotBound) || (!xkb->indicators))
400 if (unboundRtrn != NULL)
402 led->defs.next = NULL;
404 last->defs.next = (CommonInfo *) led;
414 struct xkb_indicator_map * im;
415 im = &xkb->indicators->maps[led->indicator - 1];
416 im->flags = led->flags;
417 im->which_groups = led->which_groups;
418 im->groups = led->groups;
419 im->which_mods = led->which_mods;
420 im->mods.mask = led->real_mods;
421 im->mods.real_mods = led->real_mods;
422 im->mods.vmods = led->vmods;
423 im->ctrls = led->ctrls;
424 if (xkb->names != NULL)
426 free((char *) xkb->names->indicators[led->indicator - 1]);
427 xkb->names->indicators[led->indicator-1] = XkbcAtomGetString(led->name);
432 if (unboundRtrn != NULL)
434 *unboundRtrn = unbound;
440 BindIndicators(struct xkb_desc * xkb, Bool force, LEDInfo *unbound,
441 LEDInfo **unboundRtrn)
444 LEDInfo *led, *next, *last;
446 if (xkb->names != NULL)
448 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
450 if (led->indicator == _LED_NotBound)
452 for (i = 0; i < XkbNumIndicators; i++)
454 if (xkb->names->indicators[i] &&
455 strcmp(xkb->names->indicators[i],
456 XkbcAtomText(led->name)) == 0)
458 led->indicator = i + 1;
466 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next)
468 if (led->indicator == _LED_NotBound)
470 for (i = 0; i < XkbNumIndicators; i++)
472 if (xkb->names->indicators[i] == NULL)
474 xkb->names->indicators[i] = XkbcAtomGetString(led->name);
475 led->indicator = i + 1;
476 xkb->indicators->phys_indicators &= ~(1 << i);
480 if (led->indicator == _LED_NotBound)
482 ERROR("No unnamed indicators found\n");
484 ("Virtual indicator map \"%s\" not bound\n",
485 XkbcAtomText(led->name));
492 for (last = NULL, led = unbound; led != NULL; led = next)
494 next = (LEDInfo *) led->defs.next;
495 if (led->indicator == _LED_NotBound)
505 last->defs.next = &led->defs;
513 if ((xkb->names != NULL) &&
514 (strcmp(xkb->names->indicators[led->indicator - 1],
515 XkbcAtomText(led->name)) != 0))
517 const char *old = xkb->names->indicators[led->indicator - 1];
518 ERROR("Multiple names bound to indicator %d\n",
519 (unsigned int) led->indicator);
520 ACTION("Using %s, ignoring %s\n", old, XkbcAtomText(led->name));
521 led->indicator = _LED_NotBound;
530 last->defs.next = &led->defs;
538 struct xkb_indicator_map * map;
539 map = &xkb->indicators->maps[led->indicator - 1];
540 map->flags = led->flags;
541 map->which_groups = led->which_groups;
542 map->groups = led->groups;
543 map->which_mods = led->which_mods;
544 map->mods.mask = led->real_mods;
545 map->mods.real_mods = led->real_mods;
546 map->mods.vmods = led->vmods;
547 map->ctrls = led->ctrls;
549 last->defs.next = &next->defs;
552 led->defs.next = NULL;
559 *unboundRtrn = unbound;
563 for (led = unbound; led != NULL; led = next)
565 next = led ? (LEDInfo *) led->defs.next : NULL;