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"
36 /***====================================================================***/
38 #define ReportIndicatorBadType(l, f, w) \
39 ReportBadType("indicator map", (f), XkbcAtomText((l)->name), (w))
40 #define ReportIndicatorNotArray(l, f) \
41 ReportNotArray("indicator map", (f), XkbcAtomText((l)->name))
43 /***====================================================================***/
46 ClearIndicatorMapInfo(LEDInfo * info)
48 info->name = xkb_intern_atom("default");
49 info->indicator = _LED_NotBound;
50 info->flags = info->which_mods = info->real_mods = 0;
52 info->which_groups = info->groups = 0;
57 AddIndicatorMap(LEDInfo * oldLEDs, LEDInfo * new)
63 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next)
65 if (old->name == new->name)
67 if ((old->real_mods == new->real_mods) &&
68 (old->vmods == new->vmods) &&
69 (old->groups == new->groups) &&
70 (old->ctrls == new->ctrls) &&
71 (old->which_mods == new->which_mods) &&
72 (old->which_groups == new->which_groups))
74 old->defs.defined |= new->defs.defined;
77 if (new->defs.merge == MergeReplace)
79 CommonInfo *next = old->defs.next;
80 if (((old->defs.fileID == new->defs.fileID)
81 && (warningLevel > 0)) || (warningLevel > 9))
83 WARN("Map for indicator %s redefined\n",
84 XkbcAtomText(old->name));
85 ACTION("Earlier definition ignored\n");
88 old->defs.next = next;
92 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))
99 old->which_mods = new->which_mods;
100 old->real_mods = new->real_mods;
101 old->vmods = new->vmods;
102 old->defs.defined |= _LED_Mods;
104 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide))
106 old->which_groups = new->which_groups;
107 old->groups = new->groups;
108 old->defs.defined |= _LED_Groups;
110 if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide))
112 old->ctrls = new->ctrls;
113 old->defs.defined |= _LED_Ctrls;
115 if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide))
117 old->flags &= ~XkbIM_NoExplicit;
118 old->flags |= (new->flags & XkbIM_NoExplicit);
119 old->defs.defined |= _LED_Explicit;
121 if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide))
123 old->flags &= ~XkbIM_NoAutomatic;
124 old->flags |= (new->flags & XkbIM_NoAutomatic);
125 old->defs.defined |= _LED_Automatic;
127 if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide))
129 old->flags &= ~XkbIM_LEDDrivesKB;
130 old->flags |= (new->flags & XkbIM_LEDDrivesKB);
131 old->defs.defined |= _LED_DrivesKbd;
135 WARN("Map for indicator %s redefined\n",
136 XkbcAtomText(old->name));
137 ACTION("Using %s definition for duplicate fields\n",
138 (new->defs.merge == MergeAugment ? "first" : "last"));
142 if (old->defs.next == NULL)
146 old = uTypedAlloc(LEDInfo);
149 WSGO("Couldn't allocate indicator map\n");
150 ACTION("Map for indicator %s not compiled\n",
151 XkbcAtomText(new->name));
155 old->defs.next = NULL;
158 last->defs.next = &old->defs;
164 static const LookupEntry modComponentNames[] = {
165 {"base", XkbIM_UseBase},
166 {"latched", XkbIM_UseLatched},
167 {"locked", XkbIM_UseLocked},
168 {"effective", XkbIM_UseEffective},
169 {"compat", XkbIM_UseCompat},
170 {"any", XkbIM_UseAnyMods},
174 static const LookupEntry groupComponentNames[] = {
175 {"base", XkbIM_UseBase},
176 {"latched", XkbIM_UseLatched},
177 {"locked", XkbIM_UseLocked},
178 {"effective", XkbIM_UseEffective},
179 {"any", XkbIM_UseAnyGroup},
184 static const LookupEntry groupNames[] = {
199 SetIndicatorMapField(LEDInfo * led,
200 struct xkb_desc * xkb,
201 char *field, ExprDef * arrayNdx, ExprDef * value)
207 if ((uStrCaseCmp(field, "modifiers") == 0)
208 || (uStrCaseCmp(field, "mods") == 0))
210 if (arrayNdx != NULL)
211 return ReportIndicatorNotArray(led, field);
212 if (!ExprResolveVModMask(value, &rtrn, xkb))
213 return ReportIndicatorBadType(led, field, "modifier mask");
214 led->real_mods = rtrn.uval & 0xff;
215 led->vmods = (rtrn.uval >> 8) & 0xff;
216 led->defs.defined |= _LED_Mods;
218 else if (uStrCaseCmp(field, "groups") == 0)
220 if (arrayNdx != NULL)
221 return ReportIndicatorNotArray(led, field);
222 if (!ExprResolveMask(value, &rtrn, groupNames))
223 return ReportIndicatorBadType(led, field, "group mask");
224 led->groups = rtrn.uval;
225 led->defs.defined |= _LED_Groups;
227 else if ((uStrCaseCmp(field, "controls") == 0) ||
228 (uStrCaseCmp(field, "ctrls") == 0))
230 if (arrayNdx != NULL)
231 return ReportIndicatorNotArray(led, field);
232 if (!ExprResolveMask(value, &rtrn, ctrlNames))
233 return ReportIndicatorBadType(led, field,
235 led->ctrls = rtrn.uval;
236 led->defs.defined |= _LED_Ctrls;
238 else if (uStrCaseCmp(field, "allowexplicit") == 0)
240 if (arrayNdx != NULL)
241 return ReportIndicatorNotArray(led, field);
242 if (!ExprResolveBoolean(value, &rtrn))
243 return ReportIndicatorBadType(led, field, "boolean");
245 led->flags &= ~XkbIM_NoExplicit;
247 led->flags |= XkbIM_NoExplicit;
248 led->defs.defined |= _LED_Explicit;
250 else if ((uStrCaseCmp(field, "whichmodstate") == 0) ||
251 (uStrCaseCmp(field, "whichmodifierstate") == 0))
253 if (arrayNdx != NULL)
254 return ReportIndicatorNotArray(led, field);
255 if (!ExprResolveMask(value, &rtrn, modComponentNames))
257 return ReportIndicatorBadType(led, field,
258 "mask of modifier state components");
260 led->which_mods = rtrn.uval;
262 else if (uStrCaseCmp(field, "whichgroupstate") == 0)
264 if (arrayNdx != NULL)
265 return ReportIndicatorNotArray(led, field);
266 if (!ExprResolveMask(value, &rtrn, groupComponentNames))
268 return ReportIndicatorBadType(led, field,
269 "mask of group state components");
271 led->which_groups = rtrn.uval;
273 else if ((uStrCaseCmp(field, "driveskbd") == 0) ||
274 (uStrCaseCmp(field, "driveskeyboard") == 0) ||
275 (uStrCaseCmp(field, "leddriveskbd") == 0) ||
276 (uStrCaseCmp(field, "leddriveskeyboard") == 0) ||
277 (uStrCaseCmp(field, "indicatordriveskbd") == 0) ||
278 (uStrCaseCmp(field, "indicatordriveskeyboard") == 0))
280 if (arrayNdx != NULL)
281 return ReportIndicatorNotArray(led, field);
282 if (!ExprResolveBoolean(value, &rtrn))
283 return ReportIndicatorBadType(led, field, "boolean");
285 led->flags |= XkbIM_LEDDrivesKB;
287 led->flags &= ~XkbIM_LEDDrivesKB;
288 led->defs.defined |= _LED_DrivesKbd;
290 else if (uStrCaseCmp(field, "index") == 0)
292 if (arrayNdx != NULL)
293 return ReportIndicatorNotArray(led, field);
294 if (!ExprResolveInteger(value, &rtrn))
295 return ReportIndicatorBadType(led, field,
297 if ((rtrn.uval < 1) || (rtrn.uval > 32))
299 ERROR("Illegal indicator index %d (range 1..%d)\n",
300 rtrn.uval, XkbNumIndicators);
301 ACTION("Index definition for %s indicator ignored\n",
302 XkbcAtomText(led->name));
305 led->indicator = rtrn.uval;
306 led->defs.defined |= _LED_Index;
310 ERROR("Unknown field %s in map for %s indicator\n", field,
311 XkbcAtomText(led->name));
312 ACTION("Definition ignored\n");
319 HandleIndicatorMapDef(IndicatorMapDef * def,
320 struct xkb_desc * xkb,
321 LEDInfo * dflt, LEDInfo * oldLEDs, unsigned merge)
327 if (def->merge != MergeDefault)
331 led.defs.merge = merge;
332 led.name = def->name;
335 for (var = def->body; var != NULL; var = (VarDef *) var->common.next)
337 ExprResult elem, field;
339 if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx))
344 if (elem.str != NULL)
347 ("Cannot set defaults for \"%s\" element in indicator map\n",
349 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str);
354 ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx,
362 rtrn = AddIndicatorMap(oldLEDs, &led);
369 CopyIndicatorMapDefs(struct xkb_desc * xkb, LEDInfo *leds, LEDInfo **unboundRtrn)
372 LEDInfo *unbound, *last;
374 if (XkbcAllocNames(xkb, XkbIndicatorNamesMask, 0) != Success)
376 WSGO("Couldn't allocate names\n");
377 ACTION("Indicator names may be incorrect\n");
379 if (XkbcAllocIndicatorMaps(xkb) != Success)
381 WSGO("Can't allocate indicator maps\n");
382 ACTION("Indicator map definitions may be lost\n");
385 last = unbound = (unboundRtrn ? *unboundRtrn : NULL);
386 while ((last != NULL) && (last->defs.next != NULL))
388 last = (LEDInfo *) last->defs.next;
390 for (led = leds; led != NULL; led = next)
392 next = (LEDInfo *) led->defs.next;
393 if ((led->groups != 0) && (led->which_groups == 0))
394 led->which_groups = XkbIM_UseEffective;
395 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods)))
396 led->which_mods = XkbIM_UseEffective;
397 if ((led->indicator == _LED_NotBound) || (!xkb->indicators))
399 if (unboundRtrn != NULL)
401 led->defs.next = NULL;
403 last->defs.next = (CommonInfo *) led;
413 struct xkb_indicator_map * im;
414 im = &xkb->indicators->maps[led->indicator - 1];
415 im->flags = led->flags;
416 im->which_groups = led->which_groups;
417 im->groups = led->groups;
418 im->which_mods = led->which_mods;
419 im->mods.mask = led->real_mods;
420 im->mods.real_mods = led->real_mods;
421 im->mods.vmods = led->vmods;
422 im->ctrls = led->ctrls;
423 if (xkb->names != NULL)
424 xkb->names->indicators[led->indicator - 1] = led->name;
428 if (unboundRtrn != NULL)
430 *unboundRtrn = unbound;
436 BindIndicators(struct xkb_desc * xkb, Bool force, LEDInfo *unbound,
437 LEDInfo **unboundRtrn)
440 LEDInfo *led, *next, *last;
442 if (xkb->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 (xkb->names->indicators[i] == led->name)
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 (xkb->names->indicators[i] == None)
468 xkb->names->indicators[i] = led->name;
469 led->indicator = i + 1;
470 xkb->indicators->phys_indicators &= ~(1 << i);
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 ((xkb->names != NULL) &&
508 (xkb->names->indicators[led->indicator - 1] != led->name))
510 uint32_t old = xkb->names->indicators[led->indicator - 1];
511 ERROR("Multiple names bound to indicator %d\n",
512 (unsigned int) led->indicator);
513 ACTION("Using %s, ignoring %s\n",
515 XkbcAtomText(led->name));
516 led->indicator = _LED_NotBound;
525 last->defs.next = &led->defs;
533 struct xkb_indicator_map * map;
534 map = &xkb->indicators->maps[led->indicator - 1];
535 map->flags = led->flags;
536 map->which_groups = led->which_groups;
537 map->groups = led->groups;
538 map->which_mods = led->which_mods;
539 map->mods.mask = led->real_mods;
540 map->mods.real_mods = led->real_mods;
541 map->mods.vmods = led->vmods;
542 map->ctrls = led->ctrls;
544 last->defs.next = &next->defs;
547 led->defs.next = NULL;
554 *unboundRtrn = unbound;
558 for (led = unbound; led != NULL; led = next)
560 next = led ? (LEDInfo *) led->defs.next : NULL;